Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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