Leaked source code of windows server 2003
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.

6864 lines
259 KiB

  1. /*++
  2. Copyright (c) 2000-2000 Microsoft Corporation
  3. Module Name:
  4. Receive.c
  5. Abstract:
  6. This module implements Receive handlers and other routines
  7. the PGM Transport and other routines that are specific to the
  8. NT implementation of a driver.
  9. Author:
  10. Mohammad Shabbir Alam (MAlam) 3-30-2000
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #ifdef FILE_LOGGING
  15. #include "receive.tmh"
  16. #endif // FILE_LOGGING
  17. typedef struct in_pktinfo {
  18. tIPADDRESS ipi_addr; // destination IPv4 address
  19. UINT ipi_ifindex; // received interface index
  20. } IP_PKTINFO;
  21. //******************* Pageable Routine Declarations ****************
  22. #ifdef ALLOC_PRAGMA
  23. #endif
  24. //******************* Pageable Routine Declarations ****************
  25. VOID
  26. FreeDataBuffer(
  27. IN tRECEIVE_SESSION *pReceive,
  28. IN tPENDING_DATA *pPendingData
  29. )
  30. {
  31. ASSERT (pPendingData->pDataPacket);
  32. if (pPendingData->PendingDataFlags & PENDING_DATA_LOOKASIDE_ALLOCATION_FLAG)
  33. {
  34. ExFreeToNPagedLookasideList (&pReceive->pReceiver->DataBufferLookaside, pPendingData->pDataPacket);
  35. if ((0 == --pReceive->pReceiver->NumDataBuffersFromLookaside) &&
  36. !(pReceive->SessionFlags & PGM_SESSION_DATA_FROM_LOOKASIDE))
  37. {
  38. ASSERT (pReceive->pReceiver->MaxBufferLength > pReceive->pReceiver->DataBufferLookasideLength);
  39. pReceive->pReceiver->MaxBufferLength += 100;
  40. pReceive->pReceiver->DataBufferLookasideLength = pReceive->pReceiver->MaxBufferLength;
  41. pReceive->SessionFlags |= PGM_SESSION_DATA_FROM_LOOKASIDE;
  42. ExDeleteNPagedLookasideList (&pReceive->pReceiver->DataBufferLookaside);
  43. ASSERT (pReceive->pReceiver->MaxPacketsBufferedInLookaside);
  44. ExInitializeNPagedLookasideList (&pReceive->pReceiver->DataBufferLookaside,
  45. NULL,
  46. NULL,
  47. 0,
  48. pReceive->pReceiver->DataBufferLookasideLength,
  49. PGM_TAG ('D'),
  50. pReceive->pReceiver->MaxPacketsBufferedInLookaside);
  51. }
  52. pPendingData->PendingDataFlags &= ~PENDING_DATA_LOOKASIDE_ALLOCATION_FLAG;
  53. }
  54. else
  55. {
  56. PgmFreeMem (pPendingData->pDataPacket);
  57. }
  58. pPendingData->pDataPacket = NULL;
  59. pPendingData->PacketLength = pPendingData->DataOffset = 0;
  60. }
  61. PVOID
  62. AllocateDataBuffer(
  63. IN tRECEIVE_SESSION *pReceive,
  64. IN tPENDING_DATA *pPendingData,
  65. IN ULONG BufferSize
  66. )
  67. {
  68. ASSERT (!pPendingData->pDataPacket);
  69. ASSERT (!(pPendingData->PendingDataFlags & PENDING_DATA_LOOKASIDE_ALLOCATION_FLAG));
  70. if ((pReceive->SessionFlags & PGM_SESSION_DATA_FROM_LOOKASIDE) &&
  71. (BufferSize <= pReceive->pReceiver->DataBufferLookasideLength))
  72. {
  73. if (pPendingData->pDataPacket = ExAllocateFromNPagedLookasideList (&pReceive->pReceiver->DataBufferLookaside))
  74. {
  75. pReceive->pReceiver->NumDataBuffersFromLookaside++;
  76. pPendingData->PendingDataFlags |= PENDING_DATA_LOOKASIDE_ALLOCATION_FLAG;
  77. }
  78. }
  79. else
  80. {
  81. pReceive->SessionFlags &= ~PGM_SESSION_DATA_FROM_LOOKASIDE; // Ensure no more lookaside!
  82. pPendingData->pDataPacket = PgmAllocMem (BufferSize, PGM_TAG('D'));
  83. if (BufferSize > pReceive->pReceiver->MaxBufferLength)
  84. {
  85. pReceive->pReceiver->MaxBufferLength = BufferSize;
  86. }
  87. }
  88. return (pPendingData->pDataPacket);
  89. }
  90. PVOID
  91. ReAllocateDataBuffer(
  92. IN tRECEIVE_SESSION *pReceive,
  93. IN tPENDING_DATA *pPendingData,
  94. IN ULONG BufferSize
  95. )
  96. {
  97. ULONG SavedFlags1, SavedFlags2;
  98. PUCHAR pSavedPacket1, pSavedPacket2;
  99. //
  100. // First, save the context for the current buffer
  101. //
  102. SavedFlags1 = pPendingData->PendingDataFlags;
  103. pSavedPacket1 = pPendingData->pDataPacket;
  104. pPendingData->PendingDataFlags = 0;
  105. pPendingData->pDataPacket = NULL;
  106. if (AllocateDataBuffer (pReceive, pPendingData, BufferSize))
  107. {
  108. ASSERT (pPendingData->pDataPacket);
  109. //
  110. // Now, save the context for the new buffer
  111. //
  112. SavedFlags2 = pPendingData->PendingDataFlags;
  113. pSavedPacket2 = pPendingData->pDataPacket;
  114. //
  115. // Free the original buffer
  116. //
  117. pPendingData->PendingDataFlags = SavedFlags1;
  118. pPendingData->pDataPacket = pSavedPacket1;
  119. FreeDataBuffer (pReceive, pPendingData);
  120. //
  121. // Reset the information for the new buffer!
  122. //
  123. if (SavedFlags2 & PENDING_DATA_LOOKASIDE_ALLOCATION_FLAG)
  124. {
  125. pPendingData->PendingDataFlags = SavedFlags1 | PENDING_DATA_LOOKASIDE_ALLOCATION_FLAG;
  126. }
  127. else
  128. {
  129. pPendingData->PendingDataFlags = SavedFlags1 & ~PENDING_DATA_LOOKASIDE_ALLOCATION_FLAG;
  130. }
  131. pPendingData->pDataPacket = pSavedPacket2;
  132. return (pPendingData->pDataPacket);
  133. }
  134. //
  135. // Failure case!
  136. //
  137. pPendingData->pDataPacket = pSavedPacket1;
  138. pPendingData->PendingDataFlags = SavedFlags1;
  139. return (NULL);
  140. }
  141. //----------------------------------------------------------------------------
  142. VOID
  143. RemovePendingIrps(
  144. IN tRECEIVE_SESSION *pReceive,
  145. IN LIST_ENTRY *pIrpsList
  146. )
  147. {
  148. PIRP pIrp;
  149. if (pIrp = pReceive->pReceiver->pIrpReceive)
  150. {
  151. pReceive->pReceiver->pIrpReceive = NULL;
  152. pIrp->IoStatus.Information = pReceive->pReceiver->BytesInMdl;
  153. InsertTailList (pIrpsList, &pIrp->Tail.Overlay.ListEntry);
  154. }
  155. while (!IsListEmpty (&pReceive->pReceiver->ReceiveIrpsList))
  156. {
  157. pIrp = CONTAINING_RECORD (pReceive->pReceiver->ReceiveIrpsList.Flink, IRP, Tail.Overlay.ListEntry);
  158. RemoveEntryList (&pIrp->Tail.Overlay.ListEntry);
  159. InsertTailList (pIrpsList, &pIrp->Tail.Overlay.ListEntry);
  160. pIrp->IoStatus.Information = 0;
  161. }
  162. }
  163. //----------------------------------------------------------------------------
  164. VOID
  165. FreeNakContext(
  166. IN tRECEIVE_SESSION *pReceive,
  167. IN tNAK_FORWARD_DATA *pNak
  168. )
  169. /*++
  170. Routine Description:
  171. This routine free's the context used for tracking missing sequences
  172. Arguments:
  173. IN pReceive -- Receive context
  174. IN pNak -- Nak Context to be free'ed
  175. Return Value:
  176. NONE
  177. --*/
  178. {
  179. UCHAR i, j, k, NumPackets;
  180. //
  181. // Free any memory for non-parity data
  182. //
  183. j = k = 0;
  184. NumPackets = pNak->NumDataPackets + pNak->NumParityPackets;
  185. for (i=0; i<NumPackets; i++)
  186. {
  187. if (pNak->pPendingData[i].PacketIndex < pReceive->FECGroupSize)
  188. {
  189. j++;
  190. }
  191. else
  192. {
  193. k++;
  194. }
  195. FreeDataBuffer (pReceive, &pNak->pPendingData[i]);
  196. }
  197. ASSERT (j == pNak->NumDataPackets);
  198. ASSERT (k == pNak->NumParityPackets);
  199. //
  200. // Return the pNak memory based on whether it was allocated
  201. // from the parity or non-parity lookaside list
  202. //
  203. if (pNak->OriginalGroupSize > 1)
  204. {
  205. ExFreeToNPagedLookasideList (&pReceive->pReceiver->ParityContextLookaside, pNak);
  206. }
  207. else
  208. {
  209. ExFreeToNPagedLookasideList (&pReceive->pReceiver->NonParityContextLookaside, pNak);
  210. }
  211. }
  212. //----------------------------------------------------------------------------
  213. VOID
  214. CleanupPendingNaks(
  215. IN tRECEIVE_SESSION *pReceive,
  216. IN PVOID fDerefReceive,
  217. IN PVOID fReceiveLockHeld
  218. )
  219. {
  220. LIST_ENTRY NaksList, DataList;
  221. tNAK_FORWARD_DATA *pNak;
  222. LIST_ENTRY *pEntry;
  223. ULONG NumBufferedData = 0;
  224. ULONG NumNaks = 0;
  225. PGMLockHandle OldIrq;
  226. ASSERT (pReceive->pReceiver);
  227. if (!fReceiveLockHeld)
  228. {
  229. PgmLock (pReceive, OldIrq);
  230. }
  231. else
  232. {
  233. ASSERT (!fDerefReceive);
  234. }
  235. DataList.Flink = pReceive->pReceiver->BufferedDataList.Flink;
  236. DataList.Blink = pReceive->pReceiver->BufferedDataList.Blink;
  237. pReceive->pReceiver->BufferedDataList.Flink->Blink = &DataList;
  238. pReceive->pReceiver->BufferedDataList.Blink->Flink = &DataList;
  239. InitializeListHead (&pReceive->pReceiver->BufferedDataList);
  240. NaksList.Flink = pReceive->pReceiver->NaksForwardDataList.Flink;
  241. NaksList.Blink = pReceive->pReceiver->NaksForwardDataList.Blink;
  242. pReceive->pReceiver->NaksForwardDataList.Flink->Blink = &NaksList;
  243. pReceive->pReceiver->NaksForwardDataList.Blink->Flink = &NaksList;
  244. InitializeListHead (&pReceive->pReceiver->NaksForwardDataList);
  245. RemoveAllPendingReceiverEntries (pReceive->pReceiver);
  246. pReceive->pReceiver->NumDataBuffersFromLookaside++; // So that we don't assert
  247. if (!fReceiveLockHeld)
  248. {
  249. PgmUnlock (pReceive, OldIrq);
  250. }
  251. //
  252. // Cleanup any pending Nak entries
  253. //
  254. while (!IsListEmpty (&DataList))
  255. {
  256. pEntry = RemoveHeadList (&DataList);
  257. pNak = CONTAINING_RECORD (pEntry, tNAK_FORWARD_DATA, Linkage);
  258. FreeNakContext (pReceive, pNak);
  259. NumBufferedData++;
  260. }
  261. while (!IsListEmpty (&NaksList))
  262. {
  263. pEntry = RemoveHeadList (&NaksList);
  264. pNak = CONTAINING_RECORD (pEntry, tNAK_FORWARD_DATA, Linkage);
  265. FreeNakContext (pReceive, pNak);
  266. NumNaks++;
  267. }
  268. PgmTrace (LogStatus, ("CleanupPendingNaks: " \
  269. "pReceive=<%p>, FirstNak=<%d>, NumBufferedData=<%d=%d>, TotalDataPackets=<%d>, NumNaks=<%d * %d>\n",
  270. pReceive, (ULONG) pReceive->pReceiver->FirstNakSequenceNumber,
  271. (ULONG) pReceive->pReceiver->NumPacketGroupsPendingClient, NumBufferedData,
  272. (ULONG) pReceive->pReceiver->TotalDataPacketsBuffered, NumNaks, (ULONG) pReceive->FECGroupSize));
  273. // ASSERT (NumBufferedData == pReceive->pReceiver->NumPacketGroupsPendingClient);
  274. pReceive->pReceiver->NumPacketGroupsPendingClient = 0;
  275. if (!fReceiveLockHeld)
  276. {
  277. PgmLock (pReceive, OldIrq);
  278. }
  279. pReceive->pReceiver->NumDataBuffersFromLookaside--; // Undoing what we did earlier!
  280. ASSERT (!pReceive->pReceiver->NumDataBuffersFromLookaside);
  281. if (pReceive->SessionFlags & PGM_SESSION_DATA_FROM_LOOKASIDE)
  282. {
  283. pReceive->pReceiver->MaxBufferLength = 0;
  284. pReceive->SessionFlags &= ~PGM_SESSION_DATA_FROM_LOOKASIDE; // Ensure no more lookaside!
  285. ExDeleteNPagedLookasideList (&pReceive->pReceiver->DataBufferLookaside);
  286. }
  287. if (pReceive->pReceiver->pReceiveData)
  288. {
  289. PgmFreeMem (pReceive->pReceiver->pReceiveData);
  290. pReceive->pReceiver->pReceiveData = NULL;
  291. }
  292. if (!fReceiveLockHeld)
  293. {
  294. PgmUnlock (pReceive, OldIrq);
  295. if (fDerefReceive)
  296. {
  297. PGM_DEREFERENCE_SESSION_RECEIVE (pReceive, REF_SESSION_CLEANUP_NAKS);
  298. }
  299. }
  300. }
  301. //----------------------------------------------------------------------------
  302. BOOLEAN
  303. CheckIndicateDisconnect(
  304. IN tADDRESS_CONTEXT *pAddress,
  305. IN tRECEIVE_SESSION *pReceive,
  306. IN PGMLockHandle *pOldIrqAddress,
  307. IN PGMLockHandle *pOldIrqReceive,
  308. IN BOOLEAN fAddressLockHeld
  309. )
  310. {
  311. ULONG DisconnectFlag;
  312. NTSTATUS status;
  313. BOOLEAN fDisconnectIndicated = FALSE;
  314. LIST_ENTRY PendingIrpsList;
  315. PIRP pIrp;
  316. tNAK_FORWARD_DATA *pNak;
  317. SEQ_TYPE FirstNakSequenceNumber;
  318. //
  319. // Don't abort if we are currently indicating, or if we have
  320. // already aborted!
  321. //
  322. fDisconnectIndicated = (pReceive->SessionFlags & PGM_SESSION_CLIENT_DISCONNECTED ? TRUE : FALSE);
  323. if (pReceive->SessionFlags & (PGM_SESSION_FLAG_IN_INDICATE | PGM_SESSION_CLIENT_DISCONNECTED))
  324. {
  325. return (fDisconnectIndicated);
  326. }
  327. if (IsListEmpty (&pReceive->pReceiver->NaksForwardDataList))
  328. {
  329. FirstNakSequenceNumber = pReceive->pReceiver->FirstNakSequenceNumber;
  330. }
  331. else
  332. {
  333. pNak = CONTAINING_RECORD (pReceive->pReceiver->NaksForwardDataList.Flink, tNAK_FORWARD_DATA, Linkage);
  334. FirstNakSequenceNumber = pNak->SequenceNumber + pNak->NextIndexToIndicate;
  335. }
  336. if ((pReceive->SessionFlags & PGM_SESSION_TERMINATED_ABORT) ||
  337. ((pReceive->SessionFlags & PGM_SESSION_TERMINATED_GRACEFULLY) &&
  338. (IsListEmpty (&pReceive->pReceiver->BufferedDataList)) &&
  339. SEQ_GEQ (FirstNakSequenceNumber, (pReceive->pReceiver->FinDataSequenceNumber+1))))
  340. {
  341. //
  342. // The session has terminated, so let the client know
  343. //
  344. if (pReceive->SessionFlags & PGM_SESSION_TERMINATED_ABORT)
  345. {
  346. DisconnectFlag = TDI_DISCONNECT_ABORT;
  347. }
  348. else
  349. {
  350. DisconnectFlag = TDI_DISCONNECT_RELEASE;
  351. }
  352. pReceive->SessionFlags |= (PGM_SESSION_FLAG_IN_INDICATE | PGM_SESSION_CLIENT_DISCONNECTED);
  353. InitializeListHead (&PendingIrpsList);
  354. RemovePendingIrps (pReceive, &PendingIrpsList);
  355. PGM_REFERENCE_SESSION_RECEIVE (pReceive, REF_SESSION_CLEANUP_NAKS, TRUE);
  356. PgmUnlock (pReceive, *pOldIrqReceive);
  357. if (fAddressLockHeld)
  358. {
  359. PgmUnlock (pAddress, *pOldIrqAddress);
  360. }
  361. while (!IsListEmpty (&PendingIrpsList))
  362. {
  363. pIrp = CONTAINING_RECORD (PendingIrpsList.Flink, IRP, Tail.Overlay.ListEntry);
  364. PgmCancelCancelRoutine (pIrp);
  365. RemoveEntryList (&pIrp->Tail.Overlay.ListEntry);
  366. pIrp->IoStatus.Status = STATUS_CANCELLED;
  367. IoCompleteRequest (pIrp, IO_NETWORK_INCREMENT);
  368. }
  369. PgmTrace (LogStatus, ("CheckIndicateDisconnect: " \
  370. "Disconnecting pReceive=<%p:%p>, with %s, FirstNak=<%d>, NextOData=<%d>\n",
  371. pReceive, pReceive->ClientSessionContext,
  372. (DisconnectFlag == TDI_DISCONNECT_RELEASE ? "TDI_DISCONNECT_RELEASE":"TDI_DISCONNECT_ABORT"),
  373. FirstNakSequenceNumber, pReceive->pReceiver->NextODataSequenceNumber));
  374. status = (*pAddress->evDisconnect) (pAddress->DiscEvContext,
  375. pReceive->ClientSessionContext,
  376. 0,
  377. NULL,
  378. 0,
  379. NULL,
  380. DisconnectFlag);
  381. fDisconnectIndicated = TRUE;
  382. //
  383. // See if we can Enqueue the Nak cleanup request to a Worker thread
  384. //
  385. if (STATUS_SUCCESS != PgmQueueForDelayedExecution (CleanupPendingNaks,
  386. pReceive,
  387. (PVOID) TRUE,
  388. (PVOID) FALSE,
  389. FALSE))
  390. {
  391. CleanupPendingNaks (pReceive, (PVOID) TRUE, (PVOID) FALSE);
  392. }
  393. if (fAddressLockHeld)
  394. {
  395. PgmLock (pAddress, *pOldIrqAddress);
  396. }
  397. PgmLock (pReceive, *pOldIrqReceive);
  398. pReceive->SessionFlags &= ~PGM_SESSION_FLAG_IN_INDICATE;
  399. //
  400. // We may have received a disassociate while disconnecting, so
  401. // complete the irp here
  402. //
  403. if (pIrp = pReceive->pIrpDisassociate)
  404. {
  405. pReceive->pIrpDisassociate = NULL;
  406. PgmUnlock (pReceive, *pOldIrqReceive);
  407. if (fAddressLockHeld)
  408. {
  409. PgmUnlock (pAddress, *pOldIrqAddress);
  410. }
  411. PgmIoComplete (pIrp, STATUS_SUCCESS, 0);
  412. if (fAddressLockHeld)
  413. {
  414. PgmLock (pAddress, *pOldIrqAddress);
  415. }
  416. PgmLock (pReceive, *pOldIrqReceive);
  417. }
  418. }
  419. return (fDisconnectIndicated);
  420. }
  421. //----------------------------------------------------------------------------
  422. VOID
  423. ProcessNakOption(
  424. IN tPACKET_OPTION_GENERIC UNALIGNED *pOptionHeader,
  425. OUT tNAKS_LIST *pNaksList
  426. )
  427. /*++
  428. Routine Description:
  429. This routine processes the Nak list option in the Pgm packet
  430. Arguments:
  431. IN pOptionHeader -- The Nak List option ptr
  432. OUT pNaksList -- The parameters extracted (i.e. list of Nak sequences)
  433. Return Value:
  434. NONE
  435. --*/
  436. {
  437. UCHAR i, NumNaks;
  438. ULONG pPacketNaks[MAX_SEQUENCES_PER_NAK_OPTION];
  439. NumNaks = (pOptionHeader->OptionLength - 4) / 4;
  440. ASSERT (NumNaks <= MAX_SEQUENCES_PER_NAK_OPTION);
  441. PgmCopyMemory (pPacketNaks, (pOptionHeader + 1), (pOptionHeader->OptionLength - 4));
  442. for (i=0; i < NumNaks; i++)
  443. {
  444. //
  445. // Do not fill in the 0th entry, since that is from the packet header itself
  446. //
  447. pNaksList->pNakSequences[i+1] = (SEQ_TYPE) ntohl (pPacketNaks[i]);
  448. }
  449. pNaksList->NumSequences = (USHORT) i;
  450. }
  451. //----------------------------------------------------------------------------
  452. NTSTATUS
  453. ProcessOptions(
  454. IN tPACKET_OPTION_LENGTH UNALIGNED *pPacketExtension,
  455. IN ULONG BytesAvailable,
  456. IN ULONG PacketType,
  457. OUT tPACKET_OPTIONS *pPacketOptions,
  458. OUT tNAKS_LIST *pNaksList
  459. )
  460. /*++
  461. Routine Description:
  462. This routine processes the options fields on an incoming Pgm packet
  463. and returns the options information extracted in the OUT parameters
  464. Arguments:
  465. IN pPacketExtension -- Options section of the packet
  466. IN BytesAvailable -- from the start of the options
  467. IN PacketType -- Whether Data or Spm packet, etc
  468. OUT pPacketOptions -- Structure containing the parameters from the options
  469. Return Value:
  470. NTSTATUS - Final status of the operation
  471. --*/
  472. {
  473. tPACKET_OPTION_GENERIC UNALIGNED *pOptionHeader;
  474. ULONG BytesLeft = BytesAvailable;
  475. UCHAR i;
  476. ULONG MessageFirstSequence, MessageLength, MessageOffset;
  477. ULONG pOptionsData[3];
  478. ULONG OptionsFlags = 0;
  479. ULONG NumOptionsProcessed = 0;
  480. USHORT TotalOptionsLength = 0;
  481. NTSTATUS status = STATUS_UNSUCCESSFUL;
  482. pPacketOptions->OptionsLength = 0; // Init
  483. pPacketOptions->OptionsFlags = 0; // Init
  484. if (BytesLeft > sizeof(tPACKET_OPTION_LENGTH))
  485. {
  486. PgmCopyMemory (&TotalOptionsLength, &pPacketExtension->TotalOptionsLength, sizeof (USHORT));
  487. TotalOptionsLength = ntohs (TotalOptionsLength);
  488. }
  489. //
  490. // First process the Option extension
  491. //
  492. if ((BytesLeft < ((sizeof(tPACKET_OPTION_LENGTH) + sizeof(tPACKET_OPTION_GENERIC)))) || // Ext+opt
  493. (pPacketExtension->Type != PACKET_OPTION_LENGTH) ||
  494. (pPacketExtension->Length != 4) ||
  495. (BytesLeft < TotalOptionsLength)) // Verify length
  496. {
  497. //
  498. // Need to get at least our header from transport!
  499. //
  500. PgmTrace (LogError, ("ProcessOptions: ERROR -- " \
  501. "BytesLeft=<%d> < Min=<%d>, TotalOptionsLength=<%d>, ExtLength=<%d>, ExtType=<%x>\n",
  502. BytesLeft, ((sizeof(tPACKET_OPTION_LENGTH) + sizeof(tPACKET_OPTION_GENERIC))),
  503. (ULONG) TotalOptionsLength, pPacketExtension->Length, pPacketExtension->Type));
  504. return (status);
  505. }
  506. //
  507. // Now, process each option
  508. //
  509. pOptionHeader = (tPACKET_OPTION_GENERIC UNALIGNED *) (pPacketExtension + 1);
  510. BytesLeft -= sizeof(tPACKET_OPTION_LENGTH);
  511. NumOptionsProcessed = 0;
  512. status = STATUS_SUCCESS; // By default
  513. do
  514. {
  515. if (pOptionHeader->OptionLength > BytesLeft)
  516. {
  517. PgmTrace (LogError, ("ProcessOptions: ERROR -- " \
  518. "Incorrectly formatted Options: OptionLength=<%d> > BytesLeft=<%d>, NumProcessed=<%d>\n",
  519. pOptionHeader->OptionLength, BytesLeft, NumOptionsProcessed));
  520. status = STATUS_UNSUCCESSFUL;
  521. break;
  522. }
  523. switch (pOptionHeader->E_OptionType & ~PACKET_OPTION_TYPE_END_BIT)
  524. {
  525. case (PACKET_OPTION_NAK_LIST):
  526. {
  527. if (((PacketType == PACKET_TYPE_NAK) ||
  528. (PacketType == PACKET_TYPE_NCF) ||
  529. (PacketType == PACKET_TYPE_NNAK)) &&
  530. ((pOptionHeader->OptionLength >= PGM_PACKET_OPT_MIN_NAK_LIST_LENGTH) &&
  531. (pOptionHeader->OptionLength <= PGM_PACKET_OPT_MAX_NAK_LIST_LENGTH)))
  532. {
  533. PgmTrace (LogPath, ("ProcessOptions: " \
  534. "NAK_LIST: Num Naks=<%d>\n", (pOptionHeader->OptionLength-4)/4));
  535. if (!pNaksList)
  536. {
  537. ASSERT (0);
  538. status = STATUS_UNSUCCESSFUL;
  539. break;
  540. }
  541. ProcessNakOption (pOptionHeader, pNaksList);
  542. OptionsFlags |= PGM_OPTION_FLAG_NAK_LIST;
  543. }
  544. else
  545. {
  546. PgmTrace (LogError, ("ProcessOptions: ERROR -- " \
  547. "NAK_LIST: PacketType=<%x>, Length=<0x%x>, pPacketOptions=<%p>\n",
  548. PacketType, pOptionHeader->OptionLength, pPacketOptions));
  549. status = STATUS_UNSUCCESSFUL;
  550. }
  551. break;
  552. }
  553. /*
  554. // Not supported for now!
  555. case (PACKET_OPTION_REDIRECT):
  556. {
  557. ASSERT (pOptionHeader->OptionLength > 4); // 4 + sizeof(NLA)
  558. break;
  559. }
  560. */
  561. case (PACKET_OPTION_FRAGMENT):
  562. {
  563. if (pOptionHeader->OptionLength == PGM_PACKET_OPT_FRAGMENT_LENGTH)
  564. {
  565. PgmCopyMemory (pOptionsData, (pOptionHeader + 1), (3 * sizeof(ULONG)));
  566. if (pOptionHeader->Reserved_F_Opx & PACKET_OPTION_RES_F_OPX_ENCODED_BIT)
  567. {
  568. pPacketOptions->MessageFirstSequence = pOptionsData[0];
  569. pPacketOptions->MessageOffset = pOptionsData[1];
  570. pPacketOptions->MessageLength = pOptionsData[2];
  571. pPacketOptions->FECContext.FragmentOptSpecific = pOptionHeader->U_OptSpecific;
  572. OptionsFlags |= PGM_OPTION_FLAG_FRAGMENT;
  573. }
  574. else
  575. {
  576. MessageFirstSequence = ntohl (pOptionsData[0]);
  577. MessageOffset = ntohl (pOptionsData[1]);
  578. MessageLength = ntohl (pOptionsData[2]);
  579. if ((MessageLength) && (MessageOffset <= MessageLength))
  580. {
  581. PgmTrace (LogPath, ("ProcessOptions: " \
  582. "FRAGMENT: MsgOffset/Length=<%d/%d>\n", MessageOffset, MessageLength));
  583. if (pPacketOptions)
  584. {
  585. pPacketOptions->MessageFirstSequence = MessageFirstSequence;
  586. pPacketOptions->MessageOffset = MessageOffset;
  587. pPacketOptions->MessageLength = MessageLength;
  588. // pPacketOptions->FECContext.FragmentOptSpecific = PACKET_OPTION_SPECIFIC_ENCODED_NULL_BIT;
  589. }
  590. OptionsFlags |= PGM_OPTION_FLAG_FRAGMENT;
  591. }
  592. else
  593. {
  594. PgmTrace (LogError, ("ProcessOptions: ERROR -- " \
  595. "FRAGMENT: MsgOffset/Length=<%d/%d>\n", MessageOffset, MessageLength));
  596. status = STATUS_UNSUCCESSFUL;
  597. }
  598. }
  599. }
  600. else
  601. {
  602. PgmTrace (LogError, ("ProcessOptions: ERROR -- " \
  603. "FRAGMENT: OptionLength=<%d> != PGM_PACKET_OPT_FRAGMENT_LENGTH=<%d>\n",
  604. pOptionHeader->OptionLength, PGM_PACKET_OPT_FRAGMENT_LENGTH));
  605. status = STATUS_UNSUCCESSFUL;
  606. }
  607. break;
  608. }
  609. case (PACKET_OPTION_JOIN):
  610. {
  611. if (pOptionHeader->OptionLength == PGM_PACKET_OPT_JOIN_LENGTH)
  612. {
  613. PgmCopyMemory (pOptionsData, (pOptionHeader + 1), sizeof(ULONG));
  614. PgmTrace (LogPath, ("ProcessOptions: " \
  615. "JOIN: LateJoinerSeq=<%d>\n", ntohl (pOptionsData[0])));
  616. if (pPacketOptions)
  617. {
  618. pPacketOptions->LateJoinerSequence = ntohl (pOptionsData[0]);
  619. }
  620. OptionsFlags |= PGM_OPTION_FLAG_JOIN;
  621. }
  622. else
  623. {
  624. status = STATUS_UNSUCCESSFUL;
  625. PgmTrace (LogError, ("ProcessOptions: ERROR -- " \
  626. "JOIN: OptionLength=<%d> != PGM_PACKET_OPT_JOIN_LENGTH=<%d>\n",
  627. pOptionHeader->OptionLength, PGM_PACKET_OPT_JOIN_LENGTH));
  628. }
  629. break;
  630. }
  631. case (PACKET_OPTION_SYN):
  632. {
  633. if (pOptionHeader->OptionLength == PGM_PACKET_OPT_SYN_LENGTH)
  634. {
  635. PgmTrace (LogPath, ("ProcessOptions: " \
  636. "SYN\n"));
  637. OptionsFlags |= PGM_OPTION_FLAG_SYN;
  638. }
  639. else
  640. {
  641. status = STATUS_UNSUCCESSFUL;
  642. PgmTrace (LogError, ("ProcessOptions: ERROR -- " \
  643. "SYN: OptionLength=<%d> != PGM_PACKET_OPT_SYN_LENGTH=<%d>\n",
  644. pOptionHeader->OptionLength, PGM_PACKET_OPT_SYN_LENGTH));
  645. }
  646. break;
  647. }
  648. case (PACKET_OPTION_FIN):
  649. {
  650. if (pOptionHeader->OptionLength == PGM_PACKET_OPT_FIN_LENGTH)
  651. {
  652. PgmTrace (LogPath, ("ProcessOptions: " \
  653. "FIN\n"));
  654. OptionsFlags |= PGM_OPTION_FLAG_FIN;
  655. }
  656. else
  657. {
  658. status = STATUS_UNSUCCESSFUL;
  659. PgmTrace (LogError, ("ProcessOptions: ERROR -- " \
  660. "FIN: OptionLength=<%d> != PGM_PACKET_OPT_FIN_LENGTH=<%d>\n",
  661. pOptionHeader->OptionLength, PGM_PACKET_OPT_FIN_LENGTH));
  662. }
  663. break;
  664. }
  665. case (PACKET_OPTION_RST):
  666. {
  667. if (pOptionHeader->OptionLength == PGM_PACKET_OPT_RST_LENGTH)
  668. {
  669. PgmTrace (LogPath, ("ProcessOptions: " \
  670. "RST\n"));
  671. OptionsFlags |= PGM_OPTION_FLAG_RST;
  672. }
  673. else
  674. {
  675. status = STATUS_UNSUCCESSFUL;
  676. PgmTrace (LogError, ("ProcessOptions: ERROR -- " \
  677. "RST: OptionLength=<%d> != PGM_PACKET_OPT_RST_LENGTH=<%d>\n",
  678. pOptionHeader->OptionLength, PGM_PACKET_OPT_RST_LENGTH));
  679. }
  680. break;
  681. }
  682. //
  683. // FEC options
  684. //
  685. case (PACKET_OPTION_PARITY_PRM):
  686. {
  687. if (pOptionHeader->OptionLength == PGM_PACKET_OPT_PARITY_PRM_LENGTH)
  688. {
  689. PgmCopyMemory (pOptionsData, (pOptionHeader + 1), sizeof(ULONG));
  690. PgmTrace (LogPath, ("ProcessOptions: " \
  691. "PARITY_PRM: OptionsSpecific=<%x>, FECGroupInfo=<%d>\n",
  692. pOptionHeader->U_OptSpecific, ntohl (pOptionsData[0])));
  693. if (pPacketOptions)
  694. {
  695. pOptionsData[0] = ntohl (pOptionsData[0]);
  696. ASSERT (((UCHAR) pOptionsData[0]) == pOptionsData[0]);
  697. pPacketOptions->FECContext.ReceiverFECOptions = pOptionHeader->U_OptSpecific;
  698. pPacketOptions->FECContext.FECGroupInfo = (UCHAR) pOptionsData[0];
  699. }
  700. OptionsFlags |= PGM_OPTION_FLAG_PARITY_PRM;
  701. }
  702. else
  703. {
  704. status = STATUS_UNSUCCESSFUL;
  705. PgmTrace (LogError, ("ProcessOptions: ERROR -- " \
  706. "PARITY_PRM: OptionLength=<%d> != PGM_PACKET_OPT_PARITY_PRM_LENGTH=<%d>\n",
  707. pOptionHeader->OptionLength, PGM_PACKET_OPT_PARITY_PRM_LENGTH));
  708. }
  709. break;
  710. }
  711. case (PACKET_OPTION_PARITY_GRP):
  712. {
  713. if (pOptionHeader->OptionLength == PGM_PACKET_OPT_PARITY_GRP_LENGTH)
  714. {
  715. PgmCopyMemory (pOptionsData, (pOptionHeader + 1), sizeof(ULONG));
  716. PgmTrace (LogPath, ("ProcessOptions: " \
  717. "PARITY_GRP: FECGroupInfo=<%d>\n",
  718. ntohl (pOptionsData[0])));
  719. if (pPacketOptions)
  720. {
  721. pOptionsData[0] = ntohl (pOptionsData[0]);
  722. ASSERT (((UCHAR) pOptionsData[0]) == pOptionsData[0]);
  723. pPacketOptions->FECContext.FECGroupInfo = (UCHAR) pOptionsData[0];
  724. }
  725. OptionsFlags |= PGM_OPTION_FLAG_PARITY_GRP;
  726. }
  727. else
  728. {
  729. status = STATUS_UNSUCCESSFUL;
  730. PgmTrace (LogError, ("ProcessOptions: ERROR -- " \
  731. "PARITY_GRP: OptionLength=<%d> != PGM_PACKET_OPT_PARITY_GRP_LENGTH=<%d>\n",
  732. pOptionHeader->OptionLength, PGM_PACKET_OPT_PARITY_GRP_LENGTH));
  733. }
  734. break;
  735. }
  736. case (PACKET_OPTION_CURR_TGSIZE):
  737. {
  738. if (pOptionHeader->OptionLength == PGM_PACKET_OPT_PARITY_CUR_TGSIZE_LENGTH)
  739. {
  740. PgmCopyMemory (pOptionsData, (pOptionHeader + 1), sizeof(ULONG));
  741. if (pOptionsData[0])
  742. {
  743. PgmTrace (LogPath, ("ProcessOptions: " \
  744. "CURR_TGSIZE: NumPacketsInThisGroup=<%d>\n",
  745. ntohl (pOptionsData[0])));
  746. if (pPacketOptions)
  747. {
  748. pPacketOptions->FECContext.NumPacketsInThisGroup = (UCHAR) (ntohl (pOptionsData[0]));
  749. }
  750. OptionsFlags |= PGM_OPTION_FLAG_PARITY_CUR_TGSIZE;
  751. }
  752. else
  753. {
  754. PgmTrace (LogError, ("ProcessOptions: ERROR -- " \
  755. "CURR_TGSIZE: NumPacketsInThisGroup=<%d>\n", ntohl (pOptionsData[0])));
  756. status = STATUS_UNSUCCESSFUL;
  757. }
  758. }
  759. else
  760. {
  761. status = STATUS_UNSUCCESSFUL;
  762. PgmTrace (LogError, ("ProcessOptions: ERROR -- " \
  763. "PARITY_GRP: OptionLength=<%d> != PGM_PACKET_OPT_PARITY_CUR_TGSIZE_LENGTH=<%d>\n",
  764. pOptionHeader->OptionLength, PGM_PACKET_OPT_PARITY_CUR_TGSIZE_LENGTH));
  765. }
  766. break;
  767. }
  768. case (PACKET_OPTION_REDIRECT):
  769. case (PACKET_OPTION_CR):
  770. case (PACKET_OPTION_CRQST):
  771. case (PACKET_OPTION_NAK_BO_IVL):
  772. case (PACKET_OPTION_NAK_BO_RNG):
  773. case (PACKET_OPTION_NBR_UNREACH):
  774. case (PACKET_OPTION_PATH_NLA):
  775. case (PACKET_OPTION_INVALID):
  776. {
  777. PgmTrace (LogStatus, ("ProcessOptions: " \
  778. "WARNING: PacketType=<%x>: Unhandled Option=<%x>, OptionLength=<%d>\n",
  779. PacketType, (pOptionHeader->E_OptionType & ~PACKET_OPTION_TYPE_END_BIT), pOptionHeader->OptionLength));
  780. OptionsFlags |= PGM_OPTION_FLAG_UNRECOGNIZED;
  781. break;
  782. }
  783. default:
  784. {
  785. PgmTrace (LogError, ("ProcessOptions: ERROR -- " \
  786. "PacketType=<%x>: Unrecognized Option=<%x>, OptionLength=<%d>\n",
  787. PacketType, (pOptionHeader->E_OptionType & ~PACKET_OPTION_TYPE_END_BIT), pOptionHeader->OptionLength));
  788. ASSERT (0); // We do not recognize this option, but we will continue anyway!
  789. OptionsFlags |= PGM_OPTION_FLAG_UNRECOGNIZED;
  790. status = STATUS_UNSUCCESSFUL;
  791. break;
  792. }
  793. }
  794. if (!NT_SUCCESS (status))
  795. {
  796. break;
  797. }
  798. NumOptionsProcessed++;
  799. BytesLeft -= pOptionHeader->OptionLength;
  800. if (pOptionHeader->E_OptionType & PACKET_OPTION_TYPE_END_BIT)
  801. {
  802. break;
  803. }
  804. pOptionHeader = (tPACKET_OPTION_GENERIC UNALIGNED *)
  805. (((UCHAR *) pOptionHeader) + pOptionHeader->OptionLength);
  806. } while (BytesLeft >= sizeof(tPACKET_OPTION_GENERIC));
  807. ASSERT (NT_SUCCESS (status));
  808. if (NT_SUCCESS (status))
  809. {
  810. if ((BytesLeft + TotalOptionsLength) == BytesAvailable)
  811. {
  812. pPacketOptions->OptionsLength = TotalOptionsLength;
  813. pPacketOptions->OptionsFlags = OptionsFlags;
  814. }
  815. else
  816. {
  817. PgmTrace (LogError, ("ProcessOptions: ERROR -- " \
  818. "BytesLeft=<%d> + TotalOptionsLength=<%d> != BytesAvailable=<%d>\n",
  819. BytesLeft, TotalOptionsLength, BytesAvailable));
  820. status = STATUS_INVALID_BUFFER_SIZE;
  821. }
  822. }
  823. PgmTrace (LogAllFuncs, ("ProcessOptions: " \
  824. "Processed <%d> options, TotalOptionsLength=<%d>\n", NumOptionsProcessed, TotalOptionsLength));
  825. return (status);
  826. }
  827. //----------------------------------------------------------------------------
  828. ULONG
  829. AdjustReceiveBufferLists(
  830. IN tRECEIVE_SESSION *pReceive
  831. )
  832. {
  833. tNAK_FORWARD_DATA *pNak;
  834. UCHAR TotalPackets, i;
  835. ULONG NumMoved = 0;
  836. ULONG DataPacketsMoved = 0;
  837. //
  838. // Update the last consumed time if we did not have any data buffered prior
  839. // to this
  840. //
  841. if (IsListEmpty (&pReceive->pReceiver->BufferedDataList))
  842. {
  843. pReceive->pReceiver->LastDataConsumedTime = PgmDynamicConfig.ReceiversTimerTickCount;
  844. }
  845. //
  846. // Assume we have no Naks pending
  847. //
  848. pReceive->pReceiver->FirstNakSequenceNumber = pReceive->pReceiver->FurthestKnownGroupSequenceNumber
  849. + pReceive->FECGroupSize;
  850. while (!IsListEmpty (&pReceive->pReceiver->NaksForwardDataList))
  851. {
  852. //
  853. // Move any Naks contexts for which the group is complete
  854. // to the BufferedDataList
  855. //
  856. pNak = CONTAINING_RECORD (pReceive->pReceiver->NaksForwardDataList.Flink, tNAK_FORWARD_DATA, Linkage);
  857. if (((pNak->NumDataPackets + pNak->NumParityPackets) < pNak->PacketsInGroup) &&
  858. ((pNak->NextIndexToIndicate + pNak->NumDataPackets) < pNak->PacketsInGroup))
  859. {
  860. pReceive->pReceiver->FirstNakSequenceNumber = pNak->SequenceNumber;
  861. break;
  862. }
  863. //
  864. // If this is a partial group with extraneous parity packets,
  865. // remove the parity packets
  866. //
  867. if ((pNak->NextIndexToIndicate) &&
  868. (pNak->NumParityPackets) &&
  869. ((pNak->NextIndexToIndicate + pNak->NumDataPackets) >= pNak->PacketsInGroup))
  870. {
  871. //
  872. // Start from the end and go backwards
  873. //
  874. i = TotalPackets = pNak->NumDataPackets + pNak->NumParityPackets;
  875. while (i && pNak->NumParityPackets)
  876. {
  877. i--; // Convert from packet # to index
  878. if (pNak->pPendingData[i].PacketIndex >= pNak->OriginalGroupSize)
  879. {
  880. PgmTrace (LogAllFuncs, ("AdjustReceiveBufferLists: " \
  881. "Extraneous parity [%d] -- NextIndex=<%d>, Data=<%d>, Parity=<%d>, PktsInGrp=<%d>\n",
  882. i, (ULONG) pNak->NextIndexToIndicate, (ULONG) pNak->NumDataPackets,
  883. (ULONG) pNak->NumParityPackets, (ULONG) pNak->PacketsInGroup));
  884. FreeDataBuffer (pReceive, &pNak->pPendingData[i]);
  885. if (i != (TotalPackets - 1))
  886. {
  887. PgmCopyMemory (&pNak->pPendingData[i], &pNak->pPendingData[TotalPackets-1], sizeof (tPENDING_DATA));
  888. }
  889. PgmZeroMemory (&pNak->pPendingData[TotalPackets-1], sizeof (tPENDING_DATA));
  890. pNak->NumParityPackets--;
  891. TotalPackets--;
  892. pReceive->pReceiver->DataPacketsPendingNaks--;
  893. pReceive->pReceiver->TotalDataPacketsBuffered--;
  894. }
  895. }
  896. //
  897. // Re-Init all the indices
  898. //
  899. for (i=0; i<pNak->OriginalGroupSize; i++)
  900. {
  901. pNak->pPendingData[i].ActualIndexOfDataPacket = pNak->OriginalGroupSize;
  902. }
  903. //
  904. // Set the indices only for the data packets
  905. //
  906. for (i=0; i<TotalPackets; i++)
  907. {
  908. if (pNak->pPendingData[i].PacketIndex < pNak->OriginalGroupSize)
  909. {
  910. pNak->pPendingData[pNak->pPendingData[i].PacketIndex].ActualIndexOfDataPacket = i;
  911. }
  912. }
  913. }
  914. RemoveEntryList (&pNak->Linkage);
  915. InsertTailList (&pReceive->pReceiver->BufferedDataList, &pNak->Linkage);
  916. NumMoved++;
  917. DataPacketsMoved += (pNak->NumDataPackets + pNak->NumParityPackets);
  918. }
  919. pReceive->pReceiver->NumPacketGroupsPendingClient += NumMoved;
  920. pReceive->pReceiver->DataPacketsPendingIndicate += DataPacketsMoved;
  921. pReceive->pReceiver->DataPacketsPendingNaks -= DataPacketsMoved;
  922. ASSERT (pReceive->pReceiver->TotalDataPacketsBuffered == (pReceive->pReceiver->DataPacketsPendingIndicate +
  923. pReceive->pReceiver->DataPacketsPendingNaks));
  924. return (NumMoved);
  925. }
  926. //----------------------------------------------------------------------------
  927. VOID
  928. AdjustNcfRDataResponseTimes(
  929. IN tRECEIVE_SESSION *pReceive,
  930. IN PNAK_FORWARD_DATA pLastNak
  931. )
  932. {
  933. ULONGLONG NcfRDataTickCounts;
  934. NcfRDataTickCounts = PgmDynamicConfig.ReceiversTimerTickCount - pLastNak->FirstNcfTickCount;
  935. pReceive->pReceiver->StatSumOfNcfRDataTicks += NcfRDataTickCounts;
  936. pReceive->pReceiver->NumNcfRDataTicksSamples++;
  937. if (!pReceive->pReceiver->NumNcfRDataTicksSamples)
  938. {
  939. //
  940. // This will be the divisor below, so it has to be non-zero!
  941. //
  942. ASSERT (0);
  943. return;
  944. }
  945. if ((NcfRDataTickCounts > pReceive->pReceiver->MaxOutstandingNakTimeout) &&
  946. (pReceive->pReceiver->MaxOutstandingNakTimeout !=
  947. pReceive->pReceiver->MaxRDataResponseTCFromWindow))
  948. {
  949. if (pReceive->pReceiver->MaxRDataResponseTCFromWindow &&
  950. NcfRDataTickCounts > pReceive->pReceiver->MaxRDataResponseTCFromWindow)
  951. {
  952. pReceive->pReceiver->MaxOutstandingNakTimeout = pReceive->pReceiver->MaxRDataResponseTCFromWindow;
  953. }
  954. else
  955. {
  956. pReceive->pReceiver->MaxOutstandingNakTimeout = NcfRDataTickCounts;
  957. }
  958. //
  959. // Since we just updated the Max value, we should also
  960. // recalculate the default timeout
  961. //
  962. pReceive->pReceiver->AverageNcfRDataResponseTC = pReceive->pReceiver->StatSumOfNcfRDataTicks /
  963. pReceive->pReceiver->NumNcfRDataTicksSamples;
  964. NcfRDataTickCounts = (pReceive->pReceiver->AverageNcfRDataResponseTC +
  965. pReceive->pReceiver->MaxOutstandingNakTimeout) >> 1;
  966. if (NcfRDataTickCounts > (pReceive->pReceiver->AverageNcfRDataResponseTC << 1))
  967. {
  968. NcfRDataTickCounts = pReceive->pReceiver->AverageNcfRDataResponseTC << 1;
  969. }
  970. if (NcfRDataTickCounts > pReceive->pReceiver->OutstandingNakTimeout)
  971. {
  972. pReceive->pReceiver->OutstandingNakTimeout = NcfRDataTickCounts;
  973. }
  974. }
  975. }
  976. //----------------------------------------------------------------------------
  977. VOID
  978. UpdateSpmIntervalInformation(
  979. IN tRECEIVE_SESSION *pReceive
  980. )
  981. {
  982. ULONG LastIntervalTickCount = (ULONG) (PgmDynamicConfig.ReceiversTimerTickCount -
  983. pReceive->pReceiver->LastSpmTickCount);
  984. if (!LastIntervalTickCount)
  985. {
  986. return;
  987. }
  988. pReceive->pReceiver->LastSpmTickCount = PgmDynamicConfig.ReceiversTimerTickCount;
  989. if (LastIntervalTickCount > pReceive->pReceiver->MaxSpmInterval)
  990. {
  991. pReceive->pReceiver->MaxSpmInterval = LastIntervalTickCount;
  992. }
  993. /*
  994. if (pReceive->pReceiver->NumSpmIntervalSamples)
  995. {
  996. pReceive->pReceiver->StatSumOfSpmIntervals += pReceive->pReceiver->LastSpmTickCount;
  997. pReceive->pReceiver->NumSpmIntervalSamples++;
  998. pReceive->pReceiver->AverageSpmInterval = pReceive->pReceiver->StatSumOfSpmIntervals /
  999. pReceive->pReceiver->NumSpmIntervalSamples;
  1000. }
  1001. */
  1002. }
  1003. //----------------------------------------------------------------------------
  1004. VOID
  1005. UpdateRealTimeWindowInformation(
  1006. IN tRECEIVE_SESSION *pReceive,
  1007. IN SEQ_TYPE LeadingEdgeSeqNumber,
  1008. IN SEQ_TYPE TrailingEdgeSeqNumber
  1009. )
  1010. {
  1011. tRECEIVE_CONTEXT *pReceiver = pReceive->pReceiver;
  1012. SEQ_TYPE SequencesInWindow = 1 + LeadingEdgeSeqNumber - TrailingEdgeSeqNumber;
  1013. if (SEQ_GT (SequencesInWindow, pReceiver->MaxSequencesInWindow))
  1014. {
  1015. pReceiver->MaxSequencesInWindow = SequencesInWindow;
  1016. }
  1017. if (TrailingEdgeSeqNumber)
  1018. {
  1019. if ((!pReceiver->MinSequencesInWindow) ||
  1020. SEQ_LT (SequencesInWindow, pReceiver->MinSequencesInWindow))
  1021. {
  1022. pReceiver->MinSequencesInWindow = SequencesInWindow;
  1023. }
  1024. pReceiver->StatSumOfWindowSeqs += SequencesInWindow;
  1025. pReceiver->NumWindowSamples++;
  1026. }
  1027. }
  1028. VOID
  1029. UpdateSampleTimeWindowInformation(
  1030. IN tRECEIVE_SESSION *pReceive
  1031. )
  1032. {
  1033. ULONGLONG NcfRDataTimeout;
  1034. tRECEIVE_CONTEXT *pReceiver = pReceive->pReceiver;
  1035. //
  1036. // No need to update if there is no data
  1037. //
  1038. if (!pReceive->MaxRateKBitsPerSec ||
  1039. !pReceive->TotalPacketsReceived) // Avoid divide by 0 error
  1040. {
  1041. return;
  1042. }
  1043. //
  1044. // Now, update the window information
  1045. //
  1046. if (pReceiver->NumWindowSamples)
  1047. {
  1048. pReceiver->AverageSequencesInWindow = pReceiver->StatSumOfWindowSeqs /
  1049. pReceiver->NumWindowSamples;
  1050. }
  1051. if (pReceiver->AverageSequencesInWindow)
  1052. {
  1053. pReceiver->WindowSizeLastInMSecs = ((pReceiver->AverageSequencesInWindow *
  1054. pReceive->TotalBytes) << LOG2_BITS_PER_BYTE) /
  1055. (pReceive->TotalPacketsReceived *
  1056. pReceive->MaxRateKBitsPerSec);
  1057. }
  1058. else
  1059. {
  1060. pReceiver->WindowSizeLastInMSecs = ((pReceiver->MaxSequencesInWindow *
  1061. pReceive->TotalBytes) << LOG2_BITS_PER_BYTE) /
  1062. (pReceive->TotalPacketsReceived *
  1063. pReceive->MaxRateKBitsPerSec);
  1064. }
  1065. pReceiver->MaxRDataResponseTCFromWindow = pReceiver->WindowSizeLastInMSecs /
  1066. (NCF_WAITING_RDATA_MAX_RETRIES * BASIC_TIMER_GRANULARITY_IN_MSECS);
  1067. PgmTrace (LogPath, ("UpdateSampleTimeWindowInformation: " \
  1068. "pReceive=<%p>, MaxRate=<%I64d>, AvgSeqsInWindow=<%I64d>, WinSzinMSecsLast=<%I64d>\n",
  1069. pReceive, pReceive->MaxRateKBitsPerSec, pReceiver->AverageSequencesInWindow, pReceiver->WindowSizeLastInMSecs));
  1070. //
  1071. // Now, update the NcfRData timeout information
  1072. //
  1073. if (pReceiver->StatSumOfNcfRDataTicks &&
  1074. pReceiver->NumNcfRDataTicksSamples)
  1075. {
  1076. pReceiver->AverageNcfRDataResponseTC = pReceiver->StatSumOfNcfRDataTicks /
  1077. pReceiver->NumNcfRDataTicksSamples;
  1078. }
  1079. if (pReceiver->AverageNcfRDataResponseTC)
  1080. {
  1081. NcfRDataTimeout = (pReceiver->AverageNcfRDataResponseTC +
  1082. pReceiver->MaxOutstandingNakTimeout) >> 1;
  1083. if (NcfRDataTimeout > (pReceiver->AverageNcfRDataResponseTC << 1))
  1084. {
  1085. NcfRDataTimeout = pReceiver->AverageNcfRDataResponseTC << 1;
  1086. }
  1087. if (NcfRDataTimeout >
  1088. pReceiver->InitialOutstandingNakTimeout/BASIC_TIMER_GRANULARITY_IN_MSECS)
  1089. {
  1090. pReceiver->OutstandingNakTimeout = NcfRDataTimeout;
  1091. }
  1092. else
  1093. {
  1094. pReceiver->OutstandingNakTimeout = pReceiver->InitialOutstandingNakTimeout /
  1095. BASIC_TIMER_GRANULARITY_IN_MSECS;
  1096. }
  1097. }
  1098. }
  1099. //----------------------------------------------------------------------------
  1100. VOID
  1101. RemoveRedundantNaks(
  1102. IN tRECEIVE_SESSION *pReceive,
  1103. IN tNAK_FORWARD_DATA *pNak,
  1104. IN BOOLEAN fEliminateExtraParityPackets
  1105. )
  1106. {
  1107. UCHAR i, TotalPackets;
  1108. ASSERT (fEliminateExtraParityPackets || !pNak->NumParityPackets);
  1109. TotalPackets = pNak->NumDataPackets + pNak->NumParityPackets;
  1110. //
  1111. // First, eliminate the NULL Packets
  1112. //
  1113. if (pNak->PacketsInGroup < pNak->OriginalGroupSize)
  1114. {
  1115. i = 0;
  1116. while (i < pNak->OriginalGroupSize)
  1117. {
  1118. if ((pNak->pPendingData[i].PacketIndex < pNak->PacketsInGroup) || // Non-NULL Data packet
  1119. (pNak->pPendingData[i].PacketIndex >= pNak->OriginalGroupSize)) // Parity packet
  1120. {
  1121. //
  1122. // Ignore for now!
  1123. //
  1124. i++;
  1125. continue;
  1126. }
  1127. FreeDataBuffer (pReceive, &pNak->pPendingData[i]);
  1128. if (i != (TotalPackets-1))
  1129. {
  1130. PgmCopyMemory (&pNak->pPendingData[i], &pNak->pPendingData[TotalPackets-1], sizeof (tPENDING_DATA));
  1131. }
  1132. PgmZeroMemory (&pNak->pPendingData[TotalPackets-1], sizeof (tPENDING_DATA));
  1133. pNak->NumDataPackets--;
  1134. TotalPackets--;
  1135. }
  1136. ASSERT (pNak->NumDataPackets <= TotalPackets);
  1137. if (fEliminateExtraParityPackets)
  1138. {
  1139. //
  1140. // If we still have extra parity packets, free those also
  1141. //
  1142. i = 0;
  1143. while ((i < TotalPackets) &&
  1144. (TotalPackets > pNak->PacketsInGroup))
  1145. {
  1146. ASSERT (pNak->NumParityPackets);
  1147. if (pNak->pPendingData[i].PacketIndex < pNak->OriginalGroupSize)
  1148. {
  1149. //
  1150. // Ignore data packets
  1151. //
  1152. i++;
  1153. continue;
  1154. }
  1155. FreeDataBuffer (pReceive, &pNak->pPendingData[i]);
  1156. if (i != (TotalPackets-1))
  1157. {
  1158. PgmCopyMemory (&pNak->pPendingData[i], &pNak->pPendingData[TotalPackets-1], sizeof (tPENDING_DATA));
  1159. }
  1160. PgmZeroMemory (&pNak->pPendingData[TotalPackets-1], sizeof (tPENDING_DATA));
  1161. pNak->NumParityPackets--;
  1162. TotalPackets--;
  1163. }
  1164. ASSERT (TotalPackets <= pNak->PacketsInGroup);
  1165. }
  1166. }
  1167. //
  1168. // Re-Init all the indices
  1169. //
  1170. for (i=0; i<pNak->OriginalGroupSize; i++)
  1171. {
  1172. pNak->pPendingData[i].ActualIndexOfDataPacket = pNak->OriginalGroupSize;
  1173. }
  1174. //
  1175. // Set the indices only for the data packets
  1176. //
  1177. for (i=0; i<TotalPackets; i++)
  1178. {
  1179. if (pNak->pPendingData[i].PacketIndex < pNak->OriginalGroupSize)
  1180. {
  1181. pNak->pPendingData[pNak->pPendingData[i].PacketIndex].ActualIndexOfDataPacket = i;
  1182. }
  1183. }
  1184. if ((fEliminateExtraParityPackets) &&
  1185. (((pNak->NumDataPackets + pNak->NumParityPackets) >= pNak->PacketsInGroup) ||
  1186. ((pNak->NextIndexToIndicate + pNak->NumDataPackets) >= pNak->PacketsInGroup)))
  1187. {
  1188. RemovePendingReceiverEntry (pNak);
  1189. }
  1190. }
  1191. //----------------------------------------------------------------------------
  1192. VOID
  1193. PgmSendNakCompletion(
  1194. IN tRECEIVE_SESSION *pReceive,
  1195. IN tNAK_CONTEXT *pNakContext,
  1196. IN NTSTATUS status
  1197. )
  1198. /*++
  1199. Routine Description:
  1200. This is the Completion routine called by IP on completing a NakSend
  1201. Arguments:
  1202. IN pReceive -- Receive context
  1203. IN pNakContext -- Nak Context to be free'ed
  1204. IN status -- status of send from tansport
  1205. Return Value:
  1206. NONE
  1207. --*/
  1208. {
  1209. PGMLockHandle OldIrq;
  1210. PgmLock (pReceive, OldIrq);
  1211. if (NT_SUCCESS (status))
  1212. {
  1213. //
  1214. // Set the Receiver Nak statistics
  1215. //
  1216. PgmTrace (LogAllFuncs, ("PgmSendNakCompletion: " \
  1217. "SUCCEEDED\n"));
  1218. }
  1219. else
  1220. {
  1221. PgmTrace (LogError, ("PgmSendNakCompletion: ERROR -- " \
  1222. "status=<%x>\n", status));
  1223. }
  1224. if (!(--pNakContext->RefCount))
  1225. {
  1226. PgmUnlock (pReceive, OldIrq);
  1227. //
  1228. // Free the Memory and deref the Session context for this Nak
  1229. //
  1230. PgmFreeMem (pNakContext);
  1231. PGM_DEREFERENCE_SESSION_RECEIVE (pReceive, REF_SESSION_SEND_NAK);
  1232. }
  1233. else
  1234. {
  1235. PgmUnlock (pReceive, OldIrq);
  1236. }
  1237. }
  1238. //----------------------------------------------------------------------------
  1239. NTSTATUS
  1240. PgmSendNak(
  1241. IN tRECEIVE_SESSION *pReceive,
  1242. IN tNAKS_CONTEXT *pNakSequences
  1243. )
  1244. /*++
  1245. Routine Description:
  1246. This routine sends a Nak packet with the number of sequences specified
  1247. Arguments:
  1248. IN pReceive -- Receive context
  1249. IN pNakSequences -- List of Sequence #s
  1250. Return Value:
  1251. NTSTATUS - Final status of the operation
  1252. --*/
  1253. {
  1254. tBASIC_NAK_NCF_PACKET_HEADER *pNakPacket;
  1255. tNAK_CONTEXT *pNakContext;
  1256. tPACKET_OPTION_LENGTH *pPacketExtension;
  1257. tPACKET_OPTION_GENERIC *pOptionHeader;
  1258. ULONG i;
  1259. ULONG XSum;
  1260. USHORT OptionsLength = 0;
  1261. NTSTATUS status;
  1262. if ((!pNakSequences->NumSequences) ||
  1263. (pNakSequences->NumSequences > (MAX_SEQUENCES_PER_NAK_OPTION+1)) ||
  1264. (!(pNakContext = PgmAllocMem ((2*sizeof(ULONG)+PGM_MAX_NAK_NCF_HEADER_LENGTH), PGM_TAG('2')))))
  1265. {
  1266. PgmTrace (LogError, ("PgmSendNak: ERROR -- " \
  1267. "STATUS_INSUFFICIENT_RESOURCES allocating pNakContext\n"));
  1268. return (STATUS_INSUFFICIENT_RESOURCES);
  1269. }
  1270. PgmZeroMemory (pNakContext, (2*sizeof(ULONG)+PGM_MAX_NAK_NCF_HEADER_LENGTH));
  1271. pNakContext->RefCount = 2; // 1 for the unicast, and the other for the MCast Nak
  1272. pNakPacket = &pNakContext->NakPacket;
  1273. pNakPacket->CommonHeader.SrcPort = htons (pReceive->pReceiver->ListenMCastPort);
  1274. pNakPacket->CommonHeader.DestPort = htons (pReceive->TSI.hPort);
  1275. pNakPacket->CommonHeader.Type = PACKET_TYPE_NAK;
  1276. if (pNakSequences->NakType == NAK_TYPE_PARITY)
  1277. {
  1278. pNakPacket->CommonHeader.Options = PACKET_HEADER_OPTIONS_PARITY;
  1279. pReceive->pReceiver->TotalParityNaksSent += pNakSequences->NumSequences;
  1280. }
  1281. else
  1282. {
  1283. pNakPacket->CommonHeader.Options = 0;
  1284. pReceive->pReceiver->TotalSelectiveNaksSent += pNakSequences->NumSequences;
  1285. }
  1286. PgmCopyMemory (&pNakPacket->CommonHeader.gSourceId, pReceive->TSI.GSI, SOURCE_ID_LENGTH);
  1287. pNakPacket->RequestedSequenceNumber = htonl ((ULONG) pNakSequences->Sequences[0]);
  1288. pNakPacket->SourceNLA.NLA_AFI = htons (IPV4_NLA_AFI);
  1289. pNakPacket->SourceNLA.IpAddress = htonl (pReceive->pReceiver->SenderIpAddress);
  1290. pNakPacket->MCastGroupNLA.NLA_AFI = htons (IPV4_NLA_AFI);
  1291. pNakPacket->MCastGroupNLA.IpAddress = htonl (pReceive->pReceiver->ListenMCastIpAddress);
  1292. PgmTrace (LogPath, ("PgmSendNak: " \
  1293. "Sending Naks for:\n\t[%d]\n", (ULONG) pNakSequences->Sequences[0]));
  1294. if (pNakSequences->NumSequences > 1)
  1295. {
  1296. pPacketExtension = (tPACKET_OPTION_LENGTH *) (pNakPacket + 1);
  1297. pPacketExtension->Type = PACKET_OPTION_LENGTH;
  1298. pPacketExtension->Length = PGM_PACKET_EXTENSION_LENGTH;
  1299. OptionsLength += PGM_PACKET_EXTENSION_LENGTH;
  1300. pOptionHeader = (tPACKET_OPTION_GENERIC *) (pPacketExtension + 1);
  1301. pOptionHeader->E_OptionType = PACKET_OPTION_NAK_LIST;
  1302. pOptionHeader->OptionLength = 4 + (UCHAR) ((pNakSequences->NumSequences-1) * sizeof(ULONG));
  1303. for (i=1; i<pNakSequences->NumSequences; i++)
  1304. {
  1305. PgmTrace (LogPath, ("PgmSendNak: " \
  1306. "\t[%d]\n", (ULONG) pNakSequences->Sequences[i]));
  1307. ((PULONG) (pOptionHeader))[i] = htonl ((ULONG) pNakSequences->Sequences[i]);
  1308. }
  1309. pOptionHeader->E_OptionType |= PACKET_OPTION_TYPE_END_BIT; // One and only (last) opt
  1310. pNakPacket->CommonHeader.Options |=(PACKET_HEADER_OPTIONS_PRESENT |
  1311. PACKET_HEADER_OPTIONS_NETWORK_SIGNIFICANT);
  1312. OptionsLength = PGM_PACKET_EXTENSION_LENGTH + pOptionHeader->OptionLength;
  1313. pPacketExtension->TotalOptionsLength = htons (OptionsLength);
  1314. }
  1315. OptionsLength += sizeof(tBASIC_NAK_NCF_PACKET_HEADER); // Now is whole pkt
  1316. pNakPacket->CommonHeader.Checksum = 0;
  1317. XSum = 0;
  1318. XSum = tcpxsum (XSum, (CHAR *) pNakPacket, OptionsLength);
  1319. pNakPacket->CommonHeader.Checksum = (USHORT) (~XSum);
  1320. PGM_REFERENCE_SESSION_RECEIVE (pReceive, REF_SESSION_SEND_NAK, FALSE);
  1321. //
  1322. // First multicast the Nak
  1323. //
  1324. status = TdiSendDatagram (pReceive->pReceiver->pAddress->pFileObject,
  1325. pReceive->pReceiver->pAddress->pDeviceObject,
  1326. pNakPacket,
  1327. OptionsLength,
  1328. PgmSendNakCompletion, // Completion
  1329. pReceive, // Context1
  1330. pNakContext, // Context2
  1331. pReceive->pReceiver->ListenMCastIpAddress,
  1332. pReceive->pReceiver->ListenMCastPort,
  1333. FALSE);
  1334. ASSERT (NT_SUCCESS (status));
  1335. //
  1336. // Now, Unicast the Nak
  1337. //
  1338. status = TdiSendDatagram (pReceive->pReceiver->pAddress->pFileObject,
  1339. pReceive->pReceiver->pAddress->pDeviceObject,
  1340. pNakPacket,
  1341. OptionsLength,
  1342. PgmSendNakCompletion, // Completion
  1343. pReceive, // Context1
  1344. pNakContext, // Context2
  1345. pReceive->pReceiver->LastSpmSource,
  1346. IPPROTO_RM,
  1347. FALSE);
  1348. ASSERT (NT_SUCCESS (status));
  1349. PgmTrace (LogAllFuncs, ("PgmSendNak: " \
  1350. "Sent %s Nak for <%d> Sequences [%d--%d] to <%x:%d>\n",
  1351. (pNakSequences->NakType == NAK_TYPE_PARITY ? "PARITY" : "SELECTIVE"),
  1352. pNakSequences->NumSequences, (ULONG) pNakSequences->Sequences[0],
  1353. (ULONG) pNakSequences->Sequences[pNakSequences->NumSequences-1],
  1354. pReceive->pReceiver->SenderIpAddress, IPPROTO_RM));
  1355. return (status);
  1356. }
  1357. //----------------------------------------------------------------------------
  1358. VOID
  1359. CheckSendPendingNaks(
  1360. IN tADDRESS_CONTEXT *pAddress,
  1361. IN tRECEIVE_SESSION *pReceive,
  1362. IN tRECEIVE_CONTEXT *pReceiver,
  1363. IN PGMLockHandle *pOldIrq
  1364. )
  1365. /*++
  1366. Routine Description:
  1367. This routine checks if any Naks need to be sent and sends them
  1368. as required
  1369. The PgmDynamicConfig lock is held on entry and exit from
  1370. this routine
  1371. Arguments:
  1372. IN pAddress -- Address object context
  1373. IN pReceive -- Receive context
  1374. IN pOldIrq -- Irq for PgmDynamicConfig
  1375. Return Value:
  1376. NONE
  1377. --*/
  1378. {
  1379. tNAKS_CONTEXT *pNakContext, *pSelectiveNaks = NULL;
  1380. tNAKS_CONTEXT *pParityNaks = NULL;
  1381. LIST_ENTRY NaksList;
  1382. LIST_ENTRY *pEntry;
  1383. tNAK_FORWARD_DATA *pNak;
  1384. PGMLockHandle OldIrq, OldIrq1;
  1385. ULONG NumMissingPackets, PacketsInGroup, NumNaks, TotalSeqsNacked = 0;
  1386. BOOLEAN fSendSelectiveNak, fSendParityNak;
  1387. UCHAR i, j;
  1388. ULONG NumPendingNaks = 0;
  1389. ULONG NumOutstandingNaks = 0;
  1390. USHORT Index;
  1391. ULONG NakRandomBackoffMSecs, NakRepeatIntervalMSecs;
  1392. if ((!pReceiver->LastSpmSource) ||
  1393. ((pReceiver->DataPacketsPendingNaks <= OUT_OF_ORDER_PACKETS_BEFORE_NAK) &&
  1394. ((pReceiver->LastNakSendTime + (pReceive->pReceiver->InitialOutstandingNakTimeout>>2)) >
  1395. PgmDynamicConfig.ReceiversTimerTickCount)))
  1396. {
  1397. PgmTrace (LogPath, ("CheckSendPendingNaks: " \
  1398. "No Naks to send for pReceive=<%p>, LastSpmSource=<%x>, NumDataPackets=<%d>, LastSendTime=<%I64d>, Current=<%I64d>\n",
  1399. pReceive, pReceiver->LastSpmSource,
  1400. pReceiver->DataPacketsPendingNaks,
  1401. pReceiver->LastNakSendTime+(NAK_MIN_INITIAL_BACKOFF_TIMEOUT_MSECS/BASIC_TIMER_GRANULARITY_IN_MSECS),
  1402. PgmDynamicConfig.ReceiversTimerTickCount));
  1403. return;
  1404. }
  1405. InitializeListHead (&NaksList);
  1406. if (!(pSelectiveNaks = PgmAllocMem (sizeof (tNAKS_CONTEXT), PGM_TAG('5'))) ||
  1407. !(pParityNaks = PgmAllocMem (sizeof (tNAKS_CONTEXT), PGM_TAG('6'))))
  1408. {
  1409. PgmTrace (LogError, ("CheckSendPendingNaks: ERROR -- " \
  1410. "STATUS_INSUFFICIENT_RESOURCES allocating pNakContext\n"));
  1411. if (pSelectiveNaks)
  1412. {
  1413. PgmFreeMem (pSelectiveNaks);
  1414. }
  1415. return;
  1416. }
  1417. PgmZeroMemory (pSelectiveNaks, sizeof (tNAKS_CONTEXT));
  1418. PgmZeroMemory (pParityNaks, sizeof (tNAKS_CONTEXT));
  1419. pParityNaks->NakType = NAK_TYPE_PARITY;
  1420. pSelectiveNaks->NakType = NAK_TYPE_SELECTIVE;
  1421. InsertTailList (&NaksList, &pParityNaks->Linkage);
  1422. InsertTailList (&NaksList, &pSelectiveNaks->Linkage);
  1423. PgmLock (pAddress, OldIrq);
  1424. PgmLock (pReceive, OldIrq1);
  1425. AdjustReceiveBufferLists (pReceive);
  1426. if (pAddress->Flags & PGM_ADDRESS_HIGH_SPEED_OPTIMIZED)
  1427. {
  1428. NakRandomBackoffMSecs = NAK_RANDOM_BACKOFF_MSECS_OPT;
  1429. NakRepeatIntervalMSecs = NAK_REPEAT_INTERVAL_MSECS_OPT;
  1430. }
  1431. else
  1432. {
  1433. NakRandomBackoffMSecs = NAK_RANDOM_BACKOFF_MSECS;
  1434. NakRepeatIntervalMSecs = NAK_REPEAT_INTERVAL_MSECS;
  1435. }
  1436. fSendSelectiveNak = fSendParityNak = FALSE;
  1437. pEntry = &pReceiver->PendingNaksList;
  1438. while ((pEntry = pEntry->Flink) != &pReceive->pReceiver->PendingNaksList)
  1439. {
  1440. pNak = CONTAINING_RECORD (pEntry, tNAK_FORWARD_DATA, SendNakLinkage);
  1441. NumMissingPackets = pNak->PacketsInGroup - (pNak->NumDataPackets + pNak->NumParityPackets);
  1442. ASSERT (NumMissingPackets);
  1443. //
  1444. // if this Nak is outside the trailing window, then we are hosed!
  1445. //
  1446. if (SEQ_GT (pReceiver->LastTrailingEdgeSeqNum, pNak->SequenceNumber))
  1447. {
  1448. PgmTrace (LogError, ("CheckSendPendingNaks: ERROR -- " \
  1449. "Sequence # [%d] out of trailing edge <%d>, NumNcfs received=<%d>\n",
  1450. (ULONG) pNak->SequenceNumber,
  1451. (ULONG) pReceiver->LastTrailingEdgeSeqNum,
  1452. pNak->WaitingRDataRetries));
  1453. pReceive->SessionFlags |= PGM_SESSION_FLAG_NAK_TIMED_OUT;
  1454. break;
  1455. }
  1456. //
  1457. // See if we are currently in NAK pending mode
  1458. //
  1459. if (pNak->PendingNakTimeout)
  1460. {
  1461. NumPendingNaks += NumMissingPackets;
  1462. if (PgmDynamicConfig.ReceiversTimerTickCount > pNak->PendingNakTimeout)
  1463. {
  1464. //
  1465. // Time out Naks only after we have received a FIN!
  1466. //
  1467. if (pNak->WaitingNcfRetries++ >= NAK_WAITING_NCF_MAX_RETRIES)
  1468. {
  1469. PgmTrace (LogError, ("CheckSendPendingNaks: ERROR -- " \
  1470. "Pending Nak for Sequence # [%d] Timed out! Num Naks sent=<%d>, Window=<%d--%d> ( %d seqs)\n",
  1471. (ULONG) pNak->SequenceNumber, pNak->WaitingNcfRetries,
  1472. (ULONG) pReceiver->LastTrailingEdgeSeqNum,
  1473. (ULONG) pReceiver->FurthestKnownGroupSequenceNumber,
  1474. (ULONG) (1+pReceiver->FurthestKnownGroupSequenceNumber-
  1475. pReceiver->LastTrailingEdgeSeqNum)));
  1476. pReceive->SessionFlags |= PGM_SESSION_FLAG_NAK_TIMED_OUT;
  1477. break;
  1478. }
  1479. if ((pNak->PacketsInGroup > 1) &&
  1480. (pReceive->FECOptions & PACKET_OPTION_SPECIFIC_FEC_OND_BIT) &&
  1481. ((pNak->SequenceNumber != pReceiver->FurthestKnownGroupSequenceNumber) ||
  1482. (SEQ_GEQ (pReceiver->FurthestKnownSequenceNumber, (pNak->SequenceNumber+pReceive->FECGroupSize-1)))))
  1483. {
  1484. ASSERT (NumMissingPackets <= pReceive->FECGroupSize);
  1485. pParityNaks->Sequences[pParityNaks->NumSequences] = (SEQ_TYPE) (pNak->SequenceNumber + NumMissingPackets - 1);
  1486. if (++pParityNaks->NumSequences == (MAX_SEQUENCES_PER_NAK_OPTION+1))
  1487. {
  1488. fSendParityNak = TRUE;
  1489. }
  1490. pNak->PendingNakTimeout = PgmDynamicConfig.ReceiversTimerTickCount +
  1491. ((NakRepeatIntervalMSecs + (NakRandomBackoffMSecs/NumMissingPackets)) /
  1492. BASIC_TIMER_GRANULARITY_IN_MSECS);
  1493. TotalSeqsNacked += NumMissingPackets;
  1494. NumMissingPackets = 0;
  1495. }
  1496. else
  1497. {
  1498. NumNaks = 0;
  1499. if (pReceive->FECOptions)
  1500. {
  1501. if (pNak->SequenceNumber == pReceiver->FurthestKnownGroupSequenceNumber)
  1502. {
  1503. ASSERT (SEQ_GEQ (pReceiver->FurthestKnownSequenceNumber, pReceiver->FurthestKnownGroupSequenceNumber));
  1504. PacketsInGroup = pReceiver->FurthestKnownSequenceNumber - pNak->SequenceNumber + 1;
  1505. ASSERT (PacketsInGroup >= (ULONG) (pNak->NumDataPackets + pNak->NumParityPackets));
  1506. }
  1507. else
  1508. {
  1509. PacketsInGroup = pNak->PacketsInGroup;
  1510. }
  1511. NumMissingPackets = PacketsInGroup -
  1512. (pNak->NextIndexToIndicate +pNak->NumDataPackets +pNak->NumParityPackets);
  1513. ASSERT ((NumMissingPackets) ||
  1514. (pNak->SequenceNumber == pReceiver->FurthestKnownGroupSequenceNumber));
  1515. for (i=pNak->NextIndexToIndicate; i<PacketsInGroup; i++)
  1516. {
  1517. if (pNak->pPendingData[i].ActualIndexOfDataPacket >= pNak->OriginalGroupSize)
  1518. {
  1519. if (!pNak->pPendingData[i].NcfsReceivedForActualIndex)
  1520. {
  1521. pSelectiveNaks->Sequences[pSelectiveNaks->NumSequences++] = pNak->SequenceNumber+i;
  1522. NumNaks++;
  1523. }
  1524. if (pSelectiveNaks->NumSequences == (MAX_SEQUENCES_PER_NAK_OPTION+1))
  1525. {
  1526. if (!(pSelectiveNaks = PgmAllocMem (sizeof (tNAKS_CONTEXT), PGM_TAG('5'))))
  1527. {
  1528. PgmTrace (LogError, ("CheckSendPendingNaks: ERROR -- " \
  1529. "STATUS_INSUFFICIENT_RESOURCES allocating pSelectiveNaks\n"));
  1530. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  1531. break;
  1532. }
  1533. PgmZeroMemory (pSelectiveNaks, sizeof (tNAKS_CONTEXT));
  1534. pSelectiveNaks->NakType = NAK_TYPE_SELECTIVE;
  1535. InsertTailList (&NaksList, &pSelectiveNaks->Linkage);
  1536. }
  1537. if (!--NumMissingPackets)
  1538. {
  1539. break;
  1540. }
  1541. }
  1542. }
  1543. ASSERT (!NumMissingPackets);
  1544. if (NumNaks)
  1545. {
  1546. TotalSeqsNacked += NumNaks;
  1547. }
  1548. else
  1549. {
  1550. pNak->WaitingNcfRetries--;
  1551. }
  1552. }
  1553. else
  1554. {
  1555. pSelectiveNaks->Sequences[pSelectiveNaks->NumSequences++] = pNak->SequenceNumber;
  1556. TotalSeqsNacked++;
  1557. }
  1558. pNak->PendingNakTimeout = PgmDynamicConfig.ReceiversTimerTickCount +
  1559. ((NakRepeatIntervalMSecs + NakRandomBackoffMSecs) /
  1560. BASIC_TIMER_GRANULARITY_IN_MSECS);
  1561. if (!pSelectiveNaks)
  1562. {
  1563. break;
  1564. }
  1565. if (pSelectiveNaks->NumSequences == (MAX_SEQUENCES_PER_NAK_OPTION+1))
  1566. {
  1567. fSendSelectiveNak = TRUE;
  1568. }
  1569. }
  1570. }
  1571. }
  1572. else if (pNak->OutstandingNakTimeout)
  1573. {
  1574. NumOutstandingNaks += NumMissingPackets;
  1575. if (PgmDynamicConfig.ReceiversTimerTickCount > pNak->OutstandingNakTimeout)
  1576. {
  1577. //
  1578. // We have timed-out waiting for RData -- Reset the Timeout to send
  1579. // a Nak after the Random Backoff (if we have not exceeded the Data retries)
  1580. //
  1581. if (pNak->WaitingRDataRetries++ == NCF_WAITING_RDATA_MAX_RETRIES)
  1582. {
  1583. PgmTrace (LogError, ("CheckSendPendingNaks: ERROR -- " \
  1584. "Outstanding Nak for Sequence # [%d] Timed out!, Window=<%d--%d> ( %d seqs), Ncfs=<%d>, FirstNak=<%d>\n",
  1585. (ULONG) pNak->SequenceNumber, (ULONG) pReceiver->LastTrailingEdgeSeqNum,
  1586. (ULONG) pReceiver->FurthestKnownGroupSequenceNumber,
  1587. (ULONG) (1+pReceiver->FurthestKnownGroupSequenceNumber-pReceiver->LastTrailingEdgeSeqNum),
  1588. pNak->WaitingRDataRetries, (ULONG) pReceiver->FirstNakSequenceNumber));
  1589. pReceive->SessionFlags |= PGM_SESSION_FLAG_NAK_TIMED_OUT;
  1590. break;
  1591. }
  1592. pNak->WaitingNcfRetries = 0;
  1593. pNak->OutstandingNakTimeout = 0;
  1594. pNak->PendingNakTimeout = PgmDynamicConfig.ReceiversTimerTickCount +
  1595. ((NakRandomBackoffMSecs/NumMissingPackets) /
  1596. BASIC_TIMER_GRANULARITY_IN_MSECS);
  1597. for (i=0; i<pNak->PacketsInGroup; i++)
  1598. {
  1599. pNak->pPendingData[i].NcfsReceivedForActualIndex = 0;
  1600. }
  1601. NumMissingPackets = 0;
  1602. }
  1603. }
  1604. while (fSendSelectiveNak || fSendParityNak)
  1605. {
  1606. if (fSendSelectiveNak)
  1607. {
  1608. if (!(pSelectiveNaks = PgmAllocMem (sizeof (tNAKS_CONTEXT), PGM_TAG('5'))))
  1609. {
  1610. PgmTrace (LogError, ("CheckSendPendingNaks: ERROR -- " \
  1611. "STATUS_INSUFFICIENT_RESOURCES allocating pSelectiveNaks\n"));
  1612. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  1613. break;
  1614. }
  1615. PgmZeroMemory (pSelectiveNaks, sizeof (tNAKS_CONTEXT));
  1616. pSelectiveNaks->NakType = NAK_TYPE_SELECTIVE;
  1617. InsertTailList (&NaksList, &pSelectiveNaks->Linkage);
  1618. fSendSelectiveNak = FALSE;
  1619. }
  1620. if (fSendParityNak)
  1621. {
  1622. if (!(pParityNaks = PgmAllocMem (sizeof (tNAKS_CONTEXT), PGM_TAG('6'))))
  1623. {
  1624. PgmTrace (LogError, ("CheckSendPendingNaks: ERROR -- " \
  1625. "STATUS_INSUFFICIENT_RESOURCES allocating pParityNaks\n"));
  1626. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  1627. break;
  1628. }
  1629. PgmZeroMemory (pParityNaks, sizeof (tNAKS_CONTEXT));
  1630. pParityNaks->NakType = NAK_TYPE_PARITY;
  1631. InsertTailList (&NaksList, &pParityNaks->Linkage);
  1632. fSendParityNak = FALSE;
  1633. }
  1634. }
  1635. if (pReceive->SessionFlags & PGM_SESSION_TERMINATED_ABORT)
  1636. {
  1637. break;
  1638. }
  1639. }
  1640. pReceiver->NumPendingNaks = NumPendingNaks;
  1641. pReceiver->NumOutstandingNaks = NumOutstandingNaks;
  1642. if (!IsListEmpty (&NaksList))
  1643. {
  1644. pReceiver->LastNakSendTime = PgmDynamicConfig.ReceiversTimerTickCount;
  1645. }
  1646. PgmUnlock (pReceive, OldIrq1);
  1647. PgmUnlock (pAddress, OldIrq);
  1648. PgmUnlock (&PgmDynamicConfig, *pOldIrq);
  1649. while (!IsListEmpty (&NaksList))
  1650. {
  1651. pNakContext = CONTAINING_RECORD (NaksList.Flink, tNAKS_CONTEXT, Linkage);
  1652. if (pNakContext->NumSequences &&
  1653. !(pReceive->SessionFlags & (PGM_SESSION_FLAG_NAK_TIMED_OUT | PGM_SESSION_TERMINATED_ABORT)))
  1654. {
  1655. PgmTrace (LogAllFuncs, ("CheckSendPendingNaks: " \
  1656. "Sending %s Nak for <%d> sequences, [%d -- %d]!\n",
  1657. (pNakContext->NakType == NAK_TYPE_PARITY ? "Parity" : "Selective"),
  1658. pNakContext->NumSequences, (ULONG) pNakContext->Sequences[0],
  1659. (ULONG) pNakContext->Sequences[MAX_SEQUENCES_PER_NAK_OPTION]));
  1660. PgmSendNak (pReceive, pNakContext);
  1661. }
  1662. RemoveEntryList (&pNakContext->Linkage);
  1663. PgmFreeMem (pNakContext);
  1664. }
  1665. PgmLock (&PgmDynamicConfig, *pOldIrq);
  1666. }
  1667. //----------------------------------------------------------------------------
  1668. VOID
  1669. CheckForSessionTimeout(
  1670. IN tRECEIVE_SESSION *pReceive,
  1671. IN tRECEIVE_CONTEXT *pReceiver
  1672. )
  1673. {
  1674. ULONG LastInterval;
  1675. LastInterval = (ULONG) (PgmDynamicConfig.ReceiversTimerTickCount -
  1676. pReceiver->LastSessionTickCount);
  1677. if ((LastInterval > MAX_SPM_INTERVAL_MSECS/BASIC_TIMER_GRANULARITY_IN_MSECS) &&
  1678. (LastInterval > (pReceiver->MaxSpmInterval << 5))) // (32 * MaxSpmInterval)
  1679. {
  1680. PgmTrace (LogError, ("ReceiveTimerTimeout: ERROR -- " \
  1681. "Disconnecting session because no SPM or Data packets received for <%d> Msecs\n",
  1682. (LastInterval * BASIC_TIMER_GRANULARITY_IN_MSECS)));
  1683. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  1684. return;
  1685. }
  1686. LastInterval = (ULONG) (PgmDynamicConfig.ReceiversTimerTickCount -
  1687. pReceiver->LastDataConsumedTime);
  1688. if ((!IsListEmpty (&pReceiver->BufferedDataList)) &&
  1689. (LastInterval > MAX_DATA_CONSUMPTION_TIME_MSECS/BASIC_TIMER_GRANULARITY_IN_MSECS))
  1690. {
  1691. PgmTrace (LogError, ("ReceiveTimerTimeout: ERROR -- " \
  1692. "Disconnecting session because Data has not been consumed for <%I64x> Msecs\n",
  1693. (LastInterval * BASIC_TIMER_GRANULARITY_IN_MSECS)));
  1694. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  1695. }
  1696. }
  1697. //----------------------------------------------------------------------------
  1698. VOID
  1699. ReceiveTimerTimeout(
  1700. IN PKDPC Dpc,
  1701. IN PVOID DeferredContext,
  1702. IN PVOID SystemArg1,
  1703. IN PVOID SystemArg2
  1704. )
  1705. /*++
  1706. Routine Description:
  1707. This timeout routine is called periodically to cycle through the
  1708. list of active receivers and send any Naks if required
  1709. Arguments:
  1710. IN Dpc
  1711. IN DeferredContext -- Our context for this timer
  1712. IN SystemArg1
  1713. IN SystemArg2
  1714. Return Value:
  1715. NONE
  1716. --*/
  1717. {
  1718. LIST_ENTRY *pEntry;
  1719. PGMLockHandle OldIrq, OldIrq1;
  1720. tRECEIVE_CONTEXT *pReceiver;
  1721. tRECEIVE_SESSION *pReceive;
  1722. NTSTATUS status;
  1723. LARGE_INTEGER Now;
  1724. LARGE_INTEGER DeltaTime, GranularTimeElapsed;
  1725. ULONG NumTimeouts;
  1726. BOOLEAN fReStartTimer = TRUE;
  1727. ULONGLONG BytesInLastInterval;
  1728. PgmLock (&PgmDynamicConfig, OldIrq);
  1729. ASSERT (!IsListEmpty (&PgmDynamicConfig.CurrentReceivers));
  1730. Now.QuadPart = KeQueryInterruptTime ();
  1731. DeltaTime.QuadPart = Now.QuadPart - PgmDynamicConfig.LastReceiverTimeout.QuadPart;
  1732. //
  1733. // If more than a certain number of timeouts have elapsed, we should skip the
  1734. // optimization since it could result in a big loop!
  1735. // Let's limit the optimization to 256 times the TimeoutGranularity for now.
  1736. //
  1737. if (DeltaTime.QuadPart > (PgmDynamicConfig.TimeoutGranularity.QuadPart << 8))
  1738. {
  1739. NumTimeouts = (ULONG) (DeltaTime.QuadPart / PgmDynamicConfig.TimeoutGranularity.QuadPart);
  1740. GranularTimeElapsed.QuadPart = NumTimeouts * PgmDynamicConfig.TimeoutGranularity.QuadPart;
  1741. }
  1742. else
  1743. {
  1744. for (GranularTimeElapsed.QuadPart = 0, NumTimeouts = 0;
  1745. DeltaTime.QuadPart > PgmDynamicConfig.TimeoutGranularity.QuadPart;
  1746. NumTimeouts++)
  1747. {
  1748. GranularTimeElapsed.QuadPart += PgmDynamicConfig.TimeoutGranularity.QuadPart;
  1749. DeltaTime.QuadPart -= PgmDynamicConfig.TimeoutGranularity.QuadPart;
  1750. }
  1751. }
  1752. if (!NumTimeouts)
  1753. {
  1754. PgmInitTimer (&PgmDynamicConfig.SessionTimer);
  1755. PgmStartTimer (&PgmDynamicConfig.SessionTimer, BASIC_TIMER_GRANULARITY_IN_MSECS, ReceiveTimerTimeout, NULL);
  1756. PgmUnlock (&PgmDynamicConfig, OldIrq);
  1757. return;
  1758. }
  1759. PgmDynamicConfig.ReceiversTimerTickCount += NumTimeouts;
  1760. PgmDynamicConfig.LastReceiverTimeout.QuadPart += GranularTimeElapsed.QuadPart;
  1761. pEntry = &PgmDynamicConfig.CurrentReceivers;
  1762. while ((pEntry = pEntry->Flink) != &PgmDynamicConfig.CurrentReceivers)
  1763. {
  1764. pReceiver = CONTAINING_RECORD (pEntry, tRECEIVE_CONTEXT, Linkage);
  1765. pReceive = pReceiver->pReceive;
  1766. PgmLock (pReceive, OldIrq1);
  1767. CheckForSessionTimeout (pReceive, pReceiver);
  1768. if (pReceive->SessionFlags & (PGM_SESSION_FLAG_NAK_TIMED_OUT | PGM_SESSION_TERMINATED_ABORT))
  1769. {
  1770. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  1771. pReceive->SessionFlags &= ~PGM_SESSION_ON_TIMER;
  1772. }
  1773. if (pReceive->SessionFlags & PGM_SESSION_ON_TIMER)
  1774. {
  1775. pReceive->RateCalcTimeout += NumTimeouts;
  1776. if ((pReceive->RateCalcTimeout >=
  1777. (INTERNAL_RATE_CALCULATION_FREQUENCY/BASIC_TIMER_GRANULARITY_IN_MSECS)) &&
  1778. (pReceiver->StartTickCount != PgmDynamicConfig.ReceiversTimerTickCount)) // Avoid Div by 0
  1779. {
  1780. BytesInLastInterval = pReceive->TotalBytes - pReceive->TotalBytesAtLastInterval;
  1781. pReceive->RateKBitsPerSecOverall = (pReceive->TotalBytes << LOG2_BITS_PER_BYTE) /
  1782. ((PgmDynamicConfig.ReceiversTimerTickCount-pReceiver->StartTickCount) * BASIC_TIMER_GRANULARITY_IN_MSECS);
  1783. pReceive->RateKBitsPerSecLast = BytesInLastInterval >>
  1784. (LOG2_INTERNAL_RATE_CALCULATION_FREQUENCY-LOG2_BITS_PER_BYTE);
  1785. if (pReceive->RateKBitsPerSecLast > pReceive->MaxRateKBitsPerSec)
  1786. {
  1787. pReceive->MaxRateKBitsPerSec = pReceive->RateKBitsPerSecLast;
  1788. }
  1789. //
  1790. // Now, Reset for next calculations
  1791. //
  1792. pReceive->DataBytesAtLastInterval = pReceive->DataBytes;
  1793. pReceive->TotalBytesAtLastInterval = pReceive->TotalBytes;
  1794. pReceive->RateCalcTimeout = 0;
  1795. //
  1796. // Now, update the window information, if applicable
  1797. //
  1798. if (pReceive->RateKBitsPerSecLast)
  1799. {
  1800. UpdateSampleTimeWindowInformation (pReceive);
  1801. }
  1802. pReceiver->StatSumOfWindowSeqs = pReceiver->NumWindowSamples = 0;
  1803. // pReceiver->StatSumOfNcfRDataTicks = pReceiver->NumNcfRDataTicksSamples = 0;
  1804. }
  1805. if (IsListEmpty (&pReceiver->PendingNaksList))
  1806. {
  1807. pReceiver->NumPendingNaks = 0;
  1808. pReceiver->NumOutstandingNaks = 0;
  1809. PgmUnlock (pReceive, OldIrq1);
  1810. PgmTrace (LogAllFuncs, ("ReceiveTimerTimeout: " \
  1811. "No pending Naks for pReceive=<%p>, Addr=<%x>\n",
  1812. pReceive, pReceiver->ListenMCastIpAddress));
  1813. }
  1814. else
  1815. {
  1816. PgmUnlock (pReceive, OldIrq1);
  1817. PgmTrace (LogAllFuncs, ("ReceiveTimerTimeout: " \
  1818. "Checking for pending Naks for pReceive=<%p>, Addr=<%x>\n",
  1819. pReceive, pReceiver->ListenMCastIpAddress));
  1820. CheckSendPendingNaks (pReceiver->pAddress, pReceive, pReceiver, &OldIrq);
  1821. }
  1822. }
  1823. else if (!(pReceive->SessionFlags & PGM_SESSION_FLAG_IN_INDICATE))
  1824. {
  1825. PgmTrace (LogStatus, ("ReceiveTimerTimeout: " \
  1826. "PGM_SESSION_ON_TIMER flag cleared for pReceive=<%p>, Addr=<%x>\n",
  1827. pReceive, pReceiver->ListenMCastIpAddress));
  1828. pEntry = pEntry->Blink;
  1829. RemoveEntryList (&pReceiver->Linkage);
  1830. if (IsListEmpty (&PgmDynamicConfig.CurrentReceivers))
  1831. {
  1832. fReStartTimer = FALSE;
  1833. PgmDynamicConfig.GlobalFlags &= ~PGM_CONFIG_FLAG_RECEIVE_TIMER_RUNNING;
  1834. PgmTrace (LogStatus, ("ReceiveTimerTimeout: " \
  1835. "Not restarting Timer since no Receivers currently active!\n"));
  1836. }
  1837. PgmUnlock (&PgmDynamicConfig, OldIrq1);
  1838. CheckIndicateDisconnect (pReceiver->pAddress, pReceive, NULL, &OldIrq1, FALSE);
  1839. PgmUnlock (pReceive, OldIrq);
  1840. PGM_DEREFERENCE_ADDRESS (pReceiver->pAddress, REF_ADDRESS_RECEIVE_ACTIVE);
  1841. PGM_DEREFERENCE_SESSION_RECEIVE (pReceive, REF_SESSION_TIMER_RUNNING);
  1842. if (!fReStartTimer)
  1843. {
  1844. return;
  1845. }
  1846. PgmLock (&PgmDynamicConfig, OldIrq);
  1847. }
  1848. else
  1849. {
  1850. PgmUnlock (pReceive, OldIrq1);
  1851. }
  1852. }
  1853. PgmInitTimer (&PgmDynamicConfig.SessionTimer);
  1854. PgmStartTimer (&PgmDynamicConfig.SessionTimer, BASIC_TIMER_GRANULARITY_IN_MSECS, ReceiveTimerTimeout, NULL);
  1855. PgmUnlock (&PgmDynamicConfig, OldIrq);
  1856. }
  1857. //----------------------------------------------------------------------------
  1858. NTSTATUS
  1859. ExtractNakNcfSequences(
  1860. IN tBASIC_NAK_NCF_PACKET_HEADER UNALIGNED *pNakNcfPacket,
  1861. IN ULONG BytesAvailable,
  1862. OUT tNAKS_LIST *pNakNcfList,
  1863. OUT SEQ_TYPE *pLastSequenceNumber,
  1864. IN UCHAR FECGroupSize
  1865. )
  1866. /*++
  1867. Routine Description:
  1868. This routine is called to process a Nak/Ncf packet and extract all
  1869. the Sequences specified therein into a list.
  1870. It also verifies that the sequences are unique and sorted
  1871. Arguments:
  1872. IN pNakNcfPacket -- Nak/Ncf packet
  1873. IN BytesAvailable -- PacketLength
  1874. OUT pNakNcfList -- List of sequences returned on success
  1875. Return Value:
  1876. NTSTATUS - Final status of the operation
  1877. --*/
  1878. {
  1879. NTSTATUS status;
  1880. ULONG i;
  1881. tPACKET_OPTIONS PacketOptions;
  1882. USHORT ThisSequenceIndex;
  1883. SEQ_TYPE LastSequenceNumber, ThisSequenceNumber, ThisSequenceGroup;
  1884. SEQ_TYPE NextUnsentSequenceNumber, NextUnsentSequenceGroup;
  1885. SEQ_TYPE FECSequenceMask = FECGroupSize - 1;
  1886. SEQ_TYPE FECGroupMask = ~FECSequenceMask;
  1887. // Must be called with the Session lock held!
  1888. PgmZeroMemory (pNakNcfList, sizeof (tNAKS_LIST));
  1889. if (pNakNcfPacket->CommonHeader.Options & PACKET_HEADER_OPTIONS_PARITY)
  1890. {
  1891. pNakNcfList->NakType = NAK_TYPE_PARITY;
  1892. }
  1893. else
  1894. {
  1895. pNakNcfList->NakType = NAK_TYPE_SELECTIVE;
  1896. }
  1897. PgmZeroMemory (&PacketOptions, sizeof (tPACKET_OPTIONS));
  1898. if (pNakNcfPacket->CommonHeader.Options & PACKET_HEADER_OPTIONS_PRESENT)
  1899. {
  1900. status = ProcessOptions ((tPACKET_OPTION_LENGTH *) (pNakNcfPacket + 1),
  1901. BytesAvailable,
  1902. (pNakNcfPacket->CommonHeader.Type & 0x0f),
  1903. &PacketOptions,
  1904. pNakNcfList);
  1905. if (!NT_SUCCESS (status))
  1906. {
  1907. PgmTrace (LogError, ("ExtractNakNcfSequences: ERROR -- " \
  1908. "ProcessOptions returned <%x>\n", status));
  1909. return (STATUS_DATA_NOT_ACCEPTED);
  1910. }
  1911. ASSERT (PacketOptions.OptionsFlags & PGM_OPTION_FLAG_NAK_LIST);
  1912. }
  1913. pNakNcfList->pNakSequences[0] = (SEQ_TYPE) ntohl (pNakNcfPacket->RequestedSequenceNumber);
  1914. pNakNcfList->NumSequences += 1;
  1915. //
  1916. // Now, adjust the sequences according to our local relative sequence number
  1917. // (This is to account for wrap-arounds)
  1918. //
  1919. if (pLastSequenceNumber)
  1920. {
  1921. NextUnsentSequenceNumber = *pLastSequenceNumber;
  1922. }
  1923. else
  1924. {
  1925. NextUnsentSequenceNumber = FECGroupSize + pNakNcfList->pNakSequences[pNakNcfList->NumSequences-1];
  1926. }
  1927. NextUnsentSequenceGroup = NextUnsentSequenceNumber & FECGroupMask;
  1928. LastSequenceNumber = pNakNcfList->pNakSequences[0] - FECGroupSize;
  1929. for (i=0; i < pNakNcfList->NumSequences; i++)
  1930. {
  1931. ThisSequenceNumber = pNakNcfList->pNakSequences[i];
  1932. //
  1933. // If this is a parity Nak, then we need to separate the TG_SQN from the PKT_SQN
  1934. //
  1935. ThisSequenceGroup = ThisSequenceNumber & FECGroupMask;
  1936. ThisSequenceIndex = (USHORT) (ThisSequenceNumber & FECSequenceMask);
  1937. pNakNcfList->pNakSequences[i] = ThisSequenceGroup;
  1938. pNakNcfList->NakIndex[i] = ThisSequenceIndex;
  1939. PgmTrace (LogPath, ("ExtractNakNcfSequences: " \
  1940. "[%d] Sequence# = <%d> ==> [%d:%d]\n",
  1941. i, (ULONG) pNakNcfList->pNakSequences[i], ThisSequenceNumber, ThisSequenceIndex));
  1942. if (SEQ_LEQ (ThisSequenceNumber, LastSequenceNumber))
  1943. {
  1944. //
  1945. // This list is not ordered, so just bail!
  1946. //
  1947. PgmTrace (LogError, ("ExtractNakNcfSequences: ERROR -- " \
  1948. "[%d] Unordered list! Sequence#<%d> before <%d>\n",
  1949. i, (ULONG) LastSequenceNumber, (ULONG) ThisSequenceNumber));
  1950. return (STATUS_DATA_NOT_ACCEPTED);
  1951. }
  1952. if (pNakNcfList->NakType == NAK_TYPE_SELECTIVE)
  1953. {
  1954. if (SEQ_LEQ (ThisSequenceNumber, LastSequenceNumber))
  1955. {
  1956. //
  1957. // This list is not ordered, so just bail!
  1958. //
  1959. PgmTrace (LogError, ("ExtractNakNcfSequences: ERROR -- " \
  1960. "[%d] Unordered Selective list! Sequence#<%d> before <%d>\n",
  1961. i, (ULONG) LastSequenceNumber, (ULONG) ThisSequenceNumber));
  1962. return (STATUS_DATA_NOT_ACCEPTED);
  1963. }
  1964. if (SEQ_GEQ (ThisSequenceNumber, NextUnsentSequenceNumber))
  1965. {
  1966. pNakNcfList->NumSequences = (USHORT) i; // Don't want to include this sequence!
  1967. PgmTrace (LogError, ("ExtractNakNcfSequences: ERROR -- " \
  1968. "Invalid Selective Nak = [%d] further than leading edge = [%d]\n",
  1969. (ULONG) ThisSequenceNumber, (ULONG) NextUnsentSequenceNumber));
  1970. break;
  1971. }
  1972. LastSequenceNumber = ThisSequenceNumber;
  1973. }
  1974. else // pNakNcfList->NakType == NAK_TYPE_PARITY
  1975. {
  1976. if (SEQ_LEQ (ThisSequenceGroup, LastSequenceNumber))
  1977. {
  1978. //
  1979. // This list is not ordered, so just bail!
  1980. //
  1981. PgmTrace (LogError, ("ExtractNakNcfSequences: ERROR -- " \
  1982. "[%d] Unordered Parity list! Sequence#<%d> before <%d>\n",
  1983. i, (ULONG) LastSequenceNumber, (ULONG) ThisSequenceNumber));
  1984. return (STATUS_DATA_NOT_ACCEPTED);
  1985. }
  1986. if (SEQ_GEQ (ThisSequenceGroup, NextUnsentSequenceGroup))
  1987. {
  1988. pNakNcfList->NumSequences = (USHORT) i; // Don't want to include this sequence!
  1989. PgmTrace (LogError, ("ExtractNakNcfSequences: ERROR -- " \
  1990. "Invalid Parity Nak = [%d] further than leading edge = [%d]\n",
  1991. (ULONG) ThisSequenceGroup, (ULONG) NextUnsentSequenceGroup));
  1992. break;
  1993. }
  1994. LastSequenceNumber = ThisSequenceGroup;
  1995. pNakNcfList->NumParityNaks[i]++;
  1996. }
  1997. }
  1998. if (!pNakNcfList->NumSequences)
  1999. {
  2000. PgmTrace (LogError, ("ExtractNakNcfSequences: ERROR -- " \
  2001. "No Valid %s Naks in List, First Nak=<%d>!\n",
  2002. (pNakNcfList->NakType == NAK_TYPE_PARITY ? "Parity" : "Selective"),
  2003. (ULONG) ThisSequenceNumber));
  2004. return (STATUS_DATA_NOT_ACCEPTED);
  2005. }
  2006. if (pLastSequenceNumber)
  2007. {
  2008. *pLastSequenceNumber = LastSequenceNumber;
  2009. }
  2010. if (pNakNcfList->NumSequences)
  2011. {
  2012. return (STATUS_SUCCESS);
  2013. }
  2014. else
  2015. {
  2016. return (STATUS_UNSUCCESSFUL);
  2017. }
  2018. }
  2019. //----------------------------------------------------------------------------
  2020. NTSTATUS
  2021. CheckAndAddNakRequests(
  2022. IN tRECEIVE_SESSION *pReceive,
  2023. IN SEQ_TYPE *pLatestSequenceNumber,
  2024. OUT tNAK_FORWARD_DATA **ppThisNak,
  2025. IN enum eNAK_TIMEOUT NakTimeoutType,
  2026. IN BOOLEAN fSetFurthestKnown
  2027. )
  2028. {
  2029. tNAK_FORWARD_DATA *pOldNak;
  2030. tNAK_FORWARD_DATA *pLastNak;
  2031. SEQ_TYPE MidSequenceNumber;
  2032. SEQ_TYPE FECGroupMask = pReceive->FECGroupSize-1;
  2033. SEQ_TYPE ThisSequenceNumber = *pLatestSequenceNumber;
  2034. SEQ_TYPE ThisGroupSequenceNumber = ThisSequenceNumber & ~FECGroupMask;
  2035. SEQ_TYPE FurthestGroupSequenceNumber = pReceive->pReceiver->FurthestKnownGroupSequenceNumber;
  2036. ULONG NakRequestSize = sizeof(tNAK_FORWARD_DATA) +
  2037. ((pReceive->FECGroupSize-1) * sizeof(tPENDING_DATA));
  2038. ULONGLONG Pending0NakTimeout = PgmDynamicConfig.ReceiversTimerTickCount + 2;
  2039. LIST_ENTRY *pEntry;
  2040. UCHAR i;
  2041. ULONG NakRandomBackoffMSecs, NakRepeatIntervalMSecs;
  2042. tRECEIVE_CONTEXT *pReceiver = pReceive->pReceiver;
  2043. //
  2044. // Verify that the FurthestKnownGroupSequenceNumber is on a Group boundary
  2045. //
  2046. ASSERT (!(FurthestGroupSequenceNumber & FECGroupMask));
  2047. if (SEQ_LT (ThisSequenceNumber, pReceiver->FirstNakSequenceNumber))
  2048. {
  2049. if (ppThisNak)
  2050. {
  2051. ASSERT (0);
  2052. *ppThisNak = NULL;
  2053. }
  2054. return (STATUS_SUCCESS);
  2055. }
  2056. if (SEQ_GT (ThisGroupSequenceNumber, (pReceiver->NextODataSequenceNumber + MAX_SEQUENCES_IN_RCV_WINDOW)))
  2057. {
  2058. PgmTrace (LogError, ("CheckAndAddNakRequests: ERROR -- " \
  2059. "STATUS_INSUFFICIENT_RESOURCES -- Too many packets in Window [%d, %d] = %d Sequences\n",
  2060. (ULONG) pReceiver->NextODataSequenceNumber,
  2061. (ULONG) ThisGroupSequenceNumber,
  2062. (ULONG) (ThisGroupSequenceNumber - pReceiver->NextODataSequenceNumber + 1)));
  2063. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  2064. return (STATUS_INSUFFICIENT_RESOURCES);
  2065. }
  2066. if (SEQ_GT (ThisGroupSequenceNumber, (FurthestGroupSequenceNumber + 1000)) &&
  2067. !(pReceive->SessionFlags & PGM_SESSION_FLAG_FIRST_PACKET))
  2068. {
  2069. PgmTrace (LogStatus, ("CheckAndAddNakRequests: " \
  2070. "WARNING!!! Too many successive packets lost =<%d>!!! Expecting Next=<%d>, FurthestKnown=<%d>, This=<%d>\n",
  2071. (ULONG) (ThisGroupSequenceNumber - FurthestGroupSequenceNumber),
  2072. (ULONG) pReceiver->FirstNakSequenceNumber,
  2073. (ULONG) FurthestGroupSequenceNumber,
  2074. (ULONG) ThisGroupSequenceNumber));
  2075. }
  2076. if (pReceiver->pAddress->Flags & PGM_ADDRESS_HIGH_SPEED_OPTIMIZED)
  2077. {
  2078. NakRandomBackoffMSecs = NAK_RANDOM_BACKOFF_MSECS_OPT;
  2079. NakRepeatIntervalMSecs = NAK_REPEAT_INTERVAL_MSECS_OPT;
  2080. }
  2081. else
  2082. {
  2083. NakRandomBackoffMSecs = NAK_RANDOM_BACKOFF_MSECS;
  2084. NakRepeatIntervalMSecs = NAK_REPEAT_INTERVAL_MSECS;
  2085. }
  2086. //
  2087. // Add any Nak requests if necessary!
  2088. // FurthestGroupSequenceNumber must be a multiple of the FECGroupSize (if applicable)
  2089. //
  2090. pLastNak = NULL;
  2091. while (SEQ_LT (FurthestGroupSequenceNumber, ThisGroupSequenceNumber))
  2092. {
  2093. if (pReceive->FECOptions)
  2094. {
  2095. pLastNak = ExAllocateFromNPagedLookasideList (&pReceiver->ParityContextLookaside);
  2096. }
  2097. else
  2098. {
  2099. pLastNak = ExAllocateFromNPagedLookasideList (&pReceiver->NonParityContextLookaside);
  2100. }
  2101. if (!pLastNak)
  2102. {
  2103. pReceiver->FurthestKnownGroupSequenceNumber = FurthestGroupSequenceNumber;
  2104. pReceiver->FurthestKnownSequenceNumber = pReceiver->FurthestKnownSequenceNumber + FECGroupMask; // End of prev group
  2105. PgmTrace (LogError, ("ExtractNakNcfSequences: ERROR -- " \
  2106. "STATUS_INSUFFICIENT_RESOURCES allocating tNAK_FORWARD_DATA, Size=<%d>, Seq=<%d>\n",
  2107. NakRequestSize, (ULONG) pReceiver->FurthestKnownGroupSequenceNumber));
  2108. return (STATUS_INSUFFICIENT_RESOURCES);
  2109. }
  2110. PgmZeroMemory (pLastNak, NakRequestSize);
  2111. if (pReceive->FECOptions)
  2112. {
  2113. pLastNak->OriginalGroupSize = pLastNak->PacketsInGroup = pReceive->FECGroupSize;
  2114. for (i=0; i<pLastNak->OriginalGroupSize; i++)
  2115. {
  2116. pLastNak->pPendingData[i].ActualIndexOfDataPacket = pLastNak->OriginalGroupSize;
  2117. }
  2118. }
  2119. else
  2120. {
  2121. pLastNak->OriginalGroupSize = pLastNak->PacketsInGroup = 1;
  2122. pLastNak->pPendingData[0].ActualIndexOfDataPacket = 1;
  2123. }
  2124. FurthestGroupSequenceNumber += pReceive->FECGroupSize;
  2125. pLastNak->SequenceNumber = FurthestGroupSequenceNumber;
  2126. pLastNak->MinPacketLength = pReceive->MaxFECPacketLength;
  2127. if (NakTimeoutType == NAK_OUTSTANDING)
  2128. {
  2129. pLastNak->OutstandingNakTimeout = PgmDynamicConfig.ReceiversTimerTickCount +
  2130. pReceiver->OutstandingNakTimeout;
  2131. pLastNak->PendingNakTimeout = 0;
  2132. pLastNak->WaitingNcfRetries = 0;
  2133. }
  2134. else
  2135. {
  2136. pLastNak->OutstandingNakTimeout = 0;
  2137. switch (NakTimeoutType)
  2138. {
  2139. case (NAK_PENDING_0):
  2140. {
  2141. pLastNak->PendingNakTimeout = Pending0NakTimeout;
  2142. break;
  2143. }
  2144. case (NAK_PENDING_RB):
  2145. {
  2146. pLastNak->PendingNakTimeout = PgmDynamicConfig.ReceiversTimerTickCount +
  2147. ((NakRandomBackoffMSecs/pReceive->FECGroupSize) /
  2148. BASIC_TIMER_GRANULARITY_IN_MSECS);
  2149. break;
  2150. }
  2151. case (NAK_PENDING_RPT_RB):
  2152. {
  2153. pLastNak->PendingNakTimeout = PgmDynamicConfig.ReceiversTimerTickCount +
  2154. ((NakRepeatIntervalMSecs +(NakRandomBackoffMSecs/pReceive->FECGroupSize))/
  2155. BASIC_TIMER_GRANULARITY_IN_MSECS);
  2156. break;
  2157. }
  2158. default:
  2159. {
  2160. ASSERT (0);
  2161. }
  2162. }
  2163. }
  2164. InsertTailList (&pReceiver->NaksForwardDataList, &pLastNak->Linkage);
  2165. AppendPendingReceiverEntry (pReceiver, pLastNak);
  2166. PgmTrace (LogPath, ("CheckAndAddNakRequests: " \
  2167. "ADDing NAK request for SeqNum=<%d>, Furthest=<%d>\n",
  2168. (ULONG) pLastNak->SequenceNumber, (ULONG) FurthestGroupSequenceNumber));
  2169. }
  2170. pReceiver->FurthestKnownGroupSequenceNumber = FurthestGroupSequenceNumber;
  2171. if (SEQ_GT (ThisSequenceNumber, pReceiver->FurthestKnownSequenceNumber))
  2172. {
  2173. if (fSetFurthestKnown)
  2174. {
  2175. pReceiver->FurthestKnownSequenceNumber = ThisSequenceNumber;
  2176. }
  2177. else if (SEQ_GT (FurthestGroupSequenceNumber, pReceiver->FurthestKnownSequenceNumber))
  2178. {
  2179. pReceiver->FurthestKnownSequenceNumber = FurthestGroupSequenceNumber + FECGroupMask;
  2180. }
  2181. }
  2182. if (pLastNak)
  2183. {
  2184. pLastNak->PendingNakTimeout = PgmDynamicConfig.ReceiversTimerTickCount +
  2185. NakRepeatIntervalMSecs / BASIC_TIMER_GRANULARITY_IN_MSECS;
  2186. }
  2187. else if ((ppThisNak) && (!IsListEmpty (&pReceiver->NaksForwardDataList)))
  2188. {
  2189. pLastNak = FindReceiverEntry (pReceiver, ThisGroupSequenceNumber);
  2190. ASSERT (!pLastNak || (pLastNak->SequenceNumber == ThisGroupSequenceNumber));
  2191. }
  2192. if (ppThisNak)
  2193. {
  2194. *ppThisNak = pLastNak;
  2195. }
  2196. return (STATUS_SUCCESS);
  2197. }
  2198. //----------------------------------------------------------------------------
  2199. NTSTATUS
  2200. ReceiverProcessNakNcfPacket(
  2201. IN tADDRESS_CONTEXT *pAddress,
  2202. IN tRECEIVE_SESSION *pReceive,
  2203. IN ULONG PacketLength,
  2204. IN tBASIC_NAK_NCF_PACKET_HEADER UNALIGNED *pNakNcfPacket,
  2205. IN UCHAR PacketType
  2206. )
  2207. /*++
  2208. Routine Description:
  2209. This is the common routine for processing Nak or Ncf packets
  2210. Arguments:
  2211. IN pAddress -- Address object context
  2212. IN pReceive -- Receive context
  2213. IN PacketLength -- Length of packet received from the wire
  2214. IN pNakNcfPacket -- Nak/Ncf packet
  2215. IN PacketType -- whether Nak or Ncf
  2216. Return Value:
  2217. NTSTATUS - Final status of the call
  2218. --*/
  2219. {
  2220. PGMLockHandle OldIrq;
  2221. ULONG i, j, PacketIndex;
  2222. tNAKS_LIST NakNcfList;
  2223. SEQ_TYPE LastSequenceNumber, FECGroupMask;
  2224. NTSTATUS status;
  2225. LIST_ENTRY *pEntry;
  2226. tNAK_FORWARD_DATA *pLastNak;
  2227. ULONG PacketsInGroup, NumMissingPackets;
  2228. ULONG NakRandomBackoffMSecs, NakRepeatIntervalMSecs;
  2229. BOOLEAN fValidNcf, fFECWithSelectiveNaksOnly = FALSE;
  2230. tRECEIVE_CONTEXT *pReceiver = pReceive->pReceiver;
  2231. ASSERT (!pNakNcfPacket->CommonHeader.TSDULength);
  2232. PgmZeroMemory (&NakNcfList, sizeof (tNAKS_LIST));
  2233. PgmLock (pReceive, OldIrq);
  2234. status = ExtractNakNcfSequences (pNakNcfPacket,
  2235. (PacketLength - sizeof(tBASIC_NAK_NCF_PACKET_HEADER)),
  2236. &NakNcfList,
  2237. NULL,
  2238. pReceive->FECGroupSize);
  2239. if (!NT_SUCCESS (status))
  2240. {
  2241. PgmUnlock (pReceive, OldIrq);
  2242. PgmTrace (LogError, ("ReceiverProcessNakNcfPacket: ERROR -- " \
  2243. "ExtractNakNcfSequences returned <%x>\n", status));
  2244. return (status);
  2245. }
  2246. PgmTrace (LogAllFuncs, ("ReceiverProcessNakNcfPacket: " \
  2247. "NumSequences=[%d] Range=<%d--%d>, Furthest=<%d>\n",
  2248. NakNcfList.NumSequences,
  2249. (ULONG) NakNcfList.pNakSequences[0], (ULONG) NakNcfList.pNakSequences[NakNcfList.NumSequences-1],
  2250. (ULONG) pReceiver->FurthestKnownGroupSequenceNumber));
  2251. //
  2252. // Compares apples to apples and oranges to oranges
  2253. // i.e. Process parity Naks only if we are parity-aware, and vice-versa
  2254. // Exception is ofr the case of a selective Ncf received when we have OnDemand parity
  2255. //
  2256. if ((pReceiver->SessionNakType == NakNcfList.NakType) ||
  2257. ((PacketType == PACKET_TYPE_NCF) &&
  2258. (NakNcfList.NakType == NAK_TYPE_SELECTIVE)))
  2259. {
  2260. if (pAddress->Flags & PGM_ADDRESS_HIGH_SPEED_OPTIMIZED)
  2261. {
  2262. NakRandomBackoffMSecs = NAK_RANDOM_BACKOFF_MSECS_OPT;
  2263. NakRepeatIntervalMSecs = NAK_REPEAT_INTERVAL_MSECS_OPT;
  2264. }
  2265. else
  2266. {
  2267. NakRandomBackoffMSecs = NAK_RANDOM_BACKOFF_MSECS;
  2268. NakRepeatIntervalMSecs = NAK_REPEAT_INTERVAL_MSECS;
  2269. }
  2270. }
  2271. else
  2272. {
  2273. PgmUnlock (pReceive, OldIrq);
  2274. PgmTrace (LogPath, ("ReceiverProcessNakNcfPacket: " \
  2275. "Received a %s Nak! Not processing ... \n",
  2276. ((pReceive->FECGroupSize > 1) ? "Non-parity" : "Parity")));
  2277. return (STATUS_SUCCESS);
  2278. }
  2279. i = 0;
  2280. FECGroupMask = pReceive->FECGroupSize - 1;
  2281. //
  2282. // Special case: If we have FEC enabled, but not with OnDemand parity,
  2283. // then we will process Ncf requests only
  2284. //
  2285. fFECWithSelectiveNaksOnly = pReceive->FECOptions &&
  2286. !(pReceive->FECOptions & PACKET_OPTION_SPECIFIC_FEC_OND_BIT);
  2287. if ((PacketType == PACKET_TYPE_NAK) &&
  2288. (fFECWithSelectiveNaksOnly))
  2289. {
  2290. i = NakNcfList.NumSequences;
  2291. }
  2292. for ( ; i <NakNcfList.NumSequences; i++)
  2293. {
  2294. LastSequenceNumber = NakNcfList.pNakSequences[i];
  2295. pLastNak = FindReceiverEntry (pReceiver, LastSequenceNumber);
  2296. if (pLastNak)
  2297. {
  2298. ASSERT (pLastNak->SequenceNumber == LastSequenceNumber);
  2299. if ((pReceive->FECOptions) &&
  2300. (LastSequenceNumber == pReceiver->FurthestKnownGroupSequenceNumber))
  2301. {
  2302. ASSERT (SEQ_GEQ (pReceiver->FurthestKnownSequenceNumber, pReceiver->FurthestKnownGroupSequenceNumber));
  2303. PacketsInGroup = pReceiver->FurthestKnownSequenceNumber - pLastNak->SequenceNumber + 1;
  2304. ASSERT (PacketsInGroup >= (ULONG) (pLastNak->NumDataPackets + pLastNak->NumParityPackets));
  2305. }
  2306. else
  2307. {
  2308. PacketsInGroup = pLastNak->PacketsInGroup;
  2309. }
  2310. NumMissingPackets = PacketsInGroup - (pLastNak->NextIndexToIndicate + pLastNak->NumDataPackets + pLastNak->NumParityPackets);
  2311. }
  2312. if ((!pLastNak) ||
  2313. (!NumMissingPackets))
  2314. {
  2315. continue;
  2316. }
  2317. if (PacketType == PACKET_TYPE_NAK)
  2318. {
  2319. //
  2320. // If we are currently waiting for a Nak or Ncf, we need to
  2321. // reset the timeout for either of the 2 scenarios
  2322. //
  2323. if (pLastNak->PendingNakTimeout) // We are waiting for a Nak
  2324. {
  2325. pLastNak->PendingNakTimeout = PgmDynamicConfig.ReceiversTimerTickCount +
  2326. ((NakRepeatIntervalMSecs + (NakRandomBackoffMSecs/NumMissingPackets))/
  2327. BASIC_TIMER_GRANULARITY_IN_MSECS);
  2328. }
  2329. else
  2330. {
  2331. ASSERT (pLastNak->OutstandingNakTimeout);
  2332. pLastNak->OutstandingNakTimeout = PgmDynamicConfig.ReceiversTimerTickCount +
  2333. (pReceiver->OutstandingNakTimeout <<
  2334. pLastNak->WaitingRDataRetries);
  2335. if ((pLastNak->WaitingRDataRetries >= (NCF_WAITING_RDATA_MAX_RETRIES >> 1)) &&
  2336. ((pReceiver->OutstandingNakTimeout << pLastNak->WaitingRDataRetries) <
  2337. pReceiver->MaxRDataResponseTCFromWindow))
  2338. {
  2339. pLastNak->OutstandingNakTimeout = PgmDynamicConfig.ReceiversTimerTickCount +
  2340. (pReceiver->MaxRDataResponseTCFromWindow<<1);
  2341. }
  2342. }
  2343. }
  2344. else // NCF case
  2345. {
  2346. PacketIndex = NakNcfList.NakIndex[i];
  2347. fValidNcf = FALSE;
  2348. // first check for OnDemand case
  2349. if (pReceive->FECOptions & PACKET_OPTION_SPECIFIC_FEC_OND_BIT)
  2350. {
  2351. // We may also need to process selective naks in certain cases
  2352. if (NakNcfList.NakType == NAK_TYPE_SELECTIVE)
  2353. {
  2354. fValidNcf = TRUE;
  2355. pLastNak->pPendingData[PacketIndex].NcfsReceivedForActualIndex++;
  2356. for (j=0; j<PacketsInGroup; j++)
  2357. {
  2358. if ((pLastNak->pPendingData[j].ActualIndexOfDataPacket >= pLastNak->OriginalGroupSize) &&
  2359. (!pLastNak->pPendingData[j].NcfsReceivedForActualIndex))
  2360. {
  2361. fValidNcf = FALSE;
  2362. break;
  2363. }
  2364. }
  2365. if (!pLastNak->FirstNcfTickCount)
  2366. {
  2367. pLastNak->FirstNcfTickCount = PgmDynamicConfig.ReceiversTimerTickCount;
  2368. }
  2369. }
  2370. else if (NakNcfList.NumParityNaks[i] >= NumMissingPackets) // Parity Nak
  2371. {
  2372. fValidNcf = TRUE;
  2373. if (!pLastNak->FirstNcfTickCount)
  2374. {
  2375. pLastNak->FirstNcfTickCount = PgmDynamicConfig.ReceiversTimerTickCount;
  2376. }
  2377. }
  2378. }
  2379. // Selective Naks only -- with or without FEC
  2380. else if (pLastNak->pPendingData[PacketIndex].ActualIndexOfDataPacket >= pLastNak->OriginalGroupSize)
  2381. {
  2382. fValidNcf = TRUE;
  2383. if (fFECWithSelectiveNaksOnly)
  2384. {
  2385. pLastNak->pPendingData[PacketIndex].NcfsReceivedForActualIndex++;
  2386. for (j=0; j<pLastNak->PacketsInGroup; j++)
  2387. {
  2388. if ((pLastNak->pPendingData[j].ActualIndexOfDataPacket >= pLastNak->OriginalGroupSize) &&
  2389. (!pLastNak->pPendingData[j].NcfsReceivedForActualIndex))
  2390. {
  2391. fValidNcf = FALSE;
  2392. break;
  2393. }
  2394. }
  2395. }
  2396. if (!pLastNak->FirstNcfTickCount)
  2397. {
  2398. pLastNak->FirstNcfTickCount = PgmDynamicConfig.ReceiversTimerTickCount;
  2399. }
  2400. }
  2401. if (fValidNcf)
  2402. {
  2403. pLastNak->PendingNakTimeout = 0;
  2404. pLastNak->WaitingNcfRetries = 0;
  2405. pLastNak->OutstandingNakTimeout = PgmDynamicConfig.ReceiversTimerTickCount +
  2406. (pReceiver->OutstandingNakTimeout <<
  2407. pLastNak->WaitingRDataRetries);
  2408. if ((pLastNak->WaitingRDataRetries >= (NCF_WAITING_RDATA_MAX_RETRIES >> 1)) &&
  2409. ((pReceiver->OutstandingNakTimeout << pLastNak->WaitingRDataRetries) <
  2410. pReceiver->MaxRDataResponseTCFromWindow))
  2411. {
  2412. pLastNak->OutstandingNakTimeout = PgmDynamicConfig.ReceiversTimerTickCount +
  2413. (pReceiver->MaxRDataResponseTCFromWindow<<1);
  2414. }
  2415. }
  2416. }
  2417. }
  2418. //
  2419. // So, we need to create new Nak contexts for the remaining Sequences
  2420. // Since the Sequences are ordered, just pick the highest one, and
  2421. // create Naks for all up to that
  2422. //
  2423. LastSequenceNumber = NakNcfList.pNakSequences[NakNcfList.NumSequences-1] + NakNcfList.NakIndex[NakNcfList.NumSequences-1];
  2424. if (NakNcfList.NakType == NAK_TYPE_PARITY)
  2425. {
  2426. LastSequenceNumber--;
  2427. }
  2428. if (PacketType == PACKET_TYPE_NAK)
  2429. {
  2430. status = CheckAndAddNakRequests (pReceive, &LastSequenceNumber, NULL, NAK_PENDING_RPT_RB, TRUE);
  2431. }
  2432. else // PacketType == PACKET_TYPE_NCF
  2433. {
  2434. status = CheckAndAddNakRequests (pReceive, &LastSequenceNumber, NULL, NAK_OUTSTANDING, TRUE);
  2435. }
  2436. PgmUnlock (pReceive, OldIrq);
  2437. return (STATUS_SUCCESS);
  2438. }
  2439. //----------------------------------------------------------------------------
  2440. NTSTATUS
  2441. CoalesceSelectiveNaksIntoGroups(
  2442. IN tRECEIVE_SESSION *pReceive,
  2443. IN UCHAR GroupSize
  2444. )
  2445. {
  2446. PNAK_FORWARD_DATA pOldNak, pNewNak;
  2447. LIST_ENTRY NewNaksList;
  2448. LIST_ENTRY OldNaksList;
  2449. LIST_ENTRY *pEntry;
  2450. SEQ_TYPE FirstGroupSequenceNumber, LastGroupSequenceNumber, LastSequenceNumber;
  2451. SEQ_TYPE FurthestKnownSequenceNumber;
  2452. SEQ_TYPE GroupMask = GroupSize - 1;
  2453. ULONG NakRequestSize = sizeof(tNAK_FORWARD_DATA) + ((GroupSize-1) * sizeof(tPENDING_DATA));
  2454. USHORT MinPacketLength;
  2455. UCHAR i;
  2456. NTSTATUS status = STATUS_SUCCESS;
  2457. ULONG NakRandomBackoffMSecs, NakRepeatIntervalMSecs;
  2458. ASSERT (pReceive->FECGroupSize == 1);
  2459. ASSERT (GroupSize > 1);
  2460. //
  2461. // First, call AdjustReceiveBufferLists to ensure that FirstNakSequenceNumber is current
  2462. //
  2463. AdjustReceiveBufferLists (pReceive);
  2464. FirstGroupSequenceNumber = pReceive->pReceiver->FirstNakSequenceNumber & ~GroupMask;
  2465. LastGroupSequenceNumber = pReceive->pReceiver->FurthestKnownGroupSequenceNumber & ~GroupMask;
  2466. FurthestKnownSequenceNumber = pReceive->pReceiver->FurthestKnownSequenceNumber; // Save
  2467. //
  2468. // If the next packet seq we are expecting is > the furthest known sequence #,
  2469. // then we don't need to do anything
  2470. //
  2471. LastSequenceNumber = LastGroupSequenceNumber + (GroupSize-1);
  2472. //
  2473. // First, add Nak requests for the missing packets in furthest group!
  2474. //
  2475. status = CheckAndAddNakRequests (pReceive, &LastSequenceNumber, NULL, NAK_PENDING_RB, FALSE);
  2476. if (!NT_SUCCESS (status))
  2477. {
  2478. PgmTrace (LogError, ("CoalesceSelectiveNaksIntoGroups: ERROR -- " \
  2479. "CheckAndAddNakRequests returned <%x>\n", status));
  2480. return (status);
  2481. }
  2482. pReceive->pReceiver->FurthestKnownSequenceNumber = FurthestKnownSequenceNumber; // Reset
  2483. ASSERT (LastSequenceNumber == pReceive->pReceiver->FurthestKnownGroupSequenceNumber);
  2484. ASSERT (pReceive->pReceiver->MaxPacketsBufferedInLookaside);
  2485. ExInitializeNPagedLookasideList (&pReceive->pReceiver->ParityContextLookaside,
  2486. NULL,
  2487. NULL,
  2488. 0,
  2489. NakRequestSize,
  2490. PGM_TAG('2'),
  2491. (USHORT) (pReceive->pReceiver->MaxPacketsBufferedInLookaside/GroupSize));
  2492. if (SEQ_GT (pReceive->pReceiver->FirstNakSequenceNumber, LastSequenceNumber))
  2493. {
  2494. pReceive->pReceiver->FurthestKnownGroupSequenceNumber = LastGroupSequenceNumber;
  2495. ASSERT (IsListEmpty (&pReceive->pReceiver->NaksForwardDataList));
  2496. PgmTrace (LogStatus, ("CoalesceSelectiveNaksIntoGroups: " \
  2497. "[1] NextOData=<%d>, FirstNak=<%d>, FirstGroup=<%d>, LastGroup=<%d>, no Naks pending!\n",
  2498. (ULONG) pReceive->pReceiver->NextODataSequenceNumber,
  2499. (ULONG) pReceive->pReceiver->FirstNakSequenceNumber,
  2500. (ULONG) FirstGroupSequenceNumber,
  2501. (ULONG) pReceive->pReceiver->FurthestKnownGroupSequenceNumber));
  2502. return (STATUS_SUCCESS);
  2503. }
  2504. if (pReceive->pReceiver->pAddress->Flags & PGM_ADDRESS_HIGH_SPEED_OPTIMIZED)
  2505. {
  2506. NakRandomBackoffMSecs = NAK_RANDOM_BACKOFF_MSECS_OPT;
  2507. NakRepeatIntervalMSecs = NAK_REPEAT_INTERVAL_MSECS_OPT;
  2508. }
  2509. else
  2510. {
  2511. NakRandomBackoffMSecs = NAK_RANDOM_BACKOFF_MSECS;
  2512. NakRepeatIntervalMSecs = NAK_REPEAT_INTERVAL_MSECS;
  2513. }
  2514. //
  2515. // We will start coalescing from the end of the list in case we run
  2516. // into failures
  2517. // Also, we will ignore the first Group since it may be a partial group,
  2518. // or we may have indicated some of the data already, so we may not know
  2519. // the exact data length
  2520. //
  2521. pOldNak = pNewNak = NULL;
  2522. InitializeListHead (&NewNaksList);
  2523. InitializeListHead (&OldNaksList);
  2524. while (SEQ_GEQ (LastGroupSequenceNumber, FirstGroupSequenceNumber))
  2525. {
  2526. if (!(pNewNak = ExAllocateFromNPagedLookasideList (&pReceive->pReceiver->ParityContextLookaside)))
  2527. {
  2528. PgmTrace (LogError, ("CoalesceSelectiveNaksIntoGroups: ERROR -- " \
  2529. "STATUS_INSUFFICIENT_RESOURCES allocating tNAK_FORWARD_DATA\n"));
  2530. status = STATUS_INSUFFICIENT_RESOURCES;
  2531. break;
  2532. }
  2533. PgmZeroMemory (pNewNak, NakRequestSize);
  2534. InitializeListHead (&pNewNak->SendNakLinkage);
  2535. InitializeListHead (&pNewNak->LookupLinkage);
  2536. pNewNak->OriginalGroupSize = pNewNak->PacketsInGroup = GroupSize;
  2537. pNewNak->SequenceNumber = LastGroupSequenceNumber;
  2538. MinPacketLength = pReceive->MaxFECPacketLength;
  2539. for (i=0; i<pNewNak->OriginalGroupSize; i++)
  2540. {
  2541. pNewNak->pPendingData[i].ActualIndexOfDataPacket = pNewNak->OriginalGroupSize;
  2542. }
  2543. i = 0;
  2544. while (SEQ_GEQ (LastSequenceNumber, LastGroupSequenceNumber) &&
  2545. (!IsListEmpty (&pReceive->pReceiver->NaksForwardDataList)))
  2546. {
  2547. pEntry = RemoveTailList (&pReceive->pReceiver->NaksForwardDataList);
  2548. pOldNak = CONTAINING_RECORD (pEntry, tNAK_FORWARD_DATA, Linkage);
  2549. if (!pOldNak->NumDataPackets)
  2550. {
  2551. RemovePendingReceiverEntry (pOldNak);
  2552. }
  2553. else
  2554. {
  2555. ASSERT (pOldNak->NumDataPackets == 1);
  2556. ASSERT (IsListEmpty (&pOldNak->SendNakLinkage));
  2557. ASSERT (IsListEmpty (&pOldNak->LookupLinkage));
  2558. }
  2559. ASSERT (pOldNak->SequenceNumber == LastSequenceNumber);
  2560. ASSERT (pOldNak->OriginalGroupSize == 1);
  2561. if (pOldNak->pPendingData[0].pDataPacket)
  2562. {
  2563. ASSERT (pOldNak->NumDataPackets == 1);
  2564. pNewNak->NumDataPackets++;
  2565. PgmCopyMemory (&pNewNak->pPendingData[i], &pOldNak->pPendingData[0], sizeof (tPENDING_DATA));
  2566. pNewNak->pPendingData[i].PacketIndex = (UCHAR) (LastSequenceNumber - LastGroupSequenceNumber);
  2567. pNewNak->pPendingData[LastSequenceNumber-LastGroupSequenceNumber].ActualIndexOfDataPacket = i;
  2568. i++;
  2569. pOldNak->pPendingData[0].pDataPacket = NULL;
  2570. pOldNak->pPendingData[0].PendingDataFlags = 0;
  2571. pOldNak->NumDataPackets--;
  2572. if (pOldNak->MinPacketLength < MinPacketLength)
  2573. {
  2574. MinPacketLength = pOldNak->MinPacketLength;
  2575. }
  2576. if ((pOldNak->ThisGroupSize) &&
  2577. (pOldNak->ThisGroupSize < GroupSize))
  2578. {
  2579. if (pNewNak->PacketsInGroup == GroupSize)
  2580. {
  2581. pNewNak->PacketsInGroup = pOldNak->ThisGroupSize;
  2582. }
  2583. else
  2584. {
  2585. ASSERT (pNewNak->PacketsInGroup == pOldNak->ThisGroupSize);
  2586. }
  2587. }
  2588. }
  2589. InsertHeadList (&OldNaksList, &pOldNak->Linkage);
  2590. LastSequenceNumber--;
  2591. }
  2592. pNewNak->MinPacketLength = MinPacketLength;
  2593. //
  2594. // See if we need to get rid of any excess (NULL) data packets
  2595. //
  2596. RemoveRedundantNaks (pReceive, pNewNak, FALSE);
  2597. ASSERT (!pNewNak->NumParityPackets);
  2598. if (pNewNak->NumDataPackets < pNewNak->PacketsInGroup) // No parity packets yet!
  2599. {
  2600. pNewNak->PendingNakTimeout = PgmDynamicConfig.ReceiversTimerTickCount +
  2601. ((NakRandomBackoffMSecs/(pNewNak->PacketsInGroup-pNewNak->NumDataPackets))/
  2602. BASIC_TIMER_GRANULARITY_IN_MSECS);
  2603. }
  2604. InsertHeadList (&NewNaksList, &pNewNak->Linkage);
  2605. LastGroupSequenceNumber -= GroupSize;
  2606. }
  2607. //
  2608. // If we succeeded in allocating all NewNaks above, set the
  2609. // NextIndexToIndicate for the first group.
  2610. // We may also need to adjust FirstNakSequenceNumber and NextODataSequenceNumber
  2611. //
  2612. if ((pNewNak) &&
  2613. (pNewNak->SequenceNumber == FirstGroupSequenceNumber))
  2614. {
  2615. if (SEQ_GT (pReceive->pReceiver->FirstNakSequenceNumber, pNewNak->SequenceNumber))
  2616. {
  2617. pNewNak->NextIndexToIndicate = (UCHAR) (pReceive->pReceiver->FirstNakSequenceNumber -
  2618. pNewNak->SequenceNumber);
  2619. pReceive->pReceiver->FirstNakSequenceNumber = pNewNak->SequenceNumber;
  2620. ASSERT (pNewNak->NextIndexToIndicate < GroupSize);
  2621. ASSERT ((pNewNak->NextIndexToIndicate + pNewNak->NumDataPackets) <= pNewNak->PacketsInGroup);
  2622. }
  2623. ASSERT (pReceive->pReceiver->FirstNakSequenceNumber == pNewNak->SequenceNumber);
  2624. //
  2625. // We may have data available for this group already in the buffered
  2626. // list (if it has not been indicated already) -- we should move it here
  2627. //
  2628. while ((pNewNak->NextIndexToIndicate) &&
  2629. (!IsListEmpty (&pReceive->pReceiver->BufferedDataList)))
  2630. {
  2631. ASSERT (pNewNak->NumDataPackets < pNewNak->OriginalGroupSize);
  2632. pEntry = RemoveTailList (&pReceive->pReceiver->BufferedDataList);
  2633. pOldNak = CONTAINING_RECORD (pEntry, tNAK_FORWARD_DATA, Linkage);
  2634. pReceive->pReceiver->NumPacketGroupsPendingClient--;
  2635. pReceive->pReceiver->DataPacketsPendingIndicate--;
  2636. pReceive->pReceiver->DataPacketsPendingNaks++;
  2637. pNewNak->NextIndexToIndicate--;
  2638. ASSERT (pOldNak->pPendingData[0].pDataPacket);
  2639. ASSERT ((pOldNak->NumDataPackets == 1) && (pOldNak->OriginalGroupSize == 1));
  2640. ASSERT (pOldNak->SequenceNumber == (pNewNak->SequenceNumber + pNewNak->NextIndexToIndicate));
  2641. PgmCopyMemory (&pNewNak->pPendingData[pNewNak->NumDataPackets], &pOldNak->pPendingData[0], sizeof (tPENDING_DATA));
  2642. pNewNak->pPendingData[pNewNak->NumDataPackets].PacketIndex = pNewNak->NextIndexToIndicate;
  2643. pNewNak->pPendingData[pNewNak->NextIndexToIndicate].ActualIndexOfDataPacket = pNewNak->NumDataPackets;
  2644. pNewNak->NumDataPackets++;
  2645. if (pOldNak->MinPacketLength < pNewNak->MinPacketLength)
  2646. {
  2647. pNewNak->MinPacketLength = pOldNak->MinPacketLength;
  2648. }
  2649. if ((pOldNak->ThisGroupSize) &&
  2650. (pOldNak->ThisGroupSize < GroupSize))
  2651. {
  2652. if (pNewNak->PacketsInGroup == GroupSize)
  2653. {
  2654. pNewNak->PacketsInGroup = pOldNak->ThisGroupSize;
  2655. }
  2656. else
  2657. {
  2658. ASSERT (pNewNak->PacketsInGroup == pOldNak->ThisGroupSize);
  2659. }
  2660. }
  2661. pOldNak->pPendingData[0].pDataPacket = NULL;
  2662. pOldNak->pPendingData[0].PendingDataFlags = 0;
  2663. pOldNak->NumDataPackets--;
  2664. InsertHeadList (&OldNaksList, &pOldNak->Linkage);
  2665. }
  2666. if (SEQ_GEQ (pReceive->pReceiver->NextODataSequenceNumber, pNewNak->SequenceNumber))
  2667. {
  2668. ASSERT (pReceive->pReceiver->NextODataSequenceNumber ==
  2669. (pReceive->pReceiver->FirstNakSequenceNumber + pNewNak->NextIndexToIndicate));
  2670. ASSERT (IsListEmpty (&pReceive->pReceiver->BufferedDataList));
  2671. pReceive->pReceiver->NextODataSequenceNumber = pNewNak->SequenceNumber;
  2672. }
  2673. else
  2674. {
  2675. ASSERT ((0 == pNewNak->NextIndexToIndicate) &&
  2676. !(IsListEmpty (&pReceive->pReceiver->BufferedDataList)));
  2677. }
  2678. if (SEQ_GT (pReceive->pReceiver->LastTrailingEdgeSeqNum, pReceive->pReceiver->FirstNakSequenceNumber))
  2679. {
  2680. pReceive->pReceiver->LastTrailingEdgeSeqNum = pReceive->pReceiver->FirstNakSequenceNumber;
  2681. }
  2682. RemoveRedundantNaks (pReceive, pNewNak, FALSE);
  2683. if ((pNewNak->NextIndexToIndicate + pNewNak->NumDataPackets) >= pNewNak->PacketsInGroup)
  2684. {
  2685. // This entry will be moved automatically to the buffered data list
  2686. // when we call AdjustReceiveBufferLists below
  2687. pNewNak->PendingNakTimeout = 0;
  2688. }
  2689. else
  2690. {
  2691. pNewNak->PendingNakTimeout = PgmDynamicConfig.ReceiversTimerTickCount +
  2692. ((NakRandomBackoffMSecs/(pNewNak->PacketsInGroup-(pNewNak->NextIndexToIndicate+pNewNak->NumDataPackets)))/
  2693. BASIC_TIMER_GRANULARITY_IN_MSECS);
  2694. }
  2695. }
  2696. ASSERT (IsListEmpty (&pReceive->pReceiver->NaksForwardDataList));
  2697. ASSERT (IsListEmpty (&pReceive->pReceiver->PendingNaksList));
  2698. if (!IsListEmpty (&NewNaksList))
  2699. {
  2700. //
  2701. // Now, move the new list to the end of the current list
  2702. //
  2703. NewNaksList.Flink->Blink = pReceive->pReceiver->NaksForwardDataList.Blink;
  2704. NewNaksList.Blink->Flink = &pReceive->pReceiver->NaksForwardDataList;
  2705. pReceive->pReceiver->NaksForwardDataList.Blink->Flink = NewNaksList.Flink;
  2706. pReceive->pReceiver->NaksForwardDataList.Blink = NewNaksList.Blink;
  2707. }
  2708. while (!IsListEmpty (&OldNaksList))
  2709. {
  2710. pEntry = RemoveHeadList (&OldNaksList);
  2711. pOldNak = CONTAINING_RECORD (pEntry, tNAK_FORWARD_DATA, Linkage);
  2712. FreeNakContext (pReceive, pOldNak);
  2713. }
  2714. //
  2715. // Put the pending Naks in the PendingNaks list
  2716. //
  2717. pReceive->pReceiver->ReceiveDataIndexShift = gFECLog2[GroupSize];
  2718. pEntry = &pReceive->pReceiver->NaksForwardDataList;
  2719. while ((pEntry = pEntry->Flink) != &pReceive->pReceiver->NaksForwardDataList)
  2720. {
  2721. pNewNak = CONTAINING_RECORD (pEntry, tNAK_FORWARD_DATA, Linkage);
  2722. if (((pNewNak->NumDataPackets + pNewNak->NumParityPackets) < pNewNak->PacketsInGroup) &&
  2723. ((pNewNak->NextIndexToIndicate + pNewNak->NumDataPackets) < pNewNak->PacketsInGroup))
  2724. {
  2725. AppendPendingReceiverEntry (pReceive->pReceiver, pNewNak);
  2726. }
  2727. }
  2728. AdjustReceiveBufferLists (pReceive);
  2729. pNewNak = NULL;
  2730. if (!(IsListEmpty (&pReceive->pReceiver->NaksForwardDataList)))
  2731. {
  2732. //
  2733. // For the last context, set the Nak timeout appropriately
  2734. //
  2735. pNewNak = CONTAINING_RECORD (pReceive->pReceiver->NaksForwardDataList.Blink, tNAK_FORWARD_DATA, Linkage);
  2736. if (pNewNak->NumDataPackets < pNewNak->PacketsInGroup)
  2737. {
  2738. pNewNak->PendingNakTimeout = PgmDynamicConfig.ReceiversTimerTickCount +
  2739. ((NakRepeatIntervalMSecs +
  2740. (NakRandomBackoffMSecs /
  2741. (pNewNak->PacketsInGroup-pNewNak->NumDataPackets))) /
  2742. BASIC_TIMER_GRANULARITY_IN_MSECS);
  2743. }
  2744. }
  2745. else if (!(IsListEmpty (&pReceive->pReceiver->BufferedDataList)))
  2746. {
  2747. pNewNak = CONTAINING_RECORD (pReceive->pReceiver->BufferedDataList.Blink, tNAK_FORWARD_DATA, Linkage);
  2748. }
  2749. //
  2750. // Now, set the FirstKnownGroupSequenceNumber
  2751. //
  2752. if (pNewNak)
  2753. {
  2754. pReceive->pReceiver->FurthestKnownGroupSequenceNumber = pNewNak->SequenceNumber;
  2755. }
  2756. else
  2757. {
  2758. pReceive->pReceiver->FurthestKnownGroupSequenceNumber &= ~GroupMask;
  2759. }
  2760. PgmTrace (LogStatus, ("CoalesceSelectiveNaksIntoGroups: " \
  2761. "[2] NextOData=<%d>, FirstNak=<%d->%d>, FirstGroup=<%d>, LastGroup=<%d>\n",
  2762. (ULONG) pReceive->pReceiver->NextODataSequenceNumber,
  2763. (ULONG) pReceive->pReceiver->FirstNakSequenceNumber,
  2764. (pNewNak ? (ULONG) pNewNak->NextIndexToIndicate : (ULONG) 0),
  2765. (ULONG) FirstGroupSequenceNumber,
  2766. (ULONG) pReceive->pReceiver->FurthestKnownGroupSequenceNumber));
  2767. return (status); // If we had failed earlier, we should still fail!
  2768. }
  2769. //----------------------------------------------------------------------------
  2770. NTSTATUS
  2771. PgmIndicateToClient(
  2772. IN tADDRESS_CONTEXT *pAddress,
  2773. IN tRECEIVE_SESSION *pReceive,
  2774. IN ULONG BytesAvailable,
  2775. IN PUCHAR pDataBuffer,
  2776. IN ULONG MessageOffset,
  2777. IN ULONG MessageLength,
  2778. OUT ULONG *pBytesTaken,
  2779. IN PGMLockHandle *pOldIrqAddress,
  2780. IN PGMLockHandle *pOldIrqReceive
  2781. )
  2782. /*++
  2783. Routine Description:
  2784. This routine tries to indicate the Data packet provided to the client
  2785. It is called with the pAddress and pReceive locks held
  2786. Arguments:
  2787. IN pAddress -- Address object context
  2788. IN pReceive -- Receive context
  2789. IN BytesAvailableToIndicate -- Length of packet received from the wire
  2790. IN pPgmDataHeader -- Data packet
  2791. IN pOldIrqAddress -- OldIrq for the Address lock
  2792. IN pOldIrqReceive -- OldIrq for the Receive lock
  2793. Return Value:
  2794. NTSTATUS - Final status of the call
  2795. --*/
  2796. {
  2797. PIO_STACK_LOCATION pIrpSp;
  2798. PTDI_REQUEST_KERNEL_RECEIVE pClientParams;
  2799. CONNECTION_CONTEXT ClientSessionContext;
  2800. PIRP pIrpReceive;
  2801. ULONG ReceiveFlags, BytesTaken, BytesToCopy, BytesLeftInMessage, ClientBytesTaken;
  2802. tRECEIVE_CONTEXT *pReceiver = pReceive->pReceiver;
  2803. NTSTATUS status = STATUS_SUCCESS;
  2804. PTDI_IND_RECEIVE evReceive = NULL;
  2805. PVOID RcvEvContext = NULL;
  2806. ULONG BytesAvailableToIndicate = BytesAvailable;
  2807. if (pReceive->SessionFlags & (PGM_SESSION_CLIENT_DISCONNECTED |
  2808. PGM_SESSION_TERMINATED_ABORT))
  2809. {
  2810. PgmTrace (LogError, ("PgmIndicateToClient: ERROR -- " \
  2811. "pReceive=<%p> disassociated during Receive!\n", pReceive));
  2812. *pBytesTaken = 0;
  2813. return (STATUS_DATA_NOT_ACCEPTED);
  2814. }
  2815. ASSERT ((!pReceiver->CurrentMessageLength) || (pReceiver->CurrentMessageLength == MessageLength));
  2816. ASSERT (pReceiver->CurrentMessageProcessed == MessageOffset);
  2817. pReceiver->CurrentMessageLength = MessageLength;
  2818. pReceiver->CurrentMessageProcessed = MessageOffset;
  2819. BytesLeftInMessage = MessageLength - MessageOffset;
  2820. PgmTrace (LogAllFuncs, ("PgmIndicateToClient: " \
  2821. "MessageLen=<%d/%d>, MessageOff=<%d>, CurrentML=<%d>, CurrentMP=<%d>\n",
  2822. BytesAvailableToIndicate, MessageLength, MessageOffset,
  2823. pReceiver->CurrentMessageLength, pReceiver->CurrentMessageProcessed));
  2824. //
  2825. // We may have a receive Irp pending from a previous indication,
  2826. // so see if need to fill that first!
  2827. //
  2828. while ((BytesAvailableToIndicate) &&
  2829. ((pIrpReceive = pReceiver->pIrpReceive) ||
  2830. (!IsListEmpty (&pReceiver->ReceiveIrpsList))))
  2831. {
  2832. if (!pIrpReceive)
  2833. {
  2834. //
  2835. // The client had posted a receive Irp, so use it now!
  2836. //
  2837. pIrpReceive = CONTAINING_RECORD (pReceiver->ReceiveIrpsList.Flink,
  2838. IRP, Tail.Overlay.ListEntry);
  2839. RemoveEntryList (&pIrpReceive->Tail.Overlay.ListEntry);
  2840. pIrpSp = IoGetCurrentIrpStackLocation (pIrpReceive);
  2841. pClientParams = (PTDI_REQUEST_KERNEL_RECEIVE) &pIrpSp->Parameters;
  2842. pReceiver->pIrpReceive = pIrpReceive;
  2843. pReceiver->TotalBytesInMdl = pClientParams->ReceiveLength;
  2844. pReceiver->BytesInMdl = 0;
  2845. }
  2846. //
  2847. // Copy whatever bytes we can into it
  2848. //
  2849. if (BytesAvailableToIndicate >
  2850. (pReceiver->TotalBytesInMdl - pReceiver->BytesInMdl))
  2851. {
  2852. BytesToCopy = pReceiver->TotalBytesInMdl - pReceiver->BytesInMdl;
  2853. }
  2854. else
  2855. {
  2856. BytesToCopy = BytesAvailableToIndicate;
  2857. }
  2858. ClientBytesTaken = 0;
  2859. status = TdiCopyBufferToMdl (pDataBuffer,
  2860. 0,
  2861. BytesToCopy,
  2862. pReceiver->pIrpReceive->MdlAddress,
  2863. pReceiver->BytesInMdl,
  2864. &ClientBytesTaken);
  2865. pReceiver->BytesInMdl += ClientBytesTaken;
  2866. pReceiver->CurrentMessageProcessed += ClientBytesTaken;
  2867. BytesLeftInMessage -= ClientBytesTaken;
  2868. BytesAvailableToIndicate -= ClientBytesTaken;
  2869. pDataBuffer += ClientBytesTaken;
  2870. if ((!ClientBytesTaken) ||
  2871. (pReceiver->BytesInMdl >= pReceiver->TotalBytesInMdl) ||
  2872. (!BytesLeftInMessage))
  2873. {
  2874. //
  2875. // The Irp is full, so complete the Irp!
  2876. //
  2877. pIrpReceive = pReceiver->pIrpReceive;
  2878. pIrpReceive->IoStatus.Information = pReceiver->BytesInMdl;
  2879. if (BytesLeftInMessage)
  2880. {
  2881. pIrpReceive->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
  2882. }
  2883. else
  2884. {
  2885. ASSERT (pReceiver->CurrentMessageLength == pReceiver->CurrentMessageProcessed);
  2886. pIrpReceive->IoStatus.Status = STATUS_SUCCESS;
  2887. }
  2888. //
  2889. // Before releasing the lock, set the parameters for the next receive
  2890. //
  2891. pReceiver->pIrpReceive = NULL;
  2892. pReceiver->TotalBytesInMdl = pReceiver->BytesInMdl = 0;
  2893. PgmUnlock (pReceive, *pOldIrqReceive);
  2894. PgmUnlock (pAddress, *pOldIrqAddress);
  2895. PgmCancelCancelRoutine (pIrpReceive);
  2896. PgmTrace (LogPath, ("PgmIndicateToClient: " \
  2897. "Completing prior pIrp=<%p>, Bytes=<%d>, BytesLeft=<%d>\n",
  2898. pIrpReceive, (ULONG) pIrpReceive->IoStatus.Information, BytesAvailableToIndicate));
  2899. IoCompleteRequest (pIrpReceive, IO_NETWORK_INCREMENT);
  2900. PgmLock (pAddress, *pOldIrqAddress);
  2901. PgmLock (pReceive, *pOldIrqReceive);
  2902. }
  2903. }
  2904. //
  2905. // If there are no more bytes left to indicate, return
  2906. //
  2907. if (BytesAvailableToIndicate == 0)
  2908. {
  2909. if (!BytesLeftInMessage)
  2910. {
  2911. ASSERT (pReceiver->CurrentMessageLength == pReceiver->CurrentMessageProcessed);
  2912. pReceiver->CurrentMessageLength = pReceiver->CurrentMessageProcessed = 0;
  2913. }
  2914. if (BytesTaken = (BytesAvailable - BytesAvailableToIndicate))
  2915. {
  2916. *pBytesTaken = BytesTaken;
  2917. pReceiver->LastDataConsumedTime = PgmDynamicConfig.ReceiversTimerTickCount;
  2918. }
  2919. return (STATUS_SUCCESS);
  2920. }
  2921. // call the Client Event Handler
  2922. pIrpReceive = NULL;
  2923. ClientBytesTaken = 0;
  2924. evReceive = pAddress->evReceive;
  2925. ClientSessionContext = pReceive->ClientSessionContext;
  2926. RcvEvContext = pAddress->RcvEvContext;
  2927. ASSERT (RcvEvContext);
  2928. PgmUnlock (pReceive, *pOldIrqReceive);
  2929. PgmUnlock (pAddress, *pOldIrqAddress);
  2930. ReceiveFlags = TDI_RECEIVE_NORMAL;
  2931. if (PgmGetCurrentIrql())
  2932. {
  2933. ReceiveFlags |= TDI_RECEIVE_AT_DISPATCH_LEVEL;
  2934. }
  2935. #if 0
  2936. if (BytesLeftInMessage == BytesAvailableToIndicate)
  2937. {
  2938. ReceiveFlags |= TDI_RECEIVE_ENTIRE_MESSAGE;
  2939. }
  2940. status = (*evReceive) (RcvEvContext,
  2941. ClientSessionContext,
  2942. ReceiveFlags,
  2943. BytesAvailableToIndicate,
  2944. BytesAvailableToIndicate,
  2945. &ClientBytesTaken,
  2946. pDataBuffer,
  2947. &pIrpReceive);
  2948. #else
  2949. ReceiveFlags |= TDI_RECEIVE_ENTIRE_MESSAGE;
  2950. status = (*evReceive) (RcvEvContext,
  2951. ClientSessionContext,
  2952. ReceiveFlags,
  2953. BytesAvailableToIndicate,
  2954. BytesLeftInMessage,
  2955. &ClientBytesTaken,
  2956. pDataBuffer,
  2957. &pIrpReceive);
  2958. #endif // 0
  2959. PgmTrace (LogPath, ("PgmIndicateToClient: " \
  2960. "Client's evReceive returned status=<%x>, ReceiveFlags=<%x>, Client took <%d/%d|%d>, pIrp=<%p>\n",
  2961. status, ReceiveFlags, ClientBytesTaken, BytesAvailableToIndicate, BytesLeftInMessage, pIrpReceive));
  2962. if (ClientBytesTaken > BytesAvailableToIndicate)
  2963. {
  2964. ClientBytesTaken = BytesAvailableToIndicate;
  2965. }
  2966. ASSERT (ClientBytesTaken <= BytesAvailableToIndicate);
  2967. BytesAvailableToIndicate -= ClientBytesTaken;
  2968. BytesLeftInMessage -= ClientBytesTaken;
  2969. pDataBuffer = pDataBuffer + ClientBytesTaken;
  2970. if ((status == STATUS_MORE_PROCESSING_REQUIRED) &&
  2971. (pIrpReceive) &&
  2972. (!NT_SUCCESS (PgmCheckSetCancelRoutine (pIrpReceive, PgmCancelReceiveIrp, FALSE))))
  2973. {
  2974. PgmTrace (LogError, ("PgmIndicateToClient: ERROR -- " \
  2975. "pReceive=<%p>, pIrp=<%p> Cancelled during Receive!\n", pReceive, pIrpReceive));
  2976. PgmIoComplete (pIrpReceive, STATUS_CANCELLED, 0);
  2977. PgmLock (pAddress, *pOldIrqAddress);
  2978. PgmLock (pReceive, *pOldIrqReceive);
  2979. pReceiver->CurrentMessageProcessed += ClientBytesTaken;
  2980. if (BytesTaken = (BytesAvailable - BytesAvailableToIndicate))
  2981. {
  2982. *pBytesTaken = BytesTaken;
  2983. pReceiver->LastDataConsumedTime = PgmDynamicConfig.ReceiversTimerTickCount;
  2984. }
  2985. return (STATUS_UNSUCCESSFUL);
  2986. }
  2987. PgmLock (pAddress, *pOldIrqAddress);
  2988. PgmLock (pReceive, *pOldIrqReceive);
  2989. pReceiver->CurrentMessageProcessed += ClientBytesTaken;
  2990. if (!pReceiver->pAddress)
  2991. {
  2992. // the connection was disassociated in the interim so do nothing.
  2993. if (status == STATUS_MORE_PROCESSING_REQUIRED)
  2994. {
  2995. PgmUnlock (pReceive, *pOldIrqReceive);
  2996. PgmUnlock (pAddress, *pOldIrqAddress);
  2997. PgmIoComplete (pIrpReceive, STATUS_CANCELLED, 0);
  2998. PgmLock (pAddress, *pOldIrqAddress);
  2999. PgmLock (pReceive, *pOldIrqReceive);
  3000. }
  3001. PgmTrace (LogError, ("PgmIndicateToClient: ERROR -- " \
  3002. "pReceive=<%p> disassociated during Receive!\n", pReceive));
  3003. if (BytesTaken = (BytesAvailable - BytesAvailableToIndicate))
  3004. {
  3005. *pBytesTaken = BytesTaken;
  3006. pReceiver->LastDataConsumedTime = PgmDynamicConfig.ReceiversTimerTickCount;
  3007. }
  3008. return (STATUS_UNSUCCESSFUL);
  3009. }
  3010. if (status == STATUS_MORE_PROCESSING_REQUIRED)
  3011. {
  3012. ASSERT (pIrpReceive);
  3013. ASSERT (pIrpReceive->MdlAddress);
  3014. pIrpSp = IoGetCurrentIrpStackLocation (pIrpReceive);
  3015. pClientParams = (PTDI_REQUEST_KERNEL_RECEIVE) &pIrpSp->Parameters;
  3016. ASSERT (pClientParams->ReceiveLength);
  3017. ClientBytesTaken = 0;
  3018. if (pClientParams->ReceiveLength < BytesAvailableToIndicate)
  3019. {
  3020. BytesToCopy = pClientParams->ReceiveLength;
  3021. }
  3022. else
  3023. {
  3024. BytesToCopy = BytesAvailableToIndicate;
  3025. }
  3026. status = TdiCopyBufferToMdl (pDataBuffer,
  3027. 0,
  3028. BytesToCopy,
  3029. pIrpReceive->MdlAddress,
  3030. pReceiver->BytesInMdl,
  3031. &ClientBytesTaken);
  3032. BytesLeftInMessage -= ClientBytesTaken;
  3033. BytesAvailableToIndicate -= ClientBytesTaken;
  3034. pDataBuffer = pDataBuffer + ClientBytesTaken;
  3035. pReceiver->CurrentMessageProcessed += ClientBytesTaken;
  3036. PgmTrace (LogPath, ("PgmIndicateToClient: " \
  3037. "Client's evReceive returned pIrp=<%p>, BytesInIrp=<%d>, Copied <%d> bytes\n",
  3038. pIrpReceive, pClientParams->ReceiveLength, ClientBytesTaken));
  3039. if ((!ClientBytesTaken) ||
  3040. (ClientBytesTaken >= pClientParams->ReceiveLength) ||
  3041. (pReceiver->CurrentMessageLength == pReceiver->CurrentMessageProcessed))
  3042. {
  3043. //
  3044. // The Irp is full, so complete the Irp!
  3045. //
  3046. pIrpReceive->IoStatus.Information = ClientBytesTaken;
  3047. if (pReceiver->CurrentMessageLength == pReceiver->CurrentMessageProcessed)
  3048. {
  3049. pIrpReceive->IoStatus.Status = STATUS_SUCCESS;
  3050. }
  3051. else
  3052. {
  3053. pIrpReceive->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
  3054. }
  3055. //
  3056. // Before releasing the lock, set the parameters for the next receive
  3057. //
  3058. pReceiver->TotalBytesInMdl = pReceiver->BytesInMdl = 0;
  3059. PgmUnlock (pReceive, *pOldIrqReceive);
  3060. PgmUnlock (pAddress, *pOldIrqAddress);
  3061. PgmCancelCancelRoutine (pIrpReceive);
  3062. IoCompleteRequest (pIrpReceive, IO_NETWORK_INCREMENT);
  3063. PgmLock (pAddress, *pOldIrqAddress);
  3064. PgmLock (pReceive, *pOldIrqReceive);
  3065. }
  3066. else
  3067. {
  3068. pReceiver->TotalBytesInMdl = pClientParams->ReceiveLength;
  3069. pReceiver->BytesInMdl = ClientBytesTaken;
  3070. pReceiver->pIrpReceive = pIrpReceive;
  3071. }
  3072. status = STATUS_SUCCESS;
  3073. }
  3074. else if (status == STATUS_DATA_NOT_ACCEPTED)
  3075. {
  3076. //
  3077. // An Irp could have been posted in the interval
  3078. // between the indicate and acquiring the SpinLocks,
  3079. // so check for that here
  3080. //
  3081. if ((pReceiver->pIrpReceive) ||
  3082. (!IsListEmpty (&pReceiver->ReceiveIrpsList)))
  3083. {
  3084. status = STATUS_SUCCESS;
  3085. }
  3086. else
  3087. {
  3088. pReceive->SessionFlags |= PGM_SESSION_WAIT_FOR_RECEIVE_IRP;
  3089. }
  3090. }
  3091. if (pReceiver->CurrentMessageLength == pReceiver->CurrentMessageProcessed)
  3092. {
  3093. pReceiver->CurrentMessageLength = pReceiver->CurrentMessageProcessed = 0;
  3094. }
  3095. if ((NT_SUCCESS (status)) ||
  3096. (status == STATUS_DATA_NOT_ACCEPTED))
  3097. {
  3098. PgmTrace (LogAllFuncs, ("PgmIndicateToClient: " \
  3099. "status=<%x>, pReceive=<%p>, Taken=<%d>, Available=<%d>\n",
  3100. status, pReceive, ClientBytesTaken, BytesLeftInMessage));
  3101. //
  3102. // since some bytes were taken (i.e. the session hdr) so
  3103. // return status success. (otherwise the status is
  3104. // statusNotAccpeted).
  3105. //
  3106. }
  3107. else
  3108. {
  3109. PgmTrace (LogError, ("PgmIndicateToClient: ERROR -- " \
  3110. "Unexpected status=<%x>\n", status));
  3111. ASSERT (0);
  3112. }
  3113. if (BytesTaken = (BytesAvailable - BytesAvailableToIndicate))
  3114. {
  3115. *pBytesTaken = BytesTaken;
  3116. pReceiver->LastDataConsumedTime = PgmDynamicConfig.ReceiversTimerTickCount;
  3117. }
  3118. return (status);
  3119. }
  3120. //----------------------------------------------------------------------------
  3121. NTSTATUS
  3122. PgmIndicateGroup(
  3123. IN tADDRESS_CONTEXT *pAddress,
  3124. IN tRECEIVE_SESSION *pReceive,
  3125. IN PGMLockHandle *pOldIrqAddress,
  3126. IN PGMLockHandle *pOldIrqReceive,
  3127. IN tNAK_FORWARD_DATA *pNak
  3128. )
  3129. {
  3130. UCHAR i, j;
  3131. NTSTATUS status = STATUS_SUCCESS;
  3132. ULONG BytesTaken, DataBytes, MessageLength;
  3133. ASSERT (pNak->SequenceNumber == pReceive->pReceiver->NextODataSequenceNumber);
  3134. j = pNak->NextIndexToIndicate;
  3135. while (j < pNak->PacketsInGroup)
  3136. {
  3137. if (pReceive->SessionFlags & PGM_SESSION_CLIENT_DISCONNECTED)
  3138. {
  3139. status = STATUS_DATA_NOT_ACCEPTED;
  3140. break;
  3141. }
  3142. i = pNak->pPendingData[j].ActualIndexOfDataPacket;
  3143. ASSERT (i < pNak->OriginalGroupSize);
  3144. if (pReceive->SessionFlags & PGM_SESSION_FLAG_FIRST_PACKET)
  3145. {
  3146. //
  3147. // pReceive->pReceiver->CurrentMessageProcessed would have been set
  3148. // if we were receiving a fragmented message
  3149. // or if we had only accounted for a partial message earlier
  3150. //
  3151. ASSERT (!(pReceive->pReceiver->CurrentMessageProcessed) &&
  3152. !(pReceive->pReceiver->CurrentMessageLength));
  3153. if (pNak->pPendingData[i].MessageOffset)
  3154. {
  3155. PgmTrace (LogPath, ("PgmIndicateGroup: " \
  3156. "Dropping SeqNum=[%d] since it's a PARTIAL message [%d / %d]!\n",
  3157. (ULONG) (pReceive->pReceiver->NextODataSequenceNumber + j),
  3158. pNak->pPendingData[i].MessageOffset, pNak->pPendingData[i].MessageLength));
  3159. j++;
  3160. pNak->NextIndexToIndicate++;
  3161. status = STATUS_SUCCESS;
  3162. continue;
  3163. }
  3164. pReceive->SessionFlags &= ~PGM_SESSION_FLAG_FIRST_PACKET;
  3165. }
  3166. else if ((pReceive->pReceiver->CurrentMessageProcessed !=
  3167. pNak->pPendingData[i].MessageOffset) || // Check Offsets
  3168. ((pReceive->pReceiver->CurrentMessageProcessed) && // in the midst of a Message, and
  3169. (pReceive->pReceiver->CurrentMessageLength !=
  3170. pNak->pPendingData[i].MessageLength))) // Check MessageLength
  3171. {
  3172. //
  3173. // Our state expects us to be in the middle of a message, but
  3174. // the current packets do not show this
  3175. //
  3176. PgmTrace (LogError, ("PgmIndicateGroup: ERROR -- " \
  3177. "SeqNum=[%d] Expecting MsgLen=<%d>, MsgOff=<%d>, have MsgLen=<%d>, MsgOff=<%d>\n",
  3178. (ULONG) (pReceive->pReceiver->NextODataSequenceNumber + j),
  3179. pReceive->pReceiver->CurrentMessageLength, pReceive->pReceiver->CurrentMessageProcessed,
  3180. pNak->pPendingData[i].MessageLength,
  3181. pNak->pPendingData[i].MessageOffset));
  3182. // ASSERT (0);
  3183. return (STATUS_UNSUCCESSFUL);
  3184. }
  3185. DataBytes = pNak->pPendingData[i].PacketLength - pNak->pPendingData[i].DataOffset;
  3186. if (!DataBytes)
  3187. {
  3188. //
  3189. // No need to process empty data packets (can happen if the client
  3190. // picks up partial FEC group)
  3191. //
  3192. j++;
  3193. pNak->NextIndexToIndicate++;
  3194. status = STATUS_SUCCESS;
  3195. continue;
  3196. }
  3197. if (DataBytes > (pNak->pPendingData[i].MessageLength - pNak->pPendingData[i].MessageOffset))
  3198. {
  3199. PgmTrace (LogError, ("PgmIndicateGroup: ERROR -- " \
  3200. "[%d] DataBytes=<%d> > MsgLen=<%d> - MsgOff=<%d> = <%d>\n",
  3201. (ULONG) (pReceive->pReceiver->NextODataSequenceNumber + j),
  3202. DataBytes, pNak->pPendingData[i].MessageLength,
  3203. pNak->pPendingData[i].MessageOffset,
  3204. (pNak->pPendingData[i].MessageLength - pNak->pPendingData[i].MessageOffset)));
  3205. ASSERT (0);
  3206. return (STATUS_UNSUCCESSFUL);
  3207. }
  3208. BytesTaken = 0;
  3209. status = PgmIndicateToClient (pAddress,
  3210. pReceive,
  3211. DataBytes,
  3212. (pNak->pPendingData[i].pDataPacket + pNak->pPendingData[i].DataOffset),
  3213. pNak->pPendingData[i].MessageOffset,
  3214. pNak->pPendingData[i].MessageLength,
  3215. &BytesTaken,
  3216. pOldIrqAddress,
  3217. pOldIrqReceive);
  3218. PgmTrace (LogPath, ("PgmIndicateGroup: " \
  3219. "SeqNum=[%d]: PgmIndicate returned<%x>\n",
  3220. (ULONG) pNak->SequenceNumber, status));
  3221. ASSERT (BytesTaken <= DataBytes);
  3222. pNak->pPendingData[i].MessageOffset += BytesTaken;
  3223. pNak->pPendingData[i].DataOffset += (USHORT) BytesTaken;
  3224. if (BytesTaken == DataBytes)
  3225. {
  3226. //
  3227. // Go to the next packet
  3228. //
  3229. j++;
  3230. pNak->NextIndexToIndicate++;
  3231. pReceive->pReceiver->DataPacketsIndicated++;
  3232. status = STATUS_SUCCESS;
  3233. }
  3234. else if (!NT_SUCCESS (status))
  3235. {
  3236. //
  3237. // We failed, and if the status was STATUS_DATA_NOT_ACCEPTED,
  3238. // we also don't have any ReceiveIrps pending either
  3239. //
  3240. break;
  3241. }
  3242. //
  3243. // else retry indicating this data until we get an error
  3244. //
  3245. }
  3246. //
  3247. // If the status is anything other than STATUS_DATA_NOT_ACCEPTED (whether
  3248. // success or failure), then it means we are done with this data!
  3249. //
  3250. return (status);
  3251. }
  3252. //----------------------------------------------------------------------------
  3253. NTSTATUS
  3254. DecodeParityPackets(
  3255. IN tRECEIVE_SESSION *pReceive,
  3256. IN tNAK_FORWARD_DATA *pNak
  3257. )
  3258. {
  3259. NTSTATUS status;
  3260. USHORT MinBufferSize;
  3261. USHORT DataBytes, FprOffset;
  3262. UCHAR i;
  3263. PUCHAR pDataBuffer;
  3264. tPOST_PACKET_FEC_CONTEXT FECContext;
  3265. PgmZeroMemory (&FECContext, sizeof (tPOST_PACKET_FEC_CONTEXT));
  3266. //
  3267. // Verify that the our buffer is large enough to hold the data
  3268. //
  3269. ASSERT (pReceive->MaxMTULength > pNak->ParityDataSize);
  3270. MinBufferSize = pNak->ParityDataSize + sizeof(tPOST_PACKET_FEC_CONTEXT) - sizeof(USHORT);
  3271. ASSERT (pNak->PacketsInGroup == pNak->NumDataPackets + pNak->NumParityPackets);
  3272. //
  3273. // Now, copy the data into the DecodeBuffers
  3274. //
  3275. FprOffset = pNak->ParityDataSize - sizeof(USHORT) +
  3276. FIELD_OFFSET (tPOST_PACKET_FEC_CONTEXT, FragmentOptSpecific);
  3277. pDataBuffer = pReceive->pFECBuffer;
  3278. for (i=0; i<pReceive->FECGroupSize; i++)
  3279. {
  3280. //
  3281. // See if this is a NULL buffer (for partial groups!)
  3282. //
  3283. if (i >= pNak->PacketsInGroup)
  3284. {
  3285. ASSERT (!pNak->pPendingData[i].PacketIndex);
  3286. ASSERT (!pNak->pPendingData[i].pDataPacket);
  3287. DataBytes = pNak->ParityDataSize - sizeof(USHORT) + sizeof (tPOST_PACKET_FEC_CONTEXT);
  3288. pNak->pPendingData[i].PacketIndex = i;
  3289. pNak->pPendingData[i].PacketLength = DataBytes;
  3290. pNak->pPendingData[i].DataOffset = 0;
  3291. PgmZeroMemory (pDataBuffer, DataBytes);
  3292. pDataBuffer [FprOffset] = PACKET_OPTION_SPECIFIC_ENCODED_NULL_BIT;
  3293. pNak->pPendingData[i].DecodeBuffer = pDataBuffer;
  3294. pDataBuffer += DataBytes;
  3295. PgmZeroMemory (pDataBuffer, DataBytes);
  3296. pNak->pPendingData[i].pDataPacket = pDataBuffer;
  3297. pDataBuffer += DataBytes;
  3298. continue;
  3299. }
  3300. //
  3301. // See if this is a parity packet!
  3302. //
  3303. if (pNak->pPendingData[i].PacketIndex >= pReceive->FECGroupSize)
  3304. {
  3305. DataBytes = pNak->pPendingData[i].PacketLength - pNak->pPendingData[i].DataOffset;
  3306. ASSERT (DataBytes == pNak->ParityDataSize);
  3307. PgmCopyMemory (pDataBuffer,
  3308. pNak->pPendingData[i].pDataPacket + pNak->pPendingData[i].DataOffset,
  3309. DataBytes);
  3310. pNak->pPendingData[i].DecodeBuffer = pDataBuffer;
  3311. pDataBuffer += (pNak->ParityDataSize - sizeof(USHORT));
  3312. PgmCopyMemory (&FECContext.EncodedTSDULength, pDataBuffer, sizeof (USHORT));
  3313. FECContext.FragmentOptSpecific = pNak->pPendingData[i].FragmentOptSpecific;
  3314. FECContext.EncodedFragmentOptions.MessageFirstSequence = pNak->pPendingData[i].MessageFirstSequence;
  3315. FECContext.EncodedFragmentOptions.MessageOffset = pNak->pPendingData[i].MessageOffset;
  3316. FECContext.EncodedFragmentOptions.MessageLength = pNak->pPendingData[i].MessageLength;
  3317. PgmCopyMemory (pDataBuffer, &FECContext, sizeof (tPOST_PACKET_FEC_CONTEXT));
  3318. pDataBuffer += sizeof (tPOST_PACKET_FEC_CONTEXT);
  3319. continue;
  3320. }
  3321. //
  3322. // This is a Data packet
  3323. //
  3324. ASSERT (pNak->pPendingData[i].PacketIndex < pNak->PacketsInGroup);
  3325. DataBytes = pNak->pPendingData[i].PacketLength - pNak->pPendingData[i].DataOffset;
  3326. ASSERT ((DataBytes+sizeof(USHORT)) <= pNak->ParityDataSize);
  3327. // Copy the data
  3328. PgmCopyMemory (pDataBuffer,
  3329. pNak->pPendingData[i].pDataPacket + pNak->pPendingData[i].DataOffset,
  3330. DataBytes);
  3331. //
  3332. // Verify that the Data Buffer length is sufficient for the output data
  3333. //
  3334. if ((pNak->MinPacketLength < MinBufferSize) &&
  3335. (pNak->pPendingData[i].PacketLength < pNak->ParityDataSize))
  3336. {
  3337. if (!ReAllocateDataBuffer (pReceive, &pNak->pPendingData[i], MinBufferSize))
  3338. {
  3339. ASSERT (0);
  3340. PgmTrace (LogError, ("DecodeParityPackets: ERROR -- " \
  3341. "STATUS_INSUFFICIENT_RESOURCES[2] ...\n"));
  3342. return (STATUS_INSUFFICIENT_RESOURCES);
  3343. }
  3344. }
  3345. pNak->pPendingData[i].DecodeBuffer = pDataBuffer;
  3346. //
  3347. // Zero the remaining buffer
  3348. //
  3349. PgmZeroMemory ((pDataBuffer + DataBytes), (pNak->ParityDataSize - DataBytes));
  3350. pDataBuffer += (pNak->ParityDataSize - sizeof(USHORT));
  3351. FECContext.EncodedTSDULength = htons (DataBytes);
  3352. FECContext.FragmentOptSpecific = pNak->pPendingData[i].FragmentOptSpecific;
  3353. if (FECContext.FragmentOptSpecific & PACKET_OPTION_SPECIFIC_ENCODED_NULL_BIT)
  3354. {
  3355. //
  3356. // This bit is set if the option did not exist in the original packet
  3357. //
  3358. FECContext.EncodedFragmentOptions.MessageFirstSequence = 0;
  3359. FECContext.EncodedFragmentOptions.MessageOffset = 0;
  3360. FECContext.EncodedFragmentOptions.MessageLength = 0;
  3361. }
  3362. else
  3363. {
  3364. FECContext.EncodedFragmentOptions.MessageFirstSequence = htonl (pNak->pPendingData[i].MessageFirstSequence);
  3365. FECContext.EncodedFragmentOptions.MessageOffset = htonl (pNak->pPendingData[i].MessageOffset);
  3366. FECContext.EncodedFragmentOptions.MessageLength = htonl (pNak->pPendingData[i].MessageLength);
  3367. }
  3368. PgmCopyMemory (pDataBuffer, &FECContext, sizeof (tPOST_PACKET_FEC_CONTEXT));
  3369. pDataBuffer += sizeof (tPOST_PACKET_FEC_CONTEXT);
  3370. }
  3371. #ifdef FEC_DBG
  3372. {
  3373. UCHAR i;
  3374. tPOST_PACKET_FEC_CONTEXT UNALIGNED *pFECC;
  3375. tPOST_PACKET_FEC_CONTEXT FECC;
  3376. for (i=0; i<pReceive->FECGroupSize; i++)
  3377. {
  3378. pFECC = (tPOST_PACKET_FEC_CONTEXT UNALIGNED *)
  3379. &pNak->pPendingData[i].DecodeBuffer[pNak->ParityDataSize-sizeof(USHORT)];
  3380. PgmCopyMemory (&FECC, pFECC, sizeof (tPOST_PACKET_FEC_CONTEXT));
  3381. PgmTrace (LogFec, ("\t-- [%d:%d:%d] EncTSDULen=<%x>, Fpr=<%x>, [%x -- %x -- %x]\n",
  3382. (ULONG) pNak->SequenceNumber, (ULONG) pNak->pPendingData[i].PacketIndex,
  3383. (ULONG) pNak->pPendingData[i].ActualIndexOfDataPacket,
  3384. FECC.EncodedTSDULength, FECC.FragmentOptSpecific,
  3385. FECC.EncodedFragmentOptions.MessageFirstSequence,
  3386. FECC.EncodedFragmentOptions.MessageOffset,
  3387. FECC.EncodedFragmentOptions.MessageLength)));
  3388. }
  3389. }
  3390. #endif // FEC_DBG
  3391. DataBytes = pNak->ParityDataSize - sizeof(USHORT) + sizeof (tPOST_PACKET_FEC_CONTEXT);
  3392. status = FECDecode (&pReceive->FECContext,
  3393. &(pNak->pPendingData[0]),
  3394. DataBytes,
  3395. pNak->PacketsInGroup);
  3396. //
  3397. // Before we do anything else, we should NULL out the dummy DataBuffer
  3398. // ptrs so that they don't get Free'ed accidentally!
  3399. //
  3400. for (i=0; i<pReceive->FECGroupSize; i++)
  3401. {
  3402. pNak->pPendingData[i].DecodeBuffer = NULL;
  3403. if (i >= pNak->PacketsInGroup)
  3404. {
  3405. ASSERT (!pNak->pPendingData[i].PendingDataFlags);
  3406. pNak->pPendingData[i].pDataPacket = NULL;
  3407. }
  3408. pNak->pPendingData[i].ActualIndexOfDataPacket = i;
  3409. }
  3410. if (NT_SUCCESS (status))
  3411. {
  3412. pNak->NumDataPackets = pNak->PacketsInGroup;
  3413. pNak->NumParityPackets = 0;
  3414. DataBytes -= sizeof (tPOST_PACKET_FEC_CONTEXT);
  3415. for (i=0; i<pNak->PacketsInGroup; i++)
  3416. {
  3417. PgmCopyMemory (&FECContext,
  3418. &(pNak->pPendingData[i].pDataPacket) [DataBytes],
  3419. sizeof (tPOST_PACKET_FEC_CONTEXT));
  3420. pNak->pPendingData[i].PacketLength = ntohs (FECContext.EncodedTSDULength);
  3421. if (pNak->pPendingData[i].PacketLength > DataBytes)
  3422. {
  3423. PgmTrace (LogError, ("DecodeParityPackets: ERROR -- " \
  3424. "[%d] PacketLength=<%d> > MaxDataBytes=<%d>\n",
  3425. (ULONG) i, (ULONG) pNak->pPendingData[i].PacketLength, (ULONG) DataBytes));
  3426. ASSERT (0);
  3427. return (STATUS_UNSUCCESSFUL);
  3428. }
  3429. pNak->pPendingData[i].DataOffset = 0;
  3430. pNak->pPendingData[i].PacketIndex = i;
  3431. ASSERT ((pNak->AllOptionsFlags & PGM_OPTION_FLAG_FRAGMENT) ||
  3432. (!FECContext.EncodedFragmentOptions.MessageLength));
  3433. if (!(pNak->AllOptionsFlags & PGM_OPTION_FLAG_FRAGMENT) ||
  3434. (FECContext.FragmentOptSpecific & PACKET_OPTION_SPECIFIC_ENCODED_NULL_BIT))
  3435. {
  3436. //
  3437. // This is not a packet fragment
  3438. //
  3439. pNak->pPendingData[i].MessageFirstSequence = (ULONG) (SEQ_TYPE) (pNak->SequenceNumber + i);
  3440. pNak->pPendingData[i].MessageOffset = 0;
  3441. pNak->pPendingData[i].MessageLength = pNak->pPendingData[i].PacketLength;
  3442. }
  3443. else
  3444. {
  3445. pNak->pPendingData[i].MessageFirstSequence = ntohl (FECContext.EncodedFragmentOptions.MessageFirstSequence);
  3446. pNak->pPendingData[i].MessageOffset = ntohl (FECContext.EncodedFragmentOptions.MessageOffset);
  3447. pNak->pPendingData[i].MessageLength = ntohl (FECContext.EncodedFragmentOptions.MessageLength);
  3448. }
  3449. }
  3450. }
  3451. else
  3452. {
  3453. PgmTrace (LogError, ("DecodeParityPackets: ERROR -- " \
  3454. "FECDecode returned <%x>\n", status));
  3455. ASSERT (0);
  3456. status = STATUS_UNSUCCESSFUL;
  3457. }
  3458. #ifdef FEC_DBG
  3459. if (NT_SUCCESS (status))
  3460. {
  3461. UCHAR i;
  3462. tPOST_PACKET_FEC_CONTEXT UNALIGNED *pFECC;
  3463. tPOST_PACKET_FEC_CONTEXT FECC;
  3464. DataBytes = pNak->ParityDataSize - sizeof(USHORT);
  3465. for (i=0; i<pNak->PacketsInGroup; i++)
  3466. {
  3467. pFECC = (tPOST_PACKET_FEC_CONTEXT UNALIGNED *) &pNak->pPendingData[i].pDataPacket[DataBytes];
  3468. PgmCopyMemory (&FECC, pFECC, sizeof (tPOST_PACKET_FEC_CONTEXT));
  3469. PgmTrace (LogFec, ("\t++ [%d] EncTSDULen=<%x>, Fpr=<%x>, [%x -- %x -- %x], ==> [%x -- %x -- %x]\n",
  3470. (ULONG) (pNak->SequenceNumber+i), FECC.EncodedTSDULength, FECC.FragmentOptSpecific,
  3471. FECC.EncodedFragmentOptions.MessageFirstSequence,
  3472. FECC.EncodedFragmentOptions.MessageOffset,
  3473. FECC.EncodedFragmentOptions.MessageLength,
  3474. pNak->pPendingData[i].MessageFirstSequence,
  3475. pNak->pPendingData[i].MessageOffset,
  3476. pNak->pPendingData[i].MessageLength));
  3477. }
  3478. PgmTrace (LogFec, ("\n"));
  3479. }
  3480. #endif // FEC_DBG
  3481. return (status);
  3482. }
  3483. //----------------------------------------------------------------------------
  3484. NTSTATUS
  3485. CheckIndicatePendedData(
  3486. IN tADDRESS_CONTEXT *pAddress,
  3487. IN tRECEIVE_SESSION *pReceive,
  3488. IN PGMLockHandle *pOldIrqAddress,
  3489. IN PGMLockHandle *pOldIrqReceive
  3490. )
  3491. /*++
  3492. Routine Description:
  3493. This routine is typically called if the client signalled an
  3494. inability to handle indicated data -- it will reattempt to
  3495. indicate the data to the client
  3496. It is called with the pAddress and pReceive locks held
  3497. Arguments:
  3498. IN pAddress -- Address object context
  3499. IN pReceive -- Receive context
  3500. IN pOldIrqAddress -- OldIrq for the Address lock
  3501. IN pOldIrqReceive -- OldIrq for the Receive lock
  3502. Return Value:
  3503. NTSTATUS - Final status of the call
  3504. --*/
  3505. {
  3506. tNAK_FORWARD_DATA *pNextNak;
  3507. tPACKET_OPTIONS PacketOptions;
  3508. ULONG PacketsIndicated;
  3509. tBASIC_DATA_PACKET_HEADER UNALIGNED *pPgmDataHeader;
  3510. NTSTATUS status = STATUS_SUCCESS;
  3511. tRECEIVE_CONTEXT *pReceiver = pReceive->pReceiver;
  3512. //
  3513. // If we are already indicating data on another thread, or
  3514. // waiting for the client to post a receive irp, just return
  3515. //
  3516. if (pReceive->SessionFlags & (PGM_SESSION_FLAG_IN_INDICATE | PGM_SESSION_WAIT_FOR_RECEIVE_IRP))
  3517. {
  3518. return (STATUS_SUCCESS);
  3519. }
  3520. ASSERT (!(pReceive->SessionFlags & PGM_SESSION_CLIENT_DISCONNECTED));
  3521. pReceive->SessionFlags |= PGM_SESSION_FLAG_IN_INDICATE;
  3522. while (!IsListEmpty (&pReceiver->BufferedDataList))
  3523. {
  3524. pNextNak = CONTAINING_RECORD (pReceiver->BufferedDataList.Flink, tNAK_FORWARD_DATA, Linkage);
  3525. ASSERT ((pReceiver->NumPacketGroupsPendingClient) &&
  3526. (pNextNak->SequenceNumber == pReceiver->NextODataSequenceNumber) &&
  3527. (SEQ_GT(pReceiver->FirstNakSequenceNumber, pReceiver->NextODataSequenceNumber)));
  3528. //
  3529. // If we do not have all the data packets, we will need to decode them now
  3530. //
  3531. if (pNextNak->NumParityPackets)
  3532. {
  3533. ASSERT ((pNextNak->NumParityPackets + pNextNak->NumDataPackets) == pNextNak->PacketsInGroup);
  3534. status = DecodeParityPackets (pReceive, pNextNak);
  3535. if (!NT_SUCCESS (status))
  3536. {
  3537. PgmTrace (LogError, ("CheckIndicatePendedData: ERROR -- " \
  3538. "DecodeParityPackets returned <%x>\n", status));
  3539. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  3540. break;
  3541. }
  3542. }
  3543. else
  3544. {
  3545. // The below assertion can be greater if we have only partially indicated a group
  3546. ASSERT ((pNextNak->NextIndexToIndicate + pNextNak->NumDataPackets) >= pNextNak->PacketsInGroup);
  3547. }
  3548. status = PgmIndicateGroup (pAddress, pReceive, pOldIrqAddress, pOldIrqReceive, pNextNak);
  3549. if (!NT_SUCCESS (status))
  3550. {
  3551. //
  3552. // If the client cannot accept any more data at this time, so
  3553. // we will try again later, otherwise terminate this session!
  3554. //
  3555. if (status != STATUS_DATA_NOT_ACCEPTED)
  3556. {
  3557. ASSERT (0);
  3558. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  3559. }
  3560. break;
  3561. }
  3562. //
  3563. // Advance to the next group boundary
  3564. //
  3565. pReceiver->NextODataSequenceNumber += pNextNak->OriginalGroupSize;
  3566. PacketsIndicated = pNextNak->NumDataPackets + pNextNak->NumParityPackets;
  3567. pReceiver->TotalDataPacketsBuffered -= PacketsIndicated;
  3568. pReceiver->DataPacketsPendingIndicate -= PacketsIndicated;
  3569. pReceiver->NumPacketGroupsPendingClient--;
  3570. ASSERT (pReceiver->TotalDataPacketsBuffered >= pReceiver->NumPacketGroupsPendingClient);
  3571. RemoveEntryList (&pNextNak->Linkage);
  3572. FreeNakContext (pReceive, pNextNak);
  3573. }
  3574. pReceive->SessionFlags &= ~PGM_SESSION_FLAG_IN_INDICATE;
  3575. PgmTrace (LogAllFuncs, ("CheckIndicatePendedData: " \
  3576. "status=<%x>, pReceive=<%p>, SessionFlags=<%x>\n",
  3577. status, pReceive, pReceive->SessionFlags));
  3578. CheckIndicateDisconnect (pAddress, pReceive, pOldIrqAddress, pOldIrqReceive, TRUE);
  3579. return (STATUS_SUCCESS);
  3580. }
  3581. #ifdef MAX_BUFF_DBG
  3582. ULONG MaxPacketGroupsPendingClient = 0;
  3583. ULONG MaxPacketsBuffered = 0;
  3584. ULONG MaxPacketsPendingIndicate = 0;
  3585. ULONG MaxPacketsPendingNaks = 0;
  3586. #endif // MAX_BUFF_DBG
  3587. //----------------------------------------------------------------------------
  3588. NTSTATUS
  3589. PgmHandleNewData(
  3590. IN SEQ_TYPE *pThisDataSequenceNumber,
  3591. IN tADDRESS_CONTEXT *pAddress,
  3592. IN tRECEIVE_SESSION *pReceive,
  3593. IN USHORT PacketLength,
  3594. IN tBASIC_DATA_PACKET_HEADER UNALIGNED *pOData,
  3595. IN UCHAR PacketType,
  3596. IN PGMLockHandle *pOldIrqAddress,
  3597. IN PGMLockHandle *pOldIrqReceive
  3598. )
  3599. /*++
  3600. Routine Description:
  3601. This routine buffers data packets received out-of-order
  3602. Arguments:
  3603. IN pThisDataSequenceNumber -- Sequence # of unordered data packet
  3604. IN pAddress -- Address object context
  3605. IN pReceive -- Receive context
  3606. IN PacketLength -- Length of packet received from the wire
  3607. IN pODataBuffer -- Data packet
  3608. IN PacketType -- Type of Pgm packet
  3609. Return Value:
  3610. NTSTATUS - Final status of the call
  3611. --*/
  3612. {
  3613. SEQ_TYPE ThisDataSequenceNumber = *pThisDataSequenceNumber;
  3614. LIST_ENTRY *pEntry;
  3615. PNAK_FORWARD_DATA pOldNak, pLastNak;
  3616. ULONG MessageLength, DataOffset, BytesTaken, DataBytes, BufferLength;
  3617. ULONGLONG NcfRDataTickCounts;
  3618. NTSTATUS status;
  3619. USHORT TSDULength;
  3620. tPACKET_OPTIONS PacketOptions;
  3621. UCHAR i, PacketIndex, NakIndex;
  3622. BOOLEAN fIsParityPacket, fPartiallyIndicated;
  3623. PUCHAR pDataBuffer;
  3624. tRECEIVE_CONTEXT *pReceiver = pReceive->pReceiver;
  3625. ASSERT (PacketLength <= pReceive->MaxMTULength);
  3626. fIsParityPacket = pOData->CommonHeader.Options & PACKET_HEADER_OPTIONS_PARITY;
  3627. //
  3628. // First, ensure we have a Nak context available for this data
  3629. //
  3630. pLastNak = NULL;
  3631. status = CheckAndAddNakRequests (pReceive, &ThisDataSequenceNumber, &pLastNak, NAK_PENDING_RB, (BOOLEAN) !fIsParityPacket);
  3632. if ((!NT_SUCCESS (status)) ||
  3633. (!pLastNak))
  3634. {
  3635. PgmTrace (LogAllFuncs, ("PgmHandleNewData: " \
  3636. "CheckAndAddNakRequests for <%d> returned <%x>, pLastNak=<%p>\n",
  3637. ThisDataSequenceNumber, status, pLastNak));
  3638. if (NT_SUCCESS (status))
  3639. {
  3640. pReceiver->NumDupPacketsBuffered++;
  3641. }
  3642. else
  3643. {
  3644. pReceiver->NumDataPacketsDropped++;
  3645. }
  3646. return (status);
  3647. }
  3648. //
  3649. // Now, extract all the information that we need from the packet options
  3650. //
  3651. PgmZeroMemory (&PacketOptions, sizeof (tPACKET_OPTIONS));
  3652. if (pOData->CommonHeader.Options & PACKET_HEADER_OPTIONS_PRESENT)
  3653. {
  3654. status = ProcessOptions ((tPACKET_OPTION_LENGTH *) (pOData + 1),
  3655. (PacketLength - sizeof(tBASIC_DATA_PACKET_HEADER)),
  3656. (pOData->CommonHeader.Type & 0x0f),
  3657. &PacketOptions,
  3658. NULL);
  3659. if (!NT_SUCCESS (status))
  3660. {
  3661. PgmTrace (LogError, ("PgmHandleNewData: ERROR -- " \
  3662. "ProcessOptions returned <%x>, SeqNum=[%d]: NumOutOfOrder=<%d> ...\n",
  3663. status, (ULONG) ThisDataSequenceNumber, pReceiver->TotalDataPacketsBuffered));
  3664. ASSERT (0);
  3665. pReceiver->NumDataPacketsDropped++;
  3666. return (status);
  3667. }
  3668. }
  3669. PgmCopyMemory (&TSDULength, &pOData->CommonHeader.TSDULength, sizeof (USHORT));
  3670. TSDULength = ntohs (TSDULength);
  3671. if (PacketLength != (sizeof(tBASIC_DATA_PACKET_HEADER) + PacketOptions.OptionsLength + TSDULength))
  3672. {
  3673. ASSERT (0);
  3674. pReceiver->NumDataPacketsDropped++;
  3675. return (STATUS_DATA_NOT_ACCEPTED);
  3676. }
  3677. DataOffset = sizeof (tBASIC_DATA_PACKET_HEADER) + PacketOptions.OptionsLength;
  3678. DataBytes = TSDULength;
  3679. ASSERT ((PacketOptions.OptionsFlags & ~PGM_VALID_DATA_OPTION_FLAGS) == 0);
  3680. BytesTaken = 0;
  3681. //
  3682. // If this group has a different GroupSize, set that now
  3683. //
  3684. if (PacketOptions.OptionsFlags & PGM_OPTION_FLAG_PARITY_CUR_TGSIZE)
  3685. {
  3686. if (pLastNak->OriginalGroupSize == 1)
  3687. {
  3688. //
  3689. // This path will be used if we have not yet received
  3690. // an SPM (so don't know group size, etc), but have a
  3691. // data packet from a partial group
  3692. //
  3693. pLastNak->ThisGroupSize = PacketOptions.FECContext.NumPacketsInThisGroup;
  3694. }
  3695. else if (PacketOptions.FECContext.NumPacketsInThisGroup >= pReceive->FECGroupSize)
  3696. {
  3697. //
  3698. // Bad Packet!
  3699. //
  3700. ASSERT (0);
  3701. pReceiver->NumDataPacketsDropped++;
  3702. return (STATUS_DATA_NOT_ACCEPTED);
  3703. }
  3704. //
  3705. // If we have already received all the data packets, don't do anything here
  3706. //
  3707. else if (pLastNak->PacketsInGroup == pReceive->FECGroupSize)
  3708. {
  3709. pLastNak->PacketsInGroup = PacketOptions.FECContext.NumPacketsInThisGroup;
  3710. if (pLastNak->SequenceNumber == pReceiver->FurthestKnownGroupSequenceNumber)
  3711. {
  3712. pReceiver->FurthestKnownSequenceNumber = pLastNak->SequenceNumber + pLastNak->PacketsInGroup - 1;
  3713. }
  3714. //
  3715. // Get rid of any of the excess (NULL) data packets
  3716. //
  3717. RemoveRedundantNaks (pReceive, pLastNak, TRUE);
  3718. }
  3719. else if (pLastNak->PacketsInGroup != PacketOptions.FECContext.NumPacketsInThisGroup)
  3720. {
  3721. ASSERT (0);
  3722. pReceiver->NumDataPacketsDropped++;
  3723. return (STATUS_DATA_NOT_ACCEPTED);
  3724. }
  3725. }
  3726. if (PacketOptions.OptionsFlags & PGM_OPTION_FLAG_FIN)
  3727. {
  3728. if (fIsParityPacket)
  3729. {
  3730. pReceiver->FinDataSequenceNumber = pLastNak->SequenceNumber + (pLastNak->PacketsInGroup - 1);
  3731. }
  3732. else
  3733. {
  3734. pReceiver->FinDataSequenceNumber = ThisDataSequenceNumber;
  3735. }
  3736. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_GRACEFULLY;
  3737. PgmTrace (LogStatus, ("PgmHandleNewData: " \
  3738. "SeqNum=[%d]: Got a FIN!!!\n", (ULONG) pReceiver->FinDataSequenceNumber));
  3739. if (pLastNak)
  3740. {
  3741. ASSERT (pLastNak->SequenceNumber == (pReceiver->FinDataSequenceNumber & ~(pReceive->FECGroupSize-1)));
  3742. pLastNak->PacketsInGroup = (UCHAR) (pReceiver->FinDataSequenceNumber + 1 - pLastNak->SequenceNumber);
  3743. ASSERT (pLastNak->PacketsInGroup <= pReceive->FECGroupSize);
  3744. RemoveRedundantNaks (pReceive, pLastNak, TRUE);
  3745. AdjustReceiveBufferLists (pReceive);
  3746. }
  3747. }
  3748. //
  3749. // Determine the Packet Index
  3750. //
  3751. fPartiallyIndicated = FALSE;
  3752. if (pReceive->FECOptions)
  3753. {
  3754. PacketIndex = (UCHAR) (ThisDataSequenceNumber & (pReceive->FECGroupSize-1));
  3755. //
  3756. // See if we even need this packet!
  3757. //
  3758. if (!fIsParityPacket)
  3759. {
  3760. //
  3761. // This is a data packet!
  3762. //
  3763. if ((PacketIndex >= pLastNak->PacketsInGroup) ||
  3764. (PacketIndex < pLastNak->NextIndexToIndicate))
  3765. {
  3766. //
  3767. // We don't need this Packet!
  3768. //
  3769. status = STATUS_DATA_NOT_ACCEPTED;
  3770. }
  3771. }
  3772. //
  3773. // Parity packet
  3774. //
  3775. else if (((pLastNak->NumDataPackets+pLastNak->NumParityPackets) >= pLastNak->PacketsInGroup) ||
  3776. ((pLastNak->NextIndexToIndicate + pLastNak->NumDataPackets) >= pLastNak->PacketsInGroup))
  3777. {
  3778. status = STATUS_DATA_NOT_ACCEPTED;
  3779. }
  3780. else
  3781. {
  3782. if (PacketOptions.OptionsFlags & PGM_OPTION_FLAG_PARITY_GRP)
  3783. {
  3784. ASSERT (((pOData->CommonHeader.Type & 0x0f) == PACKET_TYPE_RDATA) ||
  3785. ((pOData->CommonHeader.Type & 0x0f) == PACKET_TYPE_ODATA));
  3786. ASSERT (PacketOptions.FECContext.FECGroupInfo);
  3787. PacketIndex += ((USHORT) PacketOptions.FECContext.FECGroupInfo * pReceive->FECGroupSize);
  3788. }
  3789. }
  3790. if (status != STATUS_DATA_NOT_ACCEPTED)
  3791. {
  3792. //
  3793. // Verify that this is not a duplicate of a packet we
  3794. // may have already received
  3795. //
  3796. for (i=0; i < (pLastNak->NumDataPackets+pLastNak->NumParityPackets); i++)
  3797. {
  3798. if (pLastNak->pPendingData[i].PacketIndex == PacketIndex)
  3799. {
  3800. ASSERT (!fIsParityPacket);
  3801. status = STATUS_DATA_NOT_ACCEPTED;
  3802. break;
  3803. }
  3804. }
  3805. }
  3806. else
  3807. {
  3808. AdjustReceiveBufferLists (pReceive); // In case this became a partial group
  3809. }
  3810. if (status == STATUS_DATA_NOT_ACCEPTED)
  3811. {
  3812. pReceiver->NumDupPacketsBuffered++;
  3813. return (status);
  3814. }
  3815. }
  3816. else // We are not aware of FEC
  3817. {
  3818. //
  3819. // If we are not aware of options, drop this packet if it is a parity packet!
  3820. //
  3821. if (fIsParityPacket)
  3822. {
  3823. pReceiver->NumDataPacketsDropped++;
  3824. return (STATUS_DATA_NOT_ACCEPTED);
  3825. }
  3826. PacketIndex = 0;
  3827. ASSERT (!pLastNak->pPendingData[0].pDataPacket);
  3828. //
  3829. // If this is the next expected data packet, let's see if we can try
  3830. // to indicate this data over here only (avoid a packet copy)
  3831. // Note: This should be the regular indicate path in the case of non-FEC,
  3832. // low-loss and low-CPU sessions
  3833. //
  3834. if ((ThisDataSequenceNumber == pReceiver->NextODataSequenceNumber) &&
  3835. !(pReceive->SessionFlags & (PGM_SESSION_FLAG_IN_INDICATE |
  3836. PGM_SESSION_WAIT_FOR_RECEIVE_IRP)) &&
  3837. (IsListEmpty (&pReceiver->BufferedDataList)))
  3838. {
  3839. ASSERT (!pReceiver->NumPacketGroupsPendingClient);
  3840. //
  3841. // If we are starting receiving in the midst of a message, we should ignore them
  3842. //
  3843. if ((pReceive->SessionFlags & PGM_SESSION_FLAG_FIRST_PACKET) &&
  3844. (PacketOptions.MessageOffset))
  3845. {
  3846. //
  3847. // pReceive->pReceiver->CurrentMessageProcessed would have been set
  3848. // if we were receiving a fragmented message
  3849. // or if we had only accounted for a partial message earlier
  3850. //
  3851. ASSERT (!(pReceive->pReceiver->CurrentMessageProcessed) &&
  3852. !(pReceive->pReceiver->CurrentMessageLength));
  3853. PgmTrace (LogPath, ("PgmHandleNewData: " \
  3854. "Dropping SeqNum=[%d] since it's a PARTIAL message [%d / %d]!\n",
  3855. (ULONG) (pReceive->pReceiver->NextODataSequenceNumber),
  3856. PacketOptions.MessageOffset, PacketOptions.MessageLength));
  3857. DataBytes = 0;
  3858. status = STATUS_SUCCESS;
  3859. }
  3860. else if ((pReceiver->CurrentMessageProcessed != PacketOptions.MessageOffset) ||
  3861. ((pReceiver->CurrentMessageProcessed) &&
  3862. (pReceiver->CurrentMessageLength != PacketOptions.MessageLength)))
  3863. {
  3864. //
  3865. // Our state expects us to be in the middle of a message, but
  3866. // the current packets do not show this
  3867. //
  3868. PgmTrace (LogError, ("PgmHandleNewData: ERROR -- " \
  3869. "SeqNum=[%d] Expecting MsgLen=<%d>, MsgOff=<%d>, have MsgLen=<%d>, MsgOff=<%d>\n",
  3870. (ULONG) pReceiver->NextODataSequenceNumber,
  3871. pReceiver->CurrentMessageLength,
  3872. pReceiver->CurrentMessageProcessed,
  3873. PacketOptions.MessageLength, PacketOptions.MessageOffset));
  3874. ASSERT (0);
  3875. BytesTaken = DataBytes;
  3876. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  3877. return (STATUS_UNSUCCESSFUL);
  3878. }
  3879. RemoveEntryList (&pLastNak->Linkage);
  3880. RemovePendingReceiverEntry (pLastNak);
  3881. pReceiver->NextODataSequenceNumber++;
  3882. pReceiver->FirstNakSequenceNumber = pReceiver->NextODataSequenceNumber;
  3883. if (PacketOptions.MessageLength)
  3884. {
  3885. MessageLength = PacketOptions.MessageLength;
  3886. ASSERT (DataBytes <= MessageLength - PacketOptions.MessageOffset);
  3887. }
  3888. else
  3889. {
  3890. MessageLength = DataBytes;
  3891. ASSERT (!PacketOptions.MessageOffset);
  3892. }
  3893. //
  3894. // If we have a NULL packet, then skip it
  3895. //
  3896. if ((!DataBytes) ||
  3897. (PacketOptions.MessageOffset == MessageLength))
  3898. {
  3899. PgmTrace (LogPath, ("PgmHandleNewData: " \
  3900. "Dropping SeqNum=[%d] since it's a NULL message [%d / %d]!\n",
  3901. (ULONG) (pReceiver->NextODataSequenceNumber),
  3902. PacketOptions.MessageOffset, PacketOptions.MessageLength));
  3903. BytesTaken = DataBytes;
  3904. status = STATUS_SUCCESS;
  3905. }
  3906. else
  3907. {
  3908. ASSERT (!(pReceive->SessionFlags & PGM_SESSION_CLIENT_DISCONNECTED));
  3909. pReceive->SessionFlags |= PGM_SESSION_FLAG_IN_INDICATE;
  3910. status = PgmIndicateToClient (pAddress,
  3911. pReceive,
  3912. DataBytes,
  3913. (((PUCHAR) pOData) + DataOffset),
  3914. PacketOptions.MessageOffset,
  3915. MessageLength,
  3916. &BytesTaken,
  3917. pOldIrqAddress,
  3918. pOldIrqReceive);
  3919. pReceive->SessionFlags &= ~(PGM_SESSION_FLAG_IN_INDICATE | PGM_SESSION_FLAG_FIRST_PACKET);
  3920. pReceive->DataBytes += BytesTaken;
  3921. PgmTrace (LogPath, ("PgmHandleNewData: " \
  3922. "SeqNum=[%d]: PgmIndicate returned<%x>\n",
  3923. (ULONG) ThisDataSequenceNumber, status));
  3924. ASSERT (BytesTaken <= DataBytes);
  3925. if (!NT_SUCCESS (status))
  3926. {
  3927. //
  3928. // If the client cannot accept any more data at this time, so
  3929. // we will try again later, otherwise terminate this session!
  3930. //
  3931. if (status != STATUS_DATA_NOT_ACCEPTED)
  3932. {
  3933. ASSERT (0);
  3934. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  3935. BytesTaken = DataBytes;
  3936. }
  3937. }
  3938. }
  3939. if (BytesTaken == DataBytes)
  3940. {
  3941. if ((PacketType == PACKET_TYPE_RDATA) &&
  3942. (pLastNak->FirstNcfTickCount))
  3943. {
  3944. AdjustNcfRDataResponseTimes (pReceive, pLastNak);
  3945. }
  3946. FreeNakContext (pReceive, pLastNak);
  3947. AdjustReceiveBufferLists (pReceive); // move any additional complete groups to the BufferedDataList
  3948. return (status);
  3949. }
  3950. fPartiallyIndicated = TRUE;
  3951. InsertHeadList (&pReceiver->BufferedDataList, &pLastNak->Linkage);
  3952. }
  3953. }
  3954. #ifdef MAX_BUFF_DBG
  3955. {
  3956. if (pReceiver->NumPacketGroupsPendingClient > MaxPacketGroupsPendingClient)
  3957. {
  3958. MaxPacketGroupsPendingClient = pReceiver->NumPacketGroupsPendingClient;
  3959. }
  3960. if (pReceiver->TotalDataPacketsBuffered >= MaxPacketsBuffered)
  3961. {
  3962. MaxPacketsBuffered = pReceiver->TotalDataPacketsBuffered;
  3963. }
  3964. if (pReceiver->DataPacketsPendingIndicate >= MaxPacketsPendingIndicate)
  3965. {
  3966. MaxPacketsPendingIndicate = pReceiver->DataPacketsPendingIndicate;
  3967. }
  3968. if (pReceiver->DataPacketsPendingNaks >= MaxPacketsPendingNaks)
  3969. {
  3970. MaxPacketsPendingNaks = pReceiver->DataPacketsPendingNaks;
  3971. }
  3972. ASSERT (pReceiver->TotalDataPacketsBuffered == (pReceiver->DataPacketsPendingIndicate +
  3973. pReceiver->DataPacketsPendingNaks));
  3974. }
  3975. #endif // MAX_BUFF_DBG
  3976. if (pReceiver->TotalDataPacketsBuffered >= pReceiver->MaxPacketsBufferedInLookaside)
  3977. {
  3978. PgmTrace (LogError, ("PgmHandleNewData: ERROR -- " \
  3979. "[%d -- %d]: Excessive number of packets buffered=<%d> > <%d>, Aborting ...\n",
  3980. (ULONG) pReceiver->FirstNakSequenceNumber, (ULONG) ThisDataSequenceNumber,
  3981. (ULONG) pReceiver->TotalDataPacketsBuffered,
  3982. (ULONG) pReceiver->MaxPacketsBufferedInLookaside));
  3983. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  3984. return (STATUS_INSUFFICIENT_RESOURCES);
  3985. }
  3986. //
  3987. // First, check if we are a data packet
  3988. // (save unique data packets even if we have extra parity packets)
  3989. // This can help save CPU!
  3990. //
  3991. pDataBuffer = NULL;
  3992. NakIndex = pLastNak->NumDataPackets + pLastNak->NumParityPackets;
  3993. if (fIsParityPacket)
  3994. {
  3995. BufferLength = PacketLength + sizeof(tPOST_PACKET_FEC_CONTEXT) - sizeof(USHORT);
  3996. }
  3997. else if ((PacketLength + sizeof (tPOST_PACKET_FEC_CONTEXT)) <= pLastNak->MinPacketLength)
  3998. {
  3999. BufferLength = pLastNak->MinPacketLength;
  4000. }
  4001. else
  4002. {
  4003. BufferLength = PacketLength + sizeof(tPOST_PACKET_FEC_CONTEXT);
  4004. }
  4005. pDataBuffer = NULL;
  4006. if (!fIsParityPacket)
  4007. {
  4008. ASSERT (PacketIndex < pReceive->FECGroupSize);
  4009. ASSERT (pLastNak->pPendingData[PacketIndex].ActualIndexOfDataPacket == pLastNak->OriginalGroupSize);
  4010. //
  4011. // If we have some un-needed parity packets, we
  4012. // can free that memory now
  4013. //
  4014. if (NakIndex >= pLastNak->PacketsInGroup)
  4015. {
  4016. ASSERT (pLastNak->NumParityPackets);
  4017. for (i=0; i<pLastNak->PacketsInGroup; i++)
  4018. {
  4019. if (pLastNak->pPendingData[i].PacketIndex >= pLastNak->OriginalGroupSize)
  4020. {
  4021. pDataBuffer = ReAllocateDataBuffer (pReceive, &pLastNak->pPendingData[i], BufferLength);
  4022. BufferLength = 0;
  4023. break;
  4024. }
  4025. }
  4026. ASSERT (i < pLastNak->PacketsInGroup);
  4027. pLastNak->NumParityPackets--;
  4028. NakIndex = i;
  4029. }
  4030. else
  4031. {
  4032. ASSERT (!pLastNak->pPendingData[NakIndex].pDataPacket);
  4033. }
  4034. if (BufferLength)
  4035. {
  4036. pDataBuffer = AllocateDataBuffer (pReceive, &pLastNak->pPendingData[NakIndex], BufferLength);
  4037. }
  4038. if (!pDataBuffer)
  4039. {
  4040. PgmTrace (LogError, ("PgmHandleNewData: ERROR -- " \
  4041. "[%d]: STATUS_INSUFFICIENT_RESOURCES <%d> bytes, NumDataPackets=<%d>, Aborting ...\n",
  4042. (ULONG) ThisDataSequenceNumber, pLastNak->MinPacketLength,
  4043. (ULONG) pReceiver->TotalDataPacketsBuffered));
  4044. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  4045. return (STATUS_INSUFFICIENT_RESOURCES);
  4046. }
  4047. ASSERT (pLastNak->pPendingData[NakIndex].pDataPacket == pDataBuffer);
  4048. PgmCopyMemory (pDataBuffer, pOData, PacketLength);
  4049. pLastNak->pPendingData[NakIndex].PacketLength = PacketLength;
  4050. pLastNak->pPendingData[NakIndex].DataOffset = (USHORT) (DataOffset + BytesTaken);
  4051. pLastNak->pPendingData[NakIndex].PacketIndex = PacketIndex;
  4052. pLastNak->pPendingData[PacketIndex].ActualIndexOfDataPacket = NakIndex;
  4053. pLastNak->NumDataPackets++;
  4054. pReceive->DataBytes += PacketLength - (DataOffset + BytesTaken);
  4055. ASSERT (!(PacketOptions.OptionsFlags & PGM_OPTION_FLAG_PARITY_GRP));
  4056. //
  4057. // Save some options for future reference
  4058. //
  4059. if (PacketOptions.OptionsFlags & PGM_OPTION_FLAG_FRAGMENT)
  4060. {
  4061. pLastNak->pPendingData[NakIndex].FragmentOptSpecific = 0;
  4062. pLastNak->pPendingData[NakIndex].MessageFirstSequence = PacketOptions.MessageFirstSequence;
  4063. pLastNak->pPendingData[NakIndex].MessageLength = PacketOptions.MessageLength;
  4064. pLastNak->pPendingData[NakIndex].MessageOffset = PacketOptions.MessageOffset + BytesTaken;
  4065. }
  4066. else
  4067. {
  4068. //
  4069. // This is not a fragment
  4070. //
  4071. pLastNak->pPendingData[NakIndex].FragmentOptSpecific = PACKET_OPTION_SPECIFIC_ENCODED_NULL_BIT;
  4072. pLastNak->pPendingData[NakIndex].MessageFirstSequence = (ULONG) (SEQ_TYPE) (pLastNak->SequenceNumber + PacketIndex);
  4073. pLastNak->pPendingData[NakIndex].MessageOffset = BytesTaken;
  4074. pLastNak->pPendingData[NakIndex].MessageLength = PacketLength - DataOffset;
  4075. }
  4076. }
  4077. else
  4078. {
  4079. ASSERT (PacketIndex >= pLastNak->OriginalGroupSize);
  4080. ASSERT (NakIndex < pLastNak->PacketsInGroup);
  4081. ASSERT (!pLastNak->pPendingData[NakIndex].pDataPacket);
  4082. pDataBuffer = AllocateDataBuffer (pReceive, &pLastNak->pPendingData[NakIndex], BufferLength);
  4083. if (!pDataBuffer)
  4084. {
  4085. PgmTrace (LogError, ("PgmHandleNewData: ERROR -- " \
  4086. "[%d -- Parity]: STATUS_INSUFFICIENT_RESOURCES <%d> bytes, NumDataPackets=<%d>, Aborting ...\n",
  4087. (ULONG) ThisDataSequenceNumber, PacketLength,
  4088. (ULONG) pReceiver->TotalDataPacketsBuffered));
  4089. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  4090. return (STATUS_INSUFFICIENT_RESOURCES);
  4091. }
  4092. //
  4093. // This is a new parity packet
  4094. //
  4095. ASSERT (pLastNak->pPendingData[NakIndex].pDataPacket == pDataBuffer);
  4096. PgmCopyMemory (pDataBuffer, pOData, PacketLength);
  4097. pLastNak->pPendingData[NakIndex].PacketLength = PacketLength;
  4098. pLastNak->pPendingData[NakIndex].DataOffset = (USHORT) DataOffset;
  4099. pLastNak->pPendingData[NakIndex].PacketIndex = PacketIndex;
  4100. pLastNak->pPendingData[NakIndex].FragmentOptSpecific = PacketOptions.FECContext.FragmentOptSpecific;
  4101. pLastNak->pPendingData[NakIndex].MessageFirstSequence = PacketOptions.MessageFirstSequence;
  4102. pLastNak->pPendingData[NakIndex].MessageLength = PacketOptions.MessageLength;
  4103. pLastNak->pPendingData[NakIndex].MessageOffset = PacketOptions.MessageOffset + BytesTaken;
  4104. pLastNak->NumParityPackets++;
  4105. pReceive->DataBytes += PacketLength - DataOffset;
  4106. if (!pLastNak->ParityDataSize)
  4107. {
  4108. pLastNak->ParityDataSize = (USHORT) (PacketLength - DataOffset);
  4109. }
  4110. else
  4111. {
  4112. ASSERT (pLastNak->ParityDataSize == (USHORT) (PacketLength - DataOffset));
  4113. }
  4114. }
  4115. if ((PacketType == PACKET_TYPE_RDATA) &&
  4116. (pLastNak->FirstNcfTickCount) &&
  4117. (((pLastNak->NumDataPackets + pLastNak->NumParityPackets) >= pLastNak->PacketsInGroup) ||
  4118. ((pLastNak->NextIndexToIndicate + pLastNak->NumDataPackets) >= pLastNak->PacketsInGroup)))
  4119. {
  4120. AdjustNcfRDataResponseTimes (pReceive, pLastNak);
  4121. }
  4122. pLastNak->AllOptionsFlags |= PacketOptions.OptionsFlags;
  4123. pReceiver->TotalDataPacketsBuffered++;
  4124. if (fPartiallyIndicated)
  4125. {
  4126. pReceiver->NumPacketGroupsPendingClient++;
  4127. pReceiver->DataPacketsPendingIndicate++;
  4128. pReceiver->NextODataSequenceNumber = ThisDataSequenceNumber;
  4129. }
  4130. else
  4131. {
  4132. pReceiver->DataPacketsPendingNaks++;
  4133. //
  4134. // See if this group is complete
  4135. //
  4136. if (((pLastNak->NumDataPackets + pLastNak->NumParityPackets) >= pLastNak->PacketsInGroup) ||
  4137. ((pLastNak->NextIndexToIndicate + pLastNak->NumDataPackets) >= pLastNak->PacketsInGroup))
  4138. {
  4139. RemovePendingReceiverEntry (pLastNak);
  4140. AdjustReceiveBufferLists (pReceive);
  4141. }
  4142. }
  4143. PgmTrace (LogAllFuncs, ("PgmHandleNewData: " \
  4144. "SeqNum=[%d]: NumOutOfOrder=<%d> ...\n",
  4145. (ULONG) ThisDataSequenceNumber, pReceiver->TotalDataPacketsBuffered));
  4146. return (STATUS_SUCCESS);
  4147. }
  4148. //----------------------------------------------------------------------------
  4149. NTSTATUS
  4150. ProcessDataPacket(
  4151. IN tADDRESS_CONTEXT *pAddress,
  4152. IN tRECEIVE_SESSION *pReceive,
  4153. IN ULONG PacketLength,
  4154. IN tBASIC_DATA_PACKET_HEADER UNALIGNED *pODataBuffer,
  4155. IN UCHAR PacketType
  4156. )
  4157. /*++
  4158. Routine Description:
  4159. This routine looks at the data packet received from the wire
  4160. and handles it appropriately depending on whether it is in order
  4161. or not
  4162. Arguments:
  4163. IN pAddress -- Address object context
  4164. IN pReceive -- Receive context
  4165. IN PacketLength -- Length of packet received from the wire
  4166. IN pODataBuffer -- Data packet
  4167. IN PacketType -- Type of Pgm packet
  4168. Return Value:
  4169. NTSTATUS - Final status of the call
  4170. --*/
  4171. {
  4172. NTSTATUS status;
  4173. SEQ_TYPE ThisPacketSequenceNumber;
  4174. SEQ_TYPE ThisTrailingEdge;
  4175. tNAK_FORWARD_DATA *pNextNak;
  4176. ULONG DisconnectFlag;
  4177. PGMLockHandle OldIrq, OldIrq1;
  4178. ULONG ulData;
  4179. if (PacketLength < sizeof(tBASIC_DATA_PACKET_HEADER))
  4180. {
  4181. PgmTrace (LogError, ("ProcessDataPacket: ERROR -- " \
  4182. "PacketLength=<%d> < tBASIC_DATA_PACKET_HEADER=<%d>\n",
  4183. PacketLength, sizeof(tBASIC_DATA_PACKET_HEADER)));
  4184. return (STATUS_DATA_NOT_ACCEPTED);
  4185. }
  4186. PgmLock (pAddress, OldIrq);
  4187. PgmLock (pReceive, OldIrq1);
  4188. if (pReceive->SessionFlags & (PGM_SESSION_CLIENT_DISCONNECTED |
  4189. PGM_SESSION_TERMINATED_ABORT))
  4190. {
  4191. PgmTrace (LogPath, ("ProcessDataPacket: " \
  4192. "Dropping packet because session is terminating!\n"));
  4193. pReceive->pReceiver->NumDataPacketsDropped++;
  4194. PgmUnlock (pReceive, OldIrq1);
  4195. PgmUnlock (pAddress, OldIrq);
  4196. return (STATUS_DATA_NOT_ACCEPTED);
  4197. }
  4198. PgmCopyMemory (&ulData, &pODataBuffer->DataSequenceNumber, sizeof(ULONG));
  4199. ThisPacketSequenceNumber = (SEQ_TYPE) ntohl (ulData);
  4200. PgmCopyMemory (&ulData, &pODataBuffer->TrailingEdgeSequenceNumber, sizeof(ULONG));
  4201. ThisTrailingEdge = (SEQ_TYPE) ntohl (ulData);
  4202. ASSERT (ntohl (ulData) == (LONG) ThisTrailingEdge);
  4203. //
  4204. // Update our Window information (use offset from Leading edge to account for wrap-around)
  4205. //
  4206. if (SEQ_GT (ThisTrailingEdge, pReceive->pReceiver->LastTrailingEdgeSeqNum))
  4207. {
  4208. pReceive->pReceiver->LastTrailingEdgeSeqNum = ThisTrailingEdge;
  4209. }
  4210. //
  4211. // If the next packet we are expecting is out-of-range, then we
  4212. // should terminate the session
  4213. //
  4214. if (SEQ_LT (pReceive->pReceiver->FirstNakSequenceNumber, pReceive->pReceiver->LastTrailingEdgeSeqNum))
  4215. {
  4216. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  4217. if (SEQ_GT (pReceive->pReceiver->LastTrailingEdgeSeqNum, (1 + pReceive->pReceiver->FurthestKnownGroupSequenceNumber)))
  4218. {
  4219. PgmTrace (LogStatus, ("ProcessDataPacket: " \
  4220. "NETWORK problems -- data loss=<%d> packets > window size!\n\tExpecting=<%d>, FurthestKnown=<%d>, Window=[%d--%d]=<%d> seqs\n",
  4221. (ULONG) (1 + ThisPacketSequenceNumber -
  4222. pReceive->pReceiver->FurthestKnownGroupSequenceNumber),
  4223. (ULONG) pReceive->pReceiver->FirstNakSequenceNumber,
  4224. (ULONG) pReceive->pReceiver->FurthestKnownGroupSequenceNumber,
  4225. (ULONG) ThisTrailingEdge, (ULONG) ThisPacketSequenceNumber,
  4226. (ULONG) (1+ThisPacketSequenceNumber-ThisTrailingEdge)));
  4227. }
  4228. else
  4229. {
  4230. ASSERT (!IsListEmpty (&pReceive->pReceiver->NaksForwardDataList));
  4231. pNextNak = CONTAINING_RECORD (pReceive->pReceiver->NaksForwardDataList.Flink, tNAK_FORWARD_DATA, Linkage);
  4232. PgmTrace (LogStatus, ("ProcessDataPacket: " \
  4233. "Session window has past TrailingEdge -- Expecting=<%d==%d>, NumNcfs=<%d>, FurthestKnown=<%d>, Window=[%d--%d] = < %d > seqs\n",
  4234. (ULONG) pReceive->pReceiver->FirstNakSequenceNumber,
  4235. (ULONG) pNextNak->SequenceNumber,
  4236. (ULONG) pNextNak->WaitingRDataRetries,
  4237. (ULONG) pReceive->pReceiver->FurthestKnownGroupSequenceNumber,
  4238. (ULONG) pReceive->pReceiver->LastTrailingEdgeSeqNum,
  4239. (ULONG) ThisPacketSequenceNumber,
  4240. (ULONG) (1+ThisPacketSequenceNumber-ThisTrailingEdge)));
  4241. }
  4242. }
  4243. else if (SEQ_GT (pReceive->pReceiver->FirstNakSequenceNumber, ThisPacketSequenceNumber))
  4244. {
  4245. //
  4246. // Drop this packet since it is earlier than our window
  4247. //
  4248. pReceive->pReceiver->NumDupPacketsOlderThanWindow++;
  4249. PgmTrace (LogPath, ("ProcessDataPacket: " \
  4250. "Dropping this packet, SeqNum=[%d] < NextOData=[%d]\n",
  4251. (ULONG) ThisPacketSequenceNumber, (ULONG) pReceive->pReceiver->FirstNakSequenceNumber));
  4252. }
  4253. else
  4254. {
  4255. if (PacketType == PACKET_TYPE_ODATA)
  4256. {
  4257. UpdateRealTimeWindowInformation (pReceive, ThisPacketSequenceNumber, ThisTrailingEdge);
  4258. }
  4259. status = PgmHandleNewData (&ThisPacketSequenceNumber,
  4260. pAddress,
  4261. pReceive,
  4262. (USHORT) PacketLength,
  4263. pODataBuffer,
  4264. PacketType,
  4265. &OldIrq,
  4266. &OldIrq1);
  4267. PgmTrace (LogPath, ("ProcessDataPacket: " \
  4268. "PgmHandleNewData returned <%x>, SeqNum=[%d] < NextOData=[%d]\n",
  4269. status, (ULONG) ThisPacketSequenceNumber, (ULONG) pReceive->pReceiver->NextODataSequenceNumber));
  4270. //
  4271. // Now, try to indicate any data which may still be pending
  4272. //
  4273. status = CheckIndicatePendedData (pAddress, pReceive, &OldIrq, &OldIrq1);
  4274. }
  4275. CheckIndicateDisconnect (pAddress, pReceive, &OldIrq, &OldIrq1, TRUE);
  4276. PgmUnlock (pReceive, OldIrq1);
  4277. PgmUnlock (pAddress, OldIrq);
  4278. return (STATUS_SUCCESS);
  4279. }
  4280. //----------------------------------------------------------------------------
  4281. NTSTATUS
  4282. ProcessSpmPacket(
  4283. IN tADDRESS_CONTEXT *pAddress,
  4284. IN tRECEIVE_SESSION *pReceive,
  4285. IN ULONG PacketLength,
  4286. IN tBASIC_SPM_PACKET_HEADER UNALIGNED *pSpmPacket
  4287. )
  4288. /*++
  4289. Routine Description:
  4290. This routine processes Spm packets
  4291. Arguments:
  4292. IN pAddress -- Address object context
  4293. IN pReceive -- Receive context
  4294. IN PacketLength -- Length of packet received from the wire
  4295. IN pSpmPacket -- Spm packet
  4296. Return Value:
  4297. NTSTATUS - Final status of the call
  4298. --*/
  4299. {
  4300. SEQ_TYPE SpmSequenceNumber, LeadingEdgeSeqNumber, TrailingEdgeSeqNumber;
  4301. LIST_ENTRY *pEntry;
  4302. ULONG DisconnectFlag;
  4303. NTSTATUS status;
  4304. PGMLockHandle OldIrq, OldIrq1;
  4305. tPACKET_OPTIONS PacketOptions;
  4306. PNAK_FORWARD_DATA pNak;
  4307. USHORT TSDULength;
  4308. tNLA PathNLA;
  4309. BOOLEAN fFirstSpm;
  4310. ULONG ulData;
  4311. //
  4312. // First process the options
  4313. //
  4314. PgmZeroMemory (&PacketOptions, sizeof (tPACKET_OPTIONS));
  4315. if (pSpmPacket->CommonHeader.Options & PACKET_HEADER_OPTIONS_PRESENT)
  4316. {
  4317. status = ProcessOptions ((tPACKET_OPTION_LENGTH *) (pSpmPacket + 1),
  4318. (PacketLength - sizeof(tBASIC_SPM_PACKET_HEADER)),
  4319. (pSpmPacket->CommonHeader.Type & 0x0f),
  4320. &PacketOptions,
  4321. NULL);
  4322. if (!NT_SUCCESS (status))
  4323. {
  4324. PgmTrace (LogError, ("ProcessSpmPacket: ERROR -- " \
  4325. "ProcessOptions returned <%x>\n", status));
  4326. return (STATUS_DATA_NOT_ACCEPTED);
  4327. }
  4328. }
  4329. ASSERT ((PacketOptions.OptionsFlags & ~PGM_VALID_SPM_OPTION_FLAGS) == 0);
  4330. PgmCopyMemory (&PathNLA, &pSpmPacket->PathNLA, sizeof (tNLA));
  4331. PgmCopyMemory (&TSDULength, &pSpmPacket->CommonHeader.TSDULength, sizeof (USHORT));
  4332. TSDULength = ntohs (TSDULength);
  4333. PathNLA.NLA_AFI = ntohs (PathNLA.NLA_AFI);
  4334. if ((TSDULength) ||
  4335. (IPV4_NLA_AFI != PathNLA.NLA_AFI) ||
  4336. (!PathNLA.IpAddress))
  4337. {
  4338. PgmTrace (LogError, ("ProcessSpmPacket: ERROR -- " \
  4339. "TSDULength=<%d>, PathNLA.IpAddress=<%x>\n",
  4340. (ULONG) TSDULength, PathNLA.IpAddress));
  4341. return (STATUS_DATA_NOT_ACCEPTED);
  4342. }
  4343. PgmCopyMemory (&ulData, &pSpmPacket->SpmSequenceNumber, sizeof (ULONG));
  4344. SpmSequenceNumber = (SEQ_TYPE) ntohl (ulData);
  4345. PgmCopyMemory (&ulData, &pSpmPacket->LeadingEdgeSeqNumber, sizeof (ULONG));
  4346. LeadingEdgeSeqNumber = (SEQ_TYPE) ntohl (ulData);
  4347. PgmCopyMemory (&ulData, &pSpmPacket->TrailingEdgeSeqNumber, sizeof (ULONG));
  4348. TrailingEdgeSeqNumber = (SEQ_TYPE) ntohl (ulData);
  4349. //
  4350. // Verify Packet length
  4351. //
  4352. if ((sizeof(tBASIC_SPM_PACKET_HEADER) + PacketOptions.OptionsLength) != PacketLength)
  4353. {
  4354. PgmTrace (LogError, ("ProcessSpmPacket: ERROR -- " \
  4355. "Bad PacketLength=<%d>, OptionsLength=<%d>, TSDULength=<%d>\n",
  4356. PacketLength, PacketOptions.OptionsLength, (ULONG) TSDULength));
  4357. return (STATUS_DATA_NOT_ACCEPTED);
  4358. }
  4359. PgmLock (pAddress, OldIrq);
  4360. if (!pReceive)
  4361. {
  4362. //
  4363. // Since we do not have a live connection yet, we will
  4364. // have to store some state in the Address context
  4365. //
  4366. PgmTrace (LogPath, ("ProcessSpmPacket: " \
  4367. "[%d] Received SPM before OData for session, LastSpmSource=<%x>, FEC %sabled, Window=[%d - %d]\n",
  4368. SpmSequenceNumber, PathNLA.IpAddress,
  4369. (PacketOptions.OptionsFlags & PGM_OPTION_FLAG_PARITY_PRM ? "EN" : "DIS"),
  4370. (ULONG) TrailingEdgeSeqNumber, (ULONG) LeadingEdgeSeqNumber));
  4371. if ((ntohs (PathNLA.NLA_AFI) == IPV4_NLA_AFI) &&
  4372. (PathNLA.IpAddress))
  4373. {
  4374. pAddress->LastSpmSource = ntohl (PathNLA.IpAddress);
  4375. }
  4376. //
  4377. // Check if the sender is FEC-enabled
  4378. //
  4379. if ((PacketOptions.OptionsFlags & PGM_OPTION_FLAG_PARITY_PRM) &&
  4380. (PacketOptions.FECContext.ReceiverFECOptions) &&
  4381. (PacketOptions.FECContext.FECGroupInfo > 1))
  4382. {
  4383. pAddress->FECOptions = PacketOptions.FECContext.ReceiverFECOptions;
  4384. pAddress->FECGroupSize = (UCHAR) PacketOptions.FECContext.FECGroupInfo;
  4385. ASSERT (PacketOptions.FECContext.FECGroupInfo == pAddress->FECGroupSize);
  4386. }
  4387. PgmUnlock (pAddress, OldIrq);
  4388. return (STATUS_SUCCESS);
  4389. }
  4390. PgmLock (pReceive, OldIrq1);
  4391. UpdateSpmIntervalInformation (pReceive);
  4392. //
  4393. // If this is not the first SPM packet (LastSpmSource is not NULL), see if it is out-of-sequence,
  4394. // otherwise take this as the first packet
  4395. //
  4396. if ((pReceive->pReceiver->LastSpmSource) &&
  4397. (SEQ_LEQ (SpmSequenceNumber, pReceive->pReceiver->LastSpmSequenceNumber)))
  4398. {
  4399. PgmUnlock (pReceive, OldIrq1);
  4400. PgmUnlock (pAddress, OldIrq);
  4401. PgmTrace (LogAllFuncs, ("ProcessSpmPacket: " \
  4402. "Out-of-sequence SPM Packet received!\n"));
  4403. return (STATUS_DATA_NOT_ACCEPTED);
  4404. }
  4405. pReceive->pReceiver->LastSpmSequenceNumber = SpmSequenceNumber;
  4406. //
  4407. // Save the last Sender NLA
  4408. //
  4409. if ((ntohs(PathNLA.NLA_AFI) == IPV4_NLA_AFI) &&
  4410. (PathNLA.IpAddress))
  4411. {
  4412. pReceive->pReceiver->LastSpmSource = ntohl (PathNLA.IpAddress);
  4413. }
  4414. else
  4415. {
  4416. pReceive->pReceiver->LastSpmSource = pReceive->pReceiver->SenderIpAddress;
  4417. }
  4418. UpdateRealTimeWindowInformation (pReceive, LeadingEdgeSeqNumber, TrailingEdgeSeqNumber);
  4419. //
  4420. // Update the trailing edge if this is more ahead
  4421. //
  4422. if (SEQ_GT (TrailingEdgeSeqNumber, pReceive->pReceiver->LastTrailingEdgeSeqNum))
  4423. {
  4424. pReceive->pReceiver->LastTrailingEdgeSeqNum = TrailingEdgeSeqNumber;
  4425. }
  4426. if (SEQ_GT (pReceive->pReceiver->LastTrailingEdgeSeqNum, pReceive->pReceiver->FirstNakSequenceNumber))
  4427. {
  4428. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  4429. if (SEQ_GT (pReceive->pReceiver->LastTrailingEdgeSeqNum, (1 + pReceive->pReceiver->FurthestKnownGroupSequenceNumber)))
  4430. {
  4431. PgmTrace (LogStatus, ("ProcessSpmPacket: " \
  4432. "NETWORK problems -- data loss=<%d> packets > window size!\n\tExpecting=<%d>, FurthestKnown=<%d>, Window=[%d--%d] = < %d > seqs\n",
  4433. (ULONG) (1 + LeadingEdgeSeqNumber -
  4434. pReceive->pReceiver->FurthestKnownGroupSequenceNumber),
  4435. (ULONG) pReceive->pReceiver->FirstNakSequenceNumber,
  4436. (ULONG) pReceive->pReceiver->FurthestKnownGroupSequenceNumber,
  4437. (ULONG) pReceive->pReceiver->LastTrailingEdgeSeqNum, LeadingEdgeSeqNumber,
  4438. (ULONG) (1+LeadingEdgeSeqNumber-pReceive->pReceiver->LastTrailingEdgeSeqNum)));
  4439. }
  4440. else
  4441. {
  4442. ASSERT (!IsListEmpty (&pReceive->pReceiver->NaksForwardDataList));
  4443. pNak = CONTAINING_RECORD (pReceive->pReceiver->NaksForwardDataList.Flink, tNAK_FORWARD_DATA, Linkage);
  4444. PgmTrace (LogStatus, ("ProcessSpmPacket: " \
  4445. "Session window has past TrailingEdge -- Expecting <%d==%d>, NumNcfs=<%d>, FurthestKnown=<%d>, Window=[%d--%d] = < %d > seqs\n",
  4446. (ULONG) pReceive->pReceiver->FirstNakSequenceNumber,
  4447. (ULONG) pNak->SequenceNumber,
  4448. pNak->WaitingRDataRetries,
  4449. (ULONG) pReceive->pReceiver->FurthestKnownGroupSequenceNumber,
  4450. (ULONG) pReceive->pReceiver->LastTrailingEdgeSeqNum, LeadingEdgeSeqNumber,
  4451. (ULONG) (1+LeadingEdgeSeqNumber-pReceive->pReceiver->LastTrailingEdgeSeqNum)));
  4452. }
  4453. }
  4454. //
  4455. // If the Leading edge is > our current leading edge, then
  4456. // we need to send NAKs for the missing data Packets
  4457. //
  4458. pNak = NULL;
  4459. if (SEQ_GEQ (LeadingEdgeSeqNumber, pReceive->pReceiver->FirstNakSequenceNumber))
  4460. {
  4461. status = CheckAndAddNakRequests (pReceive, &LeadingEdgeSeqNumber, &pNak, NAK_PENDING_RB, TRUE);
  4462. if (!NT_SUCCESS (status))
  4463. {
  4464. PgmUnlock (pReceive, OldIrq1);
  4465. PgmUnlock (pAddress, OldIrq);
  4466. PgmTrace (LogError, ("ProcessSpmPacket: ERROR -- " \
  4467. "CheckAndAddNakRequests returned <%x>\n", status));
  4468. return (status);
  4469. }
  4470. }
  4471. //
  4472. // Now, process all the options
  4473. //
  4474. if (PacketOptions.OptionsFlags & PGM_OPTION_FLAG_RST_N)
  4475. {
  4476. pReceive->pReceiver->FinDataSequenceNumber = pReceive->pReceiver->FurthestKnownGroupSequenceNumber;
  4477. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  4478. PgmTrace (LogStatus, ("ProcessSpmPacket: " \
  4479. "Got an RST_N! FinSeq=<%d>, NextODataSeq=<%d>, FurthestData=<%d>\n",
  4480. (ULONG) pReceive->pReceiver->FinDataSequenceNumber,
  4481. (ULONG) pReceive->pReceiver->NextODataSequenceNumber,
  4482. (ULONG) pReceive->pReceiver->FurthestKnownGroupSequenceNumber));
  4483. }
  4484. else if (PacketOptions.OptionsFlags & PGM_OPTION_FLAG_RST)
  4485. {
  4486. pReceive->pReceiver->FinDataSequenceNumber = LeadingEdgeSeqNumber;
  4487. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  4488. PgmTrace (LogStatus, ("ProcessSpmPacket: " \
  4489. "Got an RST! FinSeq=<%d>, NextODataSeq=<%d>, FurthestData=<%d>\n",
  4490. (ULONG) pReceive->pReceiver->FinDataSequenceNumber,
  4491. (ULONG) pReceive->pReceiver->NextODataSequenceNumber,
  4492. (ULONG) pReceive->pReceiver->FurthestKnownGroupSequenceNumber));
  4493. }
  4494. else if (PacketOptions.OptionsFlags & PGM_OPTION_FLAG_FIN)
  4495. {
  4496. pReceive->pReceiver->FinDataSequenceNumber = LeadingEdgeSeqNumber;
  4497. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_GRACEFULLY;
  4498. PgmTrace (LogStatus, ("ProcessSpmPacket: " \
  4499. "Got a FIN! FinSeq=<%d>, NextODataSeq=<%d>, FirstNak=<%d>, FurthestKnown=<%d>, FurthestGroup=<%d>\n",
  4500. (ULONG) pReceive->pReceiver->FinDataSequenceNumber,
  4501. (ULONG) pReceive->pReceiver->NextODataSequenceNumber,
  4502. (ULONG) pReceive->pReceiver->FirstNakSequenceNumber,
  4503. (ULONG) pReceive->pReceiver->FurthestKnownSequenceNumber,
  4504. (ULONG) pReceive->pReceiver->FurthestKnownGroupSequenceNumber));
  4505. //
  4506. // See if we need to set the Fin Sequence #
  4507. //
  4508. if (pNak)
  4509. {
  4510. ASSERT (pNak->SequenceNumber == (LeadingEdgeSeqNumber & ~(pReceive->FECGroupSize-1)));
  4511. pNak->PacketsInGroup = (UCHAR) (LeadingEdgeSeqNumber + 1 - pNak->SequenceNumber);
  4512. ASSERT (pNak->PacketsInGroup <= pReceive->FECGroupSize);
  4513. RemoveRedundantNaks (pReceive, pNak, TRUE);
  4514. AdjustReceiveBufferLists (pReceive);
  4515. }
  4516. }
  4517. //
  4518. // See if we need to abort
  4519. //
  4520. if (CheckIndicateDisconnect (pAddress, pReceive, &OldIrq, &OldIrq1, TRUE))
  4521. {
  4522. PgmUnlock (pReceive, OldIrq1);
  4523. PgmUnlock (pAddress, OldIrq);
  4524. return (STATUS_SUCCESS);
  4525. }
  4526. //
  4527. // Check if the sender is FEC-enabled
  4528. //
  4529. if (PacketOptions.OptionsFlags & PGM_OPTION_FLAG_PARITY_PRM)
  4530. {
  4531. if ((pReceive->FECGroupSize == 1) &&
  4532. (PacketOptions.FECContext.ReceiverFECOptions) &&
  4533. (PacketOptions.FECContext.FECGroupInfo > 1))
  4534. {
  4535. ASSERT (!pReceive->pFECBuffer);
  4536. if (!(pReceive->pFECBuffer = PgmAllocMem ((pReceive->MaxFECPacketLength * PacketOptions.FECContext.FECGroupInfo*2), PGM_TAG('3'))))
  4537. {
  4538. status = STATUS_INSUFFICIENT_RESOURCES;
  4539. PgmTrace (LogError, ("ProcessSpmPacket: ERROR -- " \
  4540. "STATUS_INSUFFICIENT_RESOURCES -- MaxFECPacketLength = <%d>, GroupSize=<%d>\n",
  4541. pReceive->MaxFECPacketLength, PacketOptions.FECContext.FECGroupInfo));
  4542. }
  4543. else if (!NT_SUCCESS (status = CreateFECContext (&pReceive->FECContext, PacketOptions.FECContext.FECGroupInfo, FEC_MAX_BLOCK_SIZE, TRUE)))
  4544. {
  4545. PgmFreeMem (pReceive->pFECBuffer);
  4546. pReceive->pFECBuffer = NULL;
  4547. PgmTrace (LogError, ("ProcessSpmPacket: ERROR -- " \
  4548. "CreateFECContext returned <%x>\n", status));
  4549. }
  4550. else if (!NT_SUCCESS (status = CoalesceSelectiveNaksIntoGroups (pReceive, (UCHAR) PacketOptions.FECContext.FECGroupInfo)))
  4551. {
  4552. DestroyFECContext (&pReceive->FECContext);
  4553. PgmFreeMem (pReceive->pFECBuffer);
  4554. pReceive->pFECBuffer = NULL;
  4555. PgmTrace (LogError, ("ProcessSpmPacket: ERROR -- " \
  4556. "CoalesceSelectiveNaksIntoGroups returned <%x>\n", status));
  4557. }
  4558. else
  4559. {
  4560. pReceive->FECOptions = PacketOptions.FECContext.ReceiverFECOptions;
  4561. pReceive->FECGroupSize = (UCHAR) PacketOptions.FECContext.FECGroupInfo;
  4562. if (pReceive->FECOptions & PACKET_OPTION_SPECIFIC_FEC_OND_BIT)
  4563. {
  4564. pReceive->pReceiver->SessionNakType = NAK_TYPE_PARITY;
  4565. }
  4566. ASSERT (PacketOptions.FECContext.FECGroupInfo == pReceive->FECGroupSize);
  4567. }
  4568. if (!NT_SUCCESS (status))
  4569. {
  4570. PgmUnlock (pReceive, OldIrq1);
  4571. PgmUnlock (pAddress, OldIrq);
  4572. return (STATUS_DATA_NOT_ACCEPTED);
  4573. }
  4574. fFirstSpm = TRUE;
  4575. }
  4576. else
  4577. {
  4578. fFirstSpm = FALSE;
  4579. }
  4580. if (PacketOptions.OptionsFlags & PGM_OPTION_FLAG_PARITY_CUR_TGSIZE)
  4581. {
  4582. //
  4583. // The Leading edge Packet belongs to a Variable sized group
  4584. // so set that information appropriately
  4585. // Determine the group to which this leading edge belongs to
  4586. //
  4587. LeadingEdgeSeqNumber &= ~((SEQ_TYPE) (pReceive->FECGroupSize-1));
  4588. if ((PacketOptions.FECContext.NumPacketsInThisGroup) &&
  4589. (PacketOptions.FECContext.NumPacketsInThisGroup < pReceive->FECGroupSize) &&
  4590. SEQ_GEQ (LeadingEdgeSeqNumber, pReceive->pReceiver->FirstNakSequenceNumber) &&
  4591. (pNak = FindReceiverEntry (pReceive->pReceiver, LeadingEdgeSeqNumber)) &&
  4592. (pNak->PacketsInGroup == pReceive->FECGroupSize))
  4593. {
  4594. //
  4595. // We have already coalesced the list, so the packets should
  4596. // be ordered into groups!
  4597. //
  4598. pNak->PacketsInGroup = PacketOptions.FECContext.NumPacketsInThisGroup;
  4599. if (pNak->SequenceNumber == pReceive->pReceiver->FurthestKnownGroupSequenceNumber)
  4600. {
  4601. pReceive->pReceiver->FurthestKnownSequenceNumber = pNak->SequenceNumber + pNak->PacketsInGroup - 1;
  4602. }
  4603. RemoveRedundantNaks (pReceive, pNak, TRUE);
  4604. }
  4605. else
  4606. {
  4607. PgmTrace (LogPath, ("ProcessSpmPacket: " \
  4608. "WARNING .. PARITY_CUR_TGSIZE ThisGroupSize=<%x>, FECGroupSize=<%x>\n",
  4609. PacketOptions.FECContext.NumPacketsInThisGroup, pReceive->FECGroupSize));
  4610. }
  4611. }
  4612. }
  4613. status = CheckIndicatePendedData (pAddress, pReceive, &OldIrq, &OldIrq1);
  4614. PgmUnlock (pReceive, OldIrq1);
  4615. PgmUnlock (pAddress, OldIrq);
  4616. PgmTrace (LogAllFuncs, ("ProcessSpmPacket: " \
  4617. "NextOData=<%d>, FinDataSeq=<%d> \n",
  4618. (ULONG) pReceive->pReceiver->NextODataSequenceNumber,
  4619. (ULONG) pReceive->pReceiver->FinDataSequenceNumber));
  4620. return (STATUS_SUCCESS);
  4621. }
  4622. //----------------------------------------------------------------------------
  4623. NTSTATUS
  4624. PgmProcessIncomingPacket(
  4625. IN tADDRESS_CONTEXT *pAddress,
  4626. IN tCOMMON_SESSION_CONTEXT *pSession,
  4627. IN INT SourceAddressLength,
  4628. IN PTA_IP_ADDRESS pRemoteAddress,
  4629. IN ULONG PacketLength,
  4630. IN tCOMMON_HEADER UNALIGNED *pPgmHeader,
  4631. IN UCHAR PacketType
  4632. )
  4633. /*++
  4634. Routine Description:
  4635. This routine process an incoming packet and calls the
  4636. appropriate handler depending on whether is a data packet
  4637. packet, etc.
  4638. Arguments:
  4639. IN pAddress -- Address object context
  4640. IN pReceive -- Receive context
  4641. IN SourceAddressLength -- Length of source address
  4642. IN pRemoteAddress -- Address of remote host
  4643. IN PacketLength -- Length of packet received from the wire
  4644. IN pPgmHeader -- Pgm packet
  4645. IN PacketType -- Type of Pgm packet
  4646. Return Value:
  4647. NTSTATUS - Final status of the call
  4648. --*/
  4649. {
  4650. tIPADDRESS SrcIpAddress;
  4651. tNLA SourceNLA, MCastGroupNLA;
  4652. tBASIC_NAK_NCF_PACKET_HEADER UNALIGNED *pNakNcfPacket;
  4653. NTSTATUS status = STATUS_SUCCESS;
  4654. //
  4655. // We have an active connection for this TSI, so process the data appropriately
  4656. //
  4657. //
  4658. // First check for SPM packets
  4659. //
  4660. if (PACKET_TYPE_SPM == PacketType)
  4661. {
  4662. if (PacketLength < sizeof(tBASIC_SPM_PACKET_HEADER))
  4663. {
  4664. PgmTrace (LogError, ("PgmProcessIncomingPacket: ERROR -- " \
  4665. "Bad SPM Packet length: PacketLength=<%d> < sizeof(tBASIC_SPM_PACKET_HEADER)=<%d>\n",
  4666. PacketLength, sizeof(tBASIC_SPM_PACKET_HEADER)));
  4667. return (STATUS_DATA_NOT_ACCEPTED);
  4668. }
  4669. if (PGM_VERIFY_HANDLE (pSession, PGM_VERIFY_SESSION_RECEIVE))
  4670. {
  4671. pSession->TotalBytes += PacketLength;
  4672. pSession->TotalPacketsReceived++;
  4673. pSession->pReceiver->LastSessionTickCount = PgmDynamicConfig.ReceiversTimerTickCount;
  4674. status = ProcessSpmPacket (pAddress,
  4675. pSession,
  4676. PacketLength,
  4677. (tBASIC_SPM_PACKET_HEADER UNALIGNED *) pPgmHeader);
  4678. PgmTrace (LogAllFuncs, ("PgmProcessIncomingPacket: " \
  4679. "SPM PacketType=<%x> for pSession=<%p> PacketLength=<%d>, status=<%x>\n",
  4680. PacketType, pSession, PacketLength, status));
  4681. }
  4682. else
  4683. {
  4684. PgmTrace (LogError, ("PgmProcessIncomingPacket: ERROR -- " \
  4685. "Received SPM packet, not on Receiver session! pSession=<%p>\n", pSession));
  4686. status = STATUS_DATA_NOT_ACCEPTED;
  4687. }
  4688. return (status);
  4689. }
  4690. //
  4691. // The only other packets we process are Nak and Ncf packets, so ignore the rest!
  4692. //
  4693. if ((PACKET_TYPE_NCF != PacketType) &&
  4694. (PACKET_TYPE_NAK != PacketType))
  4695. {
  4696. PgmTrace (LogError, ("PgmProcessIncomingPacket: ERROR -- " \
  4697. "Unknown PacketType=<%x>, PacketLength=<%d>\n", PacketType, PacketLength));
  4698. return (STATUS_DATA_NOT_ACCEPTED);
  4699. }
  4700. //
  4701. // Now, verify packet info for Nak and Ncf packets
  4702. //
  4703. if (PacketLength < sizeof(tBASIC_NAK_NCF_PACKET_HEADER))
  4704. {
  4705. PgmTrace (LogError, ("PgmProcessIncomingPacket: ERROR -- " \
  4706. "NakNcf packet! PacketLength=<%d>, Min=<%d>, ...\n",
  4707. PacketLength, sizeof(tBASIC_NAK_NCF_PACKET_HEADER)));
  4708. return (STATUS_DATA_NOT_ACCEPTED);
  4709. }
  4710. pNakNcfPacket = (tBASIC_NAK_NCF_PACKET_HEADER UNALIGNED *) pPgmHeader;
  4711. PgmCopyMemory (&SourceNLA, &pNakNcfPacket->SourceNLA, sizeof (tNLA));
  4712. PgmCopyMemory (&MCastGroupNLA, &pNakNcfPacket->MCastGroupNLA, sizeof (tNLA));
  4713. if (((htons(IPV4_NLA_AFI) != SourceNLA.NLA_AFI) || (!SourceNLA.IpAddress)) ||
  4714. ((htons(IPV4_NLA_AFI) != MCastGroupNLA.NLA_AFI) || (!MCastGroupNLA.IpAddress)))
  4715. {
  4716. PgmTrace (LogError, ("PgmProcessIncomingPacket: ERROR -- " \
  4717. "NakNcf packet! PacketLength=<%d>, Min=<%d>, ...\n",
  4718. PacketLength, sizeof(tBASIC_NAK_NCF_PACKET_HEADER)));
  4719. return (STATUS_DATA_NOT_ACCEPTED);
  4720. }
  4721. if (PACKET_TYPE_NCF == PacketType)
  4722. {
  4723. if (PGM_VERIFY_HANDLE (pSession, PGM_VERIFY_SESSION_RECEIVE))
  4724. {
  4725. status = ReceiverProcessNakNcfPacket (pAddress,
  4726. pSession,
  4727. PacketLength,
  4728. pNakNcfPacket,
  4729. PacketType);
  4730. }
  4731. else
  4732. {
  4733. PgmTrace (LogError, ("PgmProcessIncomingPacket: ERROR -- " \
  4734. "Received Ncf packet, not on Receiver session! pSession=<%p>\n", pSession));
  4735. status = STATUS_DATA_NOT_ACCEPTED;
  4736. }
  4737. }
  4738. // Now process NAK packet
  4739. else if (pSession->pSender)
  4740. {
  4741. ASSERT (!pSession->pReceiver);
  4742. status = SenderProcessNakPacket (pAddress,
  4743. pSession,
  4744. PacketLength,
  4745. pNakNcfPacket);
  4746. }
  4747. else
  4748. {
  4749. ASSERT (pSession->pReceiver);
  4750. //
  4751. // Check for Remote guy's address
  4752. // If the Nak was sent by us, then we can ignore it!
  4753. //
  4754. if ((pRemoteAddress->TAAddressCount == 1) &&
  4755. (pRemoteAddress->Address[0].AddressLength == TDI_ADDRESS_LENGTH_IP) &&
  4756. (pRemoteAddress->Address[0].AddressType == TDI_ADDRESS_TYPE_IP) &&
  4757. (SrcIpAddress = ntohl(((PTDI_ADDRESS_IP)&pRemoteAddress->Address[0].Address)->in_addr)) &&
  4758. (!SrcIsUs (SrcIpAddress)) &&
  4759. (SrcIsOnLocalSubnet (SrcIpAddress)))
  4760. {
  4761. status = ReceiverProcessNakNcfPacket (pAddress,
  4762. pSession,
  4763. PacketLength,
  4764. pNakNcfPacket,
  4765. PacketType);
  4766. }
  4767. ASSERT (NT_SUCCESS (status));
  4768. }
  4769. PgmTrace (LogAllFuncs, ("PgmProcessIncomingPacket: " \
  4770. "PacketType=<%x> for pSession=<%p> PacketLength=<%d>, status=<%x>\n",
  4771. PacketType, pSession, PacketLength, status));
  4772. return (status);
  4773. }
  4774. //----------------------------------------------------------------------------
  4775. NTSTATUS
  4776. PgmNewInboundConnection(
  4777. IN tADDRESS_CONTEXT *pAddress,
  4778. IN INT SourceAddressLength,
  4779. IN PVOID pSourceAddress,
  4780. IN ULONG ReceiveDatagramFlags,
  4781. IN tBASIC_DATA_PACKET_HEADER UNALIGNED *pPgmHeader,
  4782. IN ULONG PacketLength,
  4783. OUT tRECEIVE_SESSION **ppReceive
  4784. )
  4785. /*++
  4786. Routine Description:
  4787. This routine processes a new incoming connection
  4788. Arguments:
  4789. IN pAddress -- Address object context
  4790. IN SourceAddressLength -- Length of source address
  4791. IN pSourceAddress -- Address of remote host
  4792. IN ReceiveDatagramFlags-- Flags set by the transport for this packet
  4793. IN pPgmHeader -- Pgm packet
  4794. IN PacketLength -- Length of packet received from the wire
  4795. OUT ppReceive -- pReceive context for this session returned by the client (if successful)
  4796. Return Value:
  4797. NTSTATUS - Final status of the call
  4798. --*/
  4799. {
  4800. NTSTATUS status;
  4801. tRECEIVE_SESSION *pReceive;
  4802. CONNECTION_CONTEXT ConnectId;
  4803. PIO_STACK_LOCATION pIrpSp;
  4804. TA_IP_ADDRESS RemoteAddress;
  4805. INT RemoteAddressSize;
  4806. PTDI_IND_CONNECT evConnect = NULL;
  4807. PVOID ConEvContext = NULL;
  4808. PGMLockHandle OldIrq, OldIrq1, OldIrq2;
  4809. PIRP pIrp = NULL;
  4810. ULONG ulData;
  4811. USHORT PortNum;
  4812. SEQ_TYPE FirstODataSequenceNumber;
  4813. tPACKET_OPTIONS PacketOptions;
  4814. //
  4815. // We need to set the Next expected sequence number, so first see if
  4816. // there is a late joiner option
  4817. //
  4818. PgmZeroMemory (&PacketOptions, sizeof (tPACKET_OPTIONS));
  4819. if (pPgmHeader->CommonHeader.Options & PACKET_HEADER_OPTIONS_PRESENT)
  4820. {
  4821. status = ProcessOptions ((tPACKET_OPTION_LENGTH *) (pPgmHeader + 1),
  4822. (PacketLength - sizeof(tBASIC_DATA_PACKET_HEADER)),
  4823. (pPgmHeader->CommonHeader.Type & 0x0f),
  4824. &PacketOptions,
  4825. NULL);
  4826. if (!NT_SUCCESS (status))
  4827. {
  4828. PgmTrace (LogError, ("PgmNewInboundConnection: ERROR -- " \
  4829. "ProcessOptions returned <%x>\n", status));
  4830. return (STATUS_DATA_NOT_ACCEPTED);
  4831. }
  4832. ASSERT ((PacketOptions.OptionsFlags & ~PGM_VALID_DATA_OPTION_FLAGS) == 0);
  4833. }
  4834. PgmCopyMemory (&ulData, &pPgmHeader->DataSequenceNumber, sizeof (ULONG));
  4835. FirstODataSequenceNumber = (SEQ_TYPE) ntohl (ulData);
  4836. PgmLock (pAddress, OldIrq1);
  4837. //
  4838. // The Address is already referenced in the calling routine,
  4839. // so we don not need to reference it here again!
  4840. //
  4841. #if 0
  4842. if (!IsListEmpty(&pAddress->ListenHead))
  4843. {
  4844. //
  4845. // Ignore this for now since we have not encountered posted listens! (Is this an ISSUE ?)
  4846. }
  4847. #endif // 0
  4848. if (!(ConEvContext = pAddress->ConEvContext))
  4849. {
  4850. //
  4851. // Client has not yet posted a Listen!
  4852. // take all of the data so that a disconnect will not be held up
  4853. // by data still in the transport.
  4854. //
  4855. PgmUnlock (pAddress, OldIrq1);
  4856. PgmTrace (LogError, ("PgmNewInboundConnection: ERROR -- " \
  4857. "No Connect handler, pAddress=<%p>\n", pAddress));
  4858. return (STATUS_DATA_NOT_ACCEPTED);
  4859. }
  4860. RemoteAddressSize = offsetof (TA_IP_ADDRESS, Address[0].Address) + sizeof(TDI_ADDRESS_IP);
  4861. ASSERT (SourceAddressLength <= RemoteAddressSize);
  4862. PgmCopyMemory (&RemoteAddress, pSourceAddress, RemoteAddressSize);
  4863. PgmCopyMemory (&((PTDI_ADDRESS_IP) &RemoteAddress.Address[0].Address)->sin_port,
  4864. &pPgmHeader->CommonHeader.SrcPort, sizeof (USHORT));
  4865. RemoteAddress.TAAddressCount = 1;
  4866. evConnect = pAddress->evConnect;
  4867. PgmUnlock (pAddress, OldIrq1);
  4868. status = (*evConnect) (ConEvContext,
  4869. RemoteAddressSize,
  4870. &RemoteAddress,
  4871. 0,
  4872. NULL,
  4873. 0, // options length
  4874. NULL, // Options
  4875. &ConnectId,
  4876. &pIrp);
  4877. if ((status != STATUS_MORE_PROCESSING_REQUIRED) ||
  4878. (pIrp == NULL))
  4879. {
  4880. PgmTrace (LogPath, ("PgmNewInboundConnection: " \
  4881. "Client REJECTed incoming session: status=<%x>, pAddress=<%p>, evConn=<%p>\n",
  4882. status, pAddress, pAddress->evConnect));
  4883. if (pIrp)
  4884. {
  4885. PgmIoComplete (pIrp, STATUS_INTERNAL_ERROR, 0);
  4886. }
  4887. *ppReceive = NULL;
  4888. return (STATUS_DATA_NOT_ACCEPTED);
  4889. }
  4890. PgmLock (&PgmDynamicConfig, OldIrq);
  4891. PgmLock (pAddress, OldIrq1);
  4892. //
  4893. // the pReceive ptr was stored in the FsContext value when the connection
  4894. // was initially created.
  4895. //
  4896. pIrpSp = IoGetCurrentIrpStackLocation (pIrp);
  4897. pReceive = (tRECEIVE_SESSION *) pIrpSp->FileObject->FsContext;
  4898. if ((!PGM_VERIFY_HANDLE (pReceive, PGM_VERIFY_SESSION_RECEIVE)) ||
  4899. (pReceive->pAssociatedAddress != pAddress))
  4900. {
  4901. PgmTrace (LogError, ("PgmNewInboundConnection: ERROR -- " \
  4902. "pReceive=<%p>, pAddress=<%p : %p>\n",
  4903. pReceive, (pReceive ? pReceive->pAssociatedAddress : NULL), pAddress));
  4904. PgmUnlock (pAddress, OldIrq1);
  4905. PgmUnlock (&PgmDynamicConfig, OldIrq);
  4906. PgmIoComplete (pIrp, STATUS_INTERNAL_ERROR, 0);
  4907. *ppReceive = NULL;
  4908. return (STATUS_INTERNAL_ERROR);
  4909. }
  4910. ASSERT (ConnectId == pReceive->ClientSessionContext);
  4911. PgmLock (pReceive, OldIrq2);
  4912. if (!(pReceive->pReceiver->pReceiveData = InitReceiverData (pReceive)))
  4913. {
  4914. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  4915. PgmUnlock (pAddress, OldIrq2);
  4916. PgmUnlock (&PgmDynamicConfig, OldIrq1);
  4917. PgmUnlock (pReceive, OldIrq);
  4918. PgmIoComplete (pIrp, STATUS_INSUFFICIENT_RESOURCES, 0);
  4919. *ppReceive = NULL;
  4920. PgmTrace (LogError, ("PgmNewInboundConnection: ERROR -- " \
  4921. "STATUS_INSUFFICIENT_RESOURCES allocating pReceiveData -- pReceive=<%p>, pAddress=<%p>\n",
  4922. pReceive, pAddress));
  4923. return (STATUS_INSUFFICIENT_RESOURCES);
  4924. }
  4925. pReceive->pReceiver->SenderIpAddress = ntohl (((PTDI_ADDRESS_IP)&RemoteAddress.Address[0].Address)->in_addr);
  4926. pReceive->MaxMTULength = (USHORT) PgmDynamicConfig.MaxMTU;
  4927. pReceive->MaxFECPacketLength = pReceive->MaxMTULength +
  4928. sizeof (tPOST_PACKET_FEC_CONTEXT) - sizeof (USHORT);
  4929. ASSERT (!pReceive->pFECBuffer);
  4930. if (pAddress->Flags & PGM_ADDRESS_HIGH_SPEED_OPTIMIZED)
  4931. {
  4932. pReceive->pReceiver->MaxPacketsBufferedInLookaside = MAX_PACKETS_BUFFERED * 3; // 9000, about 15 Megs!
  4933. pReceive->pReceiver->InitialOutstandingNakTimeout = INITIAL_NAK_OUTSTANDING_TIMEOUT_MS_OPT /
  4934. BASIC_TIMER_GRANULARITY_IN_MSECS;
  4935. }
  4936. else
  4937. {
  4938. pReceive->pReceiver->MaxPacketsBufferedInLookaside = MAX_PACKETS_BUFFERED;
  4939. pReceive->pReceiver->InitialOutstandingNakTimeout = INITIAL_NAK_OUTSTANDING_TIMEOUT_MSECS /
  4940. BASIC_TIMER_GRANULARITY_IN_MSECS;
  4941. }
  4942. ASSERT (pReceive->pReceiver->MaxPacketsBufferedInLookaside);
  4943. ASSERT (pReceive->pReceiver->InitialOutstandingNakTimeout);
  4944. pReceive->pReceiver->OutstandingNakTimeout = pReceive->pReceiver->InitialOutstandingNakTimeout;
  4945. //
  4946. // If we had received an Spm earlier, then we may need to set
  4947. // some of the Spm-specific options
  4948. //
  4949. pReceive->FECGroupSize = 1; // Default to non-parity mode
  4950. pReceive->pReceiver->SessionNakType = NAK_TYPE_SELECTIVE;
  4951. if ((pAddress->LastSpmSource) ||
  4952. (pAddress->FECOptions))
  4953. {
  4954. if (pAddress->LastSpmSource)
  4955. {
  4956. pReceive->pReceiver->LastSpmSource = pAddress->LastSpmSource;
  4957. }
  4958. else
  4959. {
  4960. pReceive->pReceiver->LastSpmSource = pReceive->pReceiver->SenderIpAddress;
  4961. }
  4962. if (pAddress->FECOptions)
  4963. {
  4964. status = STATUS_SUCCESS;
  4965. if (!(pReceive->pFECBuffer = PgmAllocMem ((pReceive->MaxFECPacketLength * pAddress->FECGroupSize * 2), PGM_TAG('3'))))
  4966. {
  4967. PgmTrace (LogError, ("PgmNewInboundConnection: ERROR -- " \
  4968. "STATUS_INSUFFICIENT_RESOURCES allocating pFECBuffer, %d bytes\n",
  4969. (pReceive->MaxFECPacketLength * pAddress->FECGroupSize * 2)));
  4970. status = STATUS_INSUFFICIENT_RESOURCES;
  4971. }
  4972. else if (!NT_SUCCESS (status = CreateFECContext (&pReceive->FECContext, pAddress->FECGroupSize, FEC_MAX_BLOCK_SIZE, TRUE)))
  4973. {
  4974. PgmFreeMem (pReceive->pFECBuffer);
  4975. pReceive->pFECBuffer = NULL;
  4976. PgmTrace (LogError, ("PgmNewInboundConnection: ERROR -- " \
  4977. "CreateFECContext returned <%x>\n", status));
  4978. }
  4979. if (!NT_SUCCESS (status))
  4980. {
  4981. if (pReceive->pReceiver->pReceiveData)
  4982. {
  4983. PgmFreeMem (pReceive->pReceiver->pReceiveData);
  4984. pReceive->pReceiver->pReceiveData = NULL;
  4985. }
  4986. pReceive->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  4987. PgmUnlock (pAddress, OldIrq2);
  4988. PgmUnlock (&PgmDynamicConfig, OldIrq1);
  4989. PgmUnlock (pReceive, OldIrq);
  4990. PgmIoComplete (pIrp, status, 0);
  4991. *ppReceive = NULL;
  4992. return (STATUS_DATA_NOT_ACCEPTED);
  4993. }
  4994. ASSERT (pAddress->FECGroupSize > 1);
  4995. pReceive->FECGroupSize = pAddress->FECGroupSize;
  4996. pReceive->FECOptions = pAddress->FECOptions;
  4997. if (pReceive->FECOptions & PACKET_OPTION_SPECIFIC_FEC_OND_BIT)
  4998. {
  4999. pReceive->pReceiver->SessionNakType = NAK_TYPE_PARITY;
  5000. }
  5001. ExInitializeNPagedLookasideList (&pReceive->pReceiver->ParityContextLookaside,
  5002. NULL,
  5003. NULL,
  5004. 0,
  5005. (sizeof(tNAK_FORWARD_DATA) +
  5006. ((pReceive->FECGroupSize-1) * sizeof(tPENDING_DATA))),
  5007. PGM_TAG('2'),
  5008. (USHORT) (pReceive->pReceiver->MaxPacketsBufferedInLookaside/pReceive->FECGroupSize));
  5009. }
  5010. pAddress->LastSpmSource = pAddress->FECOptions = pAddress->FECGroupSize = 0;
  5011. }
  5012. //
  5013. // Initialize our Connect info
  5014. // Save the SourceId and Src port for this connection
  5015. //
  5016. PgmCopyMemory (&PortNum, &pPgmHeader->CommonHeader.SrcPort, sizeof (USHORT));
  5017. PgmCopyMemory (pReceive->TSI.GSI, pPgmHeader->CommonHeader.gSourceId, SOURCE_ID_LENGTH);
  5018. pReceive->TSI.hPort = ntohs (PortNum);
  5019. PGM_REFERENCE_SESSION_RECEIVE (pReceive, REF_SESSION_TDI_RCV_HANDLER, TRUE);
  5020. PGM_REFERENCE_SESSION_RECEIVE (pReceive, REF_SESSION_TIMER_RUNNING, TRUE);
  5021. PGM_REFERENCE_ADDRESS (pAddress, REF_ADDRESS_RECEIVE_ACTIVE, TRUE);
  5022. pReceive->SessionFlags |= (PGM_SESSION_ON_TIMER | PGM_SESSION_FLAG_FIRST_PACKET);
  5023. pReceive->pReceiver->pAddress = pAddress;
  5024. pReceive->pReceiver->MaxBufferLength = pReceive->MaxMTULength + sizeof(tPOST_PACKET_FEC_CONTEXT);
  5025. pReceive->pReceiver->DataBufferLookasideLength = pReceive->pReceiver->MaxBufferLength;
  5026. pReceive->SessionFlags |= PGM_SESSION_DATA_FROM_LOOKASIDE;
  5027. ExInitializeNPagedLookasideList (&pReceive->pReceiver->DataBufferLookaside,
  5028. NULL,
  5029. NULL,
  5030. 0,
  5031. pReceive->pReceiver->DataBufferLookasideLength,
  5032. PGM_TAG ('D'),
  5033. pReceive->pReceiver->MaxPacketsBufferedInLookaside);
  5034. ExInitializeNPagedLookasideList (&pReceive->pReceiver->NonParityContextLookaside,
  5035. NULL,
  5036. NULL,
  5037. 0,
  5038. sizeof (tNAK_FORWARD_DATA),
  5039. PGM_TAG ('2'),
  5040. pReceive->pReceiver->MaxPacketsBufferedInLookaside);
  5041. //
  5042. // Set the NextODataSequenceNumber and FurthestKnownGroupSequenceNumber based
  5043. // on this packet's Sequence # and the lateJoin option (if present)
  5044. // Make sure all of the Sequence numbers are on group boundaries (if not,
  5045. // set them at the start of the next group)
  5046. //
  5047. FirstODataSequenceNumber &= ~((SEQ_TYPE) pReceive->FECGroupSize - 1);
  5048. if (PacketOptions.OptionsFlags & PGM_OPTION_FLAG_JOIN)
  5049. {
  5050. PacketOptions.LateJoinerSequence += (pReceive->FECGroupSize - 1);
  5051. PacketOptions.LateJoinerSequence &= ~((SEQ_TYPE) pReceive->FECGroupSize - 1);
  5052. pReceive->pReceiver->NextODataSequenceNumber = (SEQ_TYPE) PacketOptions.LateJoinerSequence;
  5053. }
  5054. else
  5055. {
  5056. //
  5057. // There is no late joiner option
  5058. //
  5059. pReceive->pReceiver->NextODataSequenceNumber = FirstODataSequenceNumber;
  5060. }
  5061. pReceive->pReceiver->LastTrailingEdgeSeqNum = pReceive->pReceiver->FirstNakSequenceNumber =
  5062. pReceive->pReceiver->NextODataSequenceNumber;
  5063. pReceive->pReceiver->MaxOutstandingNakTimeout = pReceive->pReceiver->OutstandingNakTimeout;
  5064. //
  5065. // Set the FurthestKnown Sequence # and Allocate Nak contexts
  5066. //
  5067. pReceive->pReceiver->FurthestKnownGroupSequenceNumber = (pReceive->pReceiver->NextODataSequenceNumber-
  5068. pReceive->FECGroupSize) &
  5069. ~((SEQ_TYPE) pReceive->FECGroupSize - 1);
  5070. pReceive->pReceiver->FurthestKnownSequenceNumber = pReceive->pReceiver->NextODataSequenceNumber-1;
  5071. //
  5072. // Since this is the first receive for this session, see if we need to
  5073. // start the receive timer
  5074. //
  5075. InsertTailList (&PgmDynamicConfig.CurrentReceivers, &pReceive->pReceiver->Linkage);
  5076. if (!(PgmDynamicConfig.GlobalFlags & PGM_CONFIG_FLAG_RECEIVE_TIMER_RUNNING))
  5077. {
  5078. pReceive->pReceiver->StartTickCount = PgmDynamicConfig.ReceiversTimerTickCount = 1;
  5079. PgmDynamicConfig.LastReceiverTimeout.QuadPart = KeQueryInterruptTime ();
  5080. PgmDynamicConfig.TimeoutGranularity.QuadPart = BASIC_TIMER_GRANULARITY_IN_MSECS * 10000; // 100ns
  5081. if (!PgmDynamicConfig.TimeoutGranularity.QuadPart)
  5082. {
  5083. ASSERT (0);
  5084. PgmDynamicConfig.TimeoutGranularity.QuadPart = 1;
  5085. }
  5086. PgmDynamicConfig.GlobalFlags |= PGM_CONFIG_FLAG_RECEIVE_TIMER_RUNNING;
  5087. PgmInitTimer (&PgmDynamicConfig.SessionTimer);
  5088. PgmStartTimer (&PgmDynamicConfig.SessionTimer, BASIC_TIMER_GRANULARITY_IN_MSECS, ReceiveTimerTimeout, NULL);
  5089. }
  5090. else
  5091. {
  5092. pReceive->pReceiver->StartTickCount = PgmDynamicConfig.ReceiversTimerTickCount;
  5093. }
  5094. CheckAndAddNakRequests (pReceive, &FirstODataSequenceNumber, NULL, NAK_PENDING_0, TRUE);
  5095. PgmTrace (LogStatus, ("PgmNewInboundConnection: " \
  5096. "New incoming connection, pAddress=<%p>, pReceive=<%p>, ThisSeq=<%d==>%d> (%sparity), StartSeq=<%d>\n",
  5097. pAddress, pReceive, ntohl(ulData), (ULONG) FirstODataSequenceNumber,
  5098. (pPgmHeader->CommonHeader.Options & PACKET_HEADER_OPTIONS_PARITY ? "" : "non-"),
  5099. (ULONG) pReceive->pReceiver->NextODataSequenceNumber));
  5100. PgmUnlock (pReceive, OldIrq2);
  5101. PgmUnlock (pAddress, OldIrq1);
  5102. PgmUnlock (&PgmDynamicConfig, OldIrq);
  5103. //
  5104. // We are ready to proceed! So, complete the client's Accept Irp
  5105. //
  5106. PgmIoComplete (pIrp, STATUS_SUCCESS, 0);
  5107. //
  5108. // If we had failed, we would already have returned before now!
  5109. //
  5110. *ppReceive = pReceive;
  5111. return (STATUS_SUCCESS);
  5112. }
  5113. //----------------------------------------------------------------------------
  5114. NTSTATUS
  5115. ProcessReceiveCompletionRoutine(
  5116. IN PDEVICE_OBJECT DeviceObject,
  5117. IN PIRP pIrp,
  5118. IN PVOID Context
  5119. )
  5120. /*++
  5121. Routine Description:
  5122. This routine handles the case when a datagram is too
  5123. short and and Irp has to be passed back to the transport to get the
  5124. rest of the datagram. The irp completes through here when full.
  5125. Arguments:
  5126. IN DeviceObject - unused.
  5127. IN Irp - Supplies Irp that the transport has finished processing.
  5128. IN Context - Supplies the pReceive - the connection data structure
  5129. Return Value:
  5130. The final status from the operation (success or an exception).
  5131. --*/
  5132. {
  5133. NTSTATUS status;
  5134. PIRP pIoRequestPacket;
  5135. ULONG BytesTaken;
  5136. tRCV_COMPLETE_CONTEXT *pRcvContext = (tRCV_COMPLETE_CONTEXT *) Context;
  5137. ULONG Offset = pRcvContext->BytesAvailable;
  5138. PVOID pBuffer;
  5139. ULONG SrcAddressLength;
  5140. PVOID pSrcAddress;
  5141. if (pBuffer = MmGetSystemAddressForMdlSafe (pIrp->MdlAddress, HighPagePriority))
  5142. {
  5143. PgmTrace (LogAllFuncs, ("ProcessReceiveCompletionRoutine: " \
  5144. "pIrp=<%p>, pRcvBuffer=<%p>, Status=<%x> Length=<%d>\n",
  5145. pIrp, Context, pIrp->IoStatus.Status, (ULONG) pIrp->IoStatus.Information));
  5146. SrcAddressLength = pRcvContext->SrcAddressLength;
  5147. pSrcAddress = pRcvContext->pSrcAddress;
  5148. //
  5149. // just call the regular indication routine as if UDP had done it.
  5150. //
  5151. TdiRcvDatagramHandler (pRcvContext->pAddress,
  5152. SrcAddressLength,
  5153. pSrcAddress,
  5154. 0,
  5155. NULL,
  5156. TDI_RECEIVE_NORMAL,
  5157. (ULONG) pIrp->IoStatus.Information,
  5158. (ULONG) pIrp->IoStatus.Information,
  5159. &BytesTaken,
  5160. pBuffer,
  5161. &pIoRequestPacket);
  5162. }
  5163. else
  5164. {
  5165. PgmTrace (LogError, ("ProcessReceiveCompletionRoutine: ERROR -- " \
  5166. "MmGetSystemA... FAILed, pIrp=<%p>, pLocalBuffer=<%p>\n", pIrp, pRcvContext));
  5167. }
  5168. //
  5169. // Free the Irp and Mdl and Buffer
  5170. //
  5171. IoFreeMdl (pIrp->MdlAddress);
  5172. pIrp->MdlAddress = NULL;
  5173. IoFreeIrp (pIrp);
  5174. PgmFreeMem (pRcvContext);
  5175. return (STATUS_MORE_PROCESSING_REQUIRED);
  5176. }
  5177. #ifdef DROP_DBG
  5178. ULONG MinDropInterval = 10;
  5179. ULONG MaxDropInterval = 10;
  5180. // ULONG DropCount = 10;
  5181. ULONG DropCount = -1;
  5182. #endif // DROP_DBG
  5183. //----------------------------------------------------------------------------
  5184. NTSTATUS
  5185. TdiRcvDatagramHandler(
  5186. IN PVOID pDgramEventContext,
  5187. IN INT SourceAddressLength,
  5188. IN PVOID pSourceAddress,
  5189. IN INT OptionsLength,
  5190. #if(WINVER > 0x0500)
  5191. IN TDI_CMSGHDR *pControlData,
  5192. #else
  5193. IN PVOID *pControlData,
  5194. #endif // WINVER
  5195. IN ULONG ReceiveDatagramFlags,
  5196. IN ULONG BytesIndicated,
  5197. IN ULONG BytesAvailable,
  5198. OUT ULONG *pBytesTaken,
  5199. IN PVOID pTsdu,
  5200. OUT PIRP *ppIrp
  5201. )
  5202. /*++
  5203. Routine Description:
  5204. This routine is the handler for receiving all Pgm packets from
  5205. the transport (protocol == IPPROTO_RM)
  5206. Arguments:
  5207. IN pDgramEventContext -- Our context (pAddress)
  5208. IN SourceAddressLength -- Length of source address
  5209. IN pSourceAddress -- Address of remote host
  5210. IN OptionsLength
  5211. IN pControlData -- ControlData from transport
  5212. IN ReceiveDatagramFlags -- Flags set by the transport for this packet
  5213. IN BytesIndicated -- Bytes in this indicate
  5214. IN BytesAvailable -- total bytes available with the transport
  5215. OUT pBytesTaken -- bytes taken by us
  5216. IN pTsdu -- data packet ptr
  5217. OUT ppIrp -- pIrp if more processing required
  5218. Return Value:
  5219. NTSTATUS - Final status of the call
  5220. --*/
  5221. {
  5222. NTSTATUS status;
  5223. tCOMMON_HEADER UNALIGNED *pPgmHeader;
  5224. tBASIC_SPM_PACKET_HEADER UNALIGNED *pSpmPacket;
  5225. tCOMMON_SESSION_CONTEXT *pSession;
  5226. PLIST_ENTRY pEntry;
  5227. PGMLockHandle OldIrq, OldIrq1;
  5228. USHORT LocalSessionPort, PacketSessionPort;
  5229. tTSI TSI;
  5230. PVOID pFECBuffer;
  5231. UCHAR PacketType;
  5232. IP_PKTINFO *pPktInfo;
  5233. PIRP pLocalIrp = NULL;
  5234. PMDL pLocalMdl = NULL;
  5235. tRCV_COMPLETE_CONTEXT *pRcvBuffer = NULL;
  5236. ULONG XSum, BufferLength = 0;
  5237. IPV4Header *pIp = (IPV4Header *) pTsdu;
  5238. PTA_IP_ADDRESS pIpAddress = (PTA_IP_ADDRESS) pSourceAddress;
  5239. tADDRESS_CONTEXT *pAddress = (tADDRESS_CONTEXT *) pDgramEventContext;
  5240. *pBytesTaken = 0; // Initialize the Bytes Taken!
  5241. *ppIrp = NULL;
  5242. #ifdef DROP_DBG
  5243. //
  5244. // Drop OData packets only for now!
  5245. //
  5246. pPgmHeader = (tCOMMON_HEADER UNALIGNED *) (((PUCHAR)pIp) + (pIp->HeaderLength * 4));
  5247. PacketType = pPgmHeader->Type & 0x0f;
  5248. if ((PacketType == PACKET_TYPE_ODATA) &&
  5249. !(((tBASIC_DATA_PACKET_HEADER *) pPgmHeader)->CommonHeader.Options & PACKET_HEADER_OPTIONS_PARITY) &&
  5250. !(--DropCount))
  5251. {
  5252. ULONG SequenceNumber;
  5253. LARGE_INTEGER TimeValue;
  5254. KeQuerySystemTime (&TimeValue);
  5255. DropCount = MinDropInterval + ((TimeValue.LowTime >> 8) % (MaxDropInterval - MinDropInterval + 1));
  5256. /*
  5257. PgmCopyMemory (&SequenceNumber, &((tBASIC_DATA_PACKET_HEADER *) pPgmHeader)->DataSequenceNumber, sizeof (ULONG));
  5258. DbgPrint("TdiRcvDatagramHandler: Dropping packet, %s SeqNum = %d!\n",
  5259. (((tBASIC_DATA_PACKET_HEADER *) pPgmHeader)->CommonHeader.Options & PACKET_HEADER_OPTIONS_PARITY ? "PARITY" : "DATA"),
  5260. ntohl (SequenceNumber));
  5261. */
  5262. return (STATUS_DATA_NOT_ACCEPTED);
  5263. }
  5264. #endif // DROP_DBG
  5265. PgmLock (&PgmDynamicConfig, OldIrq);
  5266. if (BytesIndicated > PgmDynamicConfig.MaxMTU)
  5267. {
  5268. PgmDynamicConfig.MaxMTU = BytesIndicated;
  5269. }
  5270. if (!PGM_VERIFY_HANDLE (pAddress, PGM_VERIFY_ADDRESS))
  5271. {
  5272. PgmTrace (LogPath, ("TdiRcvDatagramHandler: " \
  5273. "Invalid Address handle=<%p>\n", pAddress));
  5274. PgmUnlock (&PgmDynamicConfig, OldIrq);
  5275. return (STATUS_DATA_NOT_ACCEPTED);
  5276. }
  5277. //
  5278. // Now, Reference the Address so that it cannot go away
  5279. // while we are processing it!
  5280. //
  5281. PGM_REFERENCE_ADDRESS (pAddress, REF_ADDRESS_TDI_RCV_HANDLER, FALSE);
  5282. PgmUnlock (&PgmDynamicConfig, OldIrq);
  5283. //
  5284. // If we do not have the complete datagram, then pass an Irp down to retrieve it
  5285. //
  5286. if ((BytesAvailable != BytesIndicated) &&
  5287. !(ReceiveDatagramFlags & TDI_RECEIVE_ENTIRE_MESSAGE))
  5288. {
  5289. ASSERT (BytesIndicated <= BytesAvailable);
  5290. //
  5291. // Build an irp to do the receive with and attach a buffer to it.
  5292. //
  5293. BufferLength = sizeof (tRCV_COMPLETE_CONTEXT) + BytesAvailable + SourceAddressLength;
  5294. BufferLength = ((BufferLength + 3)/sizeof(ULONG)) * sizeof(ULONG);
  5295. if ((pLocalIrp = IoAllocateIrp (pgPgmDevice->pPgmDeviceObject->StackSize, FALSE)) &&
  5296. (pRcvBuffer = PgmAllocMem (BufferLength, PGM_TAG('3'))) &&
  5297. (pLocalMdl = IoAllocateMdl (&pRcvBuffer->BufferData, BytesAvailable, FALSE, FALSE, NULL)))
  5298. {
  5299. pLocalIrp->MdlAddress = pLocalMdl;
  5300. MmBuildMdlForNonPagedPool (pLocalMdl); // Map the pages in memory...
  5301. TdiBuildReceiveDatagram (pLocalIrp,
  5302. pAddress->pDeviceObject,
  5303. pAddress->pFileObject,
  5304. ProcessReceiveCompletionRoutine,
  5305. pRcvBuffer,
  5306. pLocalMdl,
  5307. BytesAvailable,
  5308. NULL,
  5309. NULL,
  5310. 0); // (ULONG) TDI_RECEIVE_NORMAL) ?
  5311. // make the next stack location the current one. Normally IoCallDriver
  5312. // would do this but we are not going through IoCallDriver here, since the
  5313. // Irp is just passed back with RcvIndication.
  5314. //
  5315. ASSERT (pLocalIrp->CurrentLocation > 1);
  5316. IoSetNextIrpStackLocation (pLocalIrp);
  5317. //
  5318. // save the source address and length in the buffer for later
  5319. // indication back to this routine.
  5320. //
  5321. pRcvBuffer->pAddress = pAddress;
  5322. pRcvBuffer->SrcAddressLength = SourceAddressLength;
  5323. pRcvBuffer->pSrcAddress = (PVOID) ((PUCHAR)&pRcvBuffer->BufferData + BytesAvailable);
  5324. PgmCopyMemory (pRcvBuffer->pSrcAddress, pSourceAddress, SourceAddressLength);
  5325. *pBytesTaken = 0;
  5326. *ppIrp = pLocalIrp;
  5327. status = STATUS_MORE_PROCESSING_REQUIRED;
  5328. PgmTrace (LogAllFuncs, ("TdiRcvDatagramHandler: " \
  5329. "BytesI=<%d>, BytesA=<%d>, Flags=<%x>, pIrp=<%p>\n",
  5330. BytesIndicated, BytesAvailable, ReceiveDatagramFlags, pLocalIrp));
  5331. }
  5332. else
  5333. {
  5334. // Cleanup on failure:
  5335. if (pLocalIrp)
  5336. {
  5337. IoFreeIrp (pLocalIrp);
  5338. }
  5339. if (pRcvBuffer)
  5340. {
  5341. PgmFreeMem (pRcvBuffer);
  5342. }
  5343. status = STATUS_DATA_NOT_ACCEPTED;
  5344. PgmTrace (LogError, ("TdiRcvDatagramHandler: ERROR -- " \
  5345. "INSUFFICIENT_RESOURCES, BuffLen=<%d>, pIrp=<%p>, pBuff=<%p>\n",
  5346. BufferLength, pLocalIrp, pRcvBuffer));
  5347. }
  5348. PGM_DEREFERENCE_ADDRESS (pAddress, REF_ADDRESS_TDI_RCV_HANDLER);
  5349. return (status);
  5350. }
  5351. //
  5352. // Now that we have the complete datagram, verify that it is valid
  5353. // First line of defense against bad packets.
  5354. //
  5355. if ((BytesIndicated < (sizeof(IPV4Header) + sizeof(tCOMMON_HEADER))) ||
  5356. (pIp->Version != 4) ||
  5357. (BytesIndicated < ((pIp->HeaderLength<<2) + sizeof(tCOMMON_HEADER))))
  5358. {
  5359. //
  5360. // Need to get at least our header from transport!
  5361. //
  5362. PgmTrace (LogError, ("TdiRcvDatagramHandler: ERROR -- " \
  5363. "IPver=<%d>, BytesI=<%d>, Min=<%d>, AddrType=<%d>\n",
  5364. pIp->Version, BytesIndicated, (sizeof(IPV4Header) + sizeof(tBASIC_DATA_PACKET_HEADER)),
  5365. pIpAddress->Address[0].AddressType));
  5366. ASSERT (0);
  5367. PGM_DEREFERENCE_ADDRESS (pAddress, REF_ADDRESS_TDI_RCV_HANDLER);
  5368. return (STATUS_DATA_NOT_ACCEPTED);
  5369. }
  5370. pPgmHeader = (tCOMMON_HEADER UNALIGNED *) (((PUCHAR)pIp) + (pIp->HeaderLength * 4));
  5371. BytesIndicated -= (pIp->HeaderLength * 4);
  5372. BytesAvailable -= (pIp->HeaderLength * 4);
  5373. //
  5374. // Now, Verify Checksum
  5375. //
  5376. if ((XSum = tcpxsum (0, (CHAR *) pPgmHeader, BytesIndicated)) != 0xffff)
  5377. {
  5378. //
  5379. // Need to get at least our header from transport!
  5380. //
  5381. PgmTrace (LogError, ("TdiRcvDatagramHandler: ERROR -- " \
  5382. "Bad Checksum on Pgm Packet (type=<%x>)! XSum=<%x> -- Rejecting packet\n",
  5383. pPgmHeader->Type, XSum));
  5384. PGM_DEREFERENCE_ADDRESS (pAddress, REF_ADDRESS_TDI_RCV_HANDLER);
  5385. return (STATUS_DATA_NOT_ACCEPTED);
  5386. }
  5387. //
  5388. // Now, determine the TSI, i.e. GSI (from packet) + TSIPort (below)
  5389. //
  5390. PacketType = pPgmHeader->Type & 0x0f;
  5391. if ((PacketType == PACKET_TYPE_NAK) ||
  5392. (PacketType == PACKET_TYPE_NNAK) ||
  5393. (PacketType == PACKET_TYPE_SPMR) ||
  5394. (PacketType == PACKET_TYPE_POLR))
  5395. {
  5396. PgmCopyMemory (&PacketSessionPort, &pPgmHeader->SrcPort, sizeof (USHORT));
  5397. PgmCopyMemory (&TSI.hPort, &pPgmHeader->DestPort, sizeof (USHORT));
  5398. }
  5399. else
  5400. {
  5401. PgmCopyMemory (&PacketSessionPort, &pPgmHeader->DestPort, sizeof (USHORT));
  5402. PgmCopyMemory (&TSI.hPort, &pPgmHeader->SrcPort, sizeof (USHORT));
  5403. }
  5404. PacketSessionPort = ntohs (PacketSessionPort);
  5405. TSI.hPort = ntohs (TSI.hPort);
  5406. PgmCopyMemory (&TSI.GSI, &pPgmHeader->gSourceId, SOURCE_ID_LENGTH);
  5407. //
  5408. // If this packet is for a different session port, drop it
  5409. //
  5410. if (pAddress->ReceiverMCastAddr)
  5411. {
  5412. LocalSessionPort = pAddress->ReceiverMCastPort;
  5413. }
  5414. else
  5415. {
  5416. LocalSessionPort = pAddress->SenderMCastPort;
  5417. }
  5418. if (LocalSessionPort != PacketSessionPort)
  5419. {
  5420. PgmTrace (LogPath, ("TdiRcvDatagramHandler: " \
  5421. "Dropping packet for different Session port, <%x>!=<%x>!\n", LocalSessionPort, PacketSessionPort));
  5422. PGM_DEREFERENCE_ADDRESS (pAddress, REF_ADDRESS_TDI_RCV_HANDLER);
  5423. return (STATUS_DATA_NOT_ACCEPTED);
  5424. }
  5425. //
  5426. // Now check if this receive is for an active connection
  5427. //
  5428. pSession = NULL;
  5429. PgmLock (pAddress, OldIrq); // So that the list cannot change!
  5430. pEntry = &pAddress->AssociatedConnections;
  5431. while ((pEntry = pEntry->Flink) != &pAddress->AssociatedConnections)
  5432. {
  5433. pSession = CONTAINING_RECORD (pEntry, tCOMMON_SESSION_CONTEXT, Linkage);
  5434. PgmLock (pSession, OldIrq1);
  5435. if ((PGM_VERIFY_HANDLE2 (pSession, PGM_VERIFY_SESSION_RECEIVE, PGM_VERIFY_SESSION_SEND)) &&
  5436. (pSession->TSI.ULLTSI == TSI.ULLTSI) &&
  5437. !(pSession->SessionFlags & (PGM_SESSION_CLIENT_DISCONNECTED | PGM_SESSION_TERMINATED_ABORT)))
  5438. {
  5439. if (pSession->pReceiver)
  5440. {
  5441. PGM_REFERENCE_SESSION_RECEIVE (pSession, REF_SESSION_TDI_RCV_HANDLER, TRUE);
  5442. if ((pSession->FECOptions) &&
  5443. (BytesIndicated > pSession->MaxMTULength))
  5444. {
  5445. if (pFECBuffer = PgmAllocMem (((BytesIndicated+sizeof(tPOST_PACKET_FEC_CONTEXT)-sizeof(USHORT))
  5446. *pSession->FECGroupSize*2), PGM_TAG('3')))
  5447. {
  5448. ASSERT (pSession->pFECBuffer);
  5449. PgmFreeMem (pSession->pFECBuffer);
  5450. pSession->pFECBuffer = pFECBuffer;
  5451. pSession->MaxMTULength = (USHORT) BytesIndicated;
  5452. pSession->MaxFECPacketLength = pSession->MaxMTULength +
  5453. sizeof (tPOST_PACKET_FEC_CONTEXT) - sizeof (USHORT);
  5454. }
  5455. else
  5456. {
  5457. PgmTrace (LogError, ("TdiRcvDatagramHandler: ERROR -- " \
  5458. "STATUS_INSUFFICIENT_RESOURCES -- pFECBuffer=<%d> bytes\n",
  5459. (BytesIndicated+sizeof(tPOST_PACKET_FEC_CONTEXT)-sizeof(USHORT))));
  5460. pSession = NULL;
  5461. pSession->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  5462. }
  5463. }
  5464. PgmUnlock (pSession, OldIrq1);
  5465. break;
  5466. }
  5467. ASSERT (pSession->pSender);
  5468. PGM_REFERENCE_SESSION_SEND (pSession, REF_SESSION_TDI_RCV_HANDLER, TRUE);
  5469. PgmUnlock (pSession, OldIrq1);
  5470. break;
  5471. }
  5472. PgmUnlock (pSession, OldIrq1);
  5473. pSession = NULL;
  5474. }
  5475. PgmUnlock (pAddress, OldIrq);
  5476. if (!pSession)
  5477. {
  5478. // We should drop this packet because we received this either because
  5479. // we may have a loopback session, or we have a listen but this
  5480. // is not an OData packet
  5481. if ((pIpAddress->TAAddressCount != 1) ||
  5482. (pIpAddress->Address[0].AddressLength != TDI_ADDRESS_LENGTH_IP) ||
  5483. (pIpAddress->Address[0].AddressType != TDI_ADDRESS_TYPE_IP))
  5484. {
  5485. PgmTrace (LogError, ("TdiRcvDatagramHandler: ERROR -- " \
  5486. "[1] Bad AddrType=<%d>\n", pIpAddress->Address[0].AddressType));
  5487. PGM_DEREFERENCE_ADDRESS (pAddress, REF_ADDRESS_TDI_RCV_HANDLER);
  5488. return (STATUS_DATA_NOT_ACCEPTED);
  5489. }
  5490. status = STATUS_DATA_NOT_ACCEPTED;
  5491. //
  5492. // New sessions will be accepted only if we are a receiver
  5493. // Also, new sessions will always be initiated only with an OData packet
  5494. // Also, verify that the client has posted a connect handler!
  5495. //
  5496. if ((pAddress->ReceiverMCastAddr) &&
  5497. (pAddress->ConEvContext))
  5498. {
  5499. if ((PacketType == PACKET_TYPE_ODATA) &&
  5500. (!(pPgmHeader->Options & PACKET_HEADER_OPTIONS_PARITY)))
  5501. {
  5502. //
  5503. // This is a new incoming connection, so see if the
  5504. // client accepts it.
  5505. //
  5506. status = PgmNewInboundConnection (pAddress,
  5507. SourceAddressLength,
  5508. pIpAddress,
  5509. ReceiveDatagramFlags,
  5510. (tBASIC_DATA_PACKET_HEADER UNALIGNED *) pPgmHeader,
  5511. BytesIndicated,
  5512. &pSession);
  5513. if (!NT_SUCCESS (status))
  5514. {
  5515. PgmTrace (LogAllFuncs, ("TdiRcvDatagramHandler: " \
  5516. "pAddress=<%p> FAILed to accept new connection, PacketType=<%x>, status=<%x>\n",
  5517. pAddress, PacketType, status));
  5518. }
  5519. }
  5520. else if ((PacketType == PACKET_TYPE_SPM) &&
  5521. (BytesIndicated >= sizeof(tBASIC_SPM_PACKET_HEADER)))
  5522. {
  5523. ProcessSpmPacket (pAddress,
  5524. NULL, // This will signify that we do not have a connection yet
  5525. BytesIndicated,
  5526. (tBASIC_SPM_PACKET_HEADER UNALIGNED *) pPgmHeader);
  5527. }
  5528. }
  5529. if (!NT_SUCCESS (status))
  5530. {
  5531. PGM_DEREFERENCE_ADDRESS (pAddress, REF_ADDRESS_TDI_RCV_HANDLER);
  5532. return (STATUS_DATA_NOT_ACCEPTED);
  5533. }
  5534. }
  5535. #if(WINVER > 0x0500)
  5536. if ((pAddress->Flags & PGM_ADDRESS_WAITING_FOR_NEW_INTERFACE) &&
  5537. (pAddress->Flags & PGM_ADDRESS_LISTEN_ON_ALL_INTERFACES) &&
  5538. (ReceiveDatagramFlags & TDI_RECEIVE_CONTROL_INFO))
  5539. {
  5540. //
  5541. // See if we can Enqueue the stop listening request
  5542. //
  5543. PgmLock (&PgmDynamicConfig, OldIrq);
  5544. PgmLock (pAddress, OldIrq1);
  5545. pPktInfo = (IP_PKTINFO*) TDI_CMSG_DATA (pControlData);
  5546. PGM_REFERENCE_ADDRESS (pAddress, REF_ADDRESS_STOP_LISTENING, TRUE);
  5547. if (STATUS_SUCCESS == PgmQueueForDelayedExecution (StopListeningOnAllInterfacesExcept,
  5548. pAddress,
  5549. ULongToPtr (pPktInfo->ipi_ifindex),
  5550. NULL,
  5551. TRUE))
  5552. {
  5553. pAddress->Flags &= ~PGM_ADDRESS_WAITING_FOR_NEW_INTERFACE;
  5554. PgmUnlock (pAddress, OldIrq1);
  5555. PgmUnlock (&PgmDynamicConfig, OldIrq);
  5556. }
  5557. else
  5558. {
  5559. PgmUnlock (pAddress, OldIrq1);
  5560. PgmUnlock (&PgmDynamicConfig, OldIrq);
  5561. PGM_DEREFERENCE_ADDRESS (pAddress, REF_ADDRESS_STOP_LISTENING);
  5562. }
  5563. }
  5564. #endif // WINVER
  5565. //
  5566. // Now, handle the packet appropriately
  5567. //
  5568. // Use fast Path for Data packets!
  5569. //
  5570. if ((PacketType == PACKET_TYPE_ODATA) ||
  5571. (PacketType == PACKET_TYPE_RDATA))
  5572. {
  5573. if (pAddress->ReceiverMCastAddr)
  5574. {
  5575. if (PacketType == PACKET_TYPE_ODATA)
  5576. {
  5577. pSession->pReceiver->NumODataPacketsReceived++;
  5578. }
  5579. else
  5580. {
  5581. pSession->pReceiver->NumRDataPacketsReceived++;
  5582. }
  5583. pSession->pReceiver->LastSessionTickCount = PgmDynamicConfig.ReceiversTimerTickCount;
  5584. pSession->TotalBytes += BytesIndicated;
  5585. pSession->TotalPacketsReceived++;
  5586. status = ProcessDataPacket (pAddress,
  5587. pSession,
  5588. BytesIndicated,
  5589. (tBASIC_DATA_PACKET_HEADER UNALIGNED *) pPgmHeader,
  5590. PacketType);
  5591. }
  5592. else
  5593. {
  5594. PgmTrace (LogError, ("TdiRcvDatagramHandler: ERROR -- " \
  5595. "Received Data packet, not on Receiver session! pSession=<%p>\n", pSession));
  5596. status = STATUS_DATA_NOT_ACCEPTED;
  5597. }
  5598. }
  5599. else
  5600. {
  5601. status = PgmProcessIncomingPacket (pAddress,
  5602. pSession,
  5603. SourceAddressLength,
  5604. pIpAddress,
  5605. BytesIndicated,
  5606. pPgmHeader,
  5607. PacketType);
  5608. }
  5609. PgmTrace (LogAllFuncs, ("TdiRcvDatagramHandler: " \
  5610. "PacketType=<%x> for pSession=<%p> BytesI=<%d>, BytesA=<%d>, status=<%x>\n",
  5611. PacketType, pSession, BytesIndicated, BytesAvailable, status));
  5612. if (pSession->pSender)
  5613. {
  5614. PGM_DEREFERENCE_SESSION_SEND (pSession, REF_SESSION_TDI_RCV_HANDLER);
  5615. }
  5616. else
  5617. {
  5618. ASSERT (pSession->pReceiver);
  5619. PGM_DEREFERENCE_SESSION_RECEIVE (pSession, REF_SESSION_TDI_RCV_HANDLER);
  5620. }
  5621. PGM_DEREFERENCE_ADDRESS (pAddress, REF_ADDRESS_TDI_RCV_HANDLER);
  5622. //
  5623. // Only acceptable return codes are STATUS_SUCCESS and STATUS_DATA_NOT_ACCPETED
  5624. // (STATUS_MORE_PROCESSING_REQUIRED is not valid here because we have no Irp).
  5625. //
  5626. if (STATUS_SUCCESS != status)
  5627. {
  5628. status = STATUS_DATA_NOT_ACCEPTED;
  5629. }
  5630. return (status);
  5631. }
  5632. //----------------------------------------------------------------------------
  5633. VOID
  5634. PgmCancelReceiveIrp(
  5635. IN PDEVICE_OBJECT DeviceContext,
  5636. IN PIRP pIrp
  5637. )
  5638. /*++
  5639. Routine Description:
  5640. This routine handles the cancelling of a Receive Irp. It must release the
  5641. cancel spin lock before returning re: IoCancelIrp().
  5642. Arguments:
  5643. Return Value:
  5644. None
  5645. --*/
  5646. {
  5647. PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation (pIrp);
  5648. tRECEIVE_SESSION *pReceive = (tRECEIVE_SESSION *) pIrpSp->FileObject->FsContext;
  5649. PGMLockHandle OldIrq;
  5650. PLIST_ENTRY pEntry;
  5651. if (!PGM_VERIFY_HANDLE (pReceive, PGM_VERIFY_SESSION_RECEIVE))
  5652. {
  5653. IoReleaseCancelSpinLock (pIrp->CancelIrql);
  5654. PgmTrace (LogError, ("PgmCancelReceiveIrp: ERROR -- " \
  5655. "pIrp=<%p> pReceive=<%p>, pAddress=<%p>\n",
  5656. pIrp, pReceive, (pReceive ? pReceive->pReceiver->pAddress : NULL)));
  5657. return;
  5658. }
  5659. PgmLock (pReceive, OldIrq);
  5660. //
  5661. // See if we are actively receiving
  5662. //
  5663. if (pIrp == pReceive->pReceiver->pIrpReceive)
  5664. {
  5665. pIrp->IoStatus.Information = pReceive->pReceiver->BytesInMdl;
  5666. pIrp->IoStatus.Status = STATUS_CANCELLED;
  5667. pReceive->pReceiver->BytesInMdl = pReceive->pReceiver->TotalBytesInMdl = 0;
  5668. pReceive->pReceiver->pIrpReceive = NULL;
  5669. PgmUnlock (pReceive, OldIrq);
  5670. IoReleaseCancelSpinLock (pIrp->CancelIrql);
  5671. IoCompleteRequest (pIrp,IO_NETWORK_INCREMENT);
  5672. return;
  5673. }
  5674. //
  5675. // We are not actively receiving, so see if this Irp is
  5676. // in our Irps list
  5677. //
  5678. pEntry = &pReceive->pReceiver->ReceiveIrpsList;
  5679. while ((pEntry = pEntry->Flink) != &pReceive->pReceiver->ReceiveIrpsList)
  5680. {
  5681. if (pEntry == &pIrp->Tail.Overlay.ListEntry)
  5682. {
  5683. RemoveEntryList (pEntry);
  5684. pIrp->IoStatus.Status = STATUS_CANCELLED;
  5685. pIrp->IoStatus.Information = 0;
  5686. PgmUnlock (pReceive, OldIrq);
  5687. IoReleaseCancelSpinLock (pIrp->CancelIrql);
  5688. IoCompleteRequest(pIrp,IO_NETWORK_INCREMENT);
  5689. return;
  5690. }
  5691. }
  5692. //
  5693. // If we have reached here, then the Irp must already
  5694. // be in the process of being completed!
  5695. //
  5696. PgmUnlock (pReceive, OldIrq);
  5697. IoReleaseCancelSpinLock (pIrp->CancelIrql);
  5698. }
  5699. //----------------------------------------------------------------------------
  5700. NTSTATUS
  5701. PgmReceive(
  5702. IN tPGM_DEVICE *pPgmDevice,
  5703. IN PIRP pIrp,
  5704. IN PIO_STACK_LOCATION pIrpSp
  5705. )
  5706. /*++
  5707. Routine Description:
  5708. This routine is called via dispatch by the client to post a Receive pIrp
  5709. Arguments:
  5710. IN pPgmDevice -- Pgm's Device object context
  5711. IN pIrp -- Client's request Irp
  5712. IN pIrpSp -- current request's stack pointer
  5713. Return Value:
  5714. NTSTATUS - Final status of the request
  5715. --*/
  5716. {
  5717. NTSTATUS status;
  5718. PGMLockHandle OldIrq, OldIrq1, OldIrq2, OldIrq3;
  5719. tADDRESS_CONTEXT *pAddress = NULL;
  5720. tRECEIVE_SESSION *pReceive = (tRECEIVE_SESSION *) pIrpSp->FileObject->FsContext;
  5721. PTDI_REQUEST_KERNEL_RECEIVE pClientParams = (PTDI_REQUEST_KERNEL_RECEIVE) &pIrpSp->Parameters;
  5722. PgmLock (&PgmDynamicConfig, OldIrq);
  5723. IoAcquireCancelSpinLock (&OldIrq1);
  5724. //
  5725. // Verify that the connection is valid and is associated with an address
  5726. //
  5727. if ((!PGM_VERIFY_HANDLE (pReceive, PGM_VERIFY_SESSION_RECEIVE)) ||
  5728. (!(pAddress = pReceive->pAssociatedAddress)) ||
  5729. (!PGM_VERIFY_HANDLE (pAddress, PGM_VERIFY_ADDRESS)))
  5730. {
  5731. PgmTrace (LogError, ("PgmReceive: ERROR -- " \
  5732. "Invalid Handles pReceive=<%p>, pAddress=<%p>\n", pReceive, pAddress));
  5733. status = STATUS_INVALID_HANDLE;
  5734. }
  5735. else if (pReceive->SessionFlags & PGM_SESSION_CLIENT_DISCONNECTED)
  5736. {
  5737. PgmTrace (LogPath, ("PgmReceive: " \
  5738. "Receive Irp=<%p> was posted after session has been Disconnected, pReceive=<%p>, pAddress=<%p>\n",
  5739. pIrp, pReceive, pAddress));
  5740. status = STATUS_CANCELLED;
  5741. }
  5742. else if (!pClientParams->ReceiveLength)
  5743. {
  5744. ASSERT (0);
  5745. PgmTrace (LogError, ("PgmReceive: ERROR -- " \
  5746. "Invalid Handles pReceive=<%p>, pAddress=<%p>\n", pReceive, pAddress));
  5747. status = STATUS_UNSUCCESSFUL;
  5748. }
  5749. else
  5750. {
  5751. status = STATUS_SUCCESS;
  5752. }
  5753. if (!NT_SUCCESS (status))
  5754. {
  5755. IoReleaseCancelSpinLock (OldIrq1);
  5756. PgmUnlock (&PgmDynamicConfig, OldIrq);
  5757. pIrp->IoStatus.Information = 0;
  5758. return (status);
  5759. }
  5760. PgmLock (pAddress, OldIrq2);
  5761. PgmLock (pReceive, OldIrq3);
  5762. if (!NT_SUCCESS (PgmCheckSetCancelRoutine (pIrp, PgmCancelReceiveIrp, TRUE)))
  5763. {
  5764. PgmUnlock (pReceive, OldIrq3);
  5765. PgmUnlock (pAddress, OldIrq2);
  5766. IoReleaseCancelSpinLock (OldIrq1);
  5767. PgmUnlock (&PgmDynamicConfig, OldIrq);
  5768. PgmTrace (LogError, ("PgmReceive: ERROR -- " \
  5769. "Could not set Cancel routine on receive Irp=<%p>, pReceive=<%p>, pAddress=<%p>\n",
  5770. pIrp, pReceive, pAddress));
  5771. return (STATUS_CANCELLED);
  5772. }
  5773. IoReleaseCancelSpinLock (OldIrq3);
  5774. PGM_REFERENCE_ADDRESS (pAddress, REF_ADDRESS_CLIENT_RECEIVE, TRUE);
  5775. PGM_REFERENCE_SESSION_RECEIVE (pReceive, REF_SESSION_CLIENT_RECEIVE, TRUE);
  5776. PgmUnlock (&PgmDynamicConfig, OldIrq2);
  5777. PgmTrace (LogAllFuncs, ("PgmReceive: " \
  5778. "Client posted ReceiveIrp = <%p> for pReceive=<%p>\n", pIrp, pReceive));
  5779. InsertTailList (&pReceive->pReceiver->ReceiveIrpsList, &pIrp->Tail.Overlay.ListEntry);
  5780. pReceive->SessionFlags &= ~PGM_SESSION_WAIT_FOR_RECEIVE_IRP;
  5781. //
  5782. // Now, try to indicate any data which may still be pending
  5783. //
  5784. // if (!(pAddress->Flags & PGM_ADDRESS_HIGH_SPEED_OPTIMIZED))
  5785. {
  5786. status = CheckIndicatePendedData (pAddress, pReceive, &OldIrq, &OldIrq1);
  5787. }
  5788. PgmUnlock (pReceive, OldIrq1);
  5789. PgmUnlock (pAddress, OldIrq);
  5790. PGM_DEREFERENCE_SESSION_RECEIVE (pReceive, REF_SESSION_CLIENT_RECEIVE);
  5791. PGM_DEREFERENCE_ADDRESS (pAddress, REF_ADDRESS_CLIENT_RECEIVE);
  5792. return (STATUS_PENDING);
  5793. }
  5794. //----------------------------------------------------------------------------