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

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