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.

1326 lines
31 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. Util.c
  5. Abstract:
  6. This file contains utility functions used by NdisWan.
  7. Author:
  8. Tony Bell (TonyBe) June 06, 1995
  9. Environment:
  10. Kernel Mode
  11. Revision History:
  12. TonyBe 06/06/95 Created
  13. --*/
  14. #include "wan.h"
  15. #define __FILE_SIG__ UTIL_FILESIG
  16. VOID
  17. NdisWanCopyFromPacketToBuffer(
  18. IN PNDIS_PACKET pNdisPacket,
  19. IN ULONG Offset,
  20. IN ULONG BytesToCopy,
  21. OUT PUCHAR Buffer,
  22. OUT PULONG BytesCopied
  23. )
  24. /*++
  25. Routine Name:
  26. Routine Description:
  27. Arguments:
  28. Return Values:
  29. --*/
  30. {
  31. ULONG NdisBufferCount;
  32. PNDIS_BUFFER CurrentBuffer;
  33. PVOID VirtualAddress;
  34. ULONG CurrentLength, AmountToMove;
  35. ULONG LocalBytesCopied = 0, PacketLength;
  36. *BytesCopied = 0;
  37. //
  38. // Take care of zero byte copy
  39. //
  40. if (!BytesToCopy) {
  41. return;
  42. }
  43. //
  44. // Get the buffer count
  45. //
  46. NdisQueryPacket(pNdisPacket,
  47. NULL,
  48. &NdisBufferCount,
  49. &CurrentBuffer,
  50. &PacketLength);
  51. //
  52. // Could be a null packet
  53. //
  54. if (!NdisBufferCount ||
  55. Offset == PacketLength) {
  56. return;
  57. }
  58. NdisQueryBuffer(CurrentBuffer,
  59. &VirtualAddress,
  60. &CurrentLength);
  61. while (LocalBytesCopied < BytesToCopy &&
  62. LocalBytesCopied < PacketLength) {
  63. //
  64. // No more bytes left in this buffer
  65. //
  66. if (!CurrentLength) {
  67. //
  68. // Get the next buffer
  69. //
  70. NdisGetNextBuffer(CurrentBuffer,
  71. &CurrentBuffer);
  72. //
  73. // End of the packet, copy what we can
  74. //
  75. if (CurrentBuffer == NULL) {
  76. break;
  77. }
  78. //
  79. //
  80. //
  81. NdisQueryBuffer(CurrentBuffer,
  82. &VirtualAddress,
  83. &CurrentLength);
  84. if (!CurrentLength) {
  85. continue;
  86. }
  87. }
  88. //
  89. // Get to the point where we can start copying
  90. //
  91. if (Offset) {
  92. if (Offset > CurrentLength) {
  93. //
  94. // Not in this buffer, go to the next one
  95. //
  96. Offset -= CurrentLength;
  97. CurrentLength = 0;
  98. continue;
  99. } else {
  100. //
  101. // At least some in this buffer
  102. //
  103. VirtualAddress = (PUCHAR)VirtualAddress + Offset;
  104. CurrentLength -= Offset;
  105. Offset = 0;
  106. }
  107. }
  108. if (!CurrentLength) {
  109. continue;
  110. }
  111. //
  112. // We can copy some data. If we need more data than is available
  113. // in this buffer we can copy what we need and go back for more.
  114. //
  115. AmountToMove = (CurrentLength > (BytesToCopy - LocalBytesCopied)) ?
  116. (BytesToCopy - LocalBytesCopied) : CurrentLength;
  117. NdisMoveMemory(Buffer, VirtualAddress, AmountToMove);
  118. Buffer = (PUCHAR)Buffer + AmountToMove;
  119. VirtualAddress = (PUCHAR)VirtualAddress + AmountToMove;
  120. LocalBytesCopied += AmountToMove;
  121. CurrentLength -= AmountToMove;
  122. }
  123. *BytesCopied = LocalBytesCopied;
  124. }
  125. VOID
  126. NdisWanCopyFromBufferToPacket(
  127. PUCHAR Buffer,
  128. ULONG BytesToCopy,
  129. PNDIS_PACKET NdisPacket,
  130. ULONG PacketOffset,
  131. PULONG BytesCopied
  132. )
  133. {
  134. PNDIS_BUFFER NdisBuffer;
  135. ULONG NdisBufferCount, NdisBufferLength;
  136. PVOID VirtualAddress;
  137. ULONG LocalBytesCopied = 0;
  138. *BytesCopied = 0;
  139. //
  140. // Make sure we actually want to do something
  141. //
  142. if (BytesToCopy == 0) {
  143. return;
  144. }
  145. //
  146. // Get the buffercount of the packet
  147. //
  148. NdisQueryPacket(NdisPacket,
  149. NULL,
  150. &NdisBufferCount,
  151. &NdisBuffer,
  152. NULL);
  153. //
  154. // Make sure this is not a null packet
  155. //
  156. if (NdisBufferCount == 0) {
  157. return;
  158. }
  159. //
  160. // Get first buffer and buffer length
  161. //
  162. NdisQueryBuffer(NdisBuffer,
  163. &VirtualAddress,
  164. &NdisBufferLength);
  165. while (LocalBytesCopied < BytesToCopy) {
  166. if (NdisBufferLength == 0) {
  167. NdisGetNextBuffer(NdisBuffer,
  168. &NdisBuffer);
  169. if (NdisBuffer == NULL) {
  170. break;
  171. }
  172. NdisQueryBuffer(NdisBuffer,
  173. &VirtualAddress,
  174. &NdisBufferLength);
  175. continue;
  176. }
  177. if (PacketOffset != 0) {
  178. if (PacketOffset > NdisBufferLength) {
  179. PacketOffset -= NdisBufferLength;
  180. NdisBufferLength = 0;
  181. continue;
  182. } else {
  183. VirtualAddress = (PUCHAR)VirtualAddress + PacketOffset;
  184. NdisBufferLength -= PacketOffset;
  185. PacketOffset = 0;
  186. }
  187. }
  188. //
  189. // Copy the data
  190. //
  191. {
  192. ULONG AmountToMove;
  193. ULONG AmountRemaining;
  194. AmountRemaining = BytesToCopy - LocalBytesCopied;
  195. AmountToMove = (NdisBufferLength < AmountRemaining) ?
  196. NdisBufferLength : AmountRemaining;
  197. NdisMoveMemory((PUCHAR)VirtualAddress,
  198. Buffer,
  199. AmountToMove);
  200. Buffer += AmountToMove;
  201. LocalBytesCopied += AmountToMove;
  202. NdisBufferLength -= AmountToMove;
  203. }
  204. }
  205. *BytesCopied = LocalBytesCopied;
  206. }
  207. BOOLEAN
  208. IsLinkValid(
  209. NDIS_HANDLE LinkHandle,
  210. BOOLEAN CheckState,
  211. PLINKCB *LinkCB
  212. )
  213. {
  214. PLINKCB plcb;
  215. LOCK_STATE LockState;
  216. BOOLEAN Valid;
  217. *LinkCB = NULL;
  218. Valid = FALSE;
  219. NdisAcquireReadWriteLock(&ConnTableLock, FALSE, &LockState);
  220. do {
  221. if (PtrToUlong(LinkHandle) > ConnectionTable->ulArraySize) {
  222. break;
  223. }
  224. plcb = *(ConnectionTable->LinkArray + PtrToUlong(LinkHandle));
  225. if (plcb == NULL) {
  226. break;
  227. }
  228. NdisDprAcquireSpinLock(&plcb->Lock);
  229. if (CheckState &&
  230. (plcb->State != LINK_UP)) {
  231. NdisDprReleaseSpinLock(&plcb->Lock);
  232. break;
  233. }
  234. REF_LINKCB(plcb);
  235. NdisDprReleaseSpinLock(&plcb->Lock);
  236. *LinkCB = plcb;
  237. Valid = TRUE;
  238. } while (FALSE);
  239. NdisReleaseReadWriteLock(&ConnTableLock, &LockState);
  240. return (Valid);
  241. }
  242. BOOLEAN
  243. IsBundleValid(
  244. NDIS_HANDLE BundleHandle,
  245. BOOLEAN CheckState,
  246. PBUNDLECB *BundleCB
  247. )
  248. {
  249. PBUNDLECB pbcb;
  250. LOCK_STATE LockState;
  251. BOOLEAN Valid;
  252. *BundleCB = NULL;
  253. Valid = FALSE;
  254. NdisAcquireReadWriteLock(&ConnTableLock, FALSE, &LockState);
  255. do {
  256. if (PtrToUlong(BundleHandle) > ConnectionTable->ulArraySize) {
  257. break;
  258. }
  259. pbcb = *(ConnectionTable->BundleArray + PtrToUlong(BundleHandle));
  260. if (pbcb == NULL) {
  261. break;
  262. }
  263. NdisDprAcquireSpinLock(&pbcb->Lock);
  264. if (CheckState &&
  265. (pbcb->State != BUNDLE_UP)) {
  266. NdisDprReleaseSpinLock(&pbcb->Lock);
  267. break;
  268. }
  269. REF_BUNDLECB(pbcb);
  270. NdisDprReleaseSpinLock(&pbcb->Lock);
  271. *BundleCB = pbcb;
  272. Valid = TRUE;
  273. } while (FALSE);
  274. NdisReleaseReadWriteLock(&ConnTableLock, &LockState);
  275. return (Valid);
  276. }
  277. BOOLEAN
  278. AreLinkAndBundleValid(
  279. NDIS_HANDLE LinkHandle,
  280. BOOLEAN CheckState,
  281. PLINKCB *LinkCB,
  282. PBUNDLECB *BundleCB
  283. )
  284. {
  285. PLINKCB plcb;
  286. PBUNDLECB pbcb;
  287. LOCK_STATE LockState;
  288. BOOLEAN Valid;
  289. *LinkCB = NULL;
  290. *BundleCB = NULL;
  291. Valid = FALSE;
  292. NdisAcquireReadWriteLock(&ConnTableLock, FALSE, &LockState);
  293. do {
  294. if (PtrToUlong(LinkHandle) > ConnectionTable->ulArraySize) {
  295. break;
  296. }
  297. plcb = *(ConnectionTable->LinkArray + PtrToUlong(LinkHandle));
  298. if (plcb == NULL) {
  299. break;
  300. }
  301. NdisDprAcquireSpinLock(&plcb->Lock);
  302. if (CheckState &&
  303. (plcb->State != LINK_UP)) {
  304. NdisDprReleaseSpinLock(&plcb->Lock);
  305. break;
  306. }
  307. pbcb = plcb->BundleCB;
  308. if (pbcb == NULL) {
  309. NdisDprReleaseSpinLock(&plcb->Lock);
  310. break;
  311. }
  312. REF_LINKCB(plcb);
  313. NdisDprReleaseSpinLock(&plcb->Lock);
  314. NdisDprAcquireSpinLock(&pbcb->Lock);
  315. REF_BUNDLECB(pbcb);
  316. NdisDprReleaseSpinLock(&pbcb->Lock);
  317. *LinkCB = plcb;
  318. *BundleCB = pbcb;
  319. Valid = TRUE;
  320. } while (FALSE);
  321. NdisReleaseReadWriteLock(&ConnTableLock, &LockState);
  322. return (Valid);
  323. }
  324. //
  325. // Called with BundleCB->Lock held
  326. //
  327. VOID
  328. DoDerefBundleCBWork(
  329. PBUNDLECB BundleCB
  330. )
  331. {
  332. ASSERT(BundleCB->State == BUNDLE_GOING_DOWN);
  333. ASSERT(BundleCB->OutstandingFrames == 0);
  334. ASSERT(BundleCB->ulNumberOfRoutes == 0);
  335. ASSERT(BundleCB->ulLinkCBCount == 0);
  336. ReleaseBundleLock(BundleCB);
  337. RemoveBundleFromConnectionTable(BundleCB);
  338. NdisWanFreeBundleCB(BundleCB);
  339. }
  340. //
  341. // Called with LinkCB->Lock held
  342. //
  343. VOID
  344. DoDerefLinkCBWork(
  345. PLINKCB LinkCB
  346. )
  347. {
  348. PBUNDLECB _pbcb = LinkCB->BundleCB;
  349. ASSERT(LinkCB->State == LINK_GOING_DOWN);
  350. ASSERT(LinkCB->OutstandingFrames == 0);
  351. NdisReleaseSpinLock(&LinkCB->Lock);
  352. RemoveLinkFromBundle(_pbcb, LinkCB, FALSE);
  353. RemoveLinkFromConnectionTable(LinkCB);
  354. NdisWanFreeLinkCB(LinkCB);
  355. }
  356. //
  357. //
  358. //
  359. VOID
  360. DoDerefCmVcCBWork(
  361. PCM_VCCB VcCB
  362. )
  363. {
  364. InterlockedExchange((PLONG)&(VcCB)->State, CMVC_DEACTIVE);
  365. NdisMCmDeactivateVc(VcCB->NdisVcHandle);
  366. NdisMCmCloseCallComplete(NDIS_STATUS_SUCCESS,
  367. VcCB->NdisVcHandle,
  368. NULL);
  369. }
  370. //
  371. // Called with ClAfSap->Lock held
  372. //
  373. VOID
  374. DoDerefClAfSapCBWork(
  375. PCL_AFSAPCB AfSapCB
  376. )
  377. {
  378. NDIS_STATUS Status;
  379. ASSERT(AfSapCB->Flags & SAP_REGISTERED);
  380. if (AfSapCB->Flags & SAP_REGISTERED) {
  381. AfSapCB->Flags &= ~(SAP_REGISTERED);
  382. AfSapCB->Flags |= (SAP_DEREGISTERING);
  383. NdisReleaseSpinLock(&AfSapCB->Lock);
  384. Status = NdisClDeregisterSap(AfSapCB->SapHandle);
  385. if (Status != NDIS_STATUS_PENDING) {
  386. ClDeregisterSapComplete(Status, AfSapCB);
  387. }
  388. } else {
  389. NdisReleaseSpinLock(&AfSapCB->Lock);
  390. }
  391. }
  392. VOID
  393. DerefVc(
  394. PLINKCB LinkCB
  395. )
  396. {
  397. //
  398. // Ref applied when we sent the packet to the underlying
  399. // miniport
  400. //
  401. LinkCB->VcRefCount--;
  402. if ((LinkCB->ClCallState == CL_CALL_CLOSE_PENDING) &&
  403. (LinkCB->VcRefCount == 0) ) {
  404. NDIS_STATUS CloseStatus;
  405. LinkCB->ClCallState = CL_CALL_CLOSED;
  406. NdisReleaseSpinLock(&LinkCB->Lock);
  407. CloseStatus =
  408. NdisClCloseCall(LinkCB->NdisLinkHandle,
  409. NULL,
  410. NULL,
  411. 0);
  412. if (CloseStatus != NDIS_STATUS_PENDING) {
  413. ClCloseCallComplete(CloseStatus,
  414. LinkCB,
  415. NULL);
  416. }
  417. NdisAcquireSpinLock(&LinkCB->Lock);
  418. }
  419. }
  420. VOID
  421. DeferredWorker(
  422. PKDPC Dpc,
  423. PVOID Context,
  424. PVOID Arg1,
  425. PVOID Arg2
  426. )
  427. {
  428. NdisAcquireSpinLock(&DeferredWorkList.Lock);
  429. while (!(IsListEmpty(&DeferredWorkList.List))) {
  430. PLIST_ENTRY Entry;
  431. PBUNDLECB BundleCB;
  432. Entry = RemoveHeadList(&DeferredWorkList.List);
  433. DeferredWorkList.ulCount--;
  434. NdisReleaseSpinLock(&DeferredWorkList.Lock);
  435. BundleCB =
  436. CONTAINING_RECORD(Entry, BUNDLECB, DeferredLinkage);
  437. AcquireBundleLock(BundleCB);
  438. BundleCB->Flags &= ~DEFERRED_WORK_QUEUED;
  439. //
  440. // Do all of the deferred work items for this Bundle
  441. //
  442. SendPacketOnBundle(BundleCB);
  443. //
  444. // Deref for the ref applied when we inserted this item on
  445. // the worker queue.
  446. //
  447. DEREF_BUNDLECB(BundleCB);
  448. NdisAcquireSpinLock(&DeferredWorkList.Lock);
  449. }
  450. DeferredWorkList.TimerScheduled = FALSE;
  451. NdisReleaseSpinLock(&DeferredWorkList.Lock);
  452. }
  453. #ifdef NT
  454. VOID
  455. NdisWanStringToNdisString(
  456. PNDIS_STRING pDestString,
  457. PWSTR pSrcBuffer
  458. )
  459. {
  460. PWSTR Dest, Src = pSrcBuffer;
  461. NDIS_STRING SrcString;
  462. NdisInitUnicodeString(&SrcString, pSrcBuffer);
  463. NdisWanAllocateMemory(&pDestString->Buffer, SrcString.MaximumLength, NDISSTRING_TAG);
  464. if (pDestString->Buffer == NULL) {
  465. return;
  466. }
  467. pDestString->MaximumLength = SrcString.MaximumLength;
  468. pDestString->Length = SrcString.Length;
  469. RtlCopyUnicodeString(pDestString, &SrcString);
  470. }
  471. VOID
  472. NdisWanFreeNdisString(
  473. PNDIS_STRING NdisString
  474. )
  475. {
  476. if (NdisString->Buffer != NULL) {
  477. NdisWanFreeMemory(NdisString->Buffer);
  478. }
  479. }
  480. VOID
  481. NdisWanAllocateAdapterName(
  482. PNDIS_STRING Dest,
  483. PNDIS_STRING Src
  484. )
  485. {
  486. NdisWanAllocateMemory(&Dest->Buffer, Src->MaximumLength, NDISSTRING_TAG);
  487. if (Dest->Buffer != NULL) {
  488. Dest->MaximumLength = Src->MaximumLength;
  489. Dest->Length = Src->Length;
  490. RtlUpcaseUnicodeString(Dest, Src, FALSE);
  491. }
  492. }
  493. //VOID
  494. //NdisWanFreeNdisString(
  495. // PNDIS_STRING NdisString
  496. // )
  497. //{
  498. // NdisFreeMemory(NdisString->Buffer,
  499. // NdisString->MaximumLength * sizeof(WCHAR),
  500. // 0);
  501. //}
  502. VOID
  503. NdisWanNdisStringToInteger(
  504. PNDIS_STRING Source,
  505. PULONG Value
  506. )
  507. /*++
  508. Routine Name:
  509. Routine Description:
  510. Arguments:
  511. Return Values:
  512. --*/
  513. {
  514. PWSTR s = Source->Buffer;
  515. ULONG Digit;
  516. *Value = 0;
  517. while (*s != UNICODE_NULL) {
  518. if (*s >= L'0' && *s < L'9') {
  519. Digit = *s - L'0';
  520. } else if (*s >= L'A' && *s <= L'F') {
  521. Digit = *s - L'A' + 10;
  522. } else if (*s >= L'a' && *s <= L'f') {
  523. Digit = *s - L'a' + 10;
  524. } else {
  525. break;
  526. }
  527. *Value = (*Value << 4) | Digit;
  528. s++;
  529. }
  530. }
  531. VOID
  532. NdisWanCopyNdisString(
  533. PNDIS_STRING Dest,
  534. PNDIS_STRING Src
  535. )
  536. /*++
  537. Routine Name:
  538. Routine Description:
  539. Arguments:
  540. Return Values:
  541. --*/
  542. {
  543. PWSTR SrcBuffer = Src->Buffer;
  544. PWSTR DestBuffer = Dest->Buffer;
  545. while (*SrcBuffer != UNICODE_NULL) {
  546. *DestBuffer = *SrcBuffer;
  547. SrcBuffer++;
  548. DestBuffer++;
  549. }
  550. *DestBuffer = UNICODE_NULL;
  551. Dest->Length = Src->Length;
  552. }
  553. VOID
  554. BonDWorker(
  555. PKDPC Dpc,
  556. PVOID Context,
  557. PVOID Arg1,
  558. PVOID Arg2
  559. )
  560. {
  561. PLIST_ENTRY Entry;
  562. NdisAcquireSpinLock(&BonDWorkList.Lock);
  563. for (Entry = BonDWorkList.List.Flink;
  564. Entry != &BonDWorkList.List;
  565. Entry = Entry->Flink) {
  566. PBUNDLECB BundleCB;
  567. BundleCB = CONTAINING_RECORD(Entry, BUNDLECB, BonDLinkage);
  568. NdisReleaseSpinLock(&BonDWorkList.Lock);
  569. AcquireBundleLock(BundleCB);
  570. if (BundleCB->State != BUNDLE_UP ||
  571. !(BundleCB->Flags & BOND_ENABLED)) {
  572. ReleaseBundleLock(BundleCB);
  573. NdisAcquireSpinLock(&BonDWorkList.Lock);
  574. continue;
  575. }
  576. AgeSampleTable(&BundleCB->SUpperBonDInfo->SampleTable);
  577. CheckUpperThreshold(BundleCB);
  578. AgeSampleTable(&BundleCB->SLowerBonDInfo->SampleTable);
  579. CheckLowerThreshold(BundleCB);
  580. AgeSampleTable(&BundleCB->RUpperBonDInfo->SampleTable);
  581. CheckUpperThreshold(BundleCB);
  582. AgeSampleTable(&BundleCB->RLowerBonDInfo->SampleTable);
  583. CheckUpperThreshold(BundleCB);
  584. ReleaseBundleLock(BundleCB);
  585. NdisAcquireSpinLock(&BonDWorkList.Lock);
  586. }
  587. NdisReleaseSpinLock(&BonDWorkList.Lock);
  588. }
  589. #if 0
  590. VOID
  591. CheckBonDInfo(
  592. PKDPC Dpc,
  593. PBUNDLECB BundleCB,
  594. PVOID SysArg1,
  595. PVOID SysArg2
  596. )
  597. {
  598. if (!(BundleCB->Flags & BOND_ENABLED)) {
  599. return;
  600. }
  601. AgeSampleTable(&BundleCB->SUpperBonDInfo.SampleTable);
  602. CheckUpperThreshold(BundleCB);
  603. AgeSampleTable(&BundleCB->SLowerBonDInfo.SampleTable);
  604. CheckLowerThreshold(BundleCB);
  605. AgeSampleTable(&BundleCB->RUpperBonDInfo.SampleTable);
  606. CheckUpperThreshold(BundleCB);
  607. AgeSampleTable(&BundleCB->RLowerBonDInfo.SampleTable);
  608. CheckUpperThreshold(BundleCB);
  609. }
  610. #endif
  611. VOID
  612. AgeSampleTable(
  613. PSAMPLE_TABLE SampleTable
  614. )
  615. /*++
  616. Routine Name:
  617. Routine Description:
  618. Arguments:
  619. Return Values:
  620. --*/
  621. {
  622. WAN_TIME CurrentTime, TimeDiff;
  623. ULONG HeadIndex = SampleTable->ulHead;
  624. //
  625. // Should return CurrentTime in 100ns units
  626. //
  627. NdisWanGetSystemTime(&CurrentTime);
  628. //
  629. // We will search through the sample indexing over samples that are more than
  630. // one second older than the current time.
  631. //
  632. while (!IsSampleTableEmpty(SampleTable) ) {
  633. PBOND_SAMPLE FirstSample;
  634. FirstSample = &SampleTable->SampleArray[SampleTable->ulHead];
  635. NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &FirstSample->TimeStamp);
  636. if (NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SamplePeriod))
  637. break;
  638. SampleTable->ulCurrentSampleByteCount -= FirstSample->ulBytes;
  639. ASSERT((LONG)SampleTable->ulCurrentSampleByteCount >= 0);
  640. FirstSample->ulReferenceCount = 0;
  641. if (++SampleTable->ulHead == SampleTable->ulSampleArraySize) {
  642. SampleTable->ulHead = 0;
  643. }
  644. SampleTable->ulSampleCount--;
  645. }
  646. if (IsSampleTableEmpty(SampleTable)) {
  647. ASSERT((LONG)SampleTable->ulCurrentSampleByteCount == 0);
  648. SampleTable->ulHead = SampleTable->ulCurrent;
  649. }
  650. }
  651. VOID
  652. UpdateSampleTable(
  653. PSAMPLE_TABLE SampleTable,
  654. ULONG Bytes
  655. )
  656. /*++
  657. Routine Name:
  658. Routine Description:
  659. Arguments:
  660. Return Values:
  661. --*/
  662. {
  663. WAN_TIME CurrentTime, TimeDiff;
  664. ULONG CurrentIndex = SampleTable->ulCurrent;
  665. PBOND_SAMPLE CurrentSample = &SampleTable->SampleArray[CurrentIndex];
  666. NdisWanGetSystemTime(&CurrentTime);
  667. NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &CurrentSample->TimeStamp);
  668. if (NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SampleRate) ||
  669. IsSampleTableFull(SampleTable)) {
  670. //
  671. // Add this send on the previous sample
  672. //
  673. CurrentSample->ulBytes += Bytes;
  674. CurrentSample->ulReferenceCount++;
  675. } else {
  676. ULONG NextIndex;
  677. //
  678. // We need a new sample
  679. //
  680. if (IsSampleTableEmpty(SampleTable)) {
  681. NextIndex = SampleTable->ulHead;
  682. ASSERT(NextIndex == SampleTable->ulCurrent);
  683. } else {
  684. NextIndex = SampleTable->ulCurrent + 1;
  685. }
  686. if (NextIndex == SampleTable->ulSampleArraySize) {
  687. NextIndex = 0;
  688. }
  689. SampleTable->ulCurrent = NextIndex;
  690. CurrentSample = &SampleTable->SampleArray[NextIndex];
  691. CurrentSample->TimeStamp = CurrentTime;
  692. CurrentSample->ulBytes = Bytes;
  693. CurrentSample->ulReferenceCount = 1;
  694. SampleTable->ulSampleCount++;
  695. ASSERT(SampleTable->ulSampleCount <= SampleTable->ulSampleArraySize);
  696. }
  697. SampleTable->ulCurrentSampleByteCount += Bytes;
  698. }
  699. VOID
  700. UpdateBandwidthOnDemand(
  701. PBOND_INFO BonDInfo,
  702. ULONG Bytes
  703. )
  704. /*++
  705. Routine Name:
  706. Routine Description:
  707. Arguments:
  708. Return Values:
  709. --*/
  710. {
  711. PSAMPLE_TABLE SampleTable = &BonDInfo->SampleTable;
  712. //
  713. // Age and update the sample table
  714. //
  715. AgeSampleTable(SampleTable);
  716. UpdateSampleTable(SampleTable, Bytes);
  717. }
  718. VOID
  719. CheckUpperThreshold(
  720. PBUNDLECB BundleCB
  721. )
  722. /*++
  723. Routine Name:
  724. Routine Description:
  725. Arguments:
  726. Return Values:
  727. --*/
  728. {
  729. WAN_TIME CurrentTime, TimeDiff;
  730. PBOND_INFO BonDInfo;
  731. PSAMPLE_TABLE SampleTable;
  732. ULONGLONG Bps;
  733. BOOLEAN SSignal, RSignal;
  734. //
  735. // First check send side
  736. //
  737. BonDInfo = BundleCB->SUpperBonDInfo;
  738. SSignal = FALSE;
  739. SampleTable = &BonDInfo->SampleTable;
  740. Bps = SampleTable->ulCurrentSampleByteCount;
  741. //
  742. // Switch on the current state
  743. //
  744. switch (BonDInfo->State) {
  745. case BonDSignaled:
  746. break;
  747. case BonDIdle:
  748. //
  749. // We are currently below the upper threshold. If we
  750. // go over the upperthreshold we will set the time and
  751. // transition to the monitor state.
  752. //
  753. if (Bps >= BonDInfo->ulBytesThreshold) {
  754. NdisWanGetSystemTime(&BonDInfo->StartTime);
  755. BonDInfo->State = BonDMonitor;
  756. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("U-S: i -> m, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
  757. }
  758. break;
  759. case BonDMonitor:
  760. //
  761. // We are currently in the monitor state which means that
  762. // we have gone above the upper threshold. If we fall below
  763. // the upper threshold we will go back to the idle state.
  764. //
  765. if (Bps < BonDInfo->ulBytesThreshold) {
  766. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("U-S: m -> i, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
  767. BonDInfo->State = BonDIdle;
  768. } else {
  769. NdisWanGetSystemTime(&CurrentTime);
  770. NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &BonDInfo->StartTime);
  771. if (!NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SamplePeriod)) {
  772. SSignal = TRUE;
  773. }
  774. }
  775. break;
  776. }
  777. //
  778. // Now check the receive side
  779. //
  780. BonDInfo = BundleCB->RUpperBonDInfo;
  781. RSignal = FALSE;
  782. SampleTable = &BonDInfo->SampleTable;
  783. Bps = SampleTable->ulCurrentSampleByteCount;
  784. switch (BonDInfo->State) {
  785. case BonDSignaled:
  786. break;
  787. case BonDIdle:
  788. //
  789. // We are currently below the upper threshold. If we
  790. // go over the upperthreshold we will set the time and
  791. // transition to the monitor state.
  792. //
  793. if (Bps >= BonDInfo->ulBytesThreshold) {
  794. NdisWanGetSystemTime(&BonDInfo->StartTime);
  795. BonDInfo->State = BonDMonitor;
  796. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("U-R: i -> m, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
  797. }
  798. break;
  799. case BonDMonitor:
  800. //
  801. // We are currently in the monitor state which means that
  802. // we have gone above the upper threshold. If we fall below
  803. // the upper threshold we will go back to the idle state.
  804. //
  805. if (Bps < BonDInfo->ulBytesThreshold) {
  806. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("U-R: m -> i, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
  807. BonDInfo->State = BonDIdle;
  808. } else {
  809. NdisWanGetSystemTime(&CurrentTime);
  810. NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &BonDInfo->StartTime);
  811. if (!NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SamplePeriod)) {
  812. RSignal = TRUE;
  813. }
  814. }
  815. break;
  816. }
  817. if (SSignal || RSignal) {
  818. //
  819. // We have been above the threshold for time greater than the
  820. // threshold sample period so we need to notify someone of this
  821. // historic event!
  822. //
  823. CompleteThresholdEvent(BundleCB, BonDInfo->DataType, UPPER_THRESHOLD);
  824. BundleCB->SUpperBonDInfo->State = BonDSignaled;
  825. BundleCB->RUpperBonDInfo->State = BonDSignaled;
  826. #if DBG
  827. {
  828. ULONGLONG util;
  829. util = BundleCB->SUpperBonDInfo->SampleTable.ulCurrentSampleByteCount;
  830. util *= 100;
  831. util /= BundleCB->SUpperBonDInfo->ulBytesInSamplePeriod;
  832. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("U-S: Bps %I64d Threshold %I64d Util %I64d",
  833. Bps, BundleCB->SUpperBonDInfo->ulBytesThreshold, util));
  834. util = BundleCB->RUpperBonDInfo->SampleTable.ulCurrentSampleByteCount;
  835. util *= 100;
  836. util /= BundleCB->RUpperBonDInfo->ulBytesInSamplePeriod;
  837. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("U-R: Bps %I64d Threshold %I64d Util %I64d",
  838. Bps, BundleCB->RUpperBonDInfo->ulBytesThreshold, util));
  839. }
  840. #endif
  841. }
  842. }
  843. VOID
  844. CheckLowerThreshold(
  845. PBUNDLECB BundleCB
  846. )
  847. /*++
  848. Routine Name:
  849. Routine Description:
  850. Arguments:
  851. Return Values:
  852. --*/
  853. {
  854. WAN_TIME CurrentTime, TimeDiff;
  855. PBOND_INFO BonDInfo;
  856. PSAMPLE_TABLE SampleTable;
  857. ULONGLONG Bps;
  858. BOOLEAN SSignal, RSignal;
  859. if (!(BundleCB->Flags & BOND_ENABLED)) {
  860. return;
  861. }
  862. //
  863. // First check send side
  864. //
  865. BonDInfo = BundleCB->SLowerBonDInfo;
  866. SampleTable = &BonDInfo->SampleTable;
  867. Bps = SampleTable->ulCurrentSampleByteCount;
  868. SSignal = FALSE;
  869. //
  870. // Switch on the current state
  871. //
  872. switch (BonDInfo->State) {
  873. case BonDIdle:
  874. //
  875. // We are currently above the lower threshold. If we
  876. // go under the lowerthreshold we will set the time and
  877. // transition to the monitor state.
  878. //
  879. if (Bps <= BonDInfo->ulBytesThreshold) {
  880. NdisWanGetSystemTime(&BonDInfo->StartTime);
  881. BonDInfo->State = BonDMonitor;
  882. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("L-S: i -> m, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
  883. }
  884. break;
  885. case BonDMonitor:
  886. //
  887. // We are currently in the monitor state which means that
  888. // we have gone below the lower threshold. If we climb above
  889. // the lower threshold we will go back to the idle state.
  890. //
  891. if (Bps > BonDInfo->ulBytesThreshold) {
  892. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("L-S: m -> i, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
  893. BonDInfo->State = BonDIdle;
  894. } else {
  895. NdisWanGetSystemTime(&CurrentTime);
  896. NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &BonDInfo->StartTime);
  897. if (!NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SamplePeriod)) {
  898. SSignal = TRUE;
  899. }
  900. }
  901. break;
  902. case BonDSignaled:
  903. break;
  904. }
  905. //
  906. // Now check the receive side
  907. //
  908. BonDInfo = BundleCB->RLowerBonDInfo;
  909. RSignal = FALSE;
  910. SampleTable = &BonDInfo->SampleTable;
  911. Bps = SampleTable->ulCurrentSampleByteCount;
  912. switch (BonDInfo->State) {
  913. case BonDIdle:
  914. //
  915. // We are currently above the lower threshold. If we
  916. // go below the lowerthreshold we will set the time and
  917. // transition to the monitor state.
  918. //
  919. if (Bps <= BonDInfo->ulBytesThreshold) {
  920. NdisWanGetSystemTime(&BonDInfo->StartTime);
  921. BonDInfo->State = BonDMonitor;
  922. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("L-R: i -> m, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
  923. }
  924. break;
  925. case BonDMonitor:
  926. //
  927. // We are currently in the monitor state which means that
  928. // we have gone below the lower threshold. If we climb above
  929. // the lower threshold we will go back to the idle state.
  930. //
  931. if (Bps > BonDInfo->ulBytesThreshold) {
  932. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("L-R: m -> i, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
  933. BonDInfo->State = BonDIdle;
  934. } else {
  935. NdisWanGetSystemTime(&CurrentTime);
  936. NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &BonDInfo->StartTime);
  937. if (!NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SamplePeriod)) {
  938. RSignal = TRUE;
  939. }
  940. }
  941. break;
  942. case BonDSignaled:
  943. break;
  944. }
  945. if (SSignal && RSignal) {
  946. //
  947. // We have been above the threshold for time greater than the
  948. // threshold sample period so we need to notify someone of this
  949. // historic event!
  950. //
  951. CompleteThresholdEvent(BundleCB, BonDInfo->DataType, LOWER_THRESHOLD);
  952. BundleCB->SLowerBonDInfo->State = BonDSignaled;
  953. BundleCB->RLowerBonDInfo->State = BonDSignaled;
  954. #if DBG
  955. {
  956. ULONGLONG util;
  957. util = BundleCB->SLowerBonDInfo->SampleTable.ulCurrentSampleByteCount;
  958. util *= 100;
  959. util /= BundleCB->SLowerBonDInfo->ulBytesInSamplePeriod;
  960. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("L-S: Bps %I64d Threshold %I64d Util %I64d",
  961. Bps, BundleCB->SLowerBonDInfo->ulBytesThreshold, util));
  962. util = BundleCB->RLowerBonDInfo->SampleTable.ulCurrentSampleByteCount;
  963. util *= 100;
  964. util /= BundleCB->RLowerBonDInfo->ulBytesInSamplePeriod;
  965. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("L-R: Bps %I64d Threshold %I64d Util %I64d",
  966. Bps, BundleCB->RLowerBonDInfo->ulBytesThreshold, util));
  967. }
  968. #endif
  969. }
  970. }
  971. #endif // end of ifdef NT
  972. #if DBG
  973. VOID
  974. InsertSendTrc(
  975. PSEND_TRC_INFO SendTrcInfo,
  976. ULONG DataLength,
  977. PUCHAR Data
  978. )
  979. {
  980. PWAN_TRC_EVENT NewTrcEvent;
  981. PSEND_TRC_INFO TrcInfo;
  982. if (WanTrcCount == 4096) {
  983. NewTrcEvent = (PWAN_TRC_EVENT)
  984. RemoveTailList(&WanTrcList);
  985. NdisWanFreeMemory(NewTrcEvent->TrcInfo);
  986. NdisZeroMemory(NewTrcEvent, sizeof(WAN_TRC_EVENT));
  987. } else {
  988. NdisWanAllocateMemory(&NewTrcEvent,
  989. sizeof(WAN_TRC_EVENT),
  990. WANTRCEVENT_TAG);
  991. if (NewTrcEvent == NULL) {
  992. return;
  993. }
  994. }
  995. WanTrcCount += 1;
  996. }
  997. #endif