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.

1601 lines
51 KiB

  1. // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
  2. //
  3. // Copyright (c) 1985-2000 Microsoft Corporation
  4. //
  5. // This file is part of the Microsoft Research IPv6 Network Protocol Stack.
  6. // You should have received a copy of the Microsoft End-User License Agreement
  7. // for this software along with this release; see the file "license.txt".
  8. // If not, please see http://www.research.microsoft.com/msripv6/license.htm,
  9. // or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
  10. //
  11. // Abstract:
  12. //
  13. // Code for TCP Control Block management.
  14. //
  15. #include "oscfg.h"
  16. #include "ndis.h"
  17. #include "ip6imp.h"
  18. #include "ip6def.h"
  19. #include "tdi.h"
  20. #include "tdint.h"
  21. #include "tdistat.h"
  22. #include "queue.h"
  23. #include "transprt.h"
  24. #include "tcp.h"
  25. #include "tcb.h"
  26. #include "tcpconn.h"
  27. #include "tcpsend.h"
  28. #include "tcprcv.h"
  29. #include "info.h"
  30. #include "tcpcfg.h"
  31. #include "tcpdeliv.h"
  32. #include "route.h"
  33. KSPIN_LOCK TCBTableLock;
  34. uint TCPTime;
  35. uint TCBWalkCount;
  36. TCB **TCBTable;
  37. TCB *LastTCB;
  38. TCB *PendingFreeList;
  39. SLIST_HEADER FreeTCBList;
  40. KSPIN_LOCK FreeTCBListLock; // Lock to protect TCB free list.
  41. extern KSPIN_LOCK AddrObjTableLock;
  42. extern SeqNum ISNMonotonicPortion;
  43. extern int ISNCredits;
  44. extern int ISNMaxCredits;
  45. extern uint GetDeltaTime();
  46. uint CurrentTCBs = 0;
  47. uint FreeTCBs = 0;
  48. uint MaxTCBs = 0xffffffff;
  49. #define MAX_FREE_TCBS 1000
  50. #define NUM_DEADMAN_TICKS MS_TO_TICKS(1000)
  51. uint MaxFreeTCBs = MAX_FREE_TCBS;
  52. uint DeadmanTicks;
  53. KTIMER TCBTimer;
  54. KDPC TCBTimeoutDpc;
  55. //
  56. // All of the init code can be discarded.
  57. //
  58. #ifdef ALLOC_PRAGMA
  59. int InitTCB(void);
  60. #pragma alloc_text(INIT, InitTCB)
  61. #endif // ALLOC_PRAGMA
  62. //* ReadNextTCB - Read the next TCB in the table.
  63. //
  64. // Called to read the next TCB in the table. The needed information
  65. // is derived from the incoming context, which is assumed to be valid.
  66. // We'll copy the information, and then update the context value with
  67. // the next TCB to be read.
  68. //
  69. uint // Returns: TRUE if more data is available to be read, FALSE is not.
  70. ReadNextTCB(
  71. void *Context, // Pointer to a TCPConnContext.
  72. void *Buffer) // Pointer to a TCPConnTableEntry structure.
  73. {
  74. TCPConnContext *TCContext = (TCPConnContext *)Context;
  75. TCP6ConnTableEntry *TCEntry = (TCP6ConnTableEntry *)Buffer;
  76. KIRQL OldIrql;
  77. TCB *CurrentTCB;
  78. uint i;
  79. CurrentTCB = TCContext->tcc_tcb;
  80. CHECK_STRUCT(CurrentTCB, tcb);
  81. KeAcquireSpinLock(&CurrentTCB->tcb_lock, &OldIrql);
  82. if (CLOSING(CurrentTCB))
  83. TCEntry->tct_state = TCP_CONN_CLOSED;
  84. else
  85. TCEntry->tct_state = (uint)CurrentTCB->tcb_state + TCB_STATE_DELTA;
  86. TCEntry->tct_localaddr = CurrentTCB->tcb_saddr;
  87. TCEntry->tct_localscopeid = CurrentTCB->tcb_sscope_id;
  88. TCEntry->tct_localport = CurrentTCB->tcb_sport;
  89. TCEntry->tct_remoteaddr = CurrentTCB->tcb_daddr;
  90. TCEntry->tct_remotescopeid = CurrentTCB->tcb_dscope_id;
  91. TCEntry->tct_remoteport = CurrentTCB->tcb_dport;
  92. TCEntry->tct_owningpid = (CurrentTCB->tcb_conn) ?
  93. CurrentTCB->tcb_conn->tc_owningpid : 0;
  94. KeReleaseSpinLock(&CurrentTCB->tcb_lock, OldIrql);
  95. // We've filled it in. Now update the context.
  96. if (CurrentTCB->tcb_next != NULL) {
  97. TCContext->tcc_tcb = CurrentTCB->tcb_next;
  98. return TRUE;
  99. } else {
  100. // NextTCB is NULL. Loop through the TCBTable looking for a new one.
  101. i = TCContext->tcc_index + 1;
  102. while (i < TcbTableSize) {
  103. if (TCBTable[i] != NULL) {
  104. TCContext->tcc_tcb = TCBTable[i];
  105. TCContext->tcc_index = i;
  106. return TRUE;
  107. break;
  108. } else
  109. i++;
  110. }
  111. TCContext->tcc_index = 0;
  112. TCContext->tcc_tcb = NULL;
  113. return FALSE;
  114. }
  115. }
  116. //* ValidateTCBContext - Validate the context for reading a TCB table.
  117. //
  118. // Called to start reading the TCB table sequentially. We take in
  119. // a context, and if the values are 0 we return information about the
  120. // first TCB in the table. Otherwise we make sure that the context value
  121. // is valid, and if it is we return TRUE.
  122. // We assume the caller holds the TCB table lock.
  123. //
  124. // Upon return, *Valid is set to true if the context is valid.
  125. //
  126. uint // Returns: TRUE if data in table, FALSE if not.
  127. ValidateTCBContext(
  128. void *Context, // Pointer to a TCPConnContext.
  129. uint *Valid) // Where to return infoformation about context being valid.
  130. {
  131. TCPConnContext *TCContext = (TCPConnContext *)Context;
  132. uint i;
  133. TCB *TargetTCB;
  134. TCB *CurrentTCB;
  135. i = TCContext->tcc_index;
  136. TargetTCB = TCContext->tcc_tcb;
  137. //
  138. // If the context values are 0 and NULL, we're starting from the beginning.
  139. //
  140. if (i == 0 && TargetTCB == NULL) {
  141. *Valid = TRUE;
  142. do {
  143. if ((CurrentTCB = TCBTable[i]) != NULL) {
  144. CHECK_STRUCT(CurrentTCB, tcb);
  145. break;
  146. }
  147. i++;
  148. } while (i < TcbTableSize);
  149. if (CurrentTCB != NULL) {
  150. TCContext->tcc_index = i;
  151. TCContext->tcc_tcb = CurrentTCB;
  152. return TRUE;
  153. } else
  154. return FALSE;
  155. } else {
  156. //
  157. // We've been given a context. We just need to make sure that it's
  158. // valid.
  159. //
  160. if (i < TcbTableSize) {
  161. CurrentTCB = TCBTable[i];
  162. while (CurrentTCB != NULL) {
  163. if (CurrentTCB == TargetTCB) {
  164. *Valid = TRUE;
  165. return TRUE;
  166. break;
  167. } else {
  168. CurrentTCB = CurrentTCB->tcb_next;
  169. }
  170. }
  171. }
  172. // If we get here, we didn't find the matching TCB.
  173. *Valid = FALSE;
  174. return FALSE;
  175. }
  176. }
  177. //* FindNextTCB - Find the next TCB in a particular chain.
  178. //
  179. // This routine is used to find the 'next' TCB in a chain. Since we keep
  180. // the chain in ascending order, we look for a TCB which is greater than
  181. // the input TCB. When we find one, we return it.
  182. //
  183. // This routine is mostly used when someone is walking the table and needs
  184. // to free the various locks to perform some action.
  185. //
  186. TCB * // Returns: Pointer to the next TCB, or NULL.
  187. FindNextTCB(
  188. uint Index, // Index into TCBTable.
  189. TCB *Current) // Current TCB - we find the one after this one.
  190. {
  191. TCB *Next;
  192. ASSERT(Index < TcbTableSize);
  193. Next = TCBTable[Index];
  194. while (Next != NULL && (Next <= Current))
  195. Next = Next->tcb_next;
  196. return Next;
  197. }
  198. //* ResetSendNext - Set the sendnext value of a TCB.
  199. //
  200. // Called to set the send next value of a TCB. We do that, and adjust all
  201. // pointers to the appropriate places. We assume the caller holds the lock
  202. // on the TCB.
  203. //
  204. void // Returns: Nothing.
  205. ResetSendNext(
  206. TCB *SeqTCB, // TCB to be updated.
  207. SeqNum NewSeq) // Sequence number to set.
  208. {
  209. TCPSendReq *SendReq;
  210. uint AmtForward;
  211. Queue *CurQ;
  212. PNDIS_BUFFER Buffer;
  213. uint Offset;
  214. CHECK_STRUCT(SeqTCB, tcb);
  215. ASSERT(SEQ_GTE(NewSeq, SeqTCB->tcb_senduna));
  216. //
  217. // The new seq must be less than send max, or NewSeq, senduna, sendnext,
  218. // and sendmax must all be equal (the latter case happens when we're
  219. // called exiting TIME_WAIT, or possibly when we're retransmitting
  220. // during a flow controlled situation).
  221. //
  222. ASSERT(SEQ_LT(NewSeq, SeqTCB->tcb_sendmax) ||
  223. (SEQ_EQ(SeqTCB->tcb_senduna, SeqTCB->tcb_sendnext) &&
  224. SEQ_EQ(SeqTCB->tcb_senduna, SeqTCB->tcb_sendmax) &&
  225. SEQ_EQ(SeqTCB->tcb_senduna, NewSeq)));
  226. AmtForward = NewSeq - SeqTCB->tcb_senduna;
  227. if ((AmtForward == 1) && (SeqTCB->tcb_flags & FIN_SENT) &&
  228. !((SeqTCB->tcb_sendnext - SeqTCB->tcb_senduna) > 1) &&
  229. (SEQ_EQ(SeqTCB->tcb_sendnext,SeqTCB->tcb_sendmax))) {
  230. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_RARE,
  231. "tcpip6: trying to set sendnext for FIN_SENT\n"));
  232. SeqTCB->tcb_sendnext = NewSeq;
  233. SeqTCB->tcb_flags &= ~FIN_OUTSTANDING;
  234. return;
  235. }
  236. if((SeqTCB->tcb_flags & FIN_SENT) &&
  237. (SEQ_EQ(SeqTCB->tcb_sendnext,SeqTCB->tcb_sendmax)) &&
  238. ((SeqTCB->tcb_sendnext - NewSeq) == 1) ){
  239. //
  240. // There is only FIN that is left beyond sendnext.
  241. //
  242. SeqTCB->tcb_sendnext = NewSeq;
  243. SeqTCB->tcb_flags &= ~FIN_OUTSTANDING;
  244. return;
  245. }
  246. SeqTCB->tcb_sendnext = NewSeq;
  247. //
  248. // If we're backing off send next, turn off the FIN_OUTSTANDING flag to
  249. // maintain a consistent state.
  250. //
  251. if (!SEQ_EQ(NewSeq, SeqTCB->tcb_sendmax))
  252. SeqTCB->tcb_flags &= ~FIN_OUTSTANDING;
  253. if (SYNC_STATE(SeqTCB->tcb_state) && SeqTCB->tcb_state != TCB_TIME_WAIT) {
  254. //
  255. // In these states we need to update the send queue.
  256. //
  257. if (!EMPTYQ(&SeqTCB->tcb_sendq)) {
  258. CurQ = QHEAD(&SeqTCB->tcb_sendq);
  259. SendReq = (TCPSendReq *)CONTAINING_RECORD(CurQ, TCPReq, tr_q);
  260. //
  261. // SendReq points to the first send request on the send queue.
  262. // Move forward AmtForward bytes on the send queue, and set the
  263. // TCB pointers to the resultant SendReq, buffer, offset, size.
  264. //
  265. while (AmtForward) {
  266. CHECK_STRUCT(SendReq, tsr);
  267. if (AmtForward >= SendReq->tsr_unasize) {
  268. //
  269. // We're going to move completely past this one. Subtract
  270. // his size from AmtForward and get the next one.
  271. //
  272. AmtForward -= SendReq->tsr_unasize;
  273. CurQ = QNEXT(CurQ);
  274. ASSERT(CurQ != QEND(&SeqTCB->tcb_sendq));
  275. SendReq = (TCPSendReq *)CONTAINING_RECORD(CurQ, TCPReq,
  276. tr_q);
  277. } else {
  278. //
  279. // We're pointing at the proper send req now. Break out
  280. // of this loop and save the information. Further down
  281. // we'll need to walk down the buffer chain to find
  282. // the proper buffer and offset.
  283. //
  284. break;
  285. }
  286. }
  287. //
  288. // We're pointing at the proper send req now. We need to go down
  289. // the buffer chain here to find the proper buffer and offset.
  290. //
  291. SeqTCB->tcb_cursend = SendReq;
  292. SeqTCB->tcb_sendsize = SendReq->tsr_unasize - AmtForward;
  293. Buffer = SendReq->tsr_buffer;
  294. Offset = SendReq->tsr_offset;
  295. while (AmtForward) {
  296. // Walk the buffer chain.
  297. uint Length;
  298. //
  299. // We'll need the length of this buffer. Use the portable
  300. // macro to get it. We have to adjust the length by the offset
  301. // into it, also.
  302. //
  303. ASSERT((Offset < NdisBufferLength(Buffer)) ||
  304. ((Offset == 0) && (NdisBufferLength(Buffer) == 0)));
  305. Length = NdisBufferLength(Buffer) - Offset;
  306. if (AmtForward >= Length) {
  307. //
  308. // We're moving past this one. Skip over him, and 0 the
  309. // Offset we're keeping.
  310. //
  311. AmtForward -= Length;
  312. Offset = 0;
  313. Buffer = NDIS_BUFFER_LINKAGE(Buffer);
  314. ASSERT(Buffer != NULL);
  315. } else
  316. break;
  317. }
  318. //
  319. // Save the buffer we found, and the offset into that buffer.
  320. //
  321. SeqTCB->tcb_sendbuf = Buffer;
  322. SeqTCB->tcb_sendofs = Offset + AmtForward;
  323. } else {
  324. ASSERT(SeqTCB->tcb_cursend == NULL);
  325. ASSERT(AmtForward == 0);
  326. }
  327. }
  328. CheckTCBSends(SeqTCB);
  329. }
  330. //* TCPAbortAndIndicateDisconnect
  331. //
  332. // Abortively closes a TCB and issues a disconnect indication up the the
  333. // transport user. This function is used to support cancellation of
  334. // TDI send and receive requests.
  335. //
  336. void // Returns: Nothing.
  337. TCPAbortAndIndicateDisconnect(
  338. CONNECTION_CONTEXT ConnectionContext // Connection ID to find a TCB for.
  339. )
  340. {
  341. TCB *AbortTCB;
  342. KIRQL Irql0, Irql1; // One per lock nesting level.
  343. TCPConn *Conn;
  344. Conn = GetConnFromConnID(PtrToUlong(ConnectionContext), &Irql0);
  345. if (Conn != NULL) {
  346. CHECK_STRUCT(Conn, tc);
  347. AbortTCB = Conn->tc_tcb;
  348. if (AbortTCB != NULL) {
  349. //
  350. // If it's CLOSING or CLOSED, skip it.
  351. //
  352. if ((AbortTCB->tcb_state != TCB_CLOSED) && !CLOSING(AbortTCB)) {
  353. CHECK_STRUCT(AbortTCB, tcb);
  354. KeAcquireSpinLock(&AbortTCB->tcb_lock, &Irql1);
  355. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql1);
  356. if (AbortTCB->tcb_state == TCB_CLOSED || CLOSING(AbortTCB)) {
  357. KeReleaseSpinLock(&AbortTCB->tcb_lock, Irql0);
  358. return;
  359. }
  360. AbortTCB->tcb_refcnt++;
  361. AbortTCB->tcb_flags |= NEED_RST; // send a reset if connected
  362. TryToCloseTCB(AbortTCB, TCB_CLOSE_ABORTED, Irql0);
  363. RemoveTCBFromConn(AbortTCB);
  364. IF_TCPDBG(TCP_DEBUG_IRP) {
  365. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_TCPDBG,
  366. "TCPAbortAndIndicateDisconnect, indicating discon\n"));
  367. }
  368. NotifyOfDisc(AbortTCB, TDI_CONNECTION_ABORTED);
  369. KeAcquireSpinLock(&AbortTCB->tcb_lock, &Irql0);
  370. DerefTCB(AbortTCB, Irql0);
  371. // TCB lock freed by DerefTCB.
  372. return;
  373. } else
  374. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql0);
  375. } else
  376. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql0);
  377. }
  378. }
  379. //* TCBTimeout - Do timeout events on TCBs.
  380. //
  381. // Called every MS_PER_TICKS milliseconds to do timeout processing on TCBs.
  382. // We run throught the TCB table, decrementing timers. If one goes to zero
  383. // we look at its state to decide what to do.
  384. //
  385. void // Returns: Nothing.
  386. TCBTimeout(
  387. PKDPC MyDpcObject, // The DPC object describing this routine.
  388. void *Context, // The argument we asked to be called with.
  389. void *Unused1,
  390. void *Unused2)
  391. {
  392. uint i;
  393. TCB *CurrentTCB;
  394. uint Delayed = FALSE;
  395. uint CallRcvComplete;
  396. int Delta;
  397. UNREFERENCED_PARAMETER(Context);
  398. UNREFERENCED_PARAMETER(Unused1);
  399. UNREFERENCED_PARAMETER(Unused2);
  400. //
  401. // Update our free running counter.
  402. //
  403. TCPTime++;
  404. ExInterlockedAddUlong(&TCBWalkCount, 1, &TCBTableLock);
  405. //
  406. // Set credits so that some more connections can increment the
  407. // Initial Sequence Number, during the next 100 ms.
  408. //
  409. InterlockedExchange(&ISNCredits, ISNMaxCredits);
  410. Delta = GetDeltaTime();
  411. //
  412. // The increment made is (256)*(Time in milliseconds). This is really close
  413. // to 25000 increment made originally every 100 ms.
  414. //
  415. if (Delta > 0) {
  416. Delta *= 0x100;
  417. InterlockedExchangeAdd(&ISNMonotonicPortion, Delta);
  418. }
  419. //
  420. // Loop through each bucket in the table, going down the chain of
  421. // TCBs on the bucket.
  422. //
  423. for (i = 0; i < TcbTableSize; i++) {
  424. TCB *TempTCB;
  425. uint maxRexmitCnt;
  426. CurrentTCB = TCBTable[i];
  427. while (CurrentTCB != NULL) {
  428. CHECK_STRUCT(CurrentTCB, tcb);
  429. KeAcquireSpinLockAtDpcLevel(&CurrentTCB->tcb_lock);
  430. //
  431. // If it's CLOSING or CLOSED, skip it.
  432. //
  433. if (CurrentTCB->tcb_state == TCB_CLOSED || CLOSING(CurrentTCB)) {
  434. TempTCB = CurrentTCB->tcb_next;
  435. KeReleaseSpinLockFromDpcLevel(&CurrentTCB->tcb_lock);
  436. CurrentTCB = TempTCB;
  437. continue;
  438. }
  439. CheckTCBSends(CurrentTCB);
  440. CheckTCBRcv(CurrentTCB);
  441. //
  442. // First check the rexmit timer.
  443. //
  444. if (TCB_TIMER_RUNNING(CurrentTCB->tcb_rexmittimer)) {
  445. //
  446. // The timer is running.
  447. //
  448. if (--(CurrentTCB->tcb_rexmittimer) == 0) {
  449. //
  450. // And it's fired. Figure out what to do now.
  451. //
  452. if (CurrentTCB->tcb_state == TCB_SYN_SENT) {
  453. maxRexmitCnt = MaxConnectRexmitCount;
  454. } else {
  455. maxRexmitCnt = MaxDataRexmitCount;
  456. }
  457. //
  458. // If we've run out of retransmits or we're in FIN_WAIT2,
  459. // time out.
  460. //
  461. CurrentTCB->tcb_rexmitcnt++;
  462. if (CurrentTCB->tcb_rexmitcnt > maxRexmitCnt) {
  463. ASSERT(CurrentTCB->tcb_state > TCB_LISTEN);
  464. //
  465. // This connection has timed out. Abort it. First
  466. // reference him, then mark as closed, notify the
  467. // user, and finally dereference and close him.
  468. //
  469. TimeoutTCB:
  470. CurrentTCB->tcb_refcnt++;
  471. TryToCloseTCB(CurrentTCB, TCB_CLOSE_TIMEOUT,
  472. DISPATCH_LEVEL);
  473. RemoveTCBFromConn(CurrentTCB);
  474. NotifyOfDisc(CurrentTCB, TDI_TIMED_OUT);
  475. KeAcquireSpinLockAtDpcLevel(&CurrentTCB->tcb_lock);
  476. DerefTCB(CurrentTCB, DISPATCH_LEVEL);
  477. CurrentTCB = FindNextTCB(i, CurrentTCB);
  478. continue;
  479. }
  480. //
  481. // Stop round trip time measurement.
  482. //
  483. CurrentTCB->tcb_rtt = 0;
  484. //
  485. // Figure out what our new retransmit timeout should be.
  486. // We double it each time we get a retransmit, and reset it
  487. // back when we get an ack for new data.
  488. //
  489. CurrentTCB->tcb_rexmit = MIN(CurrentTCB->tcb_rexmit << 1,
  490. MAX_REXMIT_TO);
  491. //
  492. // Reset the sequence number, and reset the congestion
  493. // window.
  494. //
  495. ResetSendNext(CurrentTCB, CurrentTCB->tcb_senduna);
  496. if (!(CurrentTCB->tcb_flags & FLOW_CNTLD)) {
  497. //
  498. // Don't let the slow start threshold go below 2
  499. // segments.
  500. //
  501. CurrentTCB->tcb_ssthresh =
  502. MAX(MIN(CurrentTCB->tcb_cwin,
  503. CurrentTCB->tcb_sendwin) / 2,
  504. (uint) CurrentTCB->tcb_mss * 2);
  505. CurrentTCB->tcb_cwin = CurrentTCB->tcb_mss;
  506. } else {
  507. //
  508. // We're probing, and the probe timer has fired. We
  509. // need to set the FORCE_OUTPUT bit here.
  510. //
  511. CurrentTCB->tcb_flags |= FORCE_OUTPUT;
  512. }
  513. //
  514. // See if we need to probe for a PMTU black hole.
  515. //
  516. if (PMTUBHDetect &&
  517. CurrentTCB->tcb_rexmitcnt == ((maxRexmitCnt+1)/2)) {
  518. //
  519. // We may need to probe for a black hole. If we're
  520. // doing MTU discovery on this connection and we
  521. // are retransmitting more than a minimum segment
  522. // size, or we are probing for a PMTU BH already, turn
  523. // off the DF flag and bump the probe count. If the
  524. // probe count gets too big we'll assume it's not
  525. // a PMTU black hole, and we'll try to switch the
  526. // router.
  527. //
  528. if ((CurrentTCB->tcb_flags & PMTU_BH_PROBE) ||
  529. (CurrentTCB->tcb_sendmax - CurrentTCB->tcb_senduna
  530. > 8)) {
  531. //
  532. // May need to probe. If we haven't exceeded our
  533. // probe count, do so, otherwise restore those
  534. // values.
  535. //
  536. if (CurrentTCB->tcb_bhprobecnt++ < 2) {
  537. //
  538. // We're going to probe. Turn on the flag,
  539. // drop the MSS, and turn off the don't
  540. // fragment bit.
  541. //
  542. if (!(CurrentTCB->tcb_flags & PMTU_BH_PROBE)) {
  543. CurrentTCB->tcb_flags |= PMTU_BH_PROBE;
  544. CurrentTCB->tcb_slowcount++;
  545. CurrentTCB->tcb_fastchk |= TCP_FLAG_SLOW;
  546. //
  547. // Drop the MSS to the minimum.
  548. //
  549. CurrentTCB->tcb_mss =
  550. MIN(DEFAULT_MSS,
  551. CurrentTCB->tcb_remmss);
  552. ASSERT(CurrentTCB->tcb_mss > 0);
  553. CurrentTCB->tcb_cwin = CurrentTCB->tcb_mss;
  554. }
  555. //
  556. // Drop the rexmit count so we come here again,
  557. // and don't retrigger DeadGWDetect.
  558. //
  559. CurrentTCB->tcb_rexmitcnt--;
  560. } else {
  561. //
  562. // Too many probes. Stop probing, and allow
  563. // fallover to the next gateway.
  564. //
  565. // Currently this code won't do BH probing on
  566. // the 2nd gateway. The MSS will stay at the
  567. // minimum size. This might be a little
  568. // suboptimal, but it's easy to implement for
  569. // the Sept. 95 service pack and will keep
  570. // connections alive if possible.
  571. //
  572. // In the future we should investigate doing
  573. // dead g/w detect on a per-connection basis,
  574. // and then doing PMTU probing for each
  575. // connection.
  576. //
  577. if (CurrentTCB->tcb_flags & PMTU_BH_PROBE) {
  578. CurrentTCB->tcb_flags &= ~PMTU_BH_PROBE;
  579. if (--(CurrentTCB->tcb_slowcount) == 0)
  580. CurrentTCB->tcb_fastchk &=
  581. ~TCP_FLAG_SLOW;
  582. }
  583. CurrentTCB->tcb_bhprobecnt = 0;
  584. }
  585. }
  586. }
  587. //
  588. // Since we're retransmitting, our first-hop router
  589. // may be down. Tell IP we're suspicious if this
  590. // is the first retransmit.
  591. //
  592. if (CurrentTCB->tcb_rexmitcnt == 1 &&
  593. CurrentTCB->tcb_rce != NULL) {
  594. ForwardReachabilityInDoubt(CurrentTCB->tcb_rce);
  595. }
  596. //
  597. // Now handle the various cases.
  598. //
  599. switch (CurrentTCB->tcb_state) {
  600. case TCB_SYN_SENT:
  601. case TCB_SYN_RCVD:
  602. //
  603. // In SYN-SENT or SYN-RCVD we'll need to retransmit
  604. // the SYN.
  605. //
  606. SendSYN(CurrentTCB, DISPATCH_LEVEL);
  607. CurrentTCB = FindNextTCB(i, CurrentTCB);
  608. continue;
  609. case TCB_FIN_WAIT1:
  610. case TCB_CLOSING:
  611. case TCB_LAST_ACK:
  612. //
  613. // The call to ResetSendNext (above) will have
  614. // turned off the FIN_OUTSTANDING flag.
  615. //
  616. CurrentTCB->tcb_flags |= FIN_NEEDED;
  617. case TCB_CLOSE_WAIT:
  618. case TCB_ESTAB:
  619. //
  620. // In this state we have data to retransmit, unless
  621. // the window is zero (in which case we need to
  622. // probe), or we're just sending a FIN.
  623. //
  624. CheckTCBSends(CurrentTCB);
  625. Delayed = TRUE;
  626. DelayAction(CurrentTCB, NEED_OUTPUT);
  627. break;
  628. case TCB_TIME_WAIT:
  629. //
  630. // If it's fired in TIME-WAIT, we're all done and
  631. // can clean up. We'll call TryToCloseTCB even
  632. // though he's already sort of closed. TryToCloseTCB
  633. // will figure this out and do the right thing.
  634. //
  635. TryToCloseTCB(CurrentTCB, TCB_CLOSE_SUCCESS,
  636. DISPATCH_LEVEL);
  637. CurrentTCB = FindNextTCB(i, CurrentTCB);
  638. continue;
  639. default:
  640. break;
  641. }
  642. }
  643. }
  644. //
  645. // Now check the SWS deadlock timer..
  646. //
  647. if (TCB_TIMER_RUNNING(CurrentTCB->tcb_swstimer)) {
  648. //
  649. // The timer is running.
  650. //
  651. if (--(CurrentTCB->tcb_swstimer) == 0) {
  652. //
  653. // And it's fired. Force output now.
  654. //
  655. CurrentTCB->tcb_flags |= FORCE_OUTPUT;
  656. Delayed = TRUE;
  657. DelayAction(CurrentTCB, NEED_OUTPUT);
  658. }
  659. }
  660. //
  661. // Check the push data timer.
  662. //
  663. if (TCB_TIMER_RUNNING(CurrentTCB->tcb_pushtimer)) {
  664. //
  665. // The timer is running. Decrement it.
  666. //
  667. if (--(CurrentTCB->tcb_pushtimer) == 0) {
  668. //
  669. // It's fired.
  670. //
  671. PushData(CurrentTCB);
  672. Delayed = TRUE;
  673. }
  674. }
  675. //
  676. // Check the delayed ack timer.
  677. //
  678. if (TCB_TIMER_RUNNING(CurrentTCB->tcb_delacktimer)) {
  679. //
  680. // The timer is running.
  681. //
  682. if (--(CurrentTCB->tcb_delacktimer) == 0) {
  683. //
  684. // And it's fired. Set up to send an ACK.
  685. //
  686. Delayed = TRUE;
  687. DelayAction(CurrentTCB, NEED_ACK);
  688. }
  689. }
  690. //
  691. // Finally check the keepalive timer.
  692. //
  693. if (CurrentTCB->tcb_state == TCB_ESTAB) {
  694. if ((CurrentTCB->tcb_flags & KEEPALIVE) &&
  695. (CurrentTCB->tcb_conn != NULL)) {
  696. uint Delta;
  697. Delta = TCPTime - CurrentTCB->tcb_alive;
  698. if (Delta > CurrentTCB->tcb_conn->tc_tcbkatime) {
  699. Delta -= CurrentTCB->tcb_conn->tc_tcbkatime;
  700. if (Delta > (CurrentTCB->tcb_kacount * CurrentTCB->tcb_conn->tc_tcbkainterval)) {
  701. if (CurrentTCB->tcb_kacount < MaxDataRexmitCount) {
  702. SendKA(CurrentTCB, DISPATCH_LEVEL);
  703. CurrentTCB = FindNextTCB(i, CurrentTCB);
  704. continue;
  705. } else
  706. goto TimeoutTCB;
  707. }
  708. } else
  709. CurrentTCB->tcb_kacount = 0;
  710. }
  711. }
  712. //
  713. // If this is an active open connection in SYN-SENT or SYN-RCVD,
  714. // or we have a FIN pending, check the connect timer.
  715. //
  716. if (CurrentTCB->tcb_flags &
  717. (ACTIVE_OPEN | FIN_NEEDED | FIN_SENT)) {
  718. TCPConnReq *ConnReq = CurrentTCB->tcb_connreq;
  719. ASSERT(ConnReq != NULL);
  720. if (TCB_TIMER_RUNNING(ConnReq->tcr_timeout)) {
  721. // Timer is running.
  722. if (--(ConnReq->tcr_timeout) == 0) {
  723. // The connection timer has timed out.
  724. TryToCloseTCB(CurrentTCB, TCB_CLOSE_TIMEOUT,
  725. DISPATCH_LEVEL);
  726. CurrentTCB = FindNextTCB(i, CurrentTCB);
  727. continue;
  728. }
  729. }
  730. }
  731. //
  732. // Timer isn't running, or didn't fire.
  733. //
  734. TempTCB = CurrentTCB->tcb_next;
  735. KeReleaseSpinLockFromDpcLevel(&CurrentTCB->tcb_lock);
  736. CurrentTCB = TempTCB;
  737. }
  738. }
  739. //
  740. // See if we need to call receive complete as part of deadman processing.
  741. // We do this now because we want to restart the timer before calling
  742. // receive complete, in case that takes a while. If we make this check
  743. // while the timer is running we'd have to lock, so we'll check and save
  744. // the result now before we start the timer.
  745. //
  746. if (DeadmanTicks == TCPTime) {
  747. CallRcvComplete = TRUE;
  748. DeadmanTicks += NUM_DEADMAN_TICKS;
  749. } else
  750. CallRcvComplete = FALSE;
  751. //
  752. // Now check the pending free list. If it's not null, walk down the
  753. // list and decrement the walk count. If the count goes below 2, pull it
  754. // from the list. If the count goes to 0, free the TCB. If the count is
  755. // at 1 it'll be freed by whoever called RemoveTCB.
  756. //
  757. KeAcquireSpinLockAtDpcLevel(&TCBTableLock);
  758. if (PendingFreeList != NULL) {
  759. TCB *PrevTCB;
  760. PrevTCB = CONTAINING_RECORD(&PendingFreeList, TCB, tcb_delayq.q_next);
  761. do {
  762. CurrentTCB = (TCB *)PrevTCB->tcb_delayq.q_next;
  763. CHECK_STRUCT(CurrentTCB, tcb);
  764. CurrentTCB->tcb_walkcount--;
  765. if (CurrentTCB->tcb_walkcount <= 1) {
  766. *(TCB **)&PrevTCB->tcb_delayq.q_next =
  767. (TCB *)CurrentTCB->tcb_delayq.q_next;
  768. if (CurrentTCB->tcb_walkcount == 0) {
  769. FreeTCB(CurrentTCB);
  770. }
  771. } else {
  772. PrevTCB = CurrentTCB;
  773. }
  774. } while (PrevTCB->tcb_delayq.q_next != NULL);
  775. }
  776. TCBWalkCount--;
  777. KeReleaseSpinLockFromDpcLevel(&TCBTableLock);
  778. //
  779. // Do AddrCheckTable cleanup.
  780. //
  781. if (AddrCheckTable) {
  782. TCPAddrCheckElement *Temp;
  783. KeAcquireSpinLockAtDpcLevel(&AddrObjTableLock);
  784. for (Temp = AddrCheckTable;Temp < AddrCheckTable + NTWMaxConnectCount;
  785. Temp++) {
  786. if (Temp->TickCount > 0) {
  787. if ((--(Temp->TickCount)) == 0) {
  788. Temp->SourceAddress = UnspecifiedAddr;
  789. }
  790. }
  791. }
  792. KeReleaseSpinLockFromDpcLevel(&AddrObjTableLock);
  793. }
  794. if (Delayed)
  795. ProcessTCBDelayQ();
  796. if (CallRcvComplete)
  797. TCPRcvComplete();
  798. }
  799. #if 0 // We update PMTU lazily to avoid exactly this.
  800. //* SetTCBMTU - Set TCB MTU values.
  801. //
  802. // A function called by TCBWalk to set the MTU values of all TCBs using
  803. // a particular path.
  804. //
  805. uint // Returns: TRUE.
  806. SetTCBMTU(
  807. TCB *CheckTCB, // TCB to be checked.
  808. void *DestPtr, // Destination address.
  809. void *SrcPtr, // Source address.
  810. void *MTUPtr) // New MTU.
  811. {
  812. IPv6Addr *DestAddr = (IPv6Addr *)DestPtr;
  813. IPv6Addr *SrcAddr = (IPv6Addr *)SrcPtr;
  814. KIRQL OldIrql;
  815. CHECK_STRUCT(CheckTCB, tcb);
  816. KeAcquireSpinLock(&CheckTCB->tcb_lock, &OldIrql);
  817. if (IP6_ADDR_EQUAL(&CheckTCB->tcb_daddr, DestAddr) &&
  818. IP6_ADDR_EQUAL(&CheckTCB->tcb_saddr, SrcAddr)) {
  819. uint MTU = *(uint *)MTUPtr;
  820. CheckTCB->tcb_mss = (ushort)MIN(MTU, (uint)CheckTCB->tcb_remmss);
  821. ASSERT(CheckTCB->tcb_mss > 0);
  822. //
  823. // Reset the Congestion Window if necessary.
  824. //
  825. if (CheckTCB->tcb_cwin < CheckTCB->tcb_mss) {
  826. CheckTCB->tcb_cwin = CheckTCB->tcb_mss;
  827. //
  828. // Make sure the slow start threshold is at least 2 segments.
  829. //
  830. if (CheckTCB->tcb_ssthresh < ((uint) CheckTCB->tcb_mss*2)) {
  831. CheckTCB->tcb_ssthresh = CheckTCB->tcb_mss * 2;
  832. }
  833. }
  834. }
  835. KeReleaseSpinLock(&CheckTCB->tcb_lock, OldIrql);
  836. return TRUE;
  837. }
  838. #endif
  839. //* DeleteTCBWithSrc - Delete tcbs with a particular src address.
  840. //
  841. // A function called by TCBWalk to delete all TCBs with a particular source
  842. // address.
  843. //
  844. uint // Returns: FALSE if CheckTCB is to be deleted, TRUE otherwise.
  845. DeleteTCBWithSrc(
  846. TCB *CheckTCB, // TCB to be checked.
  847. void *AddrPtr, // Pointer to address.
  848. void *Unused1, // Go figure.
  849. void *Unused3) // What happened to Unused2?
  850. {
  851. IPv6Addr *Addr = (IPv6Addr *)AddrPtr;
  852. CHECK_STRUCT(CheckTCB, tcb);
  853. if (IP6_ADDR_EQUAL(&CheckTCB->tcb_saddr, Addr))
  854. return FALSE;
  855. else
  856. return TRUE;
  857. }
  858. //* TCBWalk - Walk the TCBs in the table, and call a function for each of them.
  859. //
  860. // Called when we need to repetively do something to each TCB in the table.
  861. // We call the specified function with a pointer to the TCB and the input
  862. // context for each TCB in the table. If the function returns FALSE, we
  863. // delete the TCB.
  864. //
  865. void // Returns: Nothing.
  866. TCBWalk(
  867. uint (*CallRtn)(struct TCB *, void *, void *, void *), // Routine to call.
  868. void *Context1, // Context to pass to CallRtn.
  869. void *Context2, // Second context to pass to call routine.
  870. void *Context3) // Third context to pass to call routine.
  871. {
  872. uint i;
  873. TCB *CurTCB;
  874. KIRQL Irql0, Irql1;
  875. //
  876. // Loop through each bucket in the table, going down the chain of
  877. // TCBs on the bucket. For each one call CallRtn.
  878. //
  879. KeAcquireSpinLock(&TCBTableLock, &Irql0);
  880. for (i = 0; i < TcbTableSize; i++) {
  881. CurTCB = TCBTable[i];
  882. //
  883. // Walk down the chain on this bucket.
  884. //
  885. while (CurTCB != NULL) {
  886. if (!(*CallRtn)(CurTCB, Context1, Context2, Context3)) {
  887. //
  888. // Call failed on this one.
  889. // Notify the client and close the TCB.
  890. //
  891. KeAcquireSpinLock(&CurTCB->tcb_lock, &Irql1);
  892. if (!CLOSING(CurTCB)) {
  893. CurTCB->tcb_refcnt++;
  894. KeReleaseSpinLock(&TCBTableLock, Irql1);
  895. TryToCloseTCB(CurTCB, TCB_CLOSE_ABORTED, Irql0);
  896. RemoveTCBFromConn(CurTCB);
  897. if (CurTCB->tcb_state != TCB_TIME_WAIT)
  898. NotifyOfDisc(CurTCB, TDI_CONNECTION_ABORTED);
  899. KeAcquireSpinLock(&CurTCB->tcb_lock, &Irql0);
  900. DerefTCB(CurTCB, Irql0);
  901. KeAcquireSpinLock(&TCBTableLock, &Irql0);
  902. } else
  903. KeReleaseSpinLock(&CurTCB->tcb_lock, Irql1);
  904. CurTCB = FindNextTCB(i, CurTCB);
  905. } else {
  906. CurTCB = CurTCB->tcb_next;
  907. }
  908. }
  909. }
  910. KeReleaseSpinLock(&TCBTableLock, Irql0);
  911. }
  912. //* FindTCB - Find a TCB in the tcb table.
  913. //
  914. // Called when we need to find a TCB in the TCB table. We take a quick
  915. // look at the last TCB we found, and if it matches we return it. Otherwise
  916. // we hash into the TCB table and look for it. We assume the TCB table lock
  917. // is held when we are called.
  918. //
  919. TCB * // Returns: Pointer to TCB found, or NULL if none.
  920. FindTCB(
  921. IPv6Addr *Src, // Source IP address of TCB to be found.
  922. IPv6Addr *Dest, // Destination IP address of TCB to be found.
  923. uint SrcScopeId, // Source address scope identifier.
  924. uint DestScopeId, // Destination address scope identifier.
  925. ushort SrcPort, // Source port of TCB to be found.
  926. ushort DestPort) // Destination port of TCB to be found.
  927. {
  928. TCB *FoundTCB;
  929. if (LastTCB != NULL) {
  930. CHECK_STRUCT(LastTCB, tcb);
  931. if (IP6_ADDR_EQUAL(&LastTCB->tcb_daddr, Dest) &&
  932. LastTCB->tcb_dscope_id == DestScopeId &&
  933. LastTCB->tcb_dport == DestPort &&
  934. IP6_ADDR_EQUAL(&LastTCB->tcb_saddr, Src) &&
  935. LastTCB->tcb_sscope_id == SrcScopeId &&
  936. LastTCB->tcb_sport == SrcPort)
  937. return LastTCB;
  938. }
  939. //
  940. // Didn't find it in our 1 element cache.
  941. //
  942. FoundTCB = TCBTable[TCB_HASH(*Dest, *Src, DestPort, SrcPort)];
  943. while (FoundTCB != NULL) {
  944. CHECK_STRUCT(FoundTCB, tcb);
  945. if (IP6_ADDR_EQUAL(&FoundTCB->tcb_daddr, Dest) &&
  946. FoundTCB->tcb_dscope_id == DestScopeId &&
  947. FoundTCB->tcb_dport == DestPort &&
  948. IP6_ADDR_EQUAL(&FoundTCB->tcb_saddr, Src) &&
  949. FoundTCB->tcb_sscope_id == SrcScopeId &&
  950. FoundTCB->tcb_sport == SrcPort) {
  951. //
  952. // Found it. Update the cache for next time, and return.
  953. //
  954. LastTCB = FoundTCB;
  955. return FoundTCB;
  956. } else
  957. FoundTCB = FoundTCB->tcb_next;
  958. }
  959. return FoundTCB;
  960. }
  961. //* InsertTCB - Insert a TCB in the tcb table.
  962. //
  963. // This routine inserts a TCB in the TCB table. No locks need to be held
  964. // when this routine is called. We insert TCBs in ascending address order.
  965. // Before inserting we make sure that the TCB isn't already in the table.
  966. //
  967. uint // Returns: TRUE if we inserted, false if we didn't.
  968. InsertTCB(
  969. TCB *NewTCB) // TCB to be inserted.
  970. {
  971. uint TCBIndex;
  972. KIRQL OldIrql;
  973. TCB *PrevTCB, *CurrentTCB;
  974. TCB *WhereToInsert;
  975. ASSERT(NewTCB != NULL);
  976. CHECK_STRUCT(NewTCB, tcb);
  977. TCBIndex = TCB_HASH(NewTCB->tcb_daddr, NewTCB->tcb_saddr,
  978. NewTCB->tcb_dport, NewTCB->tcb_sport);
  979. KeAcquireSpinLock(&TCBTableLock, &OldIrql);
  980. KeAcquireSpinLockAtDpcLevel(&NewTCB->tcb_lock);
  981. //
  982. // Find the proper place in the table to insert him. While
  983. // we're walking we'll check to see if a dupe already exists.
  984. // When we find the right place to insert, we'll remember it, and
  985. // keep walking looking for a duplicate.
  986. //
  987. PrevTCB = CONTAINING_RECORD(&TCBTable[TCBIndex], TCB, tcb_next);
  988. WhereToInsert = NULL;
  989. while (PrevTCB->tcb_next != NULL) {
  990. CurrentTCB = PrevTCB->tcb_next;
  991. if (IP6_ADDR_EQUAL(&CurrentTCB->tcb_daddr, &NewTCB->tcb_daddr) &&
  992. IP6_ADDR_EQUAL(&CurrentTCB->tcb_saddr, &NewTCB->tcb_saddr) &&
  993. (CurrentTCB->tcb_sport == NewTCB->tcb_sport) &&
  994. (CurrentTCB->tcb_dport == NewTCB->tcb_dport)) {
  995. KeReleaseSpinLockFromDpcLevel(&NewTCB->tcb_lock);
  996. KeReleaseSpinLock(&TCBTableLock, OldIrql);
  997. return FALSE;
  998. } else {
  999. if (WhereToInsert == NULL && CurrentTCB > NewTCB) {
  1000. WhereToInsert = PrevTCB;
  1001. }
  1002. CHECK_STRUCT(PrevTCB->tcb_next, tcb);
  1003. PrevTCB = PrevTCB->tcb_next;
  1004. }
  1005. }
  1006. if (WhereToInsert == NULL) {
  1007. WhereToInsert = PrevTCB;
  1008. }
  1009. NewTCB->tcb_next = WhereToInsert->tcb_next;
  1010. WhereToInsert->tcb_next = NewTCB;
  1011. NewTCB->tcb_flags |= IN_TCB_TABLE;
  1012. TStats.ts_numconns++;
  1013. KeReleaseSpinLockFromDpcLevel(&NewTCB->tcb_lock);
  1014. KeReleaseSpinLock(&TCBTableLock, OldIrql);
  1015. return TRUE;
  1016. }
  1017. //* RemoveTCB - Remove a TCB from the tcb table.
  1018. //
  1019. // Called when we need to remove a TCB from the TCB table. We assume the
  1020. // TCB table lock and the TCB lock are held when we are called. If the
  1021. // TCB isn't in the table we won't try to remove him.
  1022. //
  1023. uint // Returns: TRUE if it's OK to free it, FALSE otherwise.
  1024. RemoveTCB(
  1025. TCB *RemovedTCB) // TCB to be removed.
  1026. {
  1027. uint TCBIndex;
  1028. TCB *PrevTCB;
  1029. #if DBG
  1030. uint Found = FALSE;
  1031. #endif
  1032. CHECK_STRUCT(RemovedTCB, tcb);
  1033. if (RemovedTCB->tcb_flags & IN_TCB_TABLE) {
  1034. TCBIndex = TCB_HASH(RemovedTCB->tcb_daddr, RemovedTCB->tcb_saddr,
  1035. RemovedTCB->tcb_dport, RemovedTCB->tcb_sport);
  1036. PrevTCB = CONTAINING_RECORD(&TCBTable[TCBIndex], TCB, tcb_next);
  1037. do {
  1038. if (PrevTCB->tcb_next == RemovedTCB) {
  1039. // Found him.
  1040. PrevTCB->tcb_next = RemovedTCB->tcb_next;
  1041. RemovedTCB->tcb_flags &= ~IN_TCB_TABLE;
  1042. TStats.ts_numconns--;
  1043. #if DBG
  1044. Found = TRUE;
  1045. #endif
  1046. break;
  1047. }
  1048. PrevTCB = PrevTCB->tcb_next;
  1049. #if DBG
  1050. if (PrevTCB != NULL)
  1051. CHECK_STRUCT(PrevTCB, tcb);
  1052. #endif
  1053. } while (PrevTCB != NULL);
  1054. ASSERT(Found);
  1055. }
  1056. if (LastTCB == RemovedTCB)
  1057. LastTCB = NULL;
  1058. if (TCBWalkCount == 0) {
  1059. return TRUE;
  1060. } else {
  1061. RemovedTCB->tcb_walkcount = TCBWalkCount + 1;
  1062. *(TCB **)&RemovedTCB->tcb_delayq.q_next = PendingFreeList;
  1063. PendingFreeList = RemovedTCB;
  1064. return FALSE;
  1065. }
  1066. }
  1067. //* ScavengeTCB - Scavenge a TCB that's in the TIME_WAIT state.
  1068. //
  1069. // Called when we're running low on TCBs, and need to scavenge one from
  1070. // TIME_WAIT state. We'll walk through the TCB table, looking for the oldest
  1071. // TCB in TIME_WAIT. We'll remove and return a pointer to that TCB. If we
  1072. // don't find any TCBs in TIME_WAIT, we'll return NULL.
  1073. //
  1074. TCB * // Returns: Pointer to a reusable TCB, or NULL.
  1075. ScavengeTCB(
  1076. void)
  1077. {
  1078. KIRQL Irql0, Irql1, IrqlSave;
  1079. uint Now = SystemUpTime();
  1080. uint Delta = 0;
  1081. uint i;
  1082. TCB *FoundTCB = NULL, *PrevFound;
  1083. TCB *CurrentTCB, *PrevTCB;
  1084. KeAcquireSpinLock(&TCBTableLock, &Irql0);
  1085. if (TCBWalkCount != 0) {
  1086. KeReleaseSpinLock(&TCBTableLock, Irql0);
  1087. return NULL;
  1088. }
  1089. for (i = 0; i < TcbTableSize; i++) {
  1090. PrevTCB = CONTAINING_RECORD(&TCBTable[i], TCB, tcb_next);
  1091. CurrentTCB = PrevTCB->tcb_next;
  1092. while (CurrentTCB != NULL) {
  1093. CHECK_STRUCT(CurrentTCB, tcb);
  1094. KeAcquireSpinLock(&CurrentTCB->tcb_lock, &Irql1);
  1095. if (CurrentTCB->tcb_state == TCB_TIME_WAIT &&
  1096. (CurrentTCB->tcb_refcnt == 0) && !CLOSING(CurrentTCB)){
  1097. if (FoundTCB == NULL ||
  1098. ((Now - CurrentTCB->tcb_alive) > Delta)) {
  1099. //
  1100. // Found a new 'older' TCB. If we already have one, free
  1101. // the lock on him and get the lock on the new one.
  1102. //
  1103. if (FoundTCB != NULL)
  1104. KeReleaseSpinLock(&FoundTCB->tcb_lock, Irql1);
  1105. else
  1106. IrqlSave = Irql1;
  1107. PrevFound = PrevTCB;
  1108. FoundTCB = CurrentTCB;
  1109. Delta = Now - FoundTCB->tcb_alive;
  1110. } else
  1111. KeReleaseSpinLock(&CurrentTCB->tcb_lock, Irql1);
  1112. } else
  1113. KeReleaseSpinLock(&CurrentTCB->tcb_lock, Irql1);
  1114. //
  1115. // Look at the next one.
  1116. //
  1117. PrevTCB = CurrentTCB;
  1118. CurrentTCB = PrevTCB->tcb_next;
  1119. }
  1120. }
  1121. //
  1122. // If we have one, pull him from the list.
  1123. //
  1124. if (FoundTCB != NULL) {
  1125. PrevFound->tcb_next = FoundTCB->tcb_next;
  1126. FoundTCB->tcb_flags &= ~IN_TCB_TABLE;
  1127. //
  1128. // REVIEW: Is the right place to drop the reference on our RCE?
  1129. // REVIEW: IPv4 called down to IP to close the RCE here.
  1130. //
  1131. if (FoundTCB->tcb_rce != NULL)
  1132. ReleaseRCE(FoundTCB->tcb_rce);
  1133. TStats.ts_numconns--;
  1134. if (LastTCB == FoundTCB) {
  1135. LastTCB = NULL;
  1136. }
  1137. KeReleaseSpinLock(&FoundTCB->tcb_lock, IrqlSave);
  1138. }
  1139. KeReleaseSpinLock(&TCBTableLock, Irql0);
  1140. return FoundTCB;
  1141. }
  1142. //* AllocTCB - Allocate a TCB.
  1143. //
  1144. // Called whenever we need to allocate a TCB. We try to pull one off the
  1145. // free list, or allocate one if we need one. We then initialize it, etc.
  1146. //
  1147. TCB * // Returns: Pointer to the new TCB, or NULL if we couldn't get one.
  1148. AllocTCB(
  1149. void)
  1150. {
  1151. TCB *NewTCB;
  1152. //
  1153. // First, see if we have one on the free list.
  1154. //
  1155. PSLIST_ENTRY BufferLink;
  1156. BufferLink = ExInterlockedPopEntrySList(&FreeTCBList, &FreeTCBListLock);
  1157. if (BufferLink != NULL) {
  1158. NewTCB = CONTAINING_RECORD(BufferLink, TCB, tcb_next);
  1159. CHECK_STRUCT(NewTCB, tcb);
  1160. ExInterlockedAddUlong(&FreeTCBs, -1, &FreeTCBListLock);
  1161. } else {
  1162. //
  1163. // We have none on the free list. If the total number of TCBs
  1164. // outstanding is more than we like to keep on the free list, try
  1165. // to scavenge a TCB from time wait.
  1166. //
  1167. if (CurrentTCBs < MaxFreeTCBs || ((NewTCB = ScavengeTCB()) == NULL)) {
  1168. if (CurrentTCBs < MaxTCBs) {
  1169. NewTCB = ExAllocatePool(NonPagedPool, sizeof(TCB));
  1170. if (NewTCB == NULL) {
  1171. return NewTCB;
  1172. } else {
  1173. ExInterlockedAddUlong(&CurrentTCBs, 1, &FreeTCBListLock);
  1174. }
  1175. } else
  1176. return NULL;
  1177. }
  1178. }
  1179. ASSERT(NewTCB != NULL);
  1180. RtlZeroMemory(NewTCB, sizeof(TCB));
  1181. #if DBG
  1182. NewTCB->tcb_sig = tcb_signature;
  1183. #endif
  1184. INITQ(&NewTCB->tcb_sendq);
  1185. NewTCB->tcb_cursend = NULL;
  1186. NewTCB->tcb_alive = TCPTime;
  1187. NewTCB->tcb_hops = -1;
  1188. //
  1189. // Initially we're not on the fast path because we're not established. Set
  1190. // the slowcount to one and set up the fastchk fields so we don't take the
  1191. // fast path.
  1192. //
  1193. NewTCB->tcb_slowcount = 1;
  1194. NewTCB->tcb_fastchk = TCP_FLAG_ACK | TCP_FLAG_SLOW;
  1195. KeInitializeSpinLock(&NewTCB->tcb_lock);
  1196. return NewTCB;
  1197. }
  1198. //* FreeTCB - Free a TCB.
  1199. //
  1200. // Called whenever we need to free a TCB.
  1201. //
  1202. // Note: This routine may be called with the TCBTableLock held.
  1203. //
  1204. void // Returns: Nothing.
  1205. FreeTCB(
  1206. TCB *FreedTCB) // TCB to be freed.
  1207. {
  1208. PSLIST_ENTRY BufferLink;
  1209. CHECK_STRUCT(FreedTCB, tcb);
  1210. #if defined(_WIN64)
  1211. if (CurrentTCBs > 2 * MaxFreeTCBs) {
  1212. #else
  1213. if ((CurrentTCBs > 2 * MaxFreeTCBs) || (FreeTCBList.Depth > 65000)) {
  1214. #endif
  1215. ExInterlockedAddUlong(&CurrentTCBs, (ulong) - 1, &FreeTCBListLock);
  1216. ExFreePool(FreedTCB);
  1217. return;
  1218. }
  1219. BufferLink = CONTAINING_RECORD(&(FreedTCB->tcb_next),
  1220. SLIST_ENTRY, Next);
  1221. ExInterlockedPushEntrySList(&FreeTCBList, BufferLink, &FreeTCBListLock);
  1222. ExInterlockedAddUlong(&FreeTCBs, 1, &FreeTCBListLock);
  1223. }
  1224. #pragma BEGIN_INIT
  1225. //* InitTCB - Initialize our TCB code.
  1226. //
  1227. // Called during init time to initialize our TCB code. We initialize
  1228. // the TCB table, etc, then return.
  1229. //
  1230. int // Returns: TRUE if we did initialize, false if we didn't.
  1231. InitTCB(
  1232. void)
  1233. {
  1234. LARGE_INTEGER InitialWakeUp;
  1235. uint i;
  1236. TCBTable = ExAllocatePool(NonPagedPool, TcbTableSize * sizeof(TCB*));
  1237. if (TCBTable == NULL) {
  1238. return FALSE;
  1239. }
  1240. for (i = 0; i < TcbTableSize; i++)
  1241. TCBTable[i] = NULL;
  1242. LastTCB = NULL;
  1243. ExInitializeSListHead(&FreeTCBList);
  1244. KeInitializeSpinLock(&TCBTableLock);
  1245. KeInitializeSpinLock(&FreeTCBListLock);
  1246. TCPTime = 0;
  1247. TCBWalkCount = 0;
  1248. DeadmanTicks = NUM_DEADMAN_TICKS;
  1249. //
  1250. // Set up our timer to call TCBTimeout once every MS_PER_TICK milliseconds.
  1251. //
  1252. // REVIEW: Switch this to be driven off the IPv6Timeout routine instead
  1253. // REVIEW: of having two independent timers?
  1254. //
  1255. KeInitializeDpc(&TCBTimeoutDpc, TCBTimeout, NULL);
  1256. KeInitializeTimer(&TCBTimer);
  1257. InitialWakeUp.QuadPart = -(LONGLONG) MS_PER_TICK * 10000;
  1258. KeSetTimerEx(&TCBTimer, InitialWakeUp, MS_PER_TICK, &TCBTimeoutDpc);
  1259. return TRUE;
  1260. }
  1261. #pragma END_INIT
  1262. //* UnloadTCB
  1263. //
  1264. // Called during shutdown to uninitialize
  1265. // in preparation for unloading the stack.
  1266. //
  1267. // There are no open sockets (or else we wouldn't be unloading).
  1268. // Because UnloadTCPSend has already been called,
  1269. // we are no longer receiving packets from the IPv6 layer.
  1270. //
  1271. void
  1272. UnloadTCB(void)
  1273. {
  1274. PSLIST_ENTRY BufferLink;
  1275. TCB *CurrentTCB;
  1276. uint i;
  1277. KIRQL OldIrql;
  1278. //
  1279. // First stop TCBTimeout from being called.
  1280. //
  1281. KeCancelTimer(&TCBTimer);
  1282. //
  1283. // Traverse the buckets looking for TCBs.
  1284. // REVIEW - Can we have TCBs in states other than time-wait?
  1285. //
  1286. for (i = 0; i < TcbTableSize; i++) {
  1287. while ((CurrentTCB = TCBTable[i]) != NULL) {
  1288. KeAcquireSpinLock(&CurrentTCB->tcb_lock, &OldIrql);
  1289. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_STATE,
  1290. "UnloadTCB(%p): state %x flags %x refs %x "
  1291. "reason %x pend %x walk %x\n",
  1292. CurrentTCB,
  1293. CurrentTCB->tcb_state,
  1294. CurrentTCB->tcb_flags,
  1295. CurrentTCB->tcb_refcnt,
  1296. CurrentTCB->tcb_closereason,
  1297. CurrentTCB->tcb_pending,
  1298. CurrentTCB->tcb_walkcount));
  1299. CurrentTCB->tcb_flags |= NEED_RST;
  1300. TryToCloseTCB(CurrentTCB, TCB_CLOSE_ABORTED, OldIrql);
  1301. }
  1302. }
  1303. //
  1304. // Now pull TCBs off the free list and really free them.
  1305. //
  1306. while ((BufferLink = ExInterlockedPopEntrySList(&FreeTCBList, &FreeTCBListLock)) != NULL) {
  1307. CurrentTCB = CONTAINING_RECORD(BufferLink, TCB, tcb_next);
  1308. CHECK_STRUCT(CurrentTCB, tcb);
  1309. ExFreePool(CurrentTCB);
  1310. }
  1311. ExFreePool(TCBTable);
  1312. TCBTable = NULL;
  1313. }
  1314. //* CleanupTCBWithIF
  1315. //
  1316. // Helper function for TCBWalk, to remove
  1317. // TCBs that reference the specified interface.
  1318. //
  1319. // Returns FALSE if CheckTCB should be deleted, TRUE otherwise.
  1320. //
  1321. uint
  1322. CleanupTCBWithIF(
  1323. TCB *CheckTCB,
  1324. void *Context1,
  1325. void *Context2,
  1326. void *Context3)
  1327. {
  1328. Interface *IF = (Interface *) Context1;
  1329. RouteCacheEntry *RCE;
  1330. KIRQL OldIrql;
  1331. CHECK_STRUCT(CheckTCB, tcb);
  1332. RCE = CheckTCB->tcb_rce;
  1333. if (RCE != NULL) {
  1334. ASSERT(RCE->NTE->IF == RCE->NCE->IF);
  1335. if (RCE->NTE->IF == IF)
  1336. return FALSE; // Delete this TCB.
  1337. }
  1338. return TRUE; // Do not delete this TCB.
  1339. }
  1340. //* TCPRemoveIF
  1341. //
  1342. // Remove TCP's references to the specified interface.
  1343. //
  1344. void
  1345. TCPRemoveIF(Interface *IF)
  1346. {
  1347. //
  1348. // Currently, only TCBs hold onto references.
  1349. //
  1350. TCBWalk(CleanupTCBWithIF, IF, NULL, NULL);
  1351. }