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.

1026 lines
25 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. Indicate.c
  5. Abstract:
  6. This file contains procedures to handle indications from the
  7. WAN Miniport drivers.
  8. Author:
  9. Tony Bell (TonyBe) June 06, 1995
  10. Environment:
  11. Kernel Mode
  12. Revision History:
  13. TonyBe 06/06/95 Created
  14. --*/
  15. #include "wan.h"
  16. #define __FILE_SIG__ INDICATE_FILESIG
  17. VOID
  18. NdisWanLineUpIndication(
  19. POPENCB OpenCB,
  20. PUCHAR Buffer,
  21. ULONG BufferSize
  22. )
  23. /*++
  24. Routine Name:
  25. NdisWanLineupIndication
  26. Routine Description:
  27. This routine is called when a WAN Miniport driver has a new connetion
  28. become active or when the status of an active connection changes. If
  29. this is a new connection the routine creates a LinkCB, and a BundleCB
  30. for the new connection. If this is for an already active connetion the
  31. connection info is updated.
  32. Arguments:
  33. Return Values:
  34. None
  35. --*/
  36. {
  37. PLINKCB LinkCB = NULL;
  38. PBUNDLECB BundleCB = NULL;
  39. NDIS_STATUS Status;
  40. PNDIS_MAC_LINE_UP LineUpInfo = (PNDIS_MAC_LINE_UP)Buffer;
  41. BOOLEAN EmptyList;
  42. if (BufferSize < sizeof(NDIS_MAC_LINE_UP)) {
  43. return;
  44. }
  45. //
  46. // Is this for a new connetion?
  47. //
  48. if (LineUpInfo->NdisLinkContext == NULL) {
  49. //
  50. // This is a new connection!
  51. //
  52. //
  53. // Get a linkcb
  54. //
  55. LinkCB = NdisWanAllocateLinkCB(OpenCB, LineUpInfo->SendWindow);
  56. if (LinkCB == NULL) {
  57. //
  58. // Error getting LinkCB!
  59. //
  60. return;
  61. }
  62. LinkCB->NdisLinkHandle = LineUpInfo->NdisLinkHandle;
  63. LinkCB->ConnectionWrapperID = LineUpInfo->ConnectionWrapperID;
  64. //
  65. // Get a bundlecb
  66. //
  67. BundleCB = NdisWanAllocateBundleCB();
  68. if (BundleCB == NULL) {
  69. //
  70. // Error getting BundleCB!
  71. //
  72. NdisWanFreeLinkCB(LinkCB);
  73. return;
  74. }
  75. AcquireBundleLock(BundleCB);
  76. //
  77. // Copy LineUpInfo to Link LineUpInfo
  78. //
  79. /* NdisMoveMemory((PUCHAR)&LinkCB->LineUpInfo,
  80. (PUCHAR)LineUpInfo,
  81. sizeof(NDIS_MAC_LINE_UP));
  82. */
  83. //
  84. // If a linkspeed is not reported we are
  85. // assuming 28.8K as the slowest...
  86. //
  87. if (LineUpInfo->LinkSpeed == 0) {
  88. LineUpInfo->LinkSpeed = 288;
  89. }
  90. //
  91. // Take 1/100bps to Bps without rolling over
  92. //
  93. {
  94. ULONGLONG temp;
  95. ULONG value;
  96. temp = LineUpInfo->LinkSpeed;
  97. temp *= 100;
  98. temp /= 8;
  99. //
  100. // Check for rollover
  101. //
  102. value = (ULONG)temp;
  103. if (value == 0) {
  104. value = 0xFFFFFFFF/8;
  105. }
  106. LinkCB->SFlowSpec.TokenRate =
  107. LinkCB->SFlowSpec.PeakBandwidth =
  108. LinkCB->RFlowSpec.TokenRate =
  109. LinkCB->RFlowSpec.PeakBandwidth = (ULONG)value;
  110. }
  111. LinkCB->SFlowSpec.MaxSduSize =
  112. (OpenCB->WanInfo.MaxFrameSize > glMaxMTU) ?
  113. glMaxMTU : OpenCB->WanInfo.MaxFrameSize;
  114. LinkCB->RFlowSpec.MaxSduSize = glMRRU;
  115. //
  116. // Add LinkCB to BundleCB
  117. //
  118. AddLinkToBundle(BundleCB, LinkCB);
  119. ReleaseBundleLock(BundleCB);
  120. //
  121. // Place BundleCB in active connection table
  122. //
  123. if (NULL == InsertBundleInConnectionTable(BundleCB)) {
  124. //
  125. // Error inserting link in ConnectionTable
  126. //
  127. RemoveLinkFromBundle(BundleCB, LinkCB, FALSE);
  128. NdisWanFreeLinkCB(LinkCB);
  129. NdisWanFreeBundleCB(BundleCB);
  130. return;
  131. }
  132. //
  133. // Place LinkCB in active connection table
  134. //
  135. if (NULL == InsertLinkInConnectionTable(LinkCB)) {
  136. //
  137. // Error inserting bundle in connectiontable
  138. //
  139. RemoveLinkFromBundle(BundleCB, LinkCB, FALSE);
  140. NdisWanFreeLinkCB(LinkCB);
  141. NdisWanFreeBundleCB(BundleCB);
  142. return;
  143. }
  144. LineUpInfo->NdisLinkContext = LinkCB->hLinkHandle;
  145. } else {
  146. do {
  147. //
  148. // This is an already existing connetion
  149. //
  150. if (!AreLinkAndBundleValid(LineUpInfo->NdisLinkContext,
  151. TRUE,
  152. &LinkCB,
  153. &BundleCB)) {
  154. #if DBG
  155. DbgPrint("NDISWAN: LineUp on unknown LinkContext %x\n",
  156. LineUpInfo->NdisLinkContext);
  157. DbgBreakPoint();
  158. #endif
  159. break;
  160. }
  161. AcquireBundleLock(BundleCB);
  162. if (LineUpInfo->LinkSpeed == 0) {
  163. LineUpInfo->LinkSpeed = 288;
  164. }
  165. //
  166. // Take 1/100bps to Bps
  167. //
  168. {
  169. ULONGLONG temp;
  170. temp = LineUpInfo->LinkSpeed;
  171. temp *= 100;
  172. temp /= 8;
  173. LinkCB->SFlowSpec.TokenRate =
  174. LinkCB->SFlowSpec.PeakBandwidth =
  175. LinkCB->RFlowSpec.TokenRate =
  176. LinkCB->RFlowSpec.PeakBandwidth = (ULONG)temp;
  177. }
  178. LinkCB->SendWindow = (LineUpInfo->SendWindow > OpenCB->WanInfo.MaxTransmit ||
  179. LineUpInfo->SendWindow == 0) ?
  180. OpenCB->WanInfo.MaxTransmit : LineUpInfo->SendWindow;
  181. //
  182. // If the new sendwindow is set smaller then the
  183. // current # of outstanding frames then we have to
  184. // close the sendwindow for the link and reduce the
  185. // number of sending links that the bundle sees.
  186. //
  187. // If the new sendwindow is set larger then the
  188. // current # of outstanding frames and the sendwindow
  189. // is currently closed, we need to open the sendwindow
  190. // and increase the number of sending links that the
  191. // bundle sees.
  192. //
  193. if (LinkCB->LinkActive) {
  194. if (LinkCB->SendWindow <= LinkCB->OutstandingFrames) {
  195. if (LinkCB->SendWindowOpen) {
  196. LinkCB->SendWindowOpen = FALSE;
  197. BundleCB->SendingLinks -= 1;
  198. }
  199. } else if (!LinkCB->SendWindowOpen) {
  200. LinkCB->SendWindowOpen = TRUE;
  201. BundleCB->SendingLinks += 1;
  202. }
  203. }
  204. //
  205. // Update BundleCB info
  206. //
  207. UpdateBundleInfo(BundleCB);
  208. //
  209. // Deref's for the ref's applied when we mapped the
  210. // context into the control blocks
  211. //
  212. DEREF_BUNDLECB_LOCKED(BundleCB);
  213. DEREF_LINKCB(LinkCB);
  214. } while ( 0 );
  215. }
  216. }
  217. VOID
  218. NdisWanLineDownIndication(
  219. POPENCB OpenCB,
  220. PUCHAR Buffer,
  221. ULONG BufferSize
  222. )
  223. /*++
  224. Routine Name:
  225. Routine Description:
  226. Arguments:
  227. Return Values:
  228. --*/
  229. {
  230. PNDIS_MAC_LINE_DOWN LineDownInfo = (PNDIS_MAC_LINE_DOWN)Buffer;
  231. PLINKCB LinkCB;
  232. PBUNDLECB BundleCB;
  233. PRECV_DESC RecvDesc;
  234. ULONG i;
  235. if (!AreLinkAndBundleValid(LineDownInfo->NdisLinkContext,
  236. TRUE,
  237. &LinkCB,
  238. &BundleCB)) {
  239. #if DBG
  240. DbgPrint("NDISWAN: LineDown on unknown LinkContext %x\n",
  241. LineDownInfo->NdisLinkContext);
  242. DbgBreakPoint();
  243. #endif
  244. return;
  245. }
  246. //
  247. // Link is now going down
  248. //
  249. NdisAcquireSpinLock(&LinkCB->Lock);
  250. LinkCB->State = LINK_GOING_DOWN;
  251. //
  252. // Deref for the ref applied in AreLinkAndBundleValid. We don't
  253. // have to go through the full deref code as we know that the
  254. // ref applied at lineup will hold the block around.
  255. //
  256. LinkCB->RefCount--;
  257. NdisReleaseSpinLock(&LinkCB->Lock);
  258. NdisAcquireSpinLock(&IoRecvList.Lock);
  259. RecvDesc = (PRECV_DESC)IoRecvList.DescList.Flink;
  260. while ((PVOID)RecvDesc != (PVOID)&IoRecvList.DescList) {
  261. PRECV_DESC Next;
  262. Next = (PRECV_DESC)RecvDesc->Linkage.Flink;
  263. if (RecvDesc->LinkCB == LinkCB) {
  264. RemoveEntryList(&RecvDesc->Linkage);
  265. LinkCB->RecvDescCount--;
  266. IoRecvList.ulDescCount--;
  267. NdisWanFreeRecvDesc(RecvDesc);
  268. }
  269. RecvDesc = Next;
  270. }
  271. NdisReleaseSpinLock(&IoRecvList.Lock);
  272. //
  273. // Flush the Bundle's fragment send queues that
  274. // have sends pending on this link
  275. //
  276. AcquireBundleLock(BundleCB);
  277. for (i = 0; i < MAX_MCML; i++) {
  278. PSEND_DESC SendDesc;
  279. PSEND_FRAG_INFO FragInfo;
  280. FragInfo = &BundleCB->SendFragInfo[i];
  281. SendDesc = (PSEND_DESC)FragInfo->FragQueue.Flink;
  282. while ((PVOID)SendDesc != (PVOID)&FragInfo->FragQueue) {
  283. if (SendDesc->LinkCB == LinkCB) {
  284. PSEND_DESC NextSendDesc;
  285. NextSendDesc = (PSEND_DESC)SendDesc->Linkage.Flink;
  286. RemoveEntryList(&SendDesc->Linkage);
  287. FragInfo->FragQueueDepth--;
  288. (*LinkCB->SendHandler)(SendDesc);
  289. SendDesc = NextSendDesc;
  290. } else {
  291. SendDesc = (PSEND_DESC)SendDesc->Linkage.Flink;
  292. }
  293. }
  294. }
  295. UpdateBundleInfo(BundleCB);
  296. ReleaseBundleLock(BundleCB);
  297. //
  298. // For the ref from the lineup
  299. //
  300. DEREF_LINKCB(LinkCB);
  301. //
  302. // Deref for the ref applied in AreLinkAndBundleValid
  303. //
  304. DEREF_BUNDLECB(BundleCB);
  305. }
  306. VOID
  307. NdisWanFragmentIndication(
  308. POPENCB OpenCB,
  309. PUCHAR Buffer,
  310. ULONG BufferSize
  311. )
  312. /*++
  313. Routine Name:
  314. Routine Description:
  315. Arguments:
  316. Return Values:
  317. --*/
  318. {
  319. ULONG Errors;
  320. PLINKCB LinkCB;
  321. PBUNDLECB BundleCB;
  322. PNDIS_MAC_FRAGMENT FragmentInfo =
  323. (PNDIS_MAC_FRAGMENT)Buffer;
  324. if (!AreLinkAndBundleValid(FragmentInfo->NdisLinkContext,
  325. TRUE,
  326. &LinkCB,
  327. &BundleCB)) {
  328. #if DBG
  329. DbgPrint("NDISWAN: Status indication after link has gone down LinkContext %x\n",
  330. FragmentInfo->NdisLinkContext);
  331. DbgBreakPoint();
  332. #endif
  333. return;
  334. }
  335. Errors = FragmentInfo->Errors;
  336. AcquireBundleLock(BundleCB);
  337. if (Errors & WAN_ERROR_CRC) {
  338. LinkCB->Stats.CRCErrors++;
  339. BundleCB->Stats.CRCErrors++;
  340. }
  341. if (Errors & WAN_ERROR_FRAMING) {
  342. LinkCB->Stats.FramingErrors++;
  343. BundleCB->Stats.FramingErrors++;
  344. }
  345. if (Errors & WAN_ERROR_HARDWAREOVERRUN) {
  346. LinkCB->Stats.SerialOverrunErrors++;
  347. BundleCB->Stats.SerialOverrunErrors++;
  348. }
  349. if (Errors & WAN_ERROR_BUFFEROVERRUN) {
  350. LinkCB->Stats.BufferOverrunErrors++;
  351. BundleCB->Stats.BufferOverrunErrors++;
  352. }
  353. if (Errors & WAN_ERROR_TIMEOUT) {
  354. LinkCB->Stats.TimeoutErrors++;
  355. BundleCB->Stats.TimeoutErrors++;
  356. }
  357. if (Errors & WAN_ERROR_ALIGNMENT) {
  358. LinkCB->Stats.AlignmentErrors++;
  359. BundleCB->Stats.AlignmentErrors++;
  360. }
  361. //
  362. // Deref's for the ref's applied in AreLinkAndBundleValid
  363. //
  364. DEREF_BUNDLECB_LOCKED(BundleCB);
  365. DEREF_LINKCB(LinkCB);
  366. }
  367. VOID
  368. NdisCoWanFragmentIndication(
  369. PLINKCB LinkCB,
  370. PBUNDLECB BundleCB,
  371. PUCHAR Buffer,
  372. ULONG BufferSize
  373. )
  374. /*++
  375. Routine Name:
  376. Routine Description:
  377. Arguments:
  378. Return Values:
  379. --*/
  380. {
  381. ULONG Errors;
  382. PNDIS_WAN_CO_FRAGMENT FragmentInfo =
  383. (PNDIS_WAN_CO_FRAGMENT)Buffer;
  384. Errors = FragmentInfo->Errors;
  385. AcquireBundleLock(BundleCB);
  386. if (Errors & WAN_ERROR_CRC) {
  387. LinkCB->Stats.CRCErrors++;
  388. BundleCB->Stats.CRCErrors++;
  389. }
  390. if (Errors & WAN_ERROR_FRAMING) {
  391. LinkCB->Stats.FramingErrors++;
  392. BundleCB->Stats.FramingErrors++;
  393. }
  394. if (Errors & WAN_ERROR_HARDWAREOVERRUN) {
  395. LinkCB->Stats.SerialOverrunErrors++;
  396. BundleCB->Stats.SerialOverrunErrors++;
  397. }
  398. if (Errors & WAN_ERROR_BUFFEROVERRUN) {
  399. LinkCB->Stats.BufferOverrunErrors++;
  400. BundleCB->Stats.BufferOverrunErrors++;
  401. }
  402. if (Errors & WAN_ERROR_TIMEOUT) {
  403. LinkCB->Stats.TimeoutErrors++;
  404. BundleCB->Stats.TimeoutErrors++;
  405. }
  406. if (Errors & WAN_ERROR_ALIGNMENT) {
  407. LinkCB->Stats.AlignmentErrors++;
  408. BundleCB->Stats.AlignmentErrors++;
  409. }
  410. ReleaseBundleLock(BundleCB);
  411. }
  412. VOID
  413. NdisCoWanLinkParamChange(
  414. PLINKCB LinkCB,
  415. PBUNDLECB BundleCB,
  416. PUCHAR Buffer,
  417. ULONG BufferSize
  418. )
  419. {
  420. PWAN_CO_LINKPARAMS LinkParams =
  421. (PWAN_CO_LINKPARAMS)Buffer;
  422. if (BufferSize < sizeof(WAN_CO_LINKPARAMS)) {
  423. return;
  424. }
  425. AcquireBundleLock(BundleCB);
  426. NdisWanDbgOut(DBG_TRACE, DBG_INDICATE,
  427. ("LinkParamChange: SendWindow %d XmitSpeed %d RecvSpeed %d",
  428. LinkParams->SendWindow, LinkParams->TransmitSpeed, LinkParams->ReceiveSpeed));
  429. LinkCB->SendWindow = LinkParams->SendWindow;
  430. //
  431. // If the new sendwindow is set smaller then the
  432. // current # of outstanding frames then we have to
  433. // close the sendwindow for the link and reduce the
  434. // number of sending links that the bundle sees.
  435. //
  436. // If the new sendwindow is set larger then the
  437. // current # of outstanding frames and the sendwindow
  438. // is currently closed, we need to open the sendwindow
  439. // and increase the number of sending links that the
  440. // bundle sees.
  441. //
  442. if (LinkCB->LinkActive) {
  443. if (LinkCB->SendWindow <= LinkCB->OutstandingFrames) {
  444. if (LinkCB->SendWindowOpen) {
  445. LinkCB->SendWindowOpen = FALSE;
  446. BundleCB->SendingLinks -= 1;
  447. }
  448. } else if (!LinkCB->SendWindowOpen) {
  449. LinkCB->SendWindowOpen = TRUE;
  450. BundleCB->SendingLinks += 1;
  451. }
  452. }
  453. LinkCB->SFlowSpec.PeakBandwidth =
  454. LinkParams->TransmitSpeed;
  455. LinkCB->RFlowSpec.PeakBandwidth =
  456. LinkParams->ReceiveSpeed;
  457. if (LinkCB->SFlowSpec.PeakBandwidth == 0) {
  458. LinkCB->SFlowSpec.PeakBandwidth = 28800 / 8;
  459. }
  460. if (LinkCB->RFlowSpec.PeakBandwidth == 0) {
  461. LinkCB->RFlowSpec.PeakBandwidth = LinkCB->SFlowSpec.PeakBandwidth;
  462. }
  463. UpdateBundleInfo(BundleCB);
  464. ReleaseBundleLock(BundleCB);
  465. }
  466. VOID
  467. UpdateBundleInfo(
  468. PBUNDLECB BundleCB
  469. )
  470. /*++
  471. Routine Name:
  472. Routine Description:
  473. Expects the BundleCB->Lock to be held!
  474. Arguments:
  475. Return Values:
  476. --*/
  477. {
  478. PLINKCB LinkCB;
  479. ULONG SlowestSSpeed, FastestSSpeed;
  480. ULONG SlowestRSpeed, FastestRSpeed;
  481. PPROTOCOLCB ProtocolCB;
  482. PFLOWSPEC BSFlowSpec, BRFlowSpec;
  483. ULONG i;
  484. ULONG SmallestSDU;
  485. LIST_ENTRY TempList;
  486. BSFlowSpec = &BundleCB->SFlowSpec;
  487. BRFlowSpec = &BundleCB->RFlowSpec;
  488. SlowestSSpeed = FastestSSpeed = 0;
  489. SlowestRSpeed = FastestRSpeed = 0;
  490. SmallestSDU = 0;
  491. BSFlowSpec->TokenRate = 0;
  492. BSFlowSpec->PeakBandwidth = 0;
  493. BRFlowSpec->TokenRate = 0;
  494. BRFlowSpec->PeakBandwidth = 0;
  495. BundleCB->SendWindow = 0;
  496. BundleCB->State = BUNDLE_GOING_DOWN;
  497. if (BundleCB->ulLinkCBCount != 0) {
  498. //
  499. // Currently only using the SendSide FastestSpeed so
  500. // just get it from the head of the list.
  501. //
  502. FastestSSpeed =
  503. ((PLINKCB)(BundleCB->LinkCBList.Flink))->SFlowSpec.PeakBandwidth;
  504. SmallestSDU =
  505. ((PLINKCB)(BundleCB->LinkCBList.Flink))->SFlowSpec.MaxSduSize;
  506. //
  507. // If a link has a speed that is less than the minimum
  508. // link bandwidth (% of the fastests link speed) it is flaged
  509. // as not sending and does not count as a sending link.
  510. //
  511. BundleCB->SendingLinks = 0;
  512. BundleCB->SendResources = 0;
  513. for (LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
  514. (PVOID)LinkCB != (PVOID)&BundleCB->LinkCBList;
  515. LinkCB = (PLINKCB)LinkCB->Linkage.Flink) {
  516. ULONGLONG n, d, temp;
  517. PFLOWSPEC LSFlowSpec = &LinkCB->SFlowSpec;
  518. PFLOWSPEC LRFlowSpec = &LinkCB->RFlowSpec;
  519. if (LinkCB->State == LINK_UP) {
  520. BundleCB->State = BUNDLE_UP;
  521. }
  522. n = LSFlowSpec->PeakBandwidth;
  523. n *= 100;
  524. d = FastestSSpeed;
  525. temp = n/d;
  526. LinkCB->LinkActive = ((ULONG)temp > glMinLinkBandwidth) ?
  527. TRUE : FALSE;
  528. if (LinkCB->LinkActive) {
  529. BundleCB->SendResources += LinkCB->SendResources;
  530. BundleCB->SendWindow += LinkCB->SendWindow;
  531. if (LinkCB->SendWindowOpen) {
  532. BundleCB->SendingLinks += 1;
  533. }
  534. BSFlowSpec->PeakBandwidth += LSFlowSpec->PeakBandwidth;
  535. BRFlowSpec->PeakBandwidth += LRFlowSpec->PeakBandwidth;
  536. }
  537. if (LinkCB->SFlowSpec.MaxSduSize < SmallestSDU) {
  538. SmallestSDU = LinkCB->SFlowSpec.MaxSduSize;
  539. }
  540. }
  541. BundleCB->SFlowSpec.MaxSduSize = SmallestSDU;
  542. //
  543. // Now calculate the % bandwidth that each links contributes to the
  544. // bundle. If a link has a speed that is less than the minimum
  545. // link bandwidth (% of the fastests link speed) it is flaged
  546. // as not sending and does not count as a sending link.
  547. //
  548. for (LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
  549. (PVOID)LinkCB != (PVOID)&BundleCB->LinkCBList;
  550. LinkCB = (PLINKCB)LinkCB->Linkage.Flink) {
  551. ULONGLONG n, d, temp;
  552. PFLOWSPEC LSFlowSpec = &LinkCB->SFlowSpec;
  553. PFLOWSPEC LRFlowSpec = &LinkCB->RFlowSpec;
  554. //
  555. // Do sending side
  556. //
  557. n = LSFlowSpec->PeakBandwidth;
  558. n *= 100;
  559. d = BSFlowSpec->PeakBandwidth;
  560. temp = n/d;
  561. LinkCB->SBandwidth = (temp > 0) ? (ULONG)temp : 1;
  562. //
  563. // Do receiving side
  564. //
  565. n = LRFlowSpec->PeakBandwidth;
  566. n *= 100;
  567. d = BRFlowSpec->PeakBandwidth;
  568. temp = n/d;
  569. LinkCB->RBandwidth = (temp > 0) ? (ULONG)temp : 1;
  570. }
  571. BundleCB->NextLinkToXmit =
  572. (PLINKCB)BundleCB->LinkCBList.Flink;
  573. //
  574. // Update the BandwidthOnDemand information
  575. //
  576. if (BundleCB->Flags & BOND_ENABLED) {
  577. PBOND_INFO BonDInfo;
  578. ULONGLONG SecondsInSamplePeriod;
  579. ULONGLONG BytesPerSecond;
  580. ULONGLONG BytesInSamplePeriod;
  581. ULONGLONG temp;
  582. BonDInfo = BundleCB->SUpperBonDInfo;
  583. SecondsInSamplePeriod =
  584. BonDInfo->ulSecondsInSamplePeriod;
  585. BytesPerSecond =
  586. BundleCB->SFlowSpec.PeakBandwidth;
  587. BytesInSamplePeriod =
  588. BytesPerSecond * SecondsInSamplePeriod;
  589. temp = BonDInfo->usPercentBandwidth;
  590. temp *= BytesInSamplePeriod;
  591. temp /= 100;
  592. BonDInfo->ulBytesThreshold = (ULONG)temp;
  593. BonDInfo = BundleCB->SLowerBonDInfo;
  594. SecondsInSamplePeriod =
  595. BonDInfo->ulSecondsInSamplePeriod;
  596. BytesPerSecond =
  597. BundleCB->SFlowSpec.PeakBandwidth;
  598. BytesInSamplePeriod =
  599. BytesPerSecond * SecondsInSamplePeriod;
  600. temp = BonDInfo->usPercentBandwidth;
  601. temp *= BytesInSamplePeriod;
  602. temp /= 100;
  603. BonDInfo->ulBytesThreshold = (ULONG)temp;
  604. BonDInfo = BundleCB->RUpperBonDInfo;
  605. SecondsInSamplePeriod =
  606. BonDInfo->ulSecondsInSamplePeriod;
  607. BytesPerSecond =
  608. BundleCB->RFlowSpec.PeakBandwidth;
  609. BytesInSamplePeriod =
  610. BytesPerSecond * SecondsInSamplePeriod;
  611. temp = BonDInfo->usPercentBandwidth;
  612. temp *= BytesInSamplePeriod;
  613. temp /= 100;
  614. BonDInfo->ulBytesThreshold = (ULONG)temp;
  615. BonDInfo = BundleCB->RLowerBonDInfo;
  616. SecondsInSamplePeriod =
  617. BonDInfo->ulSecondsInSamplePeriod;
  618. BytesPerSecond =
  619. BundleCB->RFlowSpec.PeakBandwidth;
  620. BytesInSamplePeriod =
  621. BytesPerSecond * SecondsInSamplePeriod;
  622. temp = BonDInfo->usPercentBandwidth;
  623. temp *= BytesInSamplePeriod;
  624. temp /= 100;
  625. BonDInfo->ulBytesThreshold = (ULONG)temp;
  626. }
  627. }
  628. //
  629. // We need to do a new lineup to all routed protocols
  630. //
  631. ProtocolCB = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
  632. InitializeListHead(&TempList);
  633. while ((PVOID)ProtocolCB != (PVOID)&BundleCB->ProtocolCBList) {
  634. REF_PROTOCOLCB(ProtocolCB);
  635. InsertHeadList(&TempList, &ProtocolCB->RefLinkage);
  636. ProtocolCB =
  637. (PPROTOCOLCB)ProtocolCB->Linkage.Flink;
  638. }
  639. while (!IsListEmpty(&TempList)) {
  640. PLIST_ENTRY Entry;
  641. Entry =
  642. RemoveHeadList(&TempList);
  643. ProtocolCB = CONTAINING_RECORD(Entry, PROTOCOLCB, RefLinkage);
  644. if (BundleCB->State == BUNDLE_UP) {
  645. ReleaseBundleLock(BundleCB);
  646. DoLineUpToProtocol(ProtocolCB);
  647. AcquireBundleLock(BundleCB);
  648. } else {
  649. //
  650. // Our link count has gone to 0. This means
  651. // that we can not send any packets. Flush the
  652. // queues and don't accept any more sends from
  653. // the transports.
  654. //
  655. FlushProtocolPacketQueue(ProtocolCB);
  656. }
  657. DEREF_PROTOCOLCB(ProtocolCB);
  658. }
  659. }
  660. VOID
  661. AddLinkToBundle(
  662. IN PBUNDLECB BundleCB,
  663. IN PLINKCB LinkCB
  664. )
  665. /*++
  666. Routine Name:
  667. Routine Description:
  668. Arguments:
  669. Return Values:
  670. --*/
  671. {
  672. UINT Class;
  673. //
  674. // Insert the links so that they are ordered with the fastest
  675. // sending link at the head of the list
  676. //
  677. if (IsListEmpty(&BundleCB->LinkCBList) ||
  678. (LinkCB->SFlowSpec.PeakBandwidth >=
  679. ((PLINKCB)(BundleCB->LinkCBList.Flink))->SFlowSpec.PeakBandwidth)) {
  680. //
  681. // The list was either empty or this link is a bigger pipe
  682. // than anything else on the bundle
  683. //
  684. InsertHeadList(&BundleCB->LinkCBList, &LinkCB->Linkage);
  685. } else if ((LinkCB->SFlowSpec.PeakBandwidth <=
  686. ((PLINKCB)(BundleCB->LinkCBList.Blink))->SFlowSpec.PeakBandwidth)) {
  687. //
  688. // This link is a smaller pipe than anything else
  689. // on the bundle.
  690. //
  691. InsertTailList(&(BundleCB->LinkCBList), &(LinkCB->Linkage));
  692. } else {
  693. PLINKCB Current, Next;
  694. BOOLEAN Inserted = FALSE;
  695. //
  696. // We need to find where this link belongs in the list!
  697. //
  698. Current = (PLINKCB)BundleCB->LinkCBList.Flink;
  699. Next = (PLINKCB)Current->Linkage.Flink;
  700. while ((PVOID)Next != (PVOID)&BundleCB->LinkCBList) {
  701. if (LinkCB->SFlowSpec.PeakBandwidth <= Current->SFlowSpec.PeakBandwidth &&
  702. LinkCB->SFlowSpec.PeakBandwidth >= Next->SFlowSpec.PeakBandwidth) {
  703. LinkCB->Linkage.Flink = (PLIST_ENTRY)Next;
  704. LinkCB->Linkage.Blink = (PLIST_ENTRY)Current;
  705. Current->Linkage.Flink =
  706. Next->Linkage.Blink =
  707. (PLIST_ENTRY)LinkCB;
  708. Inserted = TRUE;
  709. break;
  710. }
  711. Current = Next;
  712. Next = (PLINKCB)Next->Linkage.Flink;
  713. }
  714. if (!Inserted) {
  715. InsertTailList(&(BundleCB->LinkCBList), &(LinkCB->Linkage));
  716. }
  717. }
  718. BundleCB->ulLinkCBCount++;
  719. LinkCB->BundleCB = BundleCB;
  720. for (Class = 0; Class < MAX_MCML; Class++) {
  721. PLINK_RECV_INFO LinkRecvInfo;
  722. PBUNDLE_RECV_INFO BundleRecvInfo;
  723. LinkRecvInfo = &LinkCB->RecvInfo[Class];
  724. BundleRecvInfo = &BundleCB->RecvInfo[Class];
  725. LinkRecvInfo->LastSeqNumber =
  726. BundleRecvInfo->MinSeqNumber;
  727. }
  728. //
  729. // Update BundleCB info
  730. //
  731. UpdateBundleInfo(BundleCB);
  732. REF_BUNDLECB(BundleCB);
  733. }
  734. VOID
  735. RemoveLinkFromBundle(
  736. IN PBUNDLECB BundleCB,
  737. IN PLINKCB LinkCB,
  738. IN BOOLEAN Locked
  739. )
  740. /*++
  741. Routine Name:
  742. Routine Description:
  743. Expects the BundleCB->Lock to be held! Returns with the
  744. lock released!
  745. Arguments:
  746. Return Values:
  747. --*/
  748. {
  749. if (!Locked) {
  750. AcquireBundleLock(BundleCB);
  751. }
  752. //
  753. // Remove link from the bundle
  754. //
  755. RemoveEntryList(&LinkCB->Linkage);
  756. LinkCB->BundleCB = NULL;
  757. BundleCB->ulLinkCBCount--;
  758. BundleCB->SendingLinks--;
  759. //
  760. // Update BundleCB info
  761. //
  762. UpdateBundleInfo(BundleCB);
  763. //
  764. // Deref for ref applied when we added this linkcb to
  765. // the bundle
  766. //
  767. DEREF_BUNDLECB_LOCKED(BundleCB);
  768. }