Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3543 lines
112 KiB

  1. /********************************************************************/
  2. /** Microsoft LAN Manager **/
  3. /** Copyright(c) Microsoft Corp., 1990-1993 **/
  4. /********************************************************************/
  5. /* :ts=4 */
  6. //** TCB.C - TCP TCB management code.
  7. //
  8. // This file contains the code for managing TCBs.
  9. //
  10. #include "precomp.h"
  11. #include "addr.h"
  12. #include "tcp.h"
  13. #include "tcb.h"
  14. #include "tlcommon.h"
  15. #include "tcpconn.h"
  16. #include "tcpsend.h"
  17. #include "tcprcv.h"
  18. #include "info.h"
  19. #include "tcpcfg.h"
  20. #include "tcpdeliv.h"
  21. #include "pplasl.h"
  22. #include <acd.h>
  23. #include <acdapi.h>
  24. HANDLE TcbPool;
  25. HANDLE SynTcbPool;
  26. extern HANDLE TcpRequestPool;
  27. //Special spinlock and table for TIMED_WAIT states.
  28. extern CTELock *pTWTCBTableLock;
  29. extern CTELock *pSynTCBTableLock;
  30. Queue *TWTCBTable;
  31. PTIMER_WHEEL TimerWheel;
  32. // This queue is used for faster scavenging
  33. Queue *TWQueue;
  34. ulong numtwqueue = 0;
  35. ulong numtwtimedout = 0;
  36. extern
  37. void
  38. ClassifyPacket(TCB *SendTCB);
  39. void
  40. TCBTimeoutdpc(
  41. #if !MILLEN
  42. PKDPC Dpc,
  43. #else // !MILLEN
  44. PVOID arg0,
  45. #endif // MILLEN
  46. PVOID DeferredContext,
  47. PVOID arg1,
  48. PVOID arg2
  49. );
  50. extern CTELock *pTCBTableLock;
  51. #if MILLEN
  52. #define MAX_TIMER_PROCS 1
  53. #else // MILLEN
  54. #define MAX_TIMER_PROCS 32
  55. #endif // !MILLEN
  56. uint TCPTime;
  57. uint CPUTCPTime[MAX_TIMER_PROCS];
  58. uint TCBWalkCount;
  59. uint PerTimerSize = 0;
  60. uint Time_Proc = 0;
  61. TCB **TCBTable;
  62. TCB *PendingFreeList=NULL;
  63. SYNTCB *PendingSynFreeList=NULL;
  64. Queue *SYNTCBTable;
  65. CACHE_LINE_KSPIN_LOCK PendingFreeLock;
  66. #define NUM_DEADMAN_TICKS MS_TO_TICKS(1000)
  67. #define NUM_DEADMAN_TIME 1000
  68. uint MaxHashTableSize = 512;
  69. uint DeadmanTicks;
  70. //choose reasonable defaults
  71. uint NumTcbTablePartitions = 4;
  72. uint PerPartitionSize = 128;
  73. uint LogPerPartitionSize = 7;
  74. CTETimer TCBTimer[MAX_TIMER_PROCS];
  75. ULONGLONG systemtime;
  76. ULONGLONG delta=0;
  77. extern IPInfo LocalNetInfo;
  78. extern SeqNum g_CurISN;
  79. //
  80. // All of the init code can be discarded.
  81. //
  82. int InitTCB(void);
  83. void UnInitTCB(void);
  84. #ifdef ALLOC_PRAGMA
  85. #pragma alloc_text(INIT, InitTCB)
  86. #pragma alloc_text(INIT, UnInitTCB)
  87. #endif
  88. extern CTEBlockStruc TcpipUnloadBlock;
  89. BOOLEAN fTCBTimerStopping = FALSE;
  90. extern ACD_DRIVER AcdDriverG;
  91. VOID
  92. TCPNoteNewConnection(
  93. IN TCB * pTCB,
  94. IN CTELockHandle Handle
  95. );
  96. uint
  97. GetTCBInfo(PTCP_FINDTCB_RESPONSE TCBInfo,
  98. IPAddr Dest,
  99. IPAddr Src,
  100. ushort DestPort,
  101. ushort SrcPort
  102. );
  103. void
  104. TCBTimeoutdpc(
  105. #if !MILLEN
  106. PKDPC Dpc,
  107. #else // !MILLEN
  108. PVOID arg0,
  109. #endif // MILLEN
  110. PVOID DeferredContext,
  111. PVOID arg1,
  112. PVOID arg2
  113. )
  114. /*++
  115. Routine Description:
  116. System timer dpc wrapper routine for TCBTimeout().
  117. Arguments:
  118. Return Value:
  119. None.
  120. --*/
  121. {
  122. CTETimer *Timer;
  123. Timer = (CTETimer *) DeferredContext;
  124. #if MILLEN
  125. // Set the timer again to make it periodic.
  126. NdisSetTimer(&Timer->t_timer, MS_PER_TICK);
  127. #endif // MILLEN
  128. (*Timer->t_handler)((CTEEvent *)Timer, Timer->t_arg);
  129. }
  130. void
  131. CTEInitTimerEx(
  132. CTETimer *Timer
  133. )
  134. /*++
  135. Routine Description:
  136. Initializes a CTE Timer variable for periodic timer.
  137. Arguments:
  138. Timer - Timer variable to initialize.
  139. Return Value:
  140. None.
  141. --*/
  142. {
  143. Timer->t_handler = NULL;
  144. Timer->t_arg = NULL;
  145. #if !MILLEN
  146. KeInitializeDpc(&(Timer->t_dpc), TCBTimeoutdpc, Timer);
  147. KeInitializeTimerEx(&(Timer->t_timer),NotificationTimer);
  148. #else !MILLEN
  149. NdisInitializeTimer(&Timer->t_timer, TCBTimeoutdpc, Timer);
  150. #endif // MILLEN
  151. }
  152. void *
  153. CTEStartTimerEx(
  154. CTETimer *Timer,
  155. unsigned long DueTime,
  156. CTEEventRtn Handler,
  157. void *Context
  158. )
  159. /*++
  160. Routine Description:
  161. Sets a CTE Timer for expiration for periodic timer.
  162. Arguments:
  163. Timer - Pointer to a CTE Timer variable.
  164. DueTime - Time in milliseconds after which the timer should expire.
  165. Handler - Timer expiration handler routine.
  166. Context - Argument to pass to the handler.
  167. Return Value:
  168. 0 if the timer could not be set. Nonzero otherwise.
  169. --*/
  170. {
  171. #if !MILLEN
  172. LARGE_INTEGER LargeDueTime;
  173. ASSERT(Handler != NULL);
  174. //
  175. // Convert milliseconds to hundreds of nanoseconds and negate to make
  176. // an NT relative timeout.
  177. //
  178. LargeDueTime.HighPart = 0;
  179. LargeDueTime.LowPart = DueTime;
  180. LargeDueTime = RtlExtendedIntegerMultiply(LargeDueTime, 10000);
  181. LargeDueTime.QuadPart = -LargeDueTime.QuadPart;
  182. Timer->t_handler = Handler;
  183. Timer->t_arg = Context;
  184. KeSetTimerEx(
  185. &(Timer->t_timer),
  186. LargeDueTime,
  187. MS_PER_TICK,
  188. &(Timer->t_dpc)
  189. );
  190. #else // !MILLEN
  191. ASSERT(Handler != NULL);
  192. Timer->t_handler = Handler;
  193. Timer->t_arg = Context;
  194. NdisSetTimer(&Timer->t_timer, DueTime);
  195. #endif // MILLEN
  196. return((void *) 1);
  197. }
  198. //* ReadNextTCB - Read the next TCB in the table.
  199. //
  200. // Called to read the next TCB in the table. The needed information
  201. // is derived from the incoming context, which is assumed to be valid.
  202. // We'll copy the information, and then update the context value with
  203. // the next TCB to be read.
  204. // The table lock for the given index is assumed to be held when this
  205. // function is called.
  206. //
  207. // Input: Context - Poiner to a TCPConnContext.
  208. // Buffer - Pointer to a TCPConnTableEntry structure.
  209. //
  210. // Returns: TRUE if more data is available to be read, FALSE is not.
  211. //
  212. uint
  213. ReadNextTCB(void *Context, void *Buffer)
  214. {
  215. TCPConnContext *TCContext = (TCPConnContext *) Context;
  216. TCPConnTableEntry *TCEntry = (TCPConnTableEntry *) Buffer;
  217. CTELockHandle Handle;
  218. TCB *CurrentTCB;
  219. TWTCB *CurrentTWTCB;
  220. Queue *Scan;
  221. uint i;
  222. if (TCContext->tcc_index >= TCB_TABLE_SIZE) {
  223. CurrentTWTCB = (TWTCB *) TCContext->tcc_tcb;
  224. CTEStructAssert(CurrentTWTCB, twtcb);
  225. TCEntry->tct_state = TCB_TIME_WAIT + TCB_STATE_DELTA;
  226. TCEntry->tct_localaddr = CurrentTWTCB->twtcb_saddr;
  227. TCEntry->tct_localport = CurrentTWTCB->twtcb_sport;
  228. TCEntry->tct_remoteaddr = CurrentTWTCB->twtcb_daddr;
  229. TCEntry->tct_remoteport = CurrentTWTCB->twtcb_dport;
  230. if (TCContext->tcc_infosize > sizeof(TCPConnTableEntry)) {
  231. ((TCPConnTableEntryEx*)TCEntry)->tcte_owningpid = 0;
  232. }
  233. i = TCContext->tcc_index - TCB_TABLE_SIZE;
  234. Scan = QNEXT(&CurrentTWTCB->twtcb_link);
  235. if (Scan != QEND(&TWTCBTable[i])) {
  236. TCContext->tcc_tcb = (TCB *) QSTRUCT(TWTCB, Scan, twtcb_link);
  237. return TRUE;
  238. }
  239. } else {
  240. CurrentTCB = TCContext->tcc_tcb;
  241. CTEStructAssert(CurrentTCB, tcb);
  242. CTEGetLock(&CurrentTCB->tcb_lock, &Handle);
  243. if (CLOSING(CurrentTCB))
  244. TCEntry->tct_state = TCP_CONN_CLOSED;
  245. else
  246. TCEntry->tct_state = (uint) CurrentTCB->tcb_state + TCB_STATE_DELTA;
  247. TCEntry->tct_localaddr = CurrentTCB->tcb_saddr;
  248. TCEntry->tct_localport = CurrentTCB->tcb_sport;
  249. TCEntry->tct_remoteaddr = CurrentTCB->tcb_daddr;
  250. TCEntry->tct_remoteport = CurrentTCB->tcb_dport;
  251. if (TCContext->tcc_infosize > sizeof(TCPConnTableEntry)) {
  252. ((TCPConnTableEntryEx*)TCEntry)->tcte_owningpid =
  253. (CurrentTCB->tcb_conn) ? CurrentTCB->tcb_conn->tc_owningpid
  254. : 0;
  255. }
  256. CTEFreeLock(&CurrentTCB->tcb_lock, Handle);
  257. if (CurrentTCB->tcb_next != NULL) {
  258. TCContext->tcc_tcb = CurrentTCB->tcb_next;
  259. return TRUE;
  260. }
  261. }
  262. // NextTCB is NULL. Loop through the TCBTable looking for a new
  263. // one.
  264. i = TCContext->tcc_index + 1;
  265. if (i >= TCB_TABLE_SIZE) {
  266. // If the index is greater than the TCB_TABLE_SIZE,
  267. // Then it must be referring to the TIM_WAIT table.
  268. // Get the correct hash index and search in TW table.
  269. i = i - TCB_TABLE_SIZE;
  270. while (i < TCB_TABLE_SIZE) {
  271. if (!EMPTYQ(&TWTCBTable[i])) {
  272. TCContext->tcc_tcb = (TCB *)
  273. QSTRUCT(TWTCB, QHEAD(&TWTCBTable[i]), twtcb_link);
  274. TCContext->tcc_index = i + TCB_TABLE_SIZE;
  275. return TRUE;
  276. break;
  277. } else
  278. i++;
  279. }
  280. } else {
  281. //Normal table scan
  282. while (i < TCB_TABLE_SIZE) {
  283. if (TCBTable[i] != NULL) {
  284. TCContext->tcc_tcb = TCBTable[i];
  285. TCContext->tcc_index = i;
  286. return TRUE;
  287. break;
  288. } else
  289. i++;
  290. }
  291. // We exhausted normal table move on to TIM_WAIT table
  292. i = i - TCB_TABLE_SIZE;
  293. while (i < TCB_TABLE_SIZE) {
  294. if (!EMPTYQ(&TWTCBTable[i])) {
  295. TCContext->tcc_tcb = (TCB *)
  296. QSTRUCT(TWTCB, QHEAD(&TWTCBTable[i]), twtcb_link);
  297. TCContext->tcc_index = i + TCB_TABLE_SIZE;
  298. return TRUE;
  299. break;
  300. } else
  301. i++;
  302. }
  303. }
  304. TCContext->tcc_index = 0;
  305. TCContext->tcc_tcb = NULL;
  306. return FALSE;
  307. }
  308. //* ValidateTCBContext - Validate the context for reading a TCB table.
  309. //
  310. // Called to start reading the TCB table sequentially. We take in
  311. // a context, and if the values are 0 we return information about the
  312. // first TCB in the table. Otherwise we make sure that the context value
  313. // is valid, and if it is we return TRUE.
  314. // We assume the caller holds the TCB table lock.
  315. //
  316. // Input: Context - Pointer to a TCPConnContext.
  317. // Valid - Where to return information about context being
  318. // valid.
  319. //
  320. // Returns: TRUE if data in table, FALSE if not. *Valid set to true if the
  321. // context is valid.
  322. //
  323. uint
  324. ValidateTCBContext(void *Context, uint * Valid)
  325. {
  326. TCPConnContext *TCContext = (TCPConnContext *) Context;
  327. uint i;
  328. TCB *TargetTCB;
  329. TCB *CurrentTCB;
  330. TWTCB *CurrentTWTCB;
  331. Queue *Scan;
  332. i = TCContext->tcc_index;
  333. TargetTCB = TCContext->tcc_tcb;
  334. // If the context values are 0 and NULL, we're starting from the beginning.
  335. if (i == 0 && TargetTCB == NULL) {
  336. *Valid = TRUE;
  337. do {
  338. if ((CurrentTCB = TCBTable[i]) != NULL) {
  339. CTEStructAssert(CurrentTCB, tcb);
  340. TCContext->tcc_index = i;
  341. TCContext->tcc_tcb = CurrentTCB;
  342. return TRUE;
  343. }
  344. i++;
  345. } while (i < TCB_TABLE_SIZE);
  346. // We have TCBs in time wait table also...
  347. i = 0;
  348. do {
  349. if (!EMPTYQ(&TWTCBTable[i])) {
  350. CurrentTWTCB =
  351. QSTRUCT(TWTCB, QHEAD(&TWTCBTable[i]), twtcb_link);
  352. CTEStructAssert(CurrentTWTCB, twtcb);
  353. TCContext->tcc_index = i + TCB_TABLE_SIZE;
  354. TCContext->tcc_tcb = (TCB *) CurrentTWTCB;
  355. return TRUE;
  356. }
  357. i++;
  358. } while (i < TCB_TABLE_SIZE);
  359. return FALSE;
  360. } else {
  361. // We've been given a context. We just need to make sure that it's
  362. // valid.
  363. if (i >= TCB_TABLE_SIZE) {
  364. // If the index is greater than the TCB_TABLE_SIZE,
  365. // Then it must be referring to the TIM_WAIT table.
  366. // Get the correct hash index and search in TW table.
  367. i = i - TCB_TABLE_SIZE;
  368. if (i < TCB_TABLE_SIZE) {
  369. Scan = QHEAD(&TWTCBTable[i]);
  370. while (Scan != QEND(&TWTCBTable[i])) {
  371. CurrentTWTCB = QSTRUCT(TWTCB, Scan, twtcb_link);
  372. if (CurrentTWTCB == (TWTCB *) TargetTCB) {
  373. *Valid = TRUE;
  374. return TRUE;
  375. break;
  376. } else {
  377. Scan = QNEXT(Scan);
  378. }
  379. }
  380. }
  381. } else {
  382. //Normal table
  383. if (i < TCB_TABLE_SIZE) {
  384. CurrentTCB = TCBTable[i];
  385. while (CurrentTCB != NULL) {
  386. if (CurrentTCB == TargetTCB) {
  387. *Valid = TRUE;
  388. return TRUE;
  389. break;
  390. } else {
  391. CurrentTCB = CurrentTCB->tcb_next;
  392. }
  393. }
  394. }
  395. }
  396. // If we get here, we didn't find the matching TCB.
  397. *Valid = FALSE;
  398. return FALSE;
  399. }
  400. }
  401. //* FindNextTCB - Find the next TCB in a particular chain.
  402. //
  403. // This routine is used to find the 'next' TCB in a chain. Since we keep
  404. // the chain in ascending order, we look for a TCB which is greater than
  405. // the input TCB. When we find one, we return it.
  406. //
  407. // This routine is mostly used when someone is walking the table and needs
  408. // to free the various locks to perform some action.
  409. //
  410. // Input: Index - Index into TCBTable
  411. // Current - Current TCB - we find the one after this one.
  412. //
  413. // Returns: Pointer to the next TCB, or NULL.
  414. //
  415. TCB *
  416. FindNextTCB(uint Index, TCB * Current)
  417. {
  418. TCB *Next;
  419. ASSERT(Index < TCB_TABLE_SIZE);
  420. Next = TCBTable[Index];
  421. while (Next != NULL && (Next <= Current))
  422. Next = Next->tcb_next;
  423. return Next;
  424. }
  425. //* ResetSendNext - Set the sendnext value of a TCB.
  426. //
  427. // Called to set the send next value of a TCB. We do that, and adjust all
  428. // pointers to the appropriate places. We assume the caller holds the lock
  429. // on the TCB.
  430. //
  431. // Input: SeqTCB - Pointer to TCB to be updated.
  432. // NewSeq - Sequence number to set.
  433. //
  434. // Returns: Nothing.
  435. //
  436. void
  437. ResetSendNext(TCB *SeqTCB, SeqNum NewSeq)
  438. {
  439. TCPSendReq *SendReq;
  440. uint AmtForward;
  441. Queue *CurQ;
  442. PNDIS_BUFFER Buffer;
  443. uint Offset;
  444. CTEStructAssert(SeqTCB, tcb);
  445. ASSERT(SEQ_GTE(NewSeq, SeqTCB->tcb_senduna));
  446. // The new seq must be less than send max, or NewSeq, senduna, sendnext,
  447. // and sendmax must all be equal. (The latter case happens when we're
  448. // called exiting TIME_WAIT, or possibly when we're retransmitting
  449. // during a flow controlled situation).
  450. ASSERT(SEQ_LT(NewSeq, SeqTCB->tcb_sendmax) ||
  451. (SEQ_EQ(SeqTCB->tcb_senduna, SeqTCB->tcb_sendnext) &&
  452. SEQ_EQ(SeqTCB->tcb_senduna, SeqTCB->tcb_sendmax) &&
  453. SEQ_EQ(SeqTCB->tcb_senduna, NewSeq)));
  454. AmtForward = NewSeq - SeqTCB->tcb_senduna;
  455. if ((AmtForward == 1) && (SeqTCB->tcb_flags & FIN_SENT) &&
  456. !((SeqTCB->tcb_sendnext-SeqTCB->tcb_senduna) > 1) &&
  457. (SEQ_EQ(SeqTCB->tcb_sendnext, SeqTCB->tcb_sendmax))) {
  458. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  459. "tcpip: trying to set sendnext for FIN_SENT\n"));
  460. //CheckTCBSends(SeqTCB);
  461. //allow retransmits of this FIN
  462. SeqTCB->tcb_sendnext = NewSeq;
  463. SeqTCB->tcb_flags &= ~FIN_OUTSTANDING;
  464. return;
  465. }
  466. if ((SeqTCB->tcb_flags & FIN_SENT) &&
  467. (SEQ_EQ(SeqTCB->tcb_sendnext, SeqTCB->tcb_sendmax)) &&
  468. ((SeqTCB->tcb_sendnext - NewSeq) == 1)) {
  469. //There is only FIN that is left beyond sendnext.
  470. //allow retransmits of this FIN
  471. SeqTCB->tcb_sendnext = NewSeq;
  472. SeqTCB->tcb_flags &= ~FIN_OUTSTANDING;
  473. return;
  474. }
  475. SeqTCB->tcb_sendnext = NewSeq;
  476. // If we're backing off send next, turn off the FIN_OUTSTANDING flag to
  477. // maintain a consistent state.
  478. if (!SEQ_EQ(NewSeq, SeqTCB->tcb_sendmax))
  479. SeqTCB->tcb_flags &= ~FIN_OUTSTANDING;
  480. if (SYNC_STATE(SeqTCB->tcb_state) && SeqTCB->tcb_state != TCB_TIME_WAIT) {
  481. // In these states we need to update the send queue.
  482. if (!EMPTYQ(&SeqTCB->tcb_sendq)) {
  483. CurQ = QHEAD(&SeqTCB->tcb_sendq);
  484. SendReq = (TCPSendReq *) STRUCT_OF(TCPReq, CurQ, tr_q);
  485. // SendReq points to the first send request on the send queue.
  486. // Move forward AmtForward bytes on the send queue, and set the
  487. // TCB pointers to the resultant SendReq, buffer, offset, size.
  488. while (AmtForward) {
  489. CTEStructAssert(SendReq, tsr);
  490. if (AmtForward >= SendReq->tsr_unasize) {
  491. // We're going to move completely past this one. Subtract
  492. // his size from AmtForward and get the next one.
  493. AmtForward -= SendReq->tsr_unasize;
  494. CurQ = QNEXT(CurQ);
  495. ASSERT(CurQ != QEND(&SeqTCB->tcb_sendq));
  496. SendReq = (TCPSendReq *) STRUCT_OF(TCPReq, CurQ, tr_q);
  497. } else {
  498. // We're pointing at the proper send req now. Break out
  499. // of this loop and save the information. Further down
  500. // we'll need to walk down the buffer chain to find
  501. // the proper buffer and offset.
  502. break;
  503. }
  504. }
  505. // We're pointing at the proper send req now. We need to go down
  506. // the buffer chain here to find the proper buffer and offset.
  507. SeqTCB->tcb_cursend = SendReq;
  508. SeqTCB->tcb_sendsize = SendReq->tsr_unasize - AmtForward;
  509. Buffer = SendReq->tsr_buffer;
  510. Offset = SendReq->tsr_offset;
  511. while (AmtForward) {
  512. // Walk the buffer chain.
  513. uint Length;
  514. // We'll need the length of this buffer. Use the portable
  515. // macro to get it. We have to adjust the length by the offset
  516. // into it, also.
  517. ASSERT((Offset < NdisBufferLength(Buffer)) ||
  518. ((Offset == 0) && (NdisBufferLength(Buffer) == 0)));
  519. Length = NdisBufferLength(Buffer) - Offset;
  520. if (AmtForward >= Length) {
  521. // We're moving past this one. Skip over him, and 0 the
  522. // Offset we're keeping.
  523. AmtForward -= Length;
  524. Offset = 0;
  525. Buffer = NDIS_BUFFER_LINKAGE(Buffer);
  526. ASSERT(Buffer != NULL);
  527. } else
  528. break;
  529. }
  530. // Save the buffer we found, and the offset into that buffer.
  531. SeqTCB->tcb_sendbuf = Buffer;
  532. SeqTCB->tcb_sendofs = Offset + AmtForward;
  533. } else {
  534. ASSERT(SeqTCB->tcb_cursend == NULL);
  535. ASSERT(AmtForward == 0);
  536. }
  537. }
  538. CheckTCBSends(SeqTCB);
  539. }
  540. //* TCPAbortAndIndicateDisconnect
  541. //
  542. // Abortively closes a TCB and issues a disconnect indication up the the
  543. // transport user. This function is used to support cancellation of
  544. // TDI send and receive requests.
  545. //
  546. // Input: ConnectionContext - The connection ID to find a TCB for.
  547. //
  548. // Returns: Nothing.
  549. //
  550. BOOLEAN
  551. TCPAbortAndIndicateDisconnect(
  552. uint ConnectionContext,
  553. PVOID Irp,
  554. uint Rcv,
  555. CTELockHandle inHandle
  556. )
  557. {
  558. TCB *AbortTCB;
  559. CTELockHandle ConnTableHandle, TCBHandle;
  560. TCPConn *Conn;
  561. VOID *CancelContext, *CancelID;
  562. PTCP_CONTEXT tcpContext;
  563. PIO_STACK_LOCATION irpSp;
  564. irpSp = IoGetCurrentIrpStackLocation((PIRP)Irp);
  565. tcpContext = (PTCP_CONTEXT) irpSp->FileObject->FsContext;
  566. Conn = GetConnFromConnID(ConnectionContext, &ConnTableHandle);
  567. if (Conn != NULL) {
  568. CTEStructAssert(Conn, tc);
  569. AbortTCB = Conn->tc_tcb;
  570. if (AbortTCB != NULL) {
  571. // If it's CLOSING or CLOSED, skip it.
  572. if ((AbortTCB->tcb_state != TCB_CLOSED) && !CLOSING(AbortTCB)) {
  573. CTEStructAssert(AbortTCB, tcb);
  574. CTEGetLock(&AbortTCB->tcb_lock, &TCBHandle);
  575. CTEFreeLock(&(Conn->tc_ConnBlock->cb_lock), TCBHandle);
  576. if (AbortTCB->tcb_state == TCB_CLOSED || CLOSING(AbortTCB)) {
  577. CTEFreeLock(&AbortTCB->tcb_lock, ConnTableHandle);
  578. CTEFreeLock(&tcpContext->EndpointLock, inHandle);
  579. return FALSE;
  580. }
  581. if (Rcv) {
  582. if ((AbortTCB->tcb_rcvhndlr == BufferData)) {
  583. if (AbortTCB->tcb_rcvhead) {
  584. TCPRcvReq *RcvReq, *PrevReq;
  585. TDI_STATUS Status = TDI_SUCCESS;
  586. PrevReq = STRUCT_OF(TCPRcvReq, &AbortTCB->tcb_rcvhead, trr_next);
  587. RcvReq = PrevReq->trr_next;
  588. ASSERT(AbortTCB->tcb_rcvhead == AbortTCB->tcb_currcv);
  589. while (RcvReq) {
  590. CTEStructAssert(RcvReq, trr);
  591. if (RcvReq->trr_context == Irp) {
  592. PrevReq->trr_next = RcvReq->trr_next;
  593. AbortTCB->tcb_currcv = AbortTCB->tcb_rcvhead;
  594. if (AbortTCB->tcb_rcvtail == RcvReq) {
  595. AbortTCB->tcb_rcvtail = PrevReq;
  596. }
  597. if (AbortTCB->tcb_currcv == NULL) {
  598. if (AbortTCB->tcb_rcvind != NULL &&
  599. AbortTCB->tcb_indicated == 0) {
  600. AbortTCB->tcb_rcvhndlr =
  601. IndicateData;
  602. } else {
  603. AbortTCB->tcb_rcvhndlr = PendData;
  604. }
  605. }
  606. AbortTCB->tcb_flags |= IN_RCV_IND;
  607. CTEFreeLock(&AbortTCB->tcb_lock, ConnTableHandle);
  608. CTEFreeLock(&tcpContext->EndpointLock, inHandle);
  609. (*RcvReq->trr_rtn) (RcvReq->trr_context, TDI_CANCELLED, RcvReq->trr_amt);
  610. CTEGetLock(&AbortTCB->tcb_lock, &TCBHandle);
  611. AbortTCB->tcb_flags &= ~IN_RCV_IND;
  612. if ((AbortTCB->tcb_rcvind != NULL) &&
  613. (AbortTCB->tcb_indicated == 0) &&
  614. (AbortTCB->tcb_pendingcnt != 0)) {
  615. REFERENCE_TCB(AbortTCB);
  616. IndicatePendingData(AbortTCB, RcvReq, TCBHandle);
  617. SendACK(AbortTCB);
  618. CTEGetLock(&AbortTCB->tcb_lock, &TCBHandle);
  619. DerefTCB(AbortTCB, TCBHandle);
  620. } else {
  621. if (AbortTCB->tcb_rcvhead == NULL) {
  622. if (AbortTCB->tcb_rcvind != NULL &&
  623. AbortTCB->tcb_indicated == 0) {
  624. AbortTCB->tcb_rcvhndlr =
  625. IndicateData;
  626. } else {
  627. AbortTCB->tcb_rcvhndlr =
  628. PendData;
  629. }
  630. }
  631. CTEFreeLock(&AbortTCB->tcb_lock, TCBHandle);
  632. FreeRcvReq(RcvReq);
  633. }
  634. return FALSE;
  635. }
  636. PrevReq = RcvReq;
  637. RcvReq = RcvReq->trr_next;
  638. }
  639. }
  640. //try to find this irp in exprcv queue
  641. if (AbortTCB->tcb_exprcv) {
  642. TCPRcvReq *RcvReq, *PrevReq;
  643. PrevReq = STRUCT_OF(TCPRcvReq, &AbortTCB->tcb_exprcv, trr_next);
  644. RcvReq = PrevReq->trr_next;
  645. while (RcvReq) {
  646. CTEStructAssert(RcvReq, trr);
  647. if (RcvReq->trr_context == Irp) {
  648. //(*RcvReq->trr_rtn)(RcvReq->trr_context, Status, 0);
  649. PrevReq->trr_next = RcvReq->trr_next;
  650. FreeRcvReq(RcvReq);
  651. CTEFreeLock(&AbortTCB->tcb_lock, ConnTableHandle);
  652. //
  653. // Account for reference count
  654. // on endoint, as we are not calling
  655. // TCPDataRequestComplete() for this
  656. // request.
  657. //
  658. tcpContext->ReferenceCount--;
  659. CTEFreeLock(&tcpContext->EndpointLock, inHandle);
  660. return TRUE;
  661. }
  662. PrevReq = RcvReq;
  663. RcvReq = RcvReq->trr_next;
  664. }
  665. }
  666. }
  667. }
  668. CancelContext = ((PIRP)Irp)->Tail.Overlay.DriverContext[0];
  669. CancelID = ((PIRP)Irp)->Tail.Overlay.DriverContext[1];
  670. CTEFreeLock(&tcpContext->EndpointLock, ConnTableHandle);
  671. REFERENCE_TCB(AbortTCB);
  672. if (!Rcv) {
  673. CTEFreeLock(&AbortTCB->tcb_lock,TCBHandle);
  674. //Call ndis cancel packets routine to free up
  675. //queued send packets
  676. (*LocalNetInfo.ipi_cancelpackets) (CancelContext, CancelID);
  677. CTEGetLock(&AbortTCB->tcb_lock, &TCBHandle);
  678. }
  679. AbortTCB->tcb_flags |= NEED_RST; // send a reset if connected
  680. TryToCloseTCB(AbortTCB, TCB_CLOSE_ABORTED, inHandle);
  681. RemoveTCBFromConn(AbortTCB);
  682. IF_TCPDBG(TCP_DEBUG_IRP) {
  683. TCPTRACE((
  684. "TCPAbortAndIndicateDisconnect, indicating discon\n"
  685. ));
  686. }
  687. NotifyOfDisc(AbortTCB, NULL, TDI_CONNECTION_ABORTED);
  688. CTEGetLock(&AbortTCB->tcb_lock, &TCBHandle);
  689. DerefTCB(AbortTCB, TCBHandle);
  690. // TCB lock freed by DerefTCB.
  691. return FALSE;
  692. } else
  693. CTEFreeLock(&(Conn->tc_ConnBlock->cb_lock), ConnTableHandle);
  694. } else
  695. CTEFreeLock(&(Conn->tc_ConnBlock->cb_lock), ConnTableHandle);
  696. }
  697. CTEFreeLock(&tcpContext->EndpointLock, inHandle);
  698. return FALSE;
  699. }
  700. //* ProcessSynTcbs
  701. //
  702. // Called from timeout routine to handle syntcbs in syntcb table
  703. // Retransmits SYN if rexnitcnt has not expired. Else removes the
  704. // syntcb from the table and frees it.
  705. // Input: Processor number that is used to select the syntcb space
  706. // to handle.
  707. //
  708. // Returns: Nothing.
  709. //
  710. void
  711. ProcessSynTcbs(uint Processor)
  712. {
  713. Queue *Scan;
  714. SYNTCB *SynTCB;
  715. uint i,maxRexmitCnt,StartIndex=0;
  716. CTELockHandle TableHandle = DISPATCH_LEVEL,SYNTableHandle = DISPATCH_LEVEL;
  717. CTELockHandle Handle;
  718. StartIndex = Processor * PerTimerSize;
  719. for (i = StartIndex; i < MIN(TCB_TABLE_SIZE, StartIndex+PerTimerSize); i++) {
  720. Scan = QHEAD(&SYNTCBTable[i]);
  721. while (Scan != QEND(&SYNTCBTable[i])){
  722. SynTCB = QSTRUCT(SYNTCB, Scan, syntcb_link);
  723. CTEGetLockAtDPC(&SynTCB->syntcb_lock, &TableHandle);
  724. CTEStructAssert(SynTCB, syntcb);
  725. Scan = QNEXT(Scan);
  726. if (TCB_TIMER_RUNNING(SynTCB->syntcb_rexmittimer)) {
  727. // The timer is running.
  728. if (--(SynTCB->syntcb_rexmittimer) == 0) {
  729. maxRexmitCnt = MIN(MaxConnectResponseRexmitCountTmp, MaxConnectResponseRexmitCount);
  730. // Need a (greater or equal) here, because, we want to stop when the count reaches the max.
  731. if ( SynTCB->syntcb_rexmitcnt++ >= maxRexmitCnt) {
  732. SynTCB->syntcb_refcnt++;
  733. CTEFreeLockFromDPC(&SynTCB->syntcb_lock, TableHandle);
  734. CTEGetLockAtDPC(&pSynTCBTableLock[SynTCB->syntcb_partition], &SYNTableHandle);
  735. CTEGetLockAtDPC(&SynTCB->syntcb_lock, &TableHandle);
  736. if (SynTCB->syntcb_flags & IN_SYNTCB_TABLE) {
  737. REMOVEQ(&SynTCB->syntcb_link);
  738. SynTCB->syntcb_flags &= ~IN_SYNTCB_TABLE;
  739. }
  740. CTEFreeLockFromDPC(&pSynTCBTableLock[SynTCB->syntcb_partition], &SYNTableHandle);
  741. SynTCB->syntcb_refcnt--;
  742. DerefSynTCB(SynTCB,TableHandle);
  743. CTEGetLockAtDPC(&SynAttLock.Lock, &Handle);
  744. //
  745. // We have put the connection in the closed state.
  746. // Decrement the counters for keeping track of half
  747. // open connections
  748. //
  749. ASSERT((TCPHalfOpen != 0) && (TCPHalfOpenRetried != 0));
  750. TCPHalfOpen--;
  751. TCPHalfOpenRetried--;
  752. if (((TCPHalfOpen <= TCPMaxHalfOpen) ||
  753. (TCPHalfOpenRetried <= TCPMaxHalfOpenRetriedLW)) &&
  754. (MaxConnectResponseRexmitCountTmp == ADAPTED_MAX_CONNECT_RESPONSE_REXMIT_CNT)) {
  755. MaxConnectResponseRexmitCountTmp = MAX_CONNECT_RESPONSE_REXMIT_CNT;
  756. }
  757. CTEFreeLockFromDPC(&SynAttLock.Lock, Handle);
  758. } else {
  759. SynTCB->syntcb_sendnext = SynTCB->syntcb_senduna;
  760. SendSYNOnSynTCB(SynTCB,TableHandle);
  761. // Figure out what our new retransmit timeout should be. We
  762. // double it each time we get a retransmit
  763. SynTCB->syntcb_rexmit = MIN(SynTCB->syntcb_rexmit << 1,
  764. MAX_REXMIT_TO);
  765. }
  766. } else {
  767. CTEFreeLockFromDPC(&SynTCB->syntcb_lock, TableHandle);
  768. }
  769. } else {
  770. CTEFreeLockFromDPC(&SynTCB->syntcb_lock, TableHandle);
  771. }
  772. }
  773. }
  774. }
  775. __inline void
  776. InsertIntoTimerWheel(TCB *InsertTCB, ushort Slot)
  777. {
  778. PTIMER_WHEEL WheelPtr;
  779. Queue* TimerSlotPtr;
  780. CTELockHandle LockHandle;
  781. WheelPtr = &TimerWheel[InsertTCB->tcb_partition];
  782. TimerSlotPtr = &WheelPtr->tw_timerslot[Slot];
  783. ASSERT(InsertTCB->tcb_timerslot == DUMMY_SLOT);
  784. CTEGetLockAtDPC(&(WheelPtr->tw_lock), &LockHandle);
  785. InsertTCB->tcb_timerslot = Slot;
  786. PUSHQ(TimerSlotPtr, &InsertTCB->tcb_timerwheelq);
  787. CTEFreeLockFromDPC(&(WheelPtr->tw_lock), LockHandle);
  788. }
  789. __inline void
  790. RemoveFromTimerWheel(TCB *RemoveTCB)
  791. {
  792. PTIMER_WHEEL WheelPtr;
  793. CTELockHandle LockHandle;
  794. WheelPtr = &TimerWheel[RemoveTCB->tcb_partition];
  795. ASSERT(RemoveTCB->tcb_timerslot < TIMER_WHEEL_SIZE);
  796. CTEGetLockAtDPC(&(WheelPtr->tw_lock), &LockHandle);
  797. RemoveTCB->tcb_timerslot = DUMMY_SLOT;
  798. RemoveTCB->tcb_timertime = 0;
  799. REMOVEQ(&RemoveTCB->tcb_timerwheelq);
  800. CTEFreeLockFromDPC(&(WheelPtr->tw_lock), LockHandle);
  801. }
  802. __inline void
  803. RemoveAndInsertIntoTimerWheel(TCB *RemInsTCB, ushort InsertSlot)
  804. {
  805. PTIMER_WHEEL WheelPtr;
  806. Queue* InsertSlotPtr;
  807. CTELockHandle LockHandle;
  808. ASSERT(RemInsTCB->tcb_timerslot < TIMER_WHEEL_SIZE);
  809. WheelPtr = &TimerWheel[RemInsTCB->tcb_partition];
  810. InsertSlotPtr = &WheelPtr->tw_timerslot[InsertSlot];
  811. CTEGetLockAtDPC(&WheelPtr->tw_lock, &LockHandle);
  812. REMOVEQ(&RemInsTCB->tcb_timerwheelq);
  813. RemInsTCB->tcb_timerslot = InsertSlot;
  814. PUSHQ(InsertSlotPtr, &RemInsTCB->tcb_timerwheelq);
  815. CTEFreeLockFromDPC(&WheelPtr->tw_lock, LockHandle);
  816. }
  817. __inline void
  818. RecomputeTimerState(TCB *TimerTCB)
  819. {
  820. TCP_TIMER_TYPE i;
  821. TimerTCB->tcb_timertype = NO_TIMER;
  822. TimerTCB->tcb_timertime = 0;
  823. for(i = 0; i < NUM_TIMERS; i++) {
  824. if ((TimerTCB->tcb_timer[i] != 0) &&
  825. ((TimerTCB->tcb_timertime == 0) ||
  826. (TCPTIME_LTE(TimerTCB->tcb_timer[i], TimerTCB->tcb_timertime)))) {
  827. TimerTCB->tcb_timertime = TimerTCB->tcb_timer[i];
  828. TimerTCB->tcb_timertype = i;
  829. }
  830. }
  831. }
  832. // StartTCBTimerR
  833. // Arguments: A TCB, timer type, and the interval in ticks after which the
  834. // timer is supposed to fire.
  835. // Description:
  836. // Sets the array element in tcb_timer for that particular timer to the
  837. // appropriate value, and recomputes the tcb_timertime and tcb_timertype
  838. // values ONLY if we need to. All shortcuts and optimizations are done to
  839. // avoid recomputing the tcb_timertime and tcb_timertype by going through
  840. // the whole array.
  841. // return value: TRUE if minimum got changed; FALSE if not.
  842. BOOLEAN
  843. StartTCBTimerR(TCB *StartTCB, TCP_TIMER_TYPE TimerType, uint DeltaTime)
  844. {
  845. ASSERT(TimerType < NUM_TIMERS);
  846. StartTCB->tcb_timer[TimerType] = TCPTime + DeltaTime;
  847. // Make a check for the case where TCPTime + DeltaTime is 0
  848. // because of wraparound
  849. if (StartTCB->tcb_timer[TimerType] == 0) {
  850. StartTCB->tcb_timer[TimerType] = 1;
  851. }
  852. // This is really simple logic. Find out if the setting of
  853. // this timer changes the minimum. Don't care whether it was
  854. // already running, or whether it already the minimum...
  855. if ((StartTCB->tcb_timertime == 0 ) ||
  856. (TCPTIME_LT(StartTCB->tcb_timer[TimerType], StartTCB->tcb_timertime))
  857. )
  858. {
  859. // Yup it changed the minimum...
  860. StartTCB->tcb_timertime = StartTCB->tcb_timer[TimerType];
  861. StartTCB->tcb_timertype = TimerType;
  862. return TRUE;
  863. }
  864. // No it did not change the minimum.
  865. // You only have to recompute if it was already the minimum
  866. if (StartTCB->tcb_timertype == TimerType) {
  867. RecomputeTimerState(StartTCB);
  868. }
  869. return FALSE;
  870. }
  871. // StopTCBTimerR
  872. // Arguments: A TCB, and a timer type
  873. // Description:
  874. // Sets the array element for that timer to 0, and recomputes
  875. // tcb_timertime and tcb_timertype. It automatically handles
  876. // the case where the function is called for a timer which has
  877. // already stopped.
  878. void
  879. StopTCBTimerR(TCB *StopTCB, TCP_TIMER_TYPE TimerType)
  880. {
  881. ASSERT(TimerType < NUM_TIMERS);
  882. StopTCB->tcb_timer[TimerType] = 0;
  883. // Is this the lowest timer value we are running?
  884. if (StopTCB->tcb_timertype == TimerType)
  885. {
  886. // Stopping a timer can only push back the firing
  887. // time, so we will never remove a TCB from a slot.
  888. RecomputeTimerState(StopTCB);
  889. }
  890. return;
  891. }
  892. // START_TCB_TIMER_R modifies the timer state and only modifies
  893. // wheel state if the timer that was started was earlier than all the
  894. // other timers on that TCB. This is in accordance with the lazy evaluation
  895. // strategy.
  896. __inline void
  897. START_TCB_TIMER_R(TCB *StartTCB, TCP_TIMER_TYPE Type, uint Value)
  898. {
  899. ushort Slot;
  900. if( StartTCB->tcb_timerslot == DUMMY_SLOT ) {
  901. StartTCBTimerR(StartTCB, Type, Value);
  902. Slot = COMPUTE_SLOT(StartTCB->tcb_timertime);
  903. InsertIntoTimerWheel(StartTCB, Slot);
  904. } else if ( StartTCBTimerR(StartTCB, Type, Value)) {
  905. Slot = COMPUTE_SLOT(StartTCB->tcb_timertime);
  906. RemoveAndInsertIntoTimerWheel(StartTCB, Slot);
  907. }
  908. }
  909. __inline void
  910. STOP_TCB_TIMER_R(TCB *StopTCB, TCP_TIMER_TYPE Type)
  911. {
  912. StopTCBTimerR(StopTCB, Type);
  913. return;
  914. }
  915. void
  916. MakeTimerStateConsistent(TCB *TimerTCB, uint CurrentTime)
  917. {
  918. uint i;
  919. BOOLEAN TimesChanged = FALSE;
  920. for(i = 0; i < NUM_TIMERS; i++) {
  921. if (TimerTCB->tcb_timer[i] != 0) {
  922. if (TCPTIME_LTE(TimerTCB->tcb_timer[i], CurrentTime)) {
  923. // This should not happen. If it does, we either have a bug in the current code
  924. // or in the TimerWheel code.
  925. // This assert was modified because it was found that, at some point of time
  926. // ACD_CON_NOTIF was ON but not looked at after processing CONN_TIMER. So, it
  927. // alright to advance timers by 1 tick if they were supposed to go off on the
  928. // 'current' tick. Otherwise, assert.
  929. if( TCPTIME_LT(TimerTCB->tcb_timer[i], CurrentTime )) {
  930. ASSERT(0);
  931. }
  932. TimesChanged = TRUE;
  933. TimerTCB->tcb_timer[i] = CurrentTime + 1;
  934. // Code to handle wraparound.
  935. if (TimerTCB->tcb_timer[i] == 0) {
  936. TimerTCB->tcb_timer[i] = 1;
  937. }
  938. }
  939. }
  940. }
  941. return;
  942. }
  943. #if MILLEN
  944. ULONGLONG
  945. my64div(ULONGLONG Divisor, ULONGLONG Dividend)
  946. {
  947. return (Divisor/Dividend);
  948. }
  949. #endif // MILLEN
  950. //* TCBTimeout - Do timeout events on TCBs.
  951. //
  952. // Called every MS_PER_TICKS milliseconds to do timeout processing on TCBs.
  953. // We run throught the TCB table, decrementing timers. If one goes to zero
  954. // we look at it's state to decide what to do.
  955. //
  956. // Input: Timer - Event structure for timer that fired.
  957. // Context - Context for timer (NULL in this case.
  958. //
  959. // Returns: Nothing.
  960. //
  961. void
  962. TCBTimeout(CTEEvent * Timer, void *Context)
  963. {
  964. CTELockHandle TableHandle = DISPATCH_LEVEL, TCBHandle;
  965. CTELockHandle TWTableHandle;
  966. uint i, j;
  967. TCB *CurrentTCB;
  968. uint Delayed = FALSE;
  969. uint CallRcvComplete;
  970. ULONGLONG CurrentTime;
  971. ULONGLONG TimeDiff;
  972. uint tmp[2];
  973. uint Processor, StartIndex, EndIndex;
  974. #if TRACE_EVENT
  975. PTDI_DATA_REQUEST_NOTIFY_ROUTINE CPCallBack;
  976. WMIData WMIInfo;
  977. #endif
  978. // LocalTime must remain a uint. A loop below uses the
  979. // termination condition j != (LocalTime + 1) and that
  980. // works only if LocalTime is a uint so that wraparound
  981. // can be handled correctly.
  982. uint LocalTime = 0;
  983. uint PerProcPartitions, ExtraPartitions;
  984. #if MILLEN
  985. Processor = 0;
  986. #else
  987. Processor = KeGetCurrentProcessorNumber();
  988. #endif // !MILLEN
  989. // Update our free running counter.
  990. if (Processor == 0) {
  991. CurrentTime = KeQueryInterruptTime();
  992. TimeDiff = CurrentTime-systemtime+delta;
  993. systemtime = CurrentTime;
  994. #if !MILLEN
  995. *(ULONGLONG *)&tmp[0] = TimeDiff/1000000i64; //100nsec to 100msec
  996. #else // !MILLEN
  997. //
  998. // N.B. The compiler will optimize the 64-bit division followed by
  999. // the mod to one function call: aulldvrm. This function is unsupported
  1000. // on WinME and causes a runtime load failure of tcpip.sys.
  1001. // We work around this by causing a function call to get
  1002. // the quotient and then mod to get the remainder. This way, the
  1003. // compiler generates calls to generate the quotient and remainder
  1004. // seperately.
  1005. //
  1006. *(ULONGLONG *)&tmp[0] = my64div(TimeDiff, 1000000i64); //100nsec to 100msec
  1007. #endif // MILLEN
  1008. CPUTCPTime[Processor] += MIN(200,tmp[0]);
  1009. delta = TimeDiff%1000000;
  1010. #ifdef TIMER_TEST
  1011. TCPTime = CPUTCPTime[0] + 0xfffff000;
  1012. #else
  1013. TCPTime = CPUTCPTime[0];
  1014. #endif
  1015. // Update our ISN generator. 25000 every 100ms...
  1016. // (inc. every 4us, 4.55 hour cycle time)
  1017. InterlockedExchangeAdd(&g_CurISN, 25000);
  1018. }
  1019. CTEInterlockedAddUlong(&TCBWalkCount, 1, &PendingFreeLock.Lock);
  1020. TCBHandle = DISPATCH_LEVEL;
  1021. // First compute the indexes of the timer wheels that we need to
  1022. // visit on this processor.
  1023. PerProcPartitions = NumTcbTablePartitions / KeNumberProcessors;
  1024. ExtraPartitions = NumTcbTablePartitions % KeNumberProcessors;
  1025. StartIndex = Processor * PerProcPartitions;
  1026. StartIndex += MIN(Processor, ExtraPartitions);
  1027. EndIndex = MIN(NumTcbTablePartitions, StartIndex + PerProcPartitions);
  1028. if (Processor < ExtraPartitions) EndIndex ++;
  1029. // There is the question, whether LocalTime should use the value of
  1030. // TCPTime after TCPTime has been incremented or before. On processor
  1031. // 0, this may actually make a difference how the TCBs are processed.
  1032. // The following code tries to keep the new behavior as close as possible
  1033. // the original behavior, by running the timer wheel upto the slot
  1034. // corresponding to the TCPTime AFTER the increment.
  1035. LocalTime = TCPTime;
  1036. // Now loop through the timer wheels.
  1037. for (i = StartIndex; i < EndIndex; i++) {
  1038. // For each timer wheel, tw_starttick stores the first time tick which
  1039. // needs to be checked. We loop from tw_starttick to the current time,
  1040. // and each time we figure out the slot corresponding to that tick,
  1041. // and visit all the TCBs on that slot's queue.
  1042. //
  1043. ushort CurrentSlot = COMPUTE_SLOT(TimerWheel[i].tw_starttick);
  1044. // In this for-loop, the termination condition is not j <= LocalTime,
  1045. // but j != LocalTime + 1. This is because TCPTime can wraparound, and
  1046. // tw_starttick may actually be higher that LocalTime.
  1047. // It is important to make sure that j is a uint, otherwise this logic
  1048. // does not hold.
  1049. for (j = TimerWheel[i].tw_starttick;
  1050. j != (LocalTime + 1);
  1051. j++, CurrentSlot = (CurrentSlot == (TIMER_WHEEL_SIZE - 1)) ? 0 : CurrentSlot + 1) {
  1052. TCB *TempTCB = NULL;
  1053. Queue MarkerElement;
  1054. uint maxRexmitCnt;
  1055. CTELockHandle TimerWheelHandle;
  1056. ushort Slot;
  1057. // Our basic loop is going to be:
  1058. // Pull out a TCB from the timer slot queue. Process it. Put it
  1059. // back into the timer wheel if we need to, depending on if other
  1060. // timers need to be fired. The problem with this is if the TCB
  1061. // ends up falling in the same slot, we get into this loop where
  1062. // we pull the TCB out, process it, put it back into the current
  1063. // slot, pull it out again, process it, ad infinitum.
  1064. //
  1065. // So we introduce a dummy element called MarkerElement. We begin
  1066. // our processing by inserting this element into the head of the
  1067. // queue. Now we always pull out a TCB which the MarkerElement points
  1068. // to, process it, and then push it to the head of the timer slot
  1069. // queue. Since no TCBs are ever added to the timer slot queue after
  1070. // the MarkerElement (elements are always added to the head of the
  1071. // queue), MarkerElement will eventually point to the head of the
  1072. // timer slot queue, at which point we know that we are done.
  1073. CTEGetLockAtDPC(&TimerWheel[i].tw_lock, &TimerWheelHandle);
  1074. PUSHQ(&TimerWheel[i].tw_timerslot[CurrentSlot], &MarkerElement);
  1075. CTEFreeLockFromDPC(&TimerWheel[i].tw_lock, TimerWheelHandle);
  1076. while (1) {
  1077. // First remove the tcb at the head of the list
  1078. CTEGetLockAtDPC(&TimerWheel[i].tw_lock, &TimerWheelHandle);
  1079. // The list is empty if the marker points to timer slot
  1080. if (QNEXT(&MarkerElement) == &TimerWheel[i].tw_timerslot[CurrentSlot]) {
  1081. REMOVEQ(&MarkerElement);
  1082. CTEFreeLockFromDPC(&TimerWheel[i].tw_lock, TimerWheelHandle);
  1083. break;
  1084. }
  1085. CurrentTCB = STRUCT_OF(TCB, QNEXT(&MarkerElement), tcb_timerwheelq);
  1086. CTEFreeLockFromDPC(&TimerWheel[i].tw_lock, TimerWheelHandle);
  1087. CTEStructAssert(CurrentTCB, tcb);
  1088. CTEGetLockAtDPC(&CurrentTCB->tcb_lock, &TCBHandle);
  1089. // Someone may have removed this TCB before we reacquired the tcb
  1090. // lock. Check if it is still in the list and still in the same slot.
  1091. if (CurrentTCB->tcb_timerslot != CurrentSlot) {
  1092. CTEFreeLockFromDPC(&CurrentTCB->tcb_lock, TCBHandle);
  1093. continue;
  1094. }
  1095. // This TCB may not be in the TCB table anymore. In that case, it SHOULD NOT be processed.
  1096. if( !(CurrentTCB->tcb_flags & IN_TCB_TABLE) ) {
  1097. RemoveFromTimerWheel(CurrentTCB);
  1098. CTEFreeLockFromDPC(&CurrentTCB->tcb_lock, TCBHandle);
  1099. continue;
  1100. }
  1101. // Check if this is firing at the current time. In case of keepalive
  1102. // timers (which fire after hours), sometimes TCBs may queue to the
  1103. // current slot but their firing time is not the current time.
  1104. // This if statement also does the lazy evaluation -- if all timers
  1105. // have been stopped on this TCB just remove the TCB out.
  1106. // Callers of STOP_TCB_TIMER_R never end up removing the TCB. That
  1107. // job is left to this routine.
  1108. if (CurrentTCB->tcb_timertime != j) {
  1109. MakeTimerStateConsistent(CurrentTCB, j);
  1110. ASSERT(CurrentTCB->tcb_timerslot < TIMER_WHEEL_SIZE);
  1111. RecomputeTimerState( CurrentTCB );
  1112. if (CurrentTCB->tcb_timertype == NO_TIMER) {
  1113. RemoveFromTimerWheel(CurrentTCB);
  1114. } else {
  1115. Slot = COMPUTE_SLOT(CurrentTCB->tcb_timertime);
  1116. RemoveAndInsertIntoTimerWheel(CurrentTCB, Slot);
  1117. }
  1118. CTEFreeLockFromDPC(&CurrentTCB->tcb_lock, TCBHandle);
  1119. continue;
  1120. }
  1121. // If it's CLOSING or CLOSED, skip it.
  1122. if (CurrentTCB->tcb_state == TCB_CLOSED || CLOSING(CurrentTCB)) {
  1123. // CloseTCB will handle all outstanding requests.
  1124. // So, it is safe to remove the TCB from timer wheel.
  1125. RemoveFromTimerWheel(CurrentTCB);
  1126. CTEFreeLockFromDPC(&CurrentTCB->tcb_lock, TCBHandle);
  1127. continue;
  1128. }
  1129. CheckTCBSends(CurrentTCB);
  1130. CheckTCBRcv(CurrentTCB);
  1131. // First check the rexmit timer.
  1132. if (TCB_TIMER_FIRED_R(CurrentTCB, RXMIT_TIMER, j)) {
  1133. StopTCBTimerR(CurrentTCB, RXMIT_TIMER);
  1134. // And it's fired. Figure out what to do now.
  1135. // Remove all SACK rcvd entries (per RFC 2018)
  1136. if ((CurrentTCB->tcb_tcpopts & TCP_FLAG_SACK) && CurrentTCB->tcb_SackRcvd) {
  1137. SackListEntry *Prev, *Current;
  1138. Prev = STRUCT_OF(SackListEntry, &CurrentTCB->tcb_SackRcvd, next);
  1139. Current = CurrentTCB->tcb_SackRcvd;
  1140. while (Current) {
  1141. Prev->next = Current->next;
  1142. CTEFreeMem(Current);
  1143. Current = Prev->next;
  1144. }
  1145. }
  1146. // If we've had too many retransits, abort now.
  1147. CurrentTCB->tcb_rexmitcnt++;
  1148. if (CurrentTCB->tcb_state == TCB_SYN_SENT) {
  1149. maxRexmitCnt = MaxConnectRexmitCount;
  1150. } else {
  1151. if (CurrentTCB->tcb_state == TCB_SYN_RCVD) {
  1152. //
  1153. // Save on locking. Though MaxConnectRexmitCountTmp may
  1154. // be changing, we are assured that we will not use
  1155. // more than the MaxConnectRexmitCount.
  1156. //
  1157. maxRexmitCnt = MIN(MaxConnectResponseRexmitCountTmp, MaxConnectResponseRexmitCount);
  1158. } else {
  1159. maxRexmitCnt = MaxDataRexmitCount;
  1160. }
  1161. }
  1162. // If we've run out of retransmits or we're in FIN_WAIT2,
  1163. // time out.
  1164. if (CurrentTCB->tcb_rexmitcnt > maxRexmitCnt) {
  1165. ASSERT(CurrentTCB->tcb_state > TCB_LISTEN);
  1166. // This connection has timed out. Abort it. First
  1167. // reference him, then mark as closed, notify the
  1168. // user, and finally dereference and close him.
  1169. TimeoutTCB:
  1170. // This call may not be needed, but I've just added it
  1171. // for safety.
  1172. MakeTimerStateConsistent(CurrentTCB, j);
  1173. RecomputeTimerState( CurrentTCB );
  1174. ASSERT(CurrentTCB->tcb_timerslot < TIMER_WHEEL_SIZE);
  1175. if (CurrentTCB->tcb_timertype == NO_TIMER) {
  1176. RemoveFromTimerWheel(CurrentTCB);
  1177. } else {
  1178. Slot = COMPUTE_SLOT(CurrentTCB->tcb_timertime);
  1179. RemoveAndInsertIntoTimerWheel(CurrentTCB, Slot);
  1180. }
  1181. REFERENCE_TCB(CurrentTCB);
  1182. TryToCloseTCB(CurrentTCB, TCB_CLOSE_TIMEOUT, TCBHandle);
  1183. RemoveTCBFromConn(CurrentTCB);
  1184. NotifyOfDisc(CurrentTCB, NULL, TDI_TIMED_OUT);
  1185. if (SynAttackProtect) {
  1186. if (CurrentTCB->tcb_state == TCB_SYN_RCVD) {
  1187. CTELockHandle Handle;
  1188. CTEGetLockAtDPC(&SynAttLock.Lock, &Handle);
  1189. //
  1190. // We have put the connection in the closed state.
  1191. // Decrement the counters for keeping track of half
  1192. // open connections
  1193. //
  1194. ASSERT((TCPHalfOpen != 0) && (TCPHalfOpenRetried != 0));
  1195. TCPHalfOpen--;
  1196. TCPHalfOpenRetried--;
  1197. if (((TCPHalfOpen <= TCPMaxHalfOpen) ||
  1198. (TCPHalfOpenRetried <= TCPMaxHalfOpenRetriedLW)) &&
  1199. (MaxConnectResponseRexmitCountTmp == ADAPTED_MAX_CONNECT_RESPONSE_REXMIT_CNT)) {
  1200. MaxConnectResponseRexmitCountTmp = MAX_CONNECT_RESPONSE_REXMIT_CNT;
  1201. }
  1202. CTEFreeLockFromDPC(&SynAttLock.Lock, Handle);
  1203. }
  1204. }
  1205. CTEGetLockAtDPC(&CurrentTCB->tcb_lock, &TCBHandle);
  1206. DerefTCB(CurrentTCB, TCBHandle);
  1207. continue;
  1208. }
  1209. #if TRACE_EVENT
  1210. if (CurrentTCB->tcb_state == TCB_ESTAB){
  1211. CPCallBack = TCPCPHandlerRoutine;
  1212. if (CPCallBack != NULL) {
  1213. ulong GroupType;
  1214. WMIInfo.wmi_destaddr = CurrentTCB->tcb_daddr;
  1215. WMIInfo.wmi_destport = CurrentTCB->tcb_dport;
  1216. WMIInfo.wmi_srcaddr = CurrentTCB->tcb_saddr;
  1217. WMIInfo.wmi_srcport = CurrentTCB->tcb_sport;
  1218. WMIInfo.wmi_size = 0;
  1219. WMIInfo.wmi_context = CurrentTCB->tcb_cpcontext;
  1220. GroupType = EVENT_TRACE_GROUP_TCPIP + EVENT_TRACE_TYPE_RETRANSMIT;
  1221. (*CPCallBack) (GroupType, (PVOID)&WMIInfo, sizeof(WMIInfo), NULL);
  1222. }
  1223. }
  1224. #endif
  1225. CurrentTCB->tcb_rtt = 0; // Stop round trip time
  1226. // measurement.
  1227. // Figure out what our new retransmit timeout should be. We
  1228. // double it each time we get a retransmit, and reset it
  1229. // back when we get an ack for new data.
  1230. CurrentTCB->tcb_rexmit = MIN(CurrentTCB->tcb_rexmit << 1,
  1231. MAX_REXMIT_TO);
  1232. // Reset the sequence number, and reset the congestion
  1233. // window.
  1234. ResetSendNext(CurrentTCB, CurrentTCB->tcb_senduna);
  1235. if (!(CurrentTCB->tcb_flags & FLOW_CNTLD)) {
  1236. // Don't let the slow start threshold go below 2
  1237. // segments
  1238. CurrentTCB->tcb_ssthresh =
  1239. MAX(
  1240. MIN(
  1241. CurrentTCB->tcb_cwin,
  1242. CurrentTCB->tcb_sendwin
  1243. ) / 2,
  1244. (uint) CurrentTCB->tcb_mss * 2
  1245. );
  1246. CurrentTCB->tcb_cwin = CurrentTCB->tcb_mss;
  1247. } else {
  1248. // We're probing, and the probe timer has fired. We
  1249. // need to set the FORCE_OUTPUT bit here.
  1250. CurrentTCB->tcb_flags |= FORCE_OUTPUT;
  1251. }
  1252. // See if we need to probe for a PMTU black hole.
  1253. if (PMTUBHDetect &&
  1254. CurrentTCB->tcb_rexmitcnt == ((maxRexmitCnt + 1) / 2)) {
  1255. // We may need to probe for a black hole. If we're
  1256. // doing MTU discovery on this connection and we
  1257. // are retransmitting more than a minimum segment
  1258. // size, or we are probing for a PMTU BH already, turn
  1259. // off the DF flag and bump the probe count. If the
  1260. // probe count gets too big we'll assume it's not
  1261. // a PMTU black hole, and we'll try to switch the
  1262. // router.
  1263. if ((CurrentTCB->tcb_flags & PMTU_BH_PROBE) ||
  1264. ((CurrentTCB->tcb_opt.ioi_flags & IP_FLAG_DF) &&
  1265. (CurrentTCB->tcb_sendmax - CurrentTCB->tcb_senduna)
  1266. > 8)) {
  1267. // May need to probe. If we haven't exceeded our
  1268. // probe count, do so, otherwise restore those
  1269. // values.
  1270. if (CurrentTCB->tcb_bhprobecnt++ < 2) {
  1271. // We're going to probe. Turn on the flag,
  1272. // drop the MSS, and turn off the don't
  1273. // fragment bit.
  1274. if (!(CurrentTCB->tcb_flags & PMTU_BH_PROBE)) {
  1275. CurrentTCB->tcb_flags |= PMTU_BH_PROBE;
  1276. CurrentTCB->tcb_slowcount++;
  1277. CurrentTCB->tcb_fastchk |= TCP_FLAG_SLOW;
  1278. // Drop the MSS to the minimum. Save the old
  1279. // one in case we need it later.
  1280. CurrentTCB->tcb_mss = MIN(MAX_REMOTE_MSS -
  1281. CurrentTCB->tcb_opt.ioi_optlength,
  1282. CurrentTCB->tcb_remmss);
  1283. ASSERT(CurrentTCB->tcb_mss > 0);
  1284. CurrentTCB->tcb_cwin = CurrentTCB->tcb_mss;
  1285. CurrentTCB->tcb_opt.ioi_flags &= ~IP_FLAG_DF;
  1286. }
  1287. // Drop the rexmit count so we come here again,
  1288. // and don't retrigger DeadGWDetect.
  1289. CurrentTCB->tcb_rexmitcnt--;
  1290. } else {
  1291. // Too many probes. Stop probing, and allow fallover
  1292. // to the next gateway.
  1293. //
  1294. // Currently this code won't do BH probing on the 2nd
  1295. // gateway. The MSS will stay at the minimum size. This
  1296. // might be a little suboptimal, but it's
  1297. // easy to implement for the Sept. 95 service pack
  1298. // and will keep connections alive if possible.
  1299. //
  1300. // In the future we should investigate doing
  1301. // dead g/w detect on a per-connection basis, and then
  1302. // doing PMTU probing for each connection.
  1303. if (CurrentTCB->tcb_flags & PMTU_BH_PROBE) {
  1304. CurrentTCB->tcb_flags &= ~PMTU_BH_PROBE;
  1305. if (--(CurrentTCB->tcb_slowcount) == 0)
  1306. CurrentTCB->tcb_fastchk &=
  1307. ~TCP_FLAG_SLOW;
  1308. }
  1309. CurrentTCB->tcb_bhprobecnt = 0;
  1310. }
  1311. }
  1312. }
  1313. // Check to see if we're doing dead gateway detect. If we
  1314. // are, see if it's time to ask IP.
  1315. if (DeadGWDetect &&
  1316. (SYNC_STATE(CurrentTCB->tcb_state) ||
  1317. !(CurrentTCB->tcb_fastchk & TCP_FLAG_RST_WHILE_SYN)) &&
  1318. (CurrentTCB->tcb_rexmitcnt == ((maxRexmitCnt + 1) / 2))) {
  1319. uint CheckRouteFlag;
  1320. if (SYNC_STATE(CurrentTCB->tcb_state)) {
  1321. CheckRouteFlag = 0;
  1322. } else {
  1323. CheckRouteFlag = CHECK_RCE_ONLY;
  1324. }
  1325. (*LocalNetInfo.ipi_checkroute) (CurrentTCB->tcb_daddr,
  1326. CurrentTCB->tcb_saddr,
  1327. CurrentTCB->tcb_rce,
  1328. &CurrentTCB->tcb_opt,
  1329. CheckRouteFlag);
  1330. }
  1331. if (CurrentTCB->tcb_fastchk & TCP_FLAG_RST_WHILE_SYN) {
  1332. CurrentTCB->tcb_fastchk &= ~TCP_FLAG_RST_WHILE_SYN;
  1333. CurrentTCB->tcb_slowcount--;
  1334. }
  1335. // Now handle the various cases.
  1336. switch (CurrentTCB->tcb_state) {
  1337. // In SYN-SENT or SYN-RCVD we'll need to retransmit
  1338. // the SYN.
  1339. case TCB_SYN_SENT:
  1340. case TCB_SYN_RCVD:
  1341. MakeTimerStateConsistent(CurrentTCB, j);
  1342. RecomputeTimerState( CurrentTCB );
  1343. if (CurrentTCB->tcb_timertype == NO_TIMER) {
  1344. RemoveFromTimerWheel(CurrentTCB);
  1345. } else {
  1346. Slot = COMPUTE_SLOT(CurrentTCB->tcb_timertime);
  1347. RemoveAndInsertIntoTimerWheel(CurrentTCB, Slot);
  1348. }
  1349. SendSYN(CurrentTCB, TCBHandle);
  1350. continue;
  1351. case TCB_FIN_WAIT1:
  1352. case TCB_CLOSING:
  1353. case TCB_LAST_ACK:
  1354. // The call to ResetSendNext (above) will have
  1355. // turned off the FIN_OUTSTANDING flag.
  1356. CurrentTCB->tcb_flags |= FIN_NEEDED;
  1357. case TCB_CLOSE_WAIT:
  1358. case TCB_ESTAB:
  1359. // In this state we have data to retransmit, unless
  1360. // the window is zero (in which case we need to
  1361. // probe), or we're just sending a FIN.
  1362. CheckTCBSends(CurrentTCB);
  1363. Delayed = TRUE;
  1364. DelayAction(CurrentTCB, NEED_OUTPUT);
  1365. break;
  1366. // If it's fired in TIME-WAIT, we're all done and
  1367. // can clean up. We'll call TryToCloseTCB even
  1368. // though he's already sort of closed. TryToCloseTCB
  1369. // will figure this out and do the right thing.
  1370. case TCB_TIME_WAIT:
  1371. MakeTimerStateConsistent(CurrentTCB, j);
  1372. RecomputeTimerState( CurrentTCB );
  1373. if (CurrentTCB->tcb_timertype == NO_TIMER) {
  1374. RemoveFromTimerWheel(CurrentTCB);
  1375. } else {
  1376. Slot = COMPUTE_SLOT(CurrentTCB->tcb_timertime);
  1377. RemoveAndInsertIntoTimerWheel(CurrentTCB, Slot);
  1378. }
  1379. TryToCloseTCB(CurrentTCB, TCB_CLOSE_SUCCESS,
  1380. TCBHandle);
  1381. continue;
  1382. default:
  1383. break;
  1384. }
  1385. }
  1386. // Now check the SWS deadlock timer..
  1387. if (TCB_TIMER_FIRED_R(CurrentTCB, SWS_TIMER, j)) {
  1388. StopTCBTimerR(CurrentTCB, SWS_TIMER);
  1389. // And it's fired. Force output now.
  1390. CurrentTCB->tcb_flags |= FORCE_OUTPUT;
  1391. Delayed = TRUE;
  1392. DelayAction(CurrentTCB, NEED_OUTPUT);
  1393. }
  1394. // Check the push data timer.
  1395. if (TCB_TIMER_FIRED_R(CurrentTCB, PUSH_TIMER, j)) {
  1396. StopTCBTimerR(CurrentTCB, PUSH_TIMER);
  1397. // It's fired.
  1398. PushData(CurrentTCB);
  1399. Delayed = TRUE;
  1400. }
  1401. // Check the delayed ack timer.
  1402. if (TCB_TIMER_FIRED_R(CurrentTCB, DELACK_TIMER, j)) {
  1403. StopTCBTimerR(CurrentTCB, DELACK_TIMER);
  1404. // And it's fired. Set up to send an ACK.
  1405. Delayed = TRUE;
  1406. DelayAction(CurrentTCB, NEED_ACK);
  1407. }
  1408. if (TCB_TIMER_FIRED_R(CurrentTCB, KA_TIMER, j)) {
  1409. StopTCBTimerR(CurrentTCB, KA_TIMER);
  1410. // Finally check the keepalive timer.
  1411. if ((CurrentTCB->tcb_state == TCB_ESTAB) &&
  1412. (CurrentTCB->tcb_flags & KEEPALIVE) &&
  1413. (CurrentTCB->tcb_conn)) {
  1414. if (CurrentTCB->tcb_kacount < MaxDataRexmitCount) {
  1415. MakeTimerStateConsistent(CurrentTCB, j);
  1416. RecomputeTimerState( CurrentTCB );
  1417. START_TCB_TIMER_R( CurrentTCB, KA_TIMER,
  1418. CurrentTCB->tcb_conn->tc_tcbkainterval);
  1419. ASSERT(CurrentTCB->tcb_timertype != NO_TIMER);
  1420. ASSERT(CurrentTCB->tcb_timerslot < TIMER_WHEEL_SIZE);
  1421. SendKA(CurrentTCB, TCBHandle);
  1422. continue;
  1423. } else
  1424. goto TimeoutTCB;
  1425. }
  1426. }
  1427. if (TCB_TIMER_FIRED_R(CurrentTCB, CONN_TIMER, j)) {
  1428. StopTCBTimerR(CurrentTCB, CONN_TIMER);
  1429. // If this is an active open connection in SYN-SENT or SYN-RCVD,
  1430. // or we have a FIN pending, check the connect timer.
  1431. if (CurrentTCB->tcb_flags & (ACTIVE_OPEN | FIN_NEEDED | FIN_SENT)) {
  1432. if (CurrentTCB->tcb_connreq) {
  1433. // The connection timer has timed out.
  1434. CurrentTCB->tcb_flags |= NEED_RST;
  1435. MakeTimerStateConsistent(CurrentTCB, j);
  1436. RecomputeTimerState( CurrentTCB );
  1437. START_TCB_TIMER_R(CurrentTCB, RXMIT_TIMER, CurrentTCB->tcb_rexmit);
  1438. ASSERT(CurrentTCB->tcb_timertype != NO_TIMER);
  1439. ASSERT(CurrentTCB->tcb_timerslot < TIMER_WHEEL_SIZE);
  1440. TryToCloseTCB(CurrentTCB, TCB_CLOSE_TIMEOUT,
  1441. TCBHandle);
  1442. continue;
  1443. }
  1444. }
  1445. }
  1446. //
  1447. // Check to see if we have to notify the
  1448. // automatic connection driver about this
  1449. // connection.
  1450. //
  1451. if (TCB_TIMER_FIRED_R(CurrentTCB, ACD_TIMER, j)) {
  1452. BOOLEAN fEnabled;
  1453. CTELockHandle AcdHandle;
  1454. StopTCBTimerR(CurrentTCB, ACD_TIMER);
  1455. MakeTimerStateConsistent(CurrentTCB, j);
  1456. RecomputeTimerState( CurrentTCB );
  1457. ASSERT(CurrentTCB->tcb_timerslot < TIMER_WHEEL_SIZE);
  1458. if (CurrentTCB->tcb_timertype == NO_TIMER) {
  1459. RemoveFromTimerWheel(CurrentTCB);
  1460. } else {
  1461. Slot = COMPUTE_SLOT(CurrentTCB->tcb_timertime);
  1462. RemoveAndInsertIntoTimerWheel(CurrentTCB, Slot);
  1463. }
  1464. //
  1465. // Determine if we need to notify
  1466. // the automatic connection driver.
  1467. //
  1468. CTEGetLockAtDPC(&AcdDriverG.SpinLock, &AcdHandle);
  1469. fEnabled = AcdDriverG.fEnabled;
  1470. CTEFreeLockFromDPC(&AcdDriverG.SpinLock, AcdHandle);
  1471. if (fEnabled)
  1472. TCPNoteNewConnection(CurrentTCB, TCBHandle);
  1473. else
  1474. CTEFreeLockFromDPC(&CurrentTCB->tcb_lock, TCBHandle);
  1475. continue;
  1476. }
  1477. // Timer isn't running, or didn't fire.
  1478. MakeTimerStateConsistent(CurrentTCB, j);
  1479. ASSERT(CurrentTCB->tcb_timerslot < TIMER_WHEEL_SIZE);
  1480. RecomputeTimerState( CurrentTCB );
  1481. if (CurrentTCB->tcb_timertype == NO_TIMER) {
  1482. RemoveFromTimerWheel(CurrentTCB);
  1483. } else {
  1484. Slot = COMPUTE_SLOT(CurrentTCB->tcb_timertime);
  1485. RemoveAndInsertIntoTimerWheel(CurrentTCB, Slot);
  1486. }
  1487. CTEFreeLockFromDPC(&CurrentTCB->tcb_lock, TCBHandle);
  1488. }
  1489. }
  1490. TimerWheel[i].tw_starttick = LocalTime + 1;
  1491. }
  1492. ProcessSynTcbs(Processor);
  1493. // Check if it is about time to remove TCBs off TWQueue
  1494. if (Processor == 0) {
  1495. for (i = 0; i < NumTcbTablePartitions; i++) {
  1496. BOOLEAN Done = FALSE, firstime = TRUE;
  1497. TWTCB *CurrentTCB = NULL;
  1498. Queue *tmp;
  1499. CTEGetLockAtDPC(&pTWTCBTableLock[i], &TWTableHandle);
  1500. while (!Done) {
  1501. if (!EMPTYQ(&TWQueue[i])) {
  1502. PEEKQ(&TWQueue[i], CurrentTCB, TWTCB, twtcb_TWQueue);
  1503. CTEStructAssert(CurrentTCB, twtcb);
  1504. ASSERT(CurrentTCB->twtcb_flags & IN_TWQUEUE);
  1505. //Decrement its life time and the last TCB in the queue
  1506. //because this is a timer delta queue!
  1507. if (firstime) {
  1508. TWTCB *PrvTCB;
  1509. if (CurrentTCB->twtcb_rexmittimer > 0)
  1510. CurrentTCB->twtcb_rexmittimer--;
  1511. tmp = TWQueue[i].q_prev;
  1512. PrvTCB = STRUCT_OF(TWTCB, tmp, twtcb_TWQueue);
  1513. PrvTCB->twtcb_delta--;
  1514. firstime = FALSE;
  1515. }
  1516. } else {
  1517. Done = TRUE;
  1518. CurrentTCB = NULL;
  1519. }
  1520. if (CurrentTCB) {
  1521. // Check the rexmit timer.
  1522. if ((CurrentTCB->twtcb_rexmittimer <= 0)) {
  1523. // Timer fired close and remove this tcb
  1524. RemoveTWTCB(CurrentTCB, i);
  1525. numtwtimedout++;
  1526. FreeTWTCB(CurrentTCB);
  1527. } else {
  1528. Done = TRUE;
  1529. }
  1530. } else
  1531. break;
  1532. } //while
  1533. CTEFreeLockFromDPC(&pTWTCBTableLock[i], TWTableHandle);
  1534. } //for
  1535. } //proc == 0
  1536. // See if we need to call receive complete as part of deadman processing.
  1537. // We do this now because we want to restart the timer before calling
  1538. // receive complete, in case that takes a while. If we make this check
  1539. // while the timer is running we'd have to lock, so we'll check and save
  1540. // the result now before we start the timer.
  1541. CallRcvComplete = FALSE;
  1542. if (Processor == 0) {
  1543. if (DeadmanTicks <= LocalTime) {
  1544. CallRcvComplete = TRUE;
  1545. DeadmanTicks = NUM_DEADMAN_TIME+LocalTime;
  1546. }
  1547. }
  1548. // Now check the pending free list. If it's not null, walk down the
  1549. // list and decrement the walk count. If the count goes below 2, pull it
  1550. // from the list. If the count goes to 0, free the TCB. If the count is
  1551. // at 1 it'll be freed by whoever called RemoveTCB.
  1552. if (Processor == 0) {
  1553. CTEGetLockAtDPC(&PendingFreeLock.Lock, &TableHandle);
  1554. if (PendingFreeList != NULL) {
  1555. TCB *PrevTCB;
  1556. PrevTCB = STRUCT_OF(TCB, &PendingFreeList, tcb_delayq.q_next);
  1557. do {
  1558. CurrentTCB = (TCB *) PrevTCB->tcb_delayq.q_next;
  1559. CTEStructAssert(CurrentTCB, tcb);
  1560. #ifdef PENDING_FREE_DBG
  1561. // If WalkCount is 0 (before decrementing!), then something is wrong..
  1562. if( CurrentTCB->tcb_walkcount == 0)
  1563. DbgBreakPoint();
  1564. // If the TCB is still in the TCB table, sky could fall down on our heads!
  1565. if( CurrentTCB->tcb_flags & IN_TCB_TABLE)
  1566. DbgBreakPoint();
  1567. #endif
  1568. CurrentTCB->tcb_walkcount--;
  1569. if (CurrentTCB->tcb_walkcount <= 0) {
  1570. *(TCB **) & PrevTCB->tcb_delayq.q_next =
  1571. (TCB *) CurrentTCB->tcb_delayq.q_next;
  1572. FreeTCB(CurrentTCB);
  1573. } else {
  1574. PrevTCB = CurrentTCB;
  1575. }
  1576. } while (PrevTCB->tcb_delayq.q_next != NULL);
  1577. }
  1578. if (PendingSynFreeList != NULL) {
  1579. SYNTCB *PrevTCB,*CurrentTCB;
  1580. //we use q_prev in link q so that QNEXT will still walk to the
  1581. //next syntcb in processsyntcb, while this tcb is on SynFreeLis.t
  1582. PrevTCB = STRUCT_OF(SYNTCB, &PendingSynFreeList, syntcb_link.q_prev);
  1583. do {
  1584. CurrentTCB = (SYNTCB *) PrevTCB->syntcb_link.q_prev;
  1585. CTEStructAssert(CurrentTCB, syntcb);
  1586. CurrentTCB->syntcb_walkcount--;
  1587. if (CurrentTCB->syntcb_walkcount <= 0) {
  1588. *(SYNTCB **) & PrevTCB->syntcb_link.q_prev =
  1589. (SYNTCB *) CurrentTCB->syntcb_link.q_prev;
  1590. FreeSynTCB(CurrentTCB);
  1591. } else {
  1592. PrevTCB = CurrentTCB;
  1593. }
  1594. } while (PrevTCB->syntcb_link.q_prev != NULL);
  1595. }
  1596. CTEFreeLockFromDPC(&PendingFreeLock.Lock, TableHandle);
  1597. // Do AddrCheckTable cleanup
  1598. if (AddrCheckTable) {
  1599. TCPAddrCheckElement *Temp;
  1600. CTEGetLockAtDPC(&AddrObjTableLock.Lock, &TableHandle);
  1601. for (Temp = AddrCheckTable; Temp < AddrCheckTable + NTWMaxConnectCount; Temp++) {
  1602. if (Temp->TickCount > 0) {
  1603. if ((--(Temp->TickCount)) == 0) {
  1604. Temp->SourceAddress = 0;
  1605. }
  1606. }
  1607. }
  1608. CTEFreeLockFromDPC(&AddrObjTableLock.Lock, TableHandle);
  1609. }
  1610. }
  1611. CTEInterlockedAddUlong(&TCBWalkCount, -1, &PendingFreeLock.Lock);
  1612. if (Delayed) {
  1613. ProcessPerCpuTCBDelayQ(Processor, DISPATCH_LEVEL, NULL, NULL);
  1614. }
  1615. if (CallRcvComplete) {
  1616. TCPRcvComplete();
  1617. }
  1618. }
  1619. //* SetTCBMTU - Set TCB MTU values.
  1620. //
  1621. // A function called by TCBWalk to set the MTU values of all TCBs using
  1622. // a particular path.
  1623. //
  1624. // Input: CheckTCB - TCB to be checked.
  1625. // DestPtr - Ptr to destination address.
  1626. // SrcPtr - Ptr to source address.
  1627. // MTUPtr - Ptr to new MTU.
  1628. //
  1629. // Returns: TRUE.
  1630. //
  1631. uint
  1632. SetTCBMTU(TCB * CheckTCB, void *DestPtr, void *SrcPtr, void *MTUPtr)
  1633. {
  1634. IPAddr DestAddr = *(IPAddr *) DestPtr;
  1635. IPAddr SrcAddr = *(IPAddr *) SrcPtr;
  1636. CTELockHandle TCBHandle;
  1637. CTEStructAssert(CheckTCB, tcb);
  1638. CTEGetLock(&CheckTCB->tcb_lock, &TCBHandle);
  1639. if (IP_ADDR_EQUAL(CheckTCB->tcb_daddr, DestAddr) &&
  1640. IP_ADDR_EQUAL(CheckTCB->tcb_saddr, SrcAddr) &&
  1641. (CheckTCB->tcb_opt.ioi_flags & IP_FLAG_DF)) {
  1642. uint MTU = *(uint *)MTUPtr - CheckTCB->tcb_opt.ioi_optlength;
  1643. CheckTCB->tcb_mss = (ushort) MIN(MTU, (uint) CheckTCB->tcb_remmss);
  1644. ASSERT(CheckTCB->tcb_mss > 0);
  1645. ValidateMSS(CheckTCB);
  1646. //
  1647. // Reset the Congestion Window if necessary
  1648. //
  1649. if (CheckTCB->tcb_cwin < CheckTCB->tcb_mss) {
  1650. CheckTCB->tcb_cwin = CheckTCB->tcb_mss;
  1651. //
  1652. // Make sure the slow start threshold is at least
  1653. // 2 segments
  1654. //
  1655. if (CheckTCB->tcb_ssthresh < ((uint) CheckTCB->tcb_mss * 2)) {
  1656. CheckTCB->tcb_ssthresh = CheckTCB->tcb_mss * 2;
  1657. }
  1658. }
  1659. }
  1660. CTEFreeLock(&CheckTCB->tcb_lock, TCBHandle);
  1661. return TRUE;
  1662. }
  1663. //* DeleteTCBWithSrc - Delete tcbs with a particular src address.
  1664. //
  1665. // A function called by TCBWalk to delete all TCBs with a particular source
  1666. // address.
  1667. //
  1668. // Input: CheckTCB - TCB to be checked.
  1669. // AddrPtr - Ptr to address.
  1670. //
  1671. // Returns: FALSE if CheckTCB is to be deleted, TRUE otherwise.
  1672. //
  1673. uint
  1674. DeleteTCBWithSrc(TCB * CheckTCB, void *AddrPtr, void *Unused1, void *Unused3)
  1675. {
  1676. IPAddr Addr = *(IPAddr *) AddrPtr;
  1677. CTEStructAssert(CheckTCB, tcb);
  1678. if (IP_ADDR_EQUAL(CheckTCB->tcb_saddr, Addr))
  1679. return FALSE;
  1680. else
  1681. return TRUE;
  1682. }
  1683. //* TCBWalk - Walk the TCBs in the table, and call a function for each of them.
  1684. //
  1685. // Called when we need to repetively do something to each TCB in the table.
  1686. // We call the specified function with a pointer to the TCB and the input
  1687. // context for each TCB in the table. If the function returns FALSE, we
  1688. // delete the TCB.
  1689. //
  1690. // Input: CallRtn - Routine to be called.
  1691. // Context1 - Context to pass to CallRtn.
  1692. // Context2 - Second context to pass to call routine.
  1693. // Context3 - Third context to pass to call routine.
  1694. //
  1695. // Returns: Nothing.
  1696. //
  1697. void
  1698. TCBWalk(uint(*CallRtn) (struct TCB *, void *, void *, void *), void *Context1,
  1699. void *Context2, void *Context3)
  1700. {
  1701. uint i, j;
  1702. TCB *CurTCB;
  1703. CTELockHandle Handle, TCBHandle;
  1704. // Loop through each bucket in the table, going down the chain of
  1705. // TCBs on the bucket. For each one call CallRtn.
  1706. for (j = 0; j < NumTcbTablePartitions; j++) {
  1707. CTEGetLock(&pTCBTableLock[j], &Handle);
  1708. for (i = j * PerPartitionSize; i < (j + 1) * PerPartitionSize; i++) {
  1709. CurTCB = TCBTable[i];
  1710. // Walk down the chain on this bucket.
  1711. while (CurTCB != NULL) {
  1712. if (!(*CallRtn) (CurTCB, Context1, Context2, Context3)) {
  1713. // He failed the call. Notify the client and close the
  1714. // TCB.
  1715. CTEGetLock(&CurTCB->tcb_lock, &TCBHandle);
  1716. ASSERT(CurTCB->tcb_partition == j);
  1717. if (!CLOSING(CurTCB)) {
  1718. REFERENCE_TCB(CurTCB);
  1719. CTEFreeLock(&pTCBTableLock[j], TCBHandle);
  1720. TryToCloseTCB(CurTCB, TCB_CLOSE_ABORTED, Handle);
  1721. RemoveTCBFromConn(CurTCB);
  1722. if (CurTCB->tcb_state != TCB_TIME_WAIT)
  1723. NotifyOfDisc(CurTCB, NULL, TDI_CONNECTION_ABORTED);
  1724. CTEGetLock(&CurTCB->tcb_lock, &TCBHandle);
  1725. DerefTCB(CurTCB, TCBHandle);
  1726. CTEGetLock(&pTCBTableLock[j], &Handle);
  1727. } else
  1728. CTEFreeLock(&CurTCB->tcb_lock, TCBHandle);
  1729. CurTCB = FindNextTCB(i, CurTCB);
  1730. } else {
  1731. CurTCB = CurTCB->tcb_next;
  1732. }
  1733. }
  1734. }
  1735. CTEFreeLock(&pTCBTableLock[j], Handle);
  1736. } //outer for numpartitions
  1737. }
  1738. void
  1739. DerefSynTCB(SYNTCB * SynTCB, CTELockHandle TCBHandle)
  1740. {
  1741. CTELockHandle Handle=DISPATCH_LEVEL;
  1742. ASSERT(SynTCB->syntcb_refcnt != 0);
  1743. if (--SynTCB->syntcb_refcnt == 0) {
  1744. CTEGetLockAtDPC(&PendingFreeLock.Lock, &Handle);
  1745. if(TCBWalkCount){
  1746. ASSERT(!(SynTCB->syntcb_flags & IN_SYNTCB_TABLE));
  1747. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"Freeing to synpendinglist %x\n",SynTCB));
  1748. //we use q_prev in link q so that QNEXT will still walk to the
  1749. //next syntcb in processsyntcb, while this tcb is on SynFreeLis.t
  1750. SynTCB->syntcb_walkcount = TCBWalkCount + 1;
  1751. *(SYNTCB **) &SynTCB->syntcb_link.q_prev = PendingSynFreeList;
  1752. PendingSynFreeList = SynTCB;
  1753. CTEFreeLockFromDPC(&PendingFreeLock.Lock, Handle);
  1754. CTEFreeLock(&SynTCB->syntcb_lock, TCBHandle);
  1755. } else {
  1756. CTEFreeLockFromDPC(&PendingFreeLock.Lock, Handle);
  1757. CTEFreeLock(&SynTCB->syntcb_lock, TCBHandle);
  1758. FreeSynTCB(SynTCB);
  1759. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"syntcb freed %x\n",SynTCB));
  1760. }
  1761. } else {
  1762. CTEFreeLock(&SynTCB->syntcb_lock, TCBHandle);
  1763. }
  1764. }
  1765. TCB *
  1766. RemoveAndInsertSynTCB(SYNTCB *SynTCB, CTELockHandle TCBHandle)
  1767. {
  1768. TCB *NewTCB;
  1769. LOGICAL Inserted;
  1770. CTELockHandle Handle=DISPATCH_LEVEL;
  1771. NewTCB = AllocTCB();
  1772. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"reminsertsyn: %x %x\n",SynTCB,NewTCB));
  1773. if (NewTCB) {
  1774. //Initialize the full blown TCB
  1775. NewTCB->tcb_dport = SynTCB->syntcb_dport;
  1776. NewTCB->tcb_sport = SynTCB->syntcb_sport;
  1777. NewTCB->tcb_daddr = SynTCB->syntcb_daddr;
  1778. NewTCB->tcb_saddr = SynTCB->syntcb_saddr;
  1779. NewTCB->tcb_rcvnext = SynTCB->syntcb_rcvnext;
  1780. NewTCB->tcb_senduna = SynTCB->syntcb_senduna;
  1781. NewTCB->tcb_sendmax = SynTCB->syntcb_sendmax;
  1782. NewTCB->tcb_sendnext = SynTCB->syntcb_sendnext;
  1783. NewTCB->tcb_sendwin = SynTCB->syntcb_sendwin;
  1784. NewTCB->tcb_defaultwin = SynTCB->syntcb_defaultwin;
  1785. NewTCB->tcb_phxsum = PHXSUM(SynTCB->syntcb_saddr, SynTCB->syntcb_daddr,
  1786. PROTOCOL_TCP, 0);
  1787. NewTCB->tcb_rtt = SynTCB->syntcb_rtt;
  1788. NewTCB->tcb_smrtt = SynTCB->syntcb_smrtt;
  1789. NewTCB->tcb_delta = SynTCB->syntcb_delta;
  1790. NewTCB->tcb_rexmit = SynTCB->syntcb_rexmit;
  1791. NewTCB->tcb_mss = SynTCB->syntcb_mss;
  1792. NewTCB->tcb_remmss = SynTCB->syntcb_remmss;
  1793. NewTCB->tcb_rcvwin = SynTCB->syntcb_rcvwin;
  1794. NewTCB->tcb_rcvwinscale = SynTCB->syntcb_rcvwinscale;
  1795. NewTCB->tcb_sndwinscale = SynTCB->syntcb_sndwinscale;
  1796. NewTCB->tcb_tcpopts = SynTCB->syntcb_tcpopts;
  1797. NewTCB->tcb_state = TCB_SYN_RCVD;
  1798. NewTCB->tcb_connreq = NULL;
  1799. NewTCB->tcb_refcnt = 0;
  1800. REFERENCE_TCB(NewTCB);
  1801. NewTCB->tcb_fastchk |= TCP_FLAG_ACCEPT_PENDING;
  1802. NewTCB->tcb_flags |= CONN_ACCEPTED;
  1803. NewTCB->tcb_tsrecent = SynTCB->syntcb_tsrecent;
  1804. NewTCB->tcb_tsupdatetime = SynTCB->syntcb_tsupdatetime;
  1805. NewTCB->tcb_rexmitcnt = SynTCB->syntcb_rexmitcnt;
  1806. ClassifyPacket(NewTCB);
  1807. (*LocalNetInfo.ipi_initopts) (&NewTCB->tcb_opt);
  1808. Inserted = InsertTCB(NewTCB);
  1809. CTEGetLockAtDPC(&NewTCB->tcb_lock,&Handle);
  1810. DEREFERENCE_TCB(NewTCB);
  1811. if (!Inserted) {
  1812. TryToCloseTCB(NewTCB, TCB_CLOSE_ABORTED, Handle);
  1813. NewTCB = NULL;
  1814. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"tcb insertion failed %x\n",NewTCB));
  1815. }
  1816. }
  1817. //since we are not refing syntcb, it should goaway now.
  1818. DerefSynTCB(SynTCB, TCBHandle);
  1819. return NewTCB;
  1820. }
  1821. //* FindSynTCB - Find a SynTCB in the syntcb table.
  1822. //
  1823. // Called when we need to find a SynTCB in the synTCB table.
  1824. // Note : No locks are held on entry. On exit tcb lock will be held
  1825. //
  1826. // Input: Src - Source IP address of TCB to be found.
  1827. // Dest - Dest. "" "" "" "" "" "" ""
  1828. // DestPort - Destination port of TCB to be found.
  1829. // SrcPort - Source port of TCB to be found.
  1830. //
  1831. // Returns: Pointer to synTCB found, or NULL if none.
  1832. //
  1833. TCB *
  1834. FindSynTCB(IPAddr Src, IPAddr Dest, ushort DestPort, ushort SrcPort,
  1835. CTELockHandle * Handle, BOOLEAN AtDispatch, uint index, BOOLEAN *reset)
  1836. {
  1837. CTELockHandle TableHandle;
  1838. ulong Partition;
  1839. SYNTCB *FoundTCB;
  1840. TCB *NewTCB;
  1841. Queue *Scan;
  1842. Partition = GET_PARTITION(index);
  1843. CTEGetLock(&pSynTCBTableLock[Partition], Handle);
  1844. for (Scan = QHEAD(&SYNTCBTable[index]);
  1845. Scan != QEND(&SYNTCBTable[index]);
  1846. Scan = QNEXT(Scan)) {
  1847. FoundTCB = QSTRUCT(SYNTCB, Scan, syntcb_link);
  1848. CTEStructAssert(FoundTCB, syntcb);
  1849. if (IP_ADDR_EQUAL(FoundTCB->syntcb_daddr, Dest) &&
  1850. FoundTCB->syntcb_dport == DestPort &&
  1851. IP_ADDR_EQUAL(FoundTCB->syntcb_saddr, Src) &&
  1852. FoundTCB->syntcb_sport == SrcPort) {
  1853. CTEGetLock(&FoundTCB->syntcb_lock, &TableHandle);
  1854. FoundTCB->syntcb_flags &= ~IN_SYNTCB_TABLE;
  1855. REMOVEQ(&FoundTCB->syntcb_link);
  1856. CTEFreeLock(&pSynTCBTableLock[Partition], TableHandle);
  1857. //replace small syntcb with normal one.
  1858. NewTCB = RemoveAndInsertSynTCB(FoundTCB, *Handle);
  1859. if (NewTCB == NULL) {
  1860. uint maxRexmitCnt;
  1861. maxRexmitCnt = MIN(MaxConnectResponseRexmitCountTmp,
  1862. MaxConnectResponseRexmitCount);
  1863. *reset=TRUE;
  1864. if (FoundTCB->syntcb_rexmitcnt >= maxRexmitCnt) {
  1865. CTEInterlockedAddUlong(&TCPHalfOpenRetried, -1, &SynAttLock.Lock);
  1866. }
  1867. }
  1868. return NewTCB;
  1869. }
  1870. }
  1871. CTEFreeLock(&pSynTCBTableLock[Partition], *Handle);
  1872. // no matching TCB
  1873. return NULL;
  1874. }
  1875. //* FindTCB - Find a TCB in the tcb table.
  1876. //
  1877. // Called when we need to find a TCB in the TCB table. We take a quick
  1878. // look at the last TCB we found, and if it matches we return it, lock held. Otherwise
  1879. // we hash into the TCB table and look for it.
  1880. // Note : No locks are held on entry. On exit tcb lock will be held
  1881. //
  1882. // Input: Src - Source IP address of TCB to be found.
  1883. // Dest - Dest. "" "" "" "" "" "" ""
  1884. // DestPort - Destination port of TCB to be found.
  1885. // SrcPort - Source port of TCB to be found.
  1886. //
  1887. // Returns: Pointer to TCB found, or NULL if none.
  1888. //
  1889. TCB *
  1890. FindTCB(IPAddr Src, IPAddr Dest, ushort DestPort, ushort SrcPort,
  1891. CTELockHandle * Handle, BOOLEAN AtDispatch, uint * hash)
  1892. {
  1893. TCB *FoundTCB;
  1894. CTELockHandle TableHandle;
  1895. ulong index, Partition;
  1896. *hash = index = TCB_HASH(Dest, Src, DestPort, SrcPort);
  1897. Partition = GET_PARTITION(index);
  1898. if (AtDispatch) {
  1899. CTEGetLockAtDPC(&pTCBTableLock[Partition], Handle);
  1900. } else {
  1901. CTEGetLock(&pTCBTableLock[Partition], Handle);
  1902. }
  1903. // Didn't find it in our 1 element cache.
  1904. FoundTCB = TCBTable[index];
  1905. while (FoundTCB != NULL) {
  1906. CTEStructAssert(FoundTCB, tcb);
  1907. if (IP_ADDR_EQUAL(FoundTCB->tcb_daddr, Dest) &&
  1908. FoundTCB->tcb_dport == DestPort &&
  1909. IP_ADDR_EQUAL(FoundTCB->tcb_saddr, Src) &&
  1910. FoundTCB->tcb_sport == SrcPort) {
  1911. // Found it. Update the cache for next time, and return.
  1912. //LastTCB = FoundTCB;
  1913. CTEGetLockAtDPC(&FoundTCB->tcb_lock, &TableHandle);
  1914. CTEFreeLockFromDPC(&pTCBTableLock[Partition], TableHandle);
  1915. return FoundTCB;
  1916. } else
  1917. FoundTCB = FoundTCB->tcb_next;
  1918. }
  1919. if (AtDispatch) {
  1920. CTEFreeLockFromDPC(&pTCBTableLock[Partition], *Handle);
  1921. } else {
  1922. CTEFreeLock(&pTCBTableLock[Partition], *Handle);
  1923. }
  1924. // no matching TCB
  1925. return NULL;
  1926. }
  1927. //* FindTCBTW - Find a TCB in the time wait tcb table.
  1928. //
  1929. // Called when we need to find a TCB in the TCB table. We take a quick
  1930. // look at the last TCB we found, and if it matches we return it. Otherwise
  1931. // we hash into the TCB table and look for it. We assume the TCB table lock
  1932. // is held when we are called.
  1933. //
  1934. // Input: Src - Source IP address of TCB to be found.
  1935. // Dest - Dest. "" "" "" "" "" "" ""
  1936. // DestPort - Destination port of TCB to be found.
  1937. // SrcPort - Source port of TCB to be found.
  1938. //
  1939. // Returns: Pointer to TCB found, or NULL if none.
  1940. //
  1941. TWTCB *
  1942. FindTCBTW(IPAddr Src, IPAddr Dest, ushort DestPort, ushort SrcPort, uint index)
  1943. {
  1944. TWTCB *FoundTCB;
  1945. Queue *Scan;
  1946. for (Scan = QHEAD(&TWTCBTable[index]);
  1947. Scan != QEND(&TWTCBTable[index]);
  1948. Scan = QNEXT(Scan)) {
  1949. FoundTCB = QSTRUCT(TWTCB, Scan, twtcb_link);
  1950. CTEStructAssert(FoundTCB, twtcb);
  1951. if (IP_ADDR_EQUAL(FoundTCB->twtcb_daddr, Dest) &&
  1952. FoundTCB->twtcb_dport == DestPort &&
  1953. IP_ADDR_EQUAL(FoundTCB->twtcb_saddr, Src) &&
  1954. FoundTCB->twtcb_sport == SrcPort) {
  1955. return FoundTCB;
  1956. }
  1957. }
  1958. // no matching TCB
  1959. return NULL;
  1960. }
  1961. void
  1962. InsertInTimewaitQueue(TWTCB *Twtcb, uint Partition)
  1963. {
  1964. Queue *PrevLink;
  1965. TWTCB *Prev;
  1966. CTEStructAssert(Twtcb, twtcb);
  1967. ASSERT(!(Twtcb->twtcb_flags & IN_TWQUEUE));
  1968. ENQUEUE(&TWQueue[Partition], &Twtcb->twtcb_TWQueue);
  1969. PrevLink = QPREV(&Twtcb->twtcb_TWQueue);
  1970. if (PrevLink != &TWQueue[Partition]) {
  1971. Prev = STRUCT_OF(TWTCB, PrevLink, twtcb_TWQueue);
  1972. // Compute this TCB's delta value from the using previous TCB's delta
  1973. // Note that prev tcb delta is decremented by timeout routine
  1974. // every tick
  1975. Twtcb->twtcb_rexmittimer = MAX_REXMIT_TO - Prev->twtcb_delta;
  1976. } else {
  1977. Twtcb->twtcb_rexmittimer = MAX_REXMIT_TO;
  1978. }
  1979. Twtcb->twtcb_delta = MAX_REXMIT_TO;
  1980. #if DBG
  1981. Twtcb->twtcb_flags |= IN_TWQUEUE;
  1982. #endif
  1983. }
  1984. void
  1985. RemoveFromTimewaitQueue(TWTCB *Twtcb, uint Partition)
  1986. {
  1987. ushort Delta;
  1988. Queue *NextLink;
  1989. TWTCB *Next;
  1990. CTEStructAssert(Twtcb, twtcb);
  1991. ASSERT(Twtcb->twtcb_flags & IN_TWQUEUE);
  1992. Delta = Twtcb->twtcb_rexmittimer;
  1993. // Update the time for the delta queue if we are not the last
  1994. // item in the queue.
  1995. //
  1996. NextLink = QNEXT(&Twtcb->twtcb_TWQueue);
  1997. if (Delta && (NextLink != QEND(&TWQueue[Partition]))) {
  1998. Next = STRUCT_OF(TWTCB, NextLink, twtcb_TWQueue);
  1999. Next->twtcb_rexmittimer += Delta;
  2000. }
  2001. REMOVEQ(&Twtcb->twtcb_TWQueue);
  2002. #if DBG
  2003. Twtcb->twtcb_flags &= ~IN_TWQUEUE;
  2004. #endif
  2005. }
  2006. //* RemoveAndInsert();
  2007. // This routine is called by graceful close routine when the TCB
  2008. // needs to be placed in TIM_WAIT state.
  2009. // The routine removes the TCB from normal table and inserts a small
  2010. // version of it
  2011. // in TW table at the same hash index as the previous one.
  2012. // Also, it queues the TWTCB in timer delta queue for time out
  2013. // processing
  2014. //
  2015. uint
  2016. RemoveAndInsert(TCB * TimWaitTCB)
  2017. {
  2018. uint TCBIndex;
  2019. CTELockHandle TableHandle, TWTableHandle, TcbHandle = DISPATCH_LEVEL;
  2020. TCB *PrevTCB;
  2021. TWTCB *TWTcb;
  2022. uint Partition = TimWaitTCB->tcb_partition;
  2023. Queue* Scan;
  2024. #if DBG
  2025. uint Found = FALSE;
  2026. #endif
  2027. CTEStructAssert(TimWaitTCB, tcb);
  2028. ASSERT(TimWaitTCB->tcb_flags & IN_TCB_TABLE);
  2029. ASSERT(TimWaitTCB->tcb_pending == 0);
  2030. if (TimWaitTCB->tcb_flags & IN_TCB_TABLE) {
  2031. CTEGetLock(&pTCBTableLock[Partition], &TableHandle);
  2032. CTEGetLockAtDPC(&TimWaitTCB->tcb_lock, &TcbHandle);
  2033. TCBIndex = TCB_HASH(TimWaitTCB->tcb_daddr, TimWaitTCB->tcb_saddr,
  2034. TimWaitTCB->tcb_dport, TimWaitTCB->tcb_sport);
  2035. PrevTCB = STRUCT_OF(TCB, &TCBTable[TCBIndex], tcb_next);
  2036. do {
  2037. if (PrevTCB->tcb_next == TimWaitTCB) {
  2038. // Found him.
  2039. PrevTCB->tcb_next = TimWaitTCB->tcb_next;
  2040. #if DBG
  2041. Found = TRUE;
  2042. #endif
  2043. break;
  2044. }
  2045. PrevTCB = PrevTCB->tcb_next;
  2046. #if DBG
  2047. CTEStructAssert(PrevTCB, tcb);
  2048. #endif
  2049. } while (PrevTCB != NULL);
  2050. ASSERT(Found);
  2051. TimWaitTCB->tcb_flags &= ~IN_TCB_TABLE;
  2052. TimWaitTCB->tcb_pending |= FREE_PENDING;
  2053. //rce and opts are freed in dereftcb.
  2054. //at this point tcb is out of this tcbtable
  2055. //nobody should be holding on to this.
  2056. //we are free to close this tcb and
  2057. //move the state to a smaller twtcb after acquiring
  2058. //twtcbtable lock
  2059. //get a free twtcb
  2060. if ((TWTcb = AllocTWTCB(Partition)) == NULL) {
  2061. DerefTCB(TimWaitTCB, TcbHandle);
  2062. CTEFreeLock(&pTCBTableLock[Partition], TableHandle);
  2063. return TRUE;
  2064. //possibaly we should queue this tcb on wait queue
  2065. //and service it when we get free twtcb
  2066. }
  2067. // Initialize twtcb
  2068. //
  2069. TWTcb->twtcb_daddr = TimWaitTCB->tcb_daddr;
  2070. TWTcb->twtcb_saddr = TimWaitTCB->tcb_saddr;
  2071. TWTcb->twtcb_dport = TimWaitTCB->tcb_dport;
  2072. TWTcb->twtcb_sport = TimWaitTCB->tcb_sport;
  2073. TWTcb->twtcb_senduna = TimWaitTCB->tcb_senduna;
  2074. TWTcb->twtcb_rcvnext = TimWaitTCB->tcb_rcvnext;
  2075. TWTcb->twtcb_sendnext = TimWaitTCB->tcb_sendnext;
  2076. #if DBG
  2077. TWTcb->twtcb_flags = 0;
  2078. #endif
  2079. CTEGetLockAtDPC(&pTWTCBTableLock[Partition], &TWTableHandle);
  2080. // Free the parent tcb for this connection
  2081. DerefTCB(TimWaitTCB, TcbHandle);
  2082. // now insert this in to time wait table after locking
  2083. if (EMPTYQ(&TWTCBTable[TCBIndex])) {
  2084. //
  2085. // First item in this bucket.
  2086. //
  2087. PUSHQ(&TWTCBTable[TCBIndex], &TWTcb->twtcb_link);
  2088. } else {
  2089. //
  2090. // Insert the item in sorted order. The order is based
  2091. // on the address of the TWTCB. (In this case, comparison
  2092. // is made against the address of the twtcb_link member, but
  2093. // the same result is achieved.)
  2094. //
  2095. for (Scan = QHEAD(&TWTCBTable[TCBIndex]);
  2096. Scan != QEND(&TWTCBTable[TCBIndex]);
  2097. Scan = QNEXT(Scan)) {
  2098. if (Scan > &TWTcb->twtcb_link) {
  2099. TWTcb->twtcb_link.q_next = Scan;
  2100. TWTcb->twtcb_link.q_prev = Scan->q_prev;
  2101. Scan->q_prev->q_next = &TWTcb->twtcb_link;
  2102. Scan->q_prev = &TWTcb->twtcb_link;
  2103. break;
  2104. }
  2105. }
  2106. //
  2107. // If we made it to the end without inserting, insert it
  2108. // at the end.
  2109. //
  2110. if (Scan == QEND(&TWTCBTable[TCBIndex])) {
  2111. ENQUEUE(&TWTCBTable[TCBIndex], &TWTcb->twtcb_link);
  2112. }
  2113. }
  2114. //no need to hold on to tcbtablelock beyond this point
  2115. #if DBG
  2116. TWTcb->twtcb_flags |= IN_TWTCB_TABLE;
  2117. #endif
  2118. CTEFreeLockFromDPC(&pTCBTableLock[Partition], TWTableHandle);
  2119. InsertInTimewaitQueue(TWTcb, Partition);
  2120. CTEFreeLock(&pTWTCBTableLock[Partition], TableHandle);
  2121. InterlockedIncrement(&numtwqueue); //debug purpose
  2122. return TRUE;
  2123. } //if tcb in table
  2124. return FALSE;
  2125. }
  2126. //* RemoveTWTCB - Remove a TWTCB from the TWTCB table.
  2127. //
  2128. // Called when we need to remove a TCB in time-wait from the time wait TCB
  2129. // table. We assume the TWTCB table lock is held when we are called.
  2130. //
  2131. // Input: RemovedTCB - TWTCB to be removed.
  2132. //
  2133. void
  2134. RemoveTWTCB(TWTCB *RemovedTCB, uint Partition)
  2135. {
  2136. CTEStructAssert(RemovedTCB, twtcb);
  2137. ASSERT(RemovedTCB->twtcb_flags & IN_TWTCB_TABLE);
  2138. ASSERT(RemovedTCB->twtcb_flags & IN_TWQUEUE);
  2139. REMOVEQ(&RemovedTCB->twtcb_link);
  2140. InterlockedDecrement(&TStats.ts_numconns);
  2141. RemoveFromTimewaitQueue(RemovedTCB, Partition);
  2142. InterlockedDecrement(&numtwqueue);
  2143. #if DBG
  2144. RemovedTCB->twtcb_flags &= ~IN_TWTCB_TABLE;
  2145. #endif
  2146. }
  2147. void
  2148. ReInsert2MSL(TWTCB *RemovedTCB)
  2149. {
  2150. uint Index, Partition;
  2151. CTEStructAssert(RemovedTCB, twtcb);
  2152. ASSERT(RemovedTCB->twtcb_flags & IN_TWQUEUE);
  2153. Index = TCB_HASH(RemovedTCB->twtcb_daddr, RemovedTCB->twtcb_saddr,
  2154. RemovedTCB->twtcb_dport, RemovedTCB->twtcb_sport);
  2155. Partition = GET_PARTITION(Index);
  2156. RemoveFromTimewaitQueue(RemovedTCB, Partition);
  2157. InsertInTimewaitQueue(RemovedTCB, Partition);
  2158. }
  2159. //* InsertSynTCB - Insert a SYNTCB in the tcb table.
  2160. //
  2161. // This routine inserts a SYNTCB in the SYNTCB table. No locks need to be held
  2162. // when this routine is called. We insert TCBs in ascending address order.
  2163. // Before inserting we make sure that the SYNTCB isn't already in the table.
  2164. //
  2165. // Input: NewTCB - SYNTCB to be inserted.
  2166. //
  2167. // Returns: TRUE if we inserted, false if we didn't.
  2168. //
  2169. uint
  2170. InsertSynTCB(SYNTCB * NewTCB, CTELockHandle *TableHandle)
  2171. {
  2172. uint TCBIndex;
  2173. CTELockHandle TCBHandle=DISPATCH_LEVEL;
  2174. TCB *PrevTCB, *CurrentTCB;
  2175. CTELockHandle SynTableHandle=DISPATCH_LEVEL;
  2176. uint Partition;
  2177. Queue *Scan;
  2178. SYNTCB *tmpSynTCB;
  2179. ASSERT(NewTCB != NULL);
  2180. CTEStructAssert(NewTCB, syntcb);
  2181. TCBIndex = TCB_HASH(NewTCB->syntcb_daddr, NewTCB->syntcb_saddr,
  2182. NewTCB->syntcb_dport, NewTCB->syntcb_sport);
  2183. Partition = GET_PARTITION(TCBIndex);
  2184. CTEGetLock(&pTCBTableLock[Partition], TableHandle);
  2185. NewTCB->syntcb_partition = Partition;
  2186. // Find the proper place in the table to insert him. While
  2187. // we're walking we'll check to see if a dupe already exists.
  2188. // When we find the right place to insert, we'll remember it, and
  2189. // keep walking looking for a duplicate.
  2190. PrevTCB = STRUCT_OF(TCB, &TCBTable[TCBIndex], tcb_next);
  2191. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"insertsyn: %x\n",NewTCB));
  2192. while (PrevTCB->tcb_next != NULL) {
  2193. CurrentTCB = PrevTCB->tcb_next;
  2194. if (IP_ADDR_EQUAL(CurrentTCB->tcb_daddr, NewTCB->syntcb_daddr) &&
  2195. IP_ADDR_EQUAL(CurrentTCB->tcb_saddr, NewTCB->syntcb_saddr) &&
  2196. (CurrentTCB->tcb_sport == NewTCB->syntcb_sport) &&
  2197. (CurrentTCB->tcb_dport == NewTCB->syntcb_dport)) {
  2198. CTEFreeLock(&pTCBTableLock[Partition], *TableHandle);
  2199. return FALSE;
  2200. } else {
  2201. PrevTCB = PrevTCB->tcb_next;
  2202. }
  2203. }
  2204. CTEGetLockAtDPC(&pSynTCBTableLock[Partition], &SynTableHandle);
  2205. CTEGetLockAtDPC(&NewTCB->syntcb_lock, &TCBHandle);
  2206. if (EMPTYQ(&SYNTCBTable[TCBIndex])) {
  2207. PUSHQ(&SYNTCBTable[TCBIndex], &NewTCB->syntcb_link);
  2208. } else {
  2209. //Make sure that duplicate syn request has not
  2210. //resulted in inserting a dup syntcb
  2211. //which can happen on a MP system.
  2212. for (Scan = QHEAD(&SYNTCBTable[TCBIndex]);
  2213. Scan != QEND(&SYNTCBTable[TCBIndex]);
  2214. Scan = QNEXT(Scan)) {
  2215. tmpSynTCB = STRUCT_OF(SYNTCB, Scan, syntcb_link);
  2216. if (IP_ADDR_EQUAL(tmpSynTCB->syntcb_daddr, NewTCB->syntcb_daddr) &&
  2217. (tmpSynTCB->syntcb_dport == NewTCB->syntcb_dport) &&
  2218. IP_ADDR_EQUAL(tmpSynTCB->syntcb_saddr, NewTCB->syntcb_saddr) &&
  2219. (tmpSynTCB->syntcb_sport == NewTCB->syntcb_sport)) {
  2220. CTEFreeLockFromDPC(&NewTCB->syntcb_lock, TCBHandle);
  2221. CTEFreeLock(&pSynTCBTableLock[Partition],SynTableHandle);
  2222. CTEFreeLock(&pTCBTableLock[Partition], *TableHandle);
  2223. return FALSE;
  2224. }
  2225. }
  2226. // Insert the item in sorted order. The order is based
  2227. // on the address of the SYNTCB. (In this case, comparison
  2228. // is made against the address of the syntcb_link member, but
  2229. // the same result is achieved.)
  2230. //
  2231. for (Scan = QHEAD(&SYNTCBTable[TCBIndex]);
  2232. Scan != QEND(&SYNTCBTable[TCBIndex]);
  2233. Scan = QNEXT(Scan)) {
  2234. if (Scan > &NewTCB->syntcb_link) {
  2235. NewTCB->syntcb_link.q_next = Scan;
  2236. NewTCB->syntcb_link.q_prev = Scan->q_prev;
  2237. Scan->q_prev->q_next = &NewTCB->syntcb_link;
  2238. Scan->q_prev = &NewTCB->syntcb_link;
  2239. break;
  2240. }
  2241. }
  2242. //
  2243. // If we made it to the end without inserting, insert it
  2244. // at the end.
  2245. //
  2246. if (Scan == QEND(&SYNTCBTable[TCBIndex])) {
  2247. ENQUEUE(&SYNTCBTable[TCBIndex], &NewTCB->syntcb_link);
  2248. }
  2249. }
  2250. NewTCB->syntcb_flags |= IN_SYNTCB_TABLE;
  2251. CTEFreeLockFromDPC(&pSynTCBTableLock[Partition], SynTableHandle);
  2252. CTEFreeLockFromDPC(&pTCBTableLock[Partition], TCBHandle);
  2253. return TRUE;
  2254. }
  2255. //* InsertTCB - Insert a TCB in the tcb table.
  2256. //
  2257. // This routine inserts a TCB in the TCB table. No locks need to be held
  2258. // when this routine is called. We insert TCBs in ascending address order.
  2259. // Before inserting we make sure that the TCB isn't already in the table.
  2260. //
  2261. // Input: NewTCB - TCB to be inserted.
  2262. //
  2263. // Returns: TRUE if we inserted, false if we didn't.
  2264. //
  2265. uint
  2266. InsertTCB(TCB * NewTCB)
  2267. {
  2268. uint TCBIndex;
  2269. CTELockHandle TableHandle, TCBHandle;
  2270. TCB *PrevTCB, *CurrentTCB;
  2271. TCB *WhereToInsert;
  2272. CTELockHandle TWTableHandle;
  2273. TWTCB *CurrentTWTCB;
  2274. uint Partition;
  2275. Queue *Scan;
  2276. uint EarlyInsertTime;
  2277. ASSERT(NewTCB != NULL);
  2278. CTEStructAssert(NewTCB, tcb);
  2279. TCBIndex = TCB_HASH(NewTCB->tcb_daddr, NewTCB->tcb_saddr,
  2280. NewTCB->tcb_dport, NewTCB->tcb_sport);
  2281. Partition = GET_PARTITION(TCBIndex);
  2282. CTEGetLock(&pTCBTableLock[Partition], &TableHandle);
  2283. CTEGetLockAtDPC(&NewTCB->tcb_lock, &TCBHandle);
  2284. NewTCB->tcb_partition = Partition;
  2285. // Find the proper place in the table to insert him. While
  2286. // we're walking we'll check to see if a dupe already exists.
  2287. // When we find the right place to insert, we'll remember it, and
  2288. // keep walking looking for a duplicate.
  2289. PrevTCB = STRUCT_OF(TCB, &TCBTable[TCBIndex], tcb_next);
  2290. WhereToInsert = NULL;
  2291. while (PrevTCB->tcb_next != NULL) {
  2292. CurrentTCB = PrevTCB->tcb_next;
  2293. if (IP_ADDR_EQUAL(CurrentTCB->tcb_daddr, NewTCB->tcb_daddr) &&
  2294. IP_ADDR_EQUAL(CurrentTCB->tcb_saddr, NewTCB->tcb_saddr) &&
  2295. (CurrentTCB->tcb_sport == NewTCB->tcb_sport) &&
  2296. (CurrentTCB->tcb_dport == NewTCB->tcb_dport)) {
  2297. CTEFreeLockFromDPC(&NewTCB->tcb_lock, TCBHandle);
  2298. CTEFreeLock(&pTCBTableLock[Partition], TableHandle);
  2299. return FALSE;
  2300. } else {
  2301. if (WhereToInsert == NULL && CurrentTCB > NewTCB) {
  2302. WhereToInsert = PrevTCB;
  2303. }
  2304. CTEStructAssert(PrevTCB->tcb_next, tcb);
  2305. PrevTCB = PrevTCB->tcb_next;
  2306. }
  2307. }
  2308. // there can be timed_wait tcb in the tw tcb table.
  2309. // look if there is a tcb with the same address.
  2310. // Get lock on TW table too.
  2311. CTEGetLockAtDPC(&pTWTCBTableLock[Partition], &TWTableHandle);
  2312. for (Scan = QHEAD(&TWTCBTable[TCBIndex]);
  2313. Scan != QEND(&TWTCBTable[TCBIndex]);
  2314. Scan = QNEXT(Scan)) {
  2315. CurrentTWTCB = STRUCT_OF(TWTCB, Scan, twtcb_link);
  2316. CTEStructAssert(CurrentTWTCB, twtcb);
  2317. if (IP_ADDR_EQUAL(CurrentTWTCB->twtcb_daddr, NewTCB->tcb_daddr) &&
  2318. (CurrentTWTCB->twtcb_dport == NewTCB->tcb_dport) &&
  2319. IP_ADDR_EQUAL(CurrentTWTCB->twtcb_saddr, NewTCB->tcb_saddr) &&
  2320. (CurrentTWTCB->twtcb_sport == NewTCB->tcb_sport)) {
  2321. CTEFreeLockFromDPC(&pTWTCBTableLock[Partition], TWTableHandle);
  2322. CTEFreeLockFromDPC(&NewTCB->tcb_lock, TCBHandle);
  2323. CTEFreeLock(&pTCBTableLock[Partition], TableHandle);
  2324. return FALSE;
  2325. }
  2326. }
  2327. CTEFreeLockFromDPC(&pTWTCBTableLock[Partition], TWTableHandle);
  2328. if (WhereToInsert == NULL) {
  2329. WhereToInsert = PrevTCB;
  2330. }
  2331. NewTCB->tcb_next = WhereToInsert->tcb_next;
  2332. WhereToInsert->tcb_next = NewTCB;
  2333. NewTCB->tcb_flags |= IN_TCB_TABLE;
  2334. // Doing EarlyInsert..
  2335. EarlyInsertTime = TCPTime + 2;
  2336. // Taking care of looparound..
  2337. if( EarlyInsertTime == 0)
  2338. EarlyInsertTime = 1;
  2339. // Early Insertion of TCB..
  2340. if( NewTCB->tcb_timerslot == DUMMY_SLOT ) {
  2341. NewTCB->tcb_timertime = EarlyInsertTime;
  2342. InsertIntoTimerWheel( NewTCB, COMPUTE_SLOT( EarlyInsertTime ) );
  2343. } else if ( (TCPTIME_LT( EarlyInsertTime , NewTCB->tcb_timertime )) ||
  2344. (NewTCB->tcb_timertime == 0 ) ) {
  2345. NewTCB->tcb_timertime = EarlyInsertTime;
  2346. RemoveAndInsertIntoTimerWheel( NewTCB, COMPUTE_SLOT( EarlyInsertTime ));
  2347. }
  2348. CTEFreeLockFromDPC(&NewTCB->tcb_lock, TCBHandle);
  2349. CTEFreeLock(&pTCBTableLock[Partition], TableHandle);
  2350. InterlockedIncrement(&TStats.ts_numconns);
  2351. return TRUE;
  2352. }
  2353. //* RemoveTCB - Remove a TCB from the tcb table.
  2354. //
  2355. // Called when we need to remove a TCB from the TCB table. We assume the
  2356. // TCB table lock and the TCB lock are held when we are called. If the
  2357. // TCB isn't in the table we won't try to remove him.
  2358. //
  2359. // Input: RemovedTCB - TCB to be removed.
  2360. //
  2361. // Returns: TRUE if it's OK to free it, FALSE otherwise.
  2362. //
  2363. uint
  2364. RemoveTCB(TCB * RemovedTCB)
  2365. {
  2366. uint TCBIndex;
  2367. TCB *PrevTCB;
  2368. #if DBG
  2369. uint Found = FALSE;
  2370. #endif
  2371. CTELockHandle Handle;
  2372. CTEStructAssert(RemovedTCB, tcb);
  2373. if( RemovedTCB->tcb_timerslot != DUMMY_SLOT) {
  2374. ASSERT( RemovedTCB->tcb_timerslot < TIMER_WHEEL_SIZE );
  2375. RemoveFromTimerWheel( RemovedTCB );
  2376. }
  2377. if (RemovedTCB->tcb_flags & IN_TCB_TABLE) {
  2378. TCBIndex = TCB_HASH(RemovedTCB->tcb_daddr, RemovedTCB->tcb_saddr,
  2379. RemovedTCB->tcb_dport, RemovedTCB->tcb_sport);
  2380. PrevTCB = STRUCT_OF(TCB, &TCBTable[TCBIndex], tcb_next);
  2381. do {
  2382. if (PrevTCB->tcb_next == RemovedTCB) {
  2383. // Found him.
  2384. PrevTCB->tcb_next = RemovedTCB->tcb_next;
  2385. RemovedTCB->tcb_flags &= ~IN_TCB_TABLE;
  2386. InterlockedDecrement(&TStats.ts_numconns);
  2387. #if DBG
  2388. Found = TRUE;
  2389. #endif
  2390. break;
  2391. }
  2392. PrevTCB = PrevTCB->tcb_next;
  2393. #if DBG
  2394. if (PrevTCB != NULL)
  2395. CTEStructAssert(PrevTCB, tcb);
  2396. #endif
  2397. } while (PrevTCB != NULL);
  2398. ASSERT(Found);
  2399. }
  2400. CTEGetLockAtDPC(&PendingFreeLock.Lock, &Handle);
  2401. if (TCBWalkCount != 0) {
  2402. #ifdef PENDING_FREE_DBG
  2403. if( RemovedTCB->tcb_flags & IN_TCB_TABLE )
  2404. DbgBreakPoint();
  2405. #endif
  2406. RemovedTCB->tcb_walkcount = TCBWalkCount + 1;
  2407. *(TCB **) & RemovedTCB->tcb_delayq.q_next = PendingFreeList;
  2408. PendingFreeList = RemovedTCB;
  2409. CTEFreeLockFromDPC(&PendingFreeLock.Lock, Handle);
  2410. return FALSE;
  2411. } else {
  2412. CTEFreeLockFromDPC(&PendingFreeLock.Lock, Handle);
  2413. return TRUE;
  2414. }
  2415. }
  2416. //* AllocTWTCB - Allocate a TCB.
  2417. //
  2418. // Called whenever we need to allocate a TWTCB. We try to pull one off the
  2419. // free list, or allocate one if we need one. We then initialize it, etc.
  2420. //
  2421. // Input: Nothing.
  2422. //
  2423. // Returns: Pointer to the new TCB, or NULL if we couldn't get one.
  2424. //
  2425. TWTCB *
  2426. AllocTWTCB(uint index)
  2427. {
  2428. TWTCB *NewTWTCB;
  2429. LOGICAL FromList;
  2430. // We use the reqeust pool, because its buffers are in the same size
  2431. // range as TWTCB. Further, it is a very active and efficient look
  2432. // aside list whereas when TWTCBs are on their own look aside list it
  2433. // is usually at a very small depth because TWTCBs are not allocated
  2434. // very frequently w.r.t. to the update period of the look aside list.
  2435. //
  2436. NewTWTCB = PplAllocate(TcpRequestPool, &FromList);
  2437. if (NewTWTCB) {
  2438. NdisZeroMemory(NewTWTCB, sizeof(TWTCB));
  2439. #if DBG
  2440. NewTWTCB->twtcb_sig = twtcb_signature;
  2441. #endif
  2442. }
  2443. return NewTWTCB;
  2444. }
  2445. //* AllocTCB - Allocate a TCB.
  2446. //
  2447. // Called whenever we need to allocate a TCB. We try to pull one off the
  2448. // free list, or allocate one if we need one. We then initialize it, etc.
  2449. //
  2450. // Input: Nothing.
  2451. //
  2452. // Returns: Pointer to the new TCB, or NULL if we couldn't get one.
  2453. //
  2454. TCB *
  2455. AllocTCB(VOID)
  2456. {
  2457. TCB *NewTCB;
  2458. LOGICAL FromList;
  2459. NewTCB = PplAllocate(TcbPool, &FromList);
  2460. if (NewTCB) {
  2461. NdisZeroMemory(NewTCB, sizeof(TCB));
  2462. #if DBG
  2463. NewTCB->tcb_sig = tcb_signature;
  2464. #endif
  2465. INITQ(&NewTCB->tcb_sendq);
  2466. // Initially we're not on the fast path because we're not established. Set
  2467. // the slowcount to one and set up the fastchk fields so we don't take the
  2468. // fast path.
  2469. NewTCB->tcb_slowcount = 1;
  2470. NewTCB->tcb_fastchk = TCP_FLAG_ACK | TCP_FLAG_SLOW;
  2471. NewTCB->tcb_delackticks = DEL_ACK_TICKS;
  2472. CTEInitLock(&NewTCB->tcb_lock);
  2473. INITQ(&NewTCB->tcb_timerwheelq);
  2474. NewTCB->tcb_timerslot = DUMMY_SLOT;
  2475. NewTCB->tcb_timertime = 0;
  2476. NewTCB->tcb_timertype = NO_TIMER;
  2477. }
  2478. return NewTCB;
  2479. }
  2480. //* AllocSynTCB - Allocate a SYNTCB.
  2481. //
  2482. // Called whenever we need to allocate a synTCB. We try to pull one off the
  2483. // free list, or allocate one if we need one. We then initialize it, etc.
  2484. //
  2485. // Input: Nothing.
  2486. //
  2487. // Returns: Pointer to the new SYNTCB, or NULL if we couldn't get one.
  2488. //
  2489. SYNTCB *
  2490. AllocSynTCB(VOID)
  2491. {
  2492. SYNTCB *SynTCB;
  2493. LOGICAL FromList;
  2494. SynTCB = PplAllocate(SynTcbPool, &FromList);
  2495. if (SynTCB) {
  2496. NdisZeroMemory(SynTCB, sizeof(SYNTCB));
  2497. #if DBG
  2498. SynTCB->syntcb_sig = syntcb_signature;
  2499. #endif
  2500. CTEInitLock(&SynTCB->syntcb_lock);
  2501. }
  2502. return SynTCB;
  2503. }
  2504. //* FreeTCB - Free a TCB.
  2505. //
  2506. // Called whenever we need to free a TCB.
  2507. //
  2508. // Note: This routine may be called with the TCBTableLock held.
  2509. //
  2510. // Input: FreedTCB - TCB to be freed.
  2511. //
  2512. // Returns: Nothing.
  2513. //
  2514. VOID
  2515. FreeTCB(TCB * FreedTCB)
  2516. {
  2517. CTELockHandle Handle;
  2518. CTEStructAssert(FreedTCB, tcb);
  2519. if (FreedTCB->tcb_timerslot != DUMMY_SLOT) {
  2520. CTEGetLock( &FreedTCB->tcb_lock, &Handle);
  2521. // This TCB should not be touched in this stage at all..
  2522. ASSERT( FreedTCB->tcb_timerslot != DUMMY_SLOT );
  2523. // Even if it does, it has to be handled properly..
  2524. if( FreedTCB->tcb_timerslot != DUMMY_SLOT) {
  2525. ASSERT( FreedTCB->tcb_timerslot < TIMER_WHEEL_SIZE );
  2526. RemoveFromTimerWheel( FreedTCB );
  2527. }
  2528. CTEFreeLock(&FreedTCB->tcb_lock, Handle);
  2529. }
  2530. if (FreedTCB->tcb_SackBlock)
  2531. CTEFreeMem(FreedTCB->tcb_SackBlock);
  2532. if (FreedTCB->tcb_SackRcvd) {
  2533. SackListEntry *tmp, *next;
  2534. tmp = FreedTCB->tcb_SackRcvd;
  2535. while (tmp) {
  2536. next = tmp->next;
  2537. CTEFreeMem(tmp);
  2538. tmp = next;
  2539. }
  2540. }
  2541. PplFree(TcbPool, FreedTCB);
  2542. }
  2543. //* FreeSynTCB - Free a TCB.
  2544. //
  2545. // Called whenever we need to free a SynTCB.
  2546. //
  2547. // Note: This routine may be called with the SYNTCBTableLock held.
  2548. //
  2549. // Input: SynTCB - SynTCB to be freed.
  2550. //
  2551. // Returns: Nothing.
  2552. //
  2553. VOID
  2554. FreeSynTCB(SYNTCB * SynTCB)
  2555. {
  2556. CTEStructAssert(SynTCB, syntcb);
  2557. PplFree(SynTcbPool, SynTCB);
  2558. }
  2559. //* FreeTWTCB - Free a TWTCB.
  2560. //
  2561. // Called whenever we need to free a TWTCB.
  2562. //
  2563. // Note: This routine may be called with the TWTCBTableLock held.
  2564. //
  2565. // Input: FreedTCB - TCB to be freed.
  2566. //
  2567. // Returns: Nothing.
  2568. //
  2569. __inline
  2570. void
  2571. FreeTWTCB(TWTCB * FreedTWTCB)
  2572. {
  2573. PplFree(TcpRequestPool, FreedTWTCB);
  2574. }
  2575. uint
  2576. GetTCBInfo(PTCP_FINDTCB_RESPONSE TCBInfo, IPAddr Dest, IPAddr Src,
  2577. ushort DestPort, ushort SrcPort)
  2578. {
  2579. TCB *FoundTCB;
  2580. CTELockHandle Handle, TCBHandle, TwHandle;
  2581. BOOLEAN timedwait = FALSE;
  2582. uint Index, Partition;
  2583. FoundTCB = FindTCB(Src, Dest, DestPort, SrcPort, &Handle, FALSE, &Index);
  2584. Partition = GET_PARTITION(Index);
  2585. if (FoundTCB == NULL) {
  2586. CTEGetLock(&pTWTCBTableLock[Partition], &TwHandle);
  2587. (TWTCB *) FoundTCB = FindTCBTW(Src, Dest, DestPort, SrcPort, Index);
  2588. if (!FoundTCB) {
  2589. CTEFreeLock(&pTWTCBTableLock[Partition], TwHandle);
  2590. return STATUS_NOT_FOUND;
  2591. } else {
  2592. timedwait = TRUE;
  2593. }
  2594. }
  2595. // okay we now have tcb locked.
  2596. // copy the fileds
  2597. TCBInfo->tcb_addr = (ULONG_PTR) FoundTCB;
  2598. if (!timedwait) {
  2599. TCBInfo->tcb_senduna = FoundTCB->tcb_senduna;
  2600. TCBInfo->tcb_sendnext = FoundTCB->tcb_sendnext;
  2601. TCBInfo->tcb_sendmax = FoundTCB->tcb_sendmax;
  2602. TCBInfo->tcb_sendwin = FoundTCB->tcb_sendwin;
  2603. TCBInfo->tcb_unacked = FoundTCB->tcb_unacked;
  2604. TCBInfo->tcb_maxwin = FoundTCB->tcb_maxwin;
  2605. TCBInfo->tcb_cwin = FoundTCB->tcb_cwin;
  2606. TCBInfo->tcb_mss = FoundTCB->tcb_mss;
  2607. TCBInfo->tcb_rtt = FoundTCB->tcb_rtt;
  2608. TCBInfo->tcb_smrtt = FoundTCB->tcb_smrtt;
  2609. TCBInfo->tcb_rexmitcnt = FoundTCB->tcb_rexmitcnt;
  2610. TCBInfo->tcb_rexmittimer = 0; // FoundTCB->tcb_rexmittimer;
  2611. TCBInfo->tcb_rexmit = FoundTCB->tcb_rexmit;
  2612. TCBInfo->tcb_retrans = TStats.ts_retranssegs;
  2613. TCBInfo->tcb_state = FoundTCB->tcb_state;
  2614. CTEFreeLock(&FoundTCB->tcb_lock, Handle);
  2615. } else {
  2616. //TCBInfo->tcb_state = ((TWTCB *)FoundTCB)->twtcb_state;
  2617. TCBInfo->tcb_state = TCB_TIME_WAIT;
  2618. CTEFreeLock(&pTWTCBTableLock[Partition], TwHandle);
  2619. }
  2620. return STATUS_SUCCESS;
  2621. }
  2622. #if REFERENCE_DEBUG
  2623. uint
  2624. TcpReferenceTCB(
  2625. IN TCB *RefTCB,
  2626. IN uchar *File,
  2627. IN uint Line
  2628. )
  2629. /*++
  2630. Routine Description:
  2631. Increases the reference count of a TCB and records a history of who
  2632. made the call to reference.
  2633. Arguments:
  2634. RefTCB - The TCB to reference.
  2635. File - The filename containing the calling fcn (output of the __FILE__ macro).
  2636. Line - The line number of the call to this fcn. (output of the __LINE__ macro).
  2637. Return Value:
  2638. The new reference count.
  2639. --*/
  2640. {
  2641. void *CallersCaller;
  2642. TCP_REFERENCE_HISTORY *RefHistory;
  2643. RefHistory = &RefTCB->tcb_refhistory[RefTCB->tcb_refhistory_index];
  2644. RefHistory->File = File;
  2645. RefHistory->Line = Line;
  2646. RtlGetCallersAddress(&RefHistory->Caller, &CallersCaller);
  2647. RefHistory->Count = ++RefTCB->tcb_refcnt;
  2648. RefTCB->tcb_refhistory_index = ++RefTCB->tcb_refhistory_index % MAX_REFERENCE_HISTORY;
  2649. return RefTCB->tcb_refcnt;
  2650. }
  2651. uint
  2652. TcpDereferenceTCB(
  2653. IN TCB *DerefTCB,
  2654. IN uchar *File,
  2655. IN uint Line
  2656. )
  2657. /*++
  2658. Routine Description:
  2659. Decreases the reference count of a TCB and records a history of who
  2660. made the call to dereference.
  2661. Arguments:
  2662. DerefTCB - The TCB to dereference.
  2663. File - The filename containing the calling fcn (output of the __FILE__ macro).
  2664. Line - The line number of the call to this fcn. (output of the __LINE__ macro).
  2665. Return Value:
  2666. The new reference count.
  2667. --*/
  2668. {
  2669. void *Caller;
  2670. TCP_REFERENCE_HISTORY *RefHistory;
  2671. RefHistory = &DerefTCB->tcb_refhistory[DerefTCB->tcb_refhistory_index];
  2672. RefHistory->File = File;
  2673. RefHistory->Line = Line;
  2674. // Because Dereference is usually called from DerefTCB, we are more
  2675. // interested in who called DerefTCB. So for dereference, we
  2676. // store the caller's caller in our history. We still retain a history
  2677. // of the actually call to this fcn via the file and line fields, so
  2678. // we are covered if the call did not come from DerefTCB.
  2679. //
  2680. RtlGetCallersAddress(&Caller, &RefHistory->Caller);
  2681. RefHistory->Count = --DerefTCB->tcb_refcnt;
  2682. DerefTCB->tcb_refhistory_index = ++DerefTCB->tcb_refhistory_index % MAX_REFERENCE_HISTORY;
  2683. return DerefTCB->tcb_refcnt;
  2684. }
  2685. #endif // REFERENCE_DEBUG
  2686. #pragma BEGIN_INIT
  2687. //* InitTCB - Initialize our TCB code.
  2688. //
  2689. // Called during init time to initialize our TCB code. We initialize
  2690. // the TCB table, etc, then return.
  2691. //
  2692. // Input: Nothing.
  2693. //
  2694. // Returns: TRUE if we did initialize, false if we didn't.
  2695. //
  2696. int
  2697. InitTCB(void)
  2698. {
  2699. uint i;
  2700. for (i = 0; i < TCB_TABLE_SIZE; i++)
  2701. TCBTable[i] = NULL;
  2702. CTEInitLock(&PendingFreeLock.Lock);
  2703. systemtime = KeQueryInterruptTime();
  2704. #ifdef TIMER_TEST
  2705. TCPTime = 0xfffff000;
  2706. #else
  2707. TCPTime = 0;
  2708. #endif
  2709. TCBWalkCount = 0;
  2710. DeadmanTicks = NUM_DEADMAN_TIME;
  2711. #if MILLEN
  2712. Time_Proc = 1;
  2713. PerTimerSize = TCB_TABLE_SIZE;
  2714. #else // MILLEN
  2715. Time_Proc = KeNumberProcessors;
  2716. PerTimerSize = (TCB_TABLE_SIZE + Time_Proc) / Time_Proc;
  2717. #endif // !MILLEN
  2718. for (i = 0; i < Time_Proc; i++) {
  2719. CTEInitTimerEx(&TCBTimer[i]);
  2720. #if !MILLEN
  2721. KeSetTargetProcessorDpc(&(TCBTimer[i].t_dpc), (CCHAR) i);
  2722. #endif // !MILLEN
  2723. CTEStartTimerEx(&TCBTimer[i], MS_PER_TICK , TCBTimeout, NULL);
  2724. }
  2725. TcbPool = PplCreatePool(NULL, NULL, 0, sizeof(TCB), 'TPCT', 0);
  2726. if (!TcbPool)
  2727. {
  2728. return FALSE;
  2729. }
  2730. SynTcbPool = PplCreatePool(NULL, NULL, 0, sizeof(SYNTCB), 'YPCT', 0);
  2731. if (!SynTcbPool)
  2732. {
  2733. PplDestroyPool(TcbPool);
  2734. return FALSE;
  2735. }
  2736. return TRUE;
  2737. }
  2738. //* UnInitTCB - UnInitialize our TCB code.
  2739. //
  2740. // Called during init time if we're going to fail the init. We don't actually
  2741. // do anything here.
  2742. //
  2743. // Input: Nothing.
  2744. //
  2745. // Returns: Nothing.
  2746. //
  2747. void
  2748. UnInitTCB(void)
  2749. {
  2750. uint i;
  2751. for (i = 0; i < Time_Proc; i++) {
  2752. CTEStopTimer(&TCBTimer[i]);
  2753. }
  2754. }
  2755. #pragma END_INIT