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.

1596 lines
36 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. NTSTATUS
  454. TransformRegister(
  455. PVOID ClientOpenContext,
  456. ULONG CharsSize,
  457. PTRANSFORM_CHARACTERISTICS Chars,
  458. ULONG CapsSize,
  459. PTRANSFORM_INFO Caps
  460. )
  461. {
  462. PTRANSDRVCB TransDrvCB = (PTRANSDRVCB)ClientOpenContext;
  463. PTRANSDRVCB tTransDrvCB;
  464. PTRANSFORM_IE Ie = (PTRANSFORM_IE)(Caps->InfoElements);
  465. PTRANSFORM_IE tIe;
  466. UINT i, FoundCount = 0, MemoryNeeded = 0;
  467. #if 0
  468. InterlockedExchange((PLONG)&TransDrvCB->State, TRANSDRV_REGISTERING);
  469. for (i = 0; i < Caps->InfoElementCount; i++) {
  470. if (Ie->IEType == TRANS_PPP_COMPRESSION ||
  471. Ie->IEType == TRANS_PPP_ENCRYPTION) {
  472. //
  473. // This is an IEType that we are interested in
  474. // but we have some requirements...
  475. // 1. It must support the framed interface unless it is
  476. // MPPC/MPPE.
  477. // 2. If we already have a driver registered that supports
  478. // this scheme we will not add this in again.
  479. // 3. We will give priority to drivers that have hardware
  480. // assisted data transformation.
  481. //
  482. //
  483. // Walk the transform driver list and see if
  484. // this scheme is already registered by another
  485. // driver. If it is, see if either has hardware
  486. // support. If they have the same level of support
  487. // just use the one currently registered. If the new
  488. // ie has a higher level of support mark the old ie
  489. // as not being used
  490. //
  491. NdisAcquireSpinLock(&TransformDrvList.Lock);
  492. for (tTransDrvCB = (PTRANSDRVCB)TransformDrvList.List.Flink;
  493. (PVOID)tTransDrvCB != (PVOID)&TransformDrvList.List;
  494. tTransDrvCB = (PTRANSDRVCB)tTransDrvCB->Linkage.Flink) {
  495. tIe = (PTRANSFORM_IE)tTransDrvCB->Caps->InfoElements;
  496. for (i = 0; i < tTransDrvCB->Caps->InfoElementCount; i++) {
  497. if (tIe->Flags & IE_IN_USE) {
  498. }
  499. }
  500. }
  501. NdisReleaseSpinLock(&TransformDrvList.Lock);
  502. MemoryNeeded += Ie->IESize;
  503. }
  504. Ie = (PTRANSFORM_IE)((PUCHAR)Ie + Ie->IESize);
  505. }
  506. if (FoundCount == 0) {
  507. return (STATUS_UNSUCCESSFUL);
  508. }
  509. NdisWanAllocateMemory(&TransDrvCB->Caps,
  510. MemoryNeeded,
  511. TRANSDRV_TAG);
  512. if (TransDrvCB->Caps == NULL) {
  513. return (STATUS_UNSUCCESSFUL);
  514. }
  515. TransDrvCB->Caps->InfoElementCount = FoundCount;
  516. tIe = (PTRANSFORM_IE)(TransDrvCB->Caps->InfoElements);
  517. for (i = 0; i < Caps->InfoElementCount; i++) {
  518. if (Ie->IEType == TRANS_PPP_COMPRESSION ||
  519. Ie->IEType == TRANS_PPP_ENCRYPTION) {
  520. NdisMoveMemory(tIe, Ie, Ie->IESize);
  521. }
  522. Ie = (PTRANSFORM_IE)((PUCHAR)Ie + Ie->IESize);
  523. tIe = (PTRANSFORM_IE)((PUCHAR)tIe + tIe->IESize);
  524. }
  525. NdisMoveMemory(&TransDrvCB->Chars, Chars, CharsSize);
  526. #endif
  527. return (STATUS_SUCCESS);
  528. }
  529. VOID
  530. TransformTxComplete(
  531. NTSTATUS Status,
  532. PVOID TxCtx,
  533. PMDL InData,
  534. PMDL OutData,
  535. ULONG OutDataOffset,
  536. ULONG OutDataLength
  537. )
  538. {
  539. }
  540. VOID
  541. TransformRxComplete(
  542. NTSTATUS Status,
  543. PVOID RxCtx,
  544. PMDL InData,
  545. PMDL OutData,
  546. ULONG OutDataOffset,
  547. ULONG OutDataLength
  548. )
  549. {
  550. }
  551. NTSTATUS
  552. TransformSendCtrlPacket(
  553. PVOID TxCtx,
  554. ULONG DataLength,
  555. PUCHAR Data
  556. )
  557. {
  558. return (STATUS_SUCCESS);
  559. }
  560. #ifdef NT
  561. VOID
  562. NdisWanStringToNdisString(
  563. PNDIS_STRING pDestString,
  564. PWSTR pSrcBuffer
  565. )
  566. {
  567. PWSTR Dest, Src = pSrcBuffer;
  568. NDIS_STRING SrcString;
  569. NdisWanInitUnicodeString(&SrcString, pSrcBuffer);
  570. NdisWanAllocateMemory(&pDestString->Buffer, SrcString.MaximumLength, NDISSTRING_TAG);
  571. if (pDestString->Buffer == NULL) {
  572. return;
  573. }
  574. pDestString->MaximumLength = SrcString.MaximumLength;
  575. pDestString->Length = SrcString.Length;
  576. NdisWanCopyUnicodeString(pDestString, &SrcString);
  577. }
  578. VOID
  579. NdisWanInitUnicodeString(
  580. OUT PUNICODE_STRING DestinationString,
  581. IN PCWSTR SourceString OPTIONAL
  582. )
  583. /*++
  584. Routine Description:
  585. The NdisWanInitUnicodeString function initializes an NT counted
  586. unicode string. The DestinationString is initialized to point to
  587. the SourceString and the Length and MaximumLength fields of
  588. DestinationString are initialized to the length of the SourceString,
  589. which is zero if SourceString is not specified.
  590. Arguments:
  591. DestinationString - Pointer to the counted string to initialize
  592. SourceString - Optional pointer to a null terminated unicode string that
  593. the counted string is to point to.
  594. Return Value:
  595. None.
  596. --*/
  597. {
  598. ULONG Length;
  599. DestinationString->Buffer = (PWSTR)SourceString;
  600. if (ARGUMENT_PRESENT( SourceString )) {
  601. Length = wcslen( SourceString ) * sizeof( WCHAR );
  602. DestinationString->Length = (USHORT)Length;
  603. DestinationString->MaximumLength = (USHORT)(Length + sizeof(UNICODE_NULL));
  604. }
  605. else {
  606. DestinationString->MaximumLength = 0;
  607. DestinationString->Length = 0;
  608. }
  609. }
  610. VOID
  611. NdisWanCopyUnicodeString(
  612. OUT PUNICODE_STRING DestinationString,
  613. IN PUNICODE_STRING SourceString OPTIONAL
  614. )
  615. /*++
  616. Routine Description:
  617. The NdisWanCopyUnicodeString function copies the SourceString
  618. to the DestinationString. If SourceString is not specified,
  619. then the Length field of DestinationString is set to zero. The
  620. MaximumLength and Buffer fields of DestinationString are not
  621. modified by this function.
  622. The number of bytes copied from the SourceString is either the
  623. Length of SourceString or the MaximumLength of DestinationString,
  624. whichever is smaller.
  625. Arguments:
  626. DestinationString - Pointer to the destination string.
  627. SourceString - Optional pointer to the source string.
  628. Return Value:
  629. None.
  630. --*/
  631. {
  632. UNALIGNED WCHAR *src, *dst;
  633. ULONG n;
  634. if (ARGUMENT_PRESENT(SourceString)) {
  635. dst = DestinationString->Buffer;
  636. src = SourceString->Buffer;
  637. n = SourceString->Length;
  638. if ((USHORT)n > DestinationString->MaximumLength) {
  639. n = DestinationString->MaximumLength;
  640. }
  641. DestinationString->Length = (USHORT)n;
  642. RtlCopyMemory(dst, src, n);
  643. if (DestinationString->Length < DestinationString->MaximumLength) {
  644. dst[n / sizeof(WCHAR)] = UNICODE_NULL;
  645. }
  646. } else {
  647. DestinationString->Length = 0;
  648. }
  649. return;
  650. }
  651. VOID
  652. NdisWanFreeNdisString(
  653. PNDIS_STRING NdisString
  654. )
  655. {
  656. if (NdisString->Buffer != NULL) {
  657. NdisWanFreeMemory(NdisString->Buffer);
  658. }
  659. }
  660. VOID
  661. NdisWanAllocateAdapterName(
  662. PNDIS_STRING Dest,
  663. PNDIS_STRING Src
  664. )
  665. {
  666. NdisWanAllocateMemory(&Dest->Buffer, Src->MaximumLength, NDISSTRING_TAG);
  667. if (Dest->Buffer != NULL) {
  668. Dest->MaximumLength = Src->MaximumLength;
  669. Dest->Length = Src->Length;
  670. RtlUpcaseUnicodeString(Dest, Src, FALSE);
  671. }
  672. }
  673. BOOLEAN
  674. NdisWanCompareNdisString(
  675. PNDIS_STRING NdisString1,
  676. PNDIS_STRING NdisString2
  677. )
  678. {
  679. USHORT l1 = NdisString1->Length;
  680. USHORT l2 = NdisString2->Length;
  681. PWSTR s1 = NdisString1->Buffer;
  682. PWSTR s2 = NdisString2->Buffer;
  683. PWSTR EndCompare;
  684. ASSERT(l1 != 0);
  685. ASSERT(l2 != 0);
  686. if (l1 == l2) {
  687. EndCompare = (PWSTR)((PUCHAR)s1 + l1);
  688. while (s1 < EndCompare) {
  689. if (*s1++ != *s2++) {
  690. return (FALSE);
  691. }
  692. }
  693. return (TRUE);
  694. }
  695. return(FALSE);
  696. }
  697. //VOID
  698. //NdisWanFreeNdisString(
  699. // PNDIS_STRING NdisString
  700. // )
  701. //{
  702. // NdisFreeMemory(NdisString->Buffer,
  703. // NdisString->MaximumLength * sizeof(WCHAR),
  704. // 0);
  705. //}
  706. VOID
  707. NdisWanNdisStringToInteger(
  708. PNDIS_STRING Source,
  709. PULONG Value
  710. )
  711. /*++
  712. Routine Name:
  713. Routine Description:
  714. Arguments:
  715. Return Values:
  716. --*/
  717. {
  718. PWSTR s = Source->Buffer;
  719. ULONG Digit;
  720. *Value = 0;
  721. while (*s != UNICODE_NULL) {
  722. if (*s >= L'0' && *s < L'9') {
  723. Digit = *s - L'0';
  724. } else if (*s >= L'A' && *s <= L'F') {
  725. Digit = *s - L'A' + 10;
  726. } else if (*s >= L'a' && *s <= L'f') {
  727. Digit = *s - L'a' + 10;
  728. } else {
  729. break;
  730. }
  731. *Value = (*Value << 4) | Digit;
  732. s++;
  733. }
  734. }
  735. VOID
  736. NdisWanCopyNdisString(
  737. PNDIS_STRING Dest,
  738. PNDIS_STRING Src
  739. )
  740. /*++
  741. Routine Name:
  742. Routine Description:
  743. Arguments:
  744. Return Values:
  745. --*/
  746. {
  747. PWSTR SrcBuffer = Src->Buffer;
  748. PWSTR DestBuffer = Dest->Buffer;
  749. while (*SrcBuffer != UNICODE_NULL) {
  750. *DestBuffer = *SrcBuffer;
  751. SrcBuffer++;
  752. DestBuffer++;
  753. }
  754. *DestBuffer = UNICODE_NULL;
  755. Dest->Length = Src->Length;
  756. }
  757. VOID
  758. BonDWorker(
  759. PKDPC Dpc,
  760. PVOID Context,
  761. PVOID Arg1,
  762. PVOID Arg2
  763. )
  764. {
  765. PLIST_ENTRY Entry;
  766. NdisAcquireSpinLock(&BonDWorkList.Lock);
  767. for (Entry = BonDWorkList.List.Flink;
  768. Entry != &BonDWorkList.List;
  769. Entry = Entry->Flink) {
  770. PBUNDLECB BundleCB;
  771. BundleCB = CONTAINING_RECORD(Entry, BUNDLECB, BonDLinkage);
  772. NdisReleaseSpinLock(&BonDWorkList.Lock);
  773. AcquireBundleLock(BundleCB);
  774. if (BundleCB->State != BUNDLE_UP ||
  775. !(BundleCB->Flags & BOND_ENABLED)) {
  776. ReleaseBundleLock(BundleCB);
  777. NdisAcquireSpinLock(&BonDWorkList.Lock);
  778. continue;
  779. }
  780. AgeSampleTable(&BundleCB->SUpperBonDInfo->SampleTable);
  781. CheckUpperThreshold(BundleCB);
  782. AgeSampleTable(&BundleCB->SLowerBonDInfo->SampleTable);
  783. CheckLowerThreshold(BundleCB);
  784. AgeSampleTable(&BundleCB->RUpperBonDInfo->SampleTable);
  785. CheckUpperThreshold(BundleCB);
  786. AgeSampleTable(&BundleCB->RLowerBonDInfo->SampleTable);
  787. CheckUpperThreshold(BundleCB);
  788. ReleaseBundleLock(BundleCB);
  789. NdisAcquireSpinLock(&BonDWorkList.Lock);
  790. }
  791. NdisReleaseSpinLock(&BonDWorkList.Lock);
  792. }
  793. #if 0
  794. VOID
  795. CheckBonDInfo(
  796. PKDPC Dpc,
  797. PBUNDLECB BundleCB,
  798. PVOID SysArg1,
  799. PVOID SysArg2
  800. )
  801. {
  802. if (!(BundleCB->Flags & BOND_ENABLED)) {
  803. return;
  804. }
  805. AgeSampleTable(&BundleCB->SUpperBonDInfo.SampleTable);
  806. CheckUpperThreshold(BundleCB);
  807. AgeSampleTable(&BundleCB->SLowerBonDInfo.SampleTable);
  808. CheckLowerThreshold(BundleCB);
  809. AgeSampleTable(&BundleCB->RUpperBonDInfo.SampleTable);
  810. CheckUpperThreshold(BundleCB);
  811. AgeSampleTable(&BundleCB->RLowerBonDInfo.SampleTable);
  812. CheckUpperThreshold(BundleCB);
  813. }
  814. #endif
  815. VOID
  816. AgeSampleTable(
  817. PSAMPLE_TABLE SampleTable
  818. )
  819. /*++
  820. Routine Name:
  821. Routine Description:
  822. Arguments:
  823. Return Values:
  824. --*/
  825. {
  826. WAN_TIME CurrentTime, TimeDiff;
  827. ULONG HeadIndex = SampleTable->ulHead;
  828. //
  829. // Should return CurrentTime in 100ns units
  830. //
  831. NdisWanGetSystemTime(&CurrentTime);
  832. //
  833. // We will search through the sample indexing over samples that are more than
  834. // one second older than the current time.
  835. //
  836. while (!IsSampleTableEmpty(SampleTable) ) {
  837. PBOND_SAMPLE FirstSample;
  838. FirstSample = &SampleTable->SampleArray[SampleTable->ulHead];
  839. NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &FirstSample->TimeStamp);
  840. if (NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SamplePeriod))
  841. break;
  842. SampleTable->ulCurrentSampleByteCount -= FirstSample->ulBytes;
  843. ASSERT((LONG)SampleTable->ulCurrentSampleByteCount >= 0);
  844. FirstSample->ulReferenceCount = 0;
  845. if (++SampleTable->ulHead == SampleTable->ulSampleArraySize) {
  846. SampleTable->ulHead = 0;
  847. }
  848. SampleTable->ulSampleCount--;
  849. }
  850. if (IsSampleTableEmpty(SampleTable)) {
  851. ASSERT((LONG)SampleTable->ulCurrentSampleByteCount == 0);
  852. SampleTable->ulHead = SampleTable->ulCurrent;
  853. }
  854. }
  855. VOID
  856. UpdateSampleTable(
  857. PSAMPLE_TABLE SampleTable,
  858. ULONG Bytes
  859. )
  860. /*++
  861. Routine Name:
  862. Routine Description:
  863. Arguments:
  864. Return Values:
  865. --*/
  866. {
  867. WAN_TIME CurrentTime, TimeDiff;
  868. ULONG CurrentIndex = SampleTable->ulCurrent;
  869. PBOND_SAMPLE CurrentSample = &SampleTable->SampleArray[CurrentIndex];
  870. NdisWanGetSystemTime(&CurrentTime);
  871. NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &CurrentSample->TimeStamp);
  872. if (NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SampleRate) ||
  873. IsSampleTableFull(SampleTable)) {
  874. //
  875. // Add this send on the previous sample
  876. //
  877. CurrentSample->ulBytes += Bytes;
  878. CurrentSample->ulReferenceCount++;
  879. } else {
  880. ULONG NextIndex;
  881. //
  882. // We need a new sample
  883. //
  884. if (IsSampleTableEmpty(SampleTable)) {
  885. NextIndex = SampleTable->ulHead;
  886. ASSERT(NextIndex == SampleTable->ulCurrent);
  887. } else {
  888. NextIndex = SampleTable->ulCurrent + 1;
  889. }
  890. if (NextIndex == SampleTable->ulSampleArraySize) {
  891. NextIndex = 0;
  892. }
  893. SampleTable->ulCurrent = NextIndex;
  894. CurrentSample = &SampleTable->SampleArray[NextIndex];
  895. CurrentSample->TimeStamp = CurrentTime;
  896. CurrentSample->ulBytes = Bytes;
  897. CurrentSample->ulReferenceCount = 1;
  898. SampleTable->ulSampleCount++;
  899. ASSERT(SampleTable->ulSampleCount <= SampleTable->ulSampleArraySize);
  900. }
  901. SampleTable->ulCurrentSampleByteCount += Bytes;
  902. }
  903. VOID
  904. UpdateBandwidthOnDemand(
  905. PBOND_INFO BonDInfo,
  906. ULONG Bytes
  907. )
  908. /*++
  909. Routine Name:
  910. Routine Description:
  911. Arguments:
  912. Return Values:
  913. --*/
  914. {
  915. PSAMPLE_TABLE SampleTable = &BonDInfo->SampleTable;
  916. //
  917. // Age and update the sample table
  918. //
  919. AgeSampleTable(SampleTable);
  920. UpdateSampleTable(SampleTable, Bytes);
  921. }
  922. VOID
  923. CheckUpperThreshold(
  924. PBUNDLECB BundleCB
  925. )
  926. /*++
  927. Routine Name:
  928. Routine Description:
  929. Arguments:
  930. Return Values:
  931. --*/
  932. {
  933. WAN_TIME CurrentTime, TimeDiff;
  934. PBOND_INFO BonDInfo;
  935. PSAMPLE_TABLE SampleTable;
  936. ULONGLONG Bps;
  937. BOOLEAN SSignal, RSignal;
  938. //
  939. // First check send side
  940. //
  941. BonDInfo = BundleCB->SUpperBonDInfo;
  942. SSignal = FALSE;
  943. SampleTable = &BonDInfo->SampleTable;
  944. Bps = SampleTable->ulCurrentSampleByteCount;
  945. //
  946. // Switch on the current state
  947. //
  948. switch (BonDInfo->State) {
  949. case BonDSignaled:
  950. break;
  951. case BonDIdle:
  952. //
  953. // We are currently below the upper threshold. If we
  954. // go over the upperthreshold we will set the time and
  955. // transition to the monitor state.
  956. //
  957. if (Bps >= BonDInfo->ulBytesThreshold) {
  958. NdisWanGetSystemTime(&BonDInfo->StartTime);
  959. BonDInfo->State = BonDMonitor;
  960. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("U-S: i -> m, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
  961. }
  962. break;
  963. case BonDMonitor:
  964. //
  965. // We are currently in the monitor state which means that
  966. // we have gone above the upper threshold. If we fall below
  967. // the upper threshold we will go back to the idle state.
  968. //
  969. if (Bps < BonDInfo->ulBytesThreshold) {
  970. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("U-S: m -> i, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
  971. BonDInfo->State = BonDIdle;
  972. } else {
  973. NdisWanGetSystemTime(&CurrentTime);
  974. NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &BonDInfo->StartTime);
  975. if (!NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SamplePeriod)) {
  976. SSignal = TRUE;
  977. }
  978. }
  979. break;
  980. }
  981. //
  982. // Now check the receive side
  983. //
  984. BonDInfo = BundleCB->RUpperBonDInfo;
  985. RSignal = FALSE;
  986. SampleTable = &BonDInfo->SampleTable;
  987. Bps = SampleTable->ulCurrentSampleByteCount;
  988. switch (BonDInfo->State) {
  989. case BonDSignaled:
  990. break;
  991. case BonDIdle:
  992. //
  993. // We are currently below the upper threshold. If we
  994. // go over the upperthreshold we will set the time and
  995. // transition to the monitor state.
  996. //
  997. if (Bps >= BonDInfo->ulBytesThreshold) {
  998. NdisWanGetSystemTime(&BonDInfo->StartTime);
  999. BonDInfo->State = BonDMonitor;
  1000. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("U-R: i -> m, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
  1001. }
  1002. break;
  1003. case BonDMonitor:
  1004. //
  1005. // We are currently in the monitor state which means that
  1006. // we have gone above the upper threshold. If we fall below
  1007. // the upper threshold we will go back to the idle state.
  1008. //
  1009. if (Bps < BonDInfo->ulBytesThreshold) {
  1010. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("U-R: m -> i, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
  1011. BonDInfo->State = BonDIdle;
  1012. } else {
  1013. NdisWanGetSystemTime(&CurrentTime);
  1014. NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &BonDInfo->StartTime);
  1015. if (!NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SamplePeriod)) {
  1016. RSignal = TRUE;
  1017. }
  1018. }
  1019. break;
  1020. }
  1021. if (SSignal || RSignal) {
  1022. //
  1023. // We have been above the threshold for time greater than the
  1024. // threshold sample period so we need to notify someone of this
  1025. // historic event!
  1026. //
  1027. CompleteThresholdEvent(BundleCB, BonDInfo->DataType, UPPER_THRESHOLD);
  1028. BundleCB->SUpperBonDInfo->State = BonDSignaled;
  1029. BundleCB->RUpperBonDInfo->State = BonDSignaled;
  1030. #if DBG
  1031. {
  1032. ULONGLONG util;
  1033. util = BundleCB->SUpperBonDInfo->SampleTable.ulCurrentSampleByteCount;
  1034. util *= 100;
  1035. util /= BundleCB->SUpperBonDInfo->ulBytesInSamplePeriod;
  1036. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("U-S: Bps %I64d Threshold %I64d Util %I64d",
  1037. Bps, BundleCB->SUpperBonDInfo->ulBytesThreshold, util));
  1038. util = BundleCB->RUpperBonDInfo->SampleTable.ulCurrentSampleByteCount;
  1039. util *= 100;
  1040. util /= BundleCB->RUpperBonDInfo->ulBytesInSamplePeriod;
  1041. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("U-R: Bps %I64d Threshold %I64d Util %I64d",
  1042. Bps, BundleCB->RUpperBonDInfo->ulBytesThreshold, util));
  1043. }
  1044. #endif
  1045. }
  1046. }
  1047. VOID
  1048. CheckLowerThreshold(
  1049. PBUNDLECB BundleCB
  1050. )
  1051. /*++
  1052. Routine Name:
  1053. Routine Description:
  1054. Arguments:
  1055. Return Values:
  1056. --*/
  1057. {
  1058. WAN_TIME CurrentTime, TimeDiff;
  1059. PBOND_INFO BonDInfo;
  1060. PSAMPLE_TABLE SampleTable;
  1061. ULONGLONG Bps;
  1062. BOOLEAN SSignal, RSignal;
  1063. if (!(BundleCB->Flags & BOND_ENABLED)) {
  1064. return;
  1065. }
  1066. //
  1067. // First check send side
  1068. //
  1069. BonDInfo = BundleCB->SLowerBonDInfo;
  1070. SampleTable = &BonDInfo->SampleTable;
  1071. Bps = SampleTable->ulCurrentSampleByteCount;
  1072. SSignal = FALSE;
  1073. //
  1074. // Switch on the current state
  1075. //
  1076. switch (BonDInfo->State) {
  1077. case BonDIdle:
  1078. //
  1079. // We are currently above the lower threshold. If we
  1080. // go under the lowerthreshold we will set the time and
  1081. // transition to the monitor state.
  1082. //
  1083. if (Bps <= BonDInfo->ulBytesThreshold) {
  1084. NdisWanGetSystemTime(&BonDInfo->StartTime);
  1085. BonDInfo->State = BonDMonitor;
  1086. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("L-S: i -> m, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
  1087. }
  1088. break;
  1089. case BonDMonitor:
  1090. //
  1091. // We are currently in the monitor state which means that
  1092. // we have gone below the lower threshold. If we climb above
  1093. // the lower threshold we will go back to the idle state.
  1094. //
  1095. if (Bps > BonDInfo->ulBytesThreshold) {
  1096. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("L-S: m -> i, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
  1097. BonDInfo->State = BonDIdle;
  1098. } else {
  1099. NdisWanGetSystemTime(&CurrentTime);
  1100. NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &BonDInfo->StartTime);
  1101. if (!NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SamplePeriod)) {
  1102. SSignal = TRUE;
  1103. }
  1104. }
  1105. break;
  1106. case BonDSignaled:
  1107. break;
  1108. }
  1109. //
  1110. // Now check the receive side
  1111. //
  1112. BonDInfo = BundleCB->RLowerBonDInfo;
  1113. RSignal = FALSE;
  1114. SampleTable = &BonDInfo->SampleTable;
  1115. Bps = SampleTable->ulCurrentSampleByteCount;
  1116. switch (BonDInfo->State) {
  1117. case BonDIdle:
  1118. //
  1119. // We are currently above the lower threshold. If we
  1120. // go below the lowerthreshold we will set the time and
  1121. // transition to the monitor state.
  1122. //
  1123. if (Bps <= BonDInfo->ulBytesThreshold) {
  1124. NdisWanGetSystemTime(&BonDInfo->StartTime);
  1125. BonDInfo->State = BonDMonitor;
  1126. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("L-R: i -> m, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
  1127. }
  1128. break;
  1129. case BonDMonitor:
  1130. //
  1131. // We are currently in the monitor state which means that
  1132. // we have gone below the lower threshold. If we climb above
  1133. // the lower threshold we will go back to the idle state.
  1134. //
  1135. if (Bps > BonDInfo->ulBytesThreshold) {
  1136. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("L-R: m -> i, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
  1137. BonDInfo->State = BonDIdle;
  1138. } else {
  1139. NdisWanGetSystemTime(&CurrentTime);
  1140. NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &BonDInfo->StartTime);
  1141. if (!NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SamplePeriod)) {
  1142. RSignal = TRUE;
  1143. }
  1144. }
  1145. break;
  1146. case BonDSignaled:
  1147. break;
  1148. }
  1149. if (SSignal && RSignal) {
  1150. //
  1151. // We have been above the threshold for time greater than the
  1152. // threshold sample period so we need to notify someone of this
  1153. // historic event!
  1154. //
  1155. CompleteThresholdEvent(BundleCB, BonDInfo->DataType, LOWER_THRESHOLD);
  1156. BundleCB->SLowerBonDInfo->State = BonDSignaled;
  1157. BundleCB->RLowerBonDInfo->State = BonDSignaled;
  1158. #if DBG
  1159. {
  1160. ULONGLONG util;
  1161. util = BundleCB->SLowerBonDInfo->SampleTable.ulCurrentSampleByteCount;
  1162. util *= 100;
  1163. util /= BundleCB->SLowerBonDInfo->ulBytesInSamplePeriod;
  1164. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("L-S: Bps %I64d Threshold %I64d Util %I64d",
  1165. Bps, BundleCB->SLowerBonDInfo->ulBytesThreshold, util));
  1166. util = BundleCB->RLowerBonDInfo->SampleTable.ulCurrentSampleByteCount;
  1167. util *= 100;
  1168. util /= BundleCB->RLowerBonDInfo->ulBytesInSamplePeriod;
  1169. NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("L-R: Bps %I64d Threshold %I64d Util %I64d",
  1170. Bps, BundleCB->RLowerBonDInfo->ulBytesThreshold, util));
  1171. }
  1172. #endif
  1173. }
  1174. }
  1175. #endif // end of ifdef NT
  1176. #if DBG
  1177. VOID
  1178. InsertSendTrc(
  1179. PSEND_TRC_INFO SendTrcInfo,
  1180. ULONG DataLength,
  1181. PUCHAR Data
  1182. )
  1183. {
  1184. PWAN_TRC_EVENT NewTrcEvent;
  1185. PSEND_TRC_INFO TrcInfo;
  1186. if (WanTrcCount == 4096) {
  1187. NewTrcEvent = (PWAN_TRC_EVENT)
  1188. RemoveTailList(&WanTrcList);
  1189. NdisWanFreeMemory(NewTrcEvent->TrcInfo);
  1190. NdisZeroMemory(NewTrcEvent, sizeof(WAN_TRC_EVENT));
  1191. } else {
  1192. NdisWanAllocateMemory(&NewTrcEvent,
  1193. sizeof(WAN_TRC_EVENT),
  1194. WANTRCEVENT_TAG);
  1195. if (NewTrcEvent == NULL) {
  1196. return;
  1197. }
  1198. }
  1199. WanTrcCount += 1;
  1200. }
  1201. #endif