mirror of https://github.com/tongzx/nt5src
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
1596 lines
36 KiB
/*++
|
|
|
|
Copyright (c) 1990-1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Util.c
|
|
|
|
Abstract:
|
|
|
|
This file contains utility functions used by NdisWan.
|
|
|
|
Author:
|
|
|
|
Tony Bell (TonyBe) June 06, 1995
|
|
|
|
Environment:
|
|
|
|
Kernel Mode
|
|
|
|
Revision History:
|
|
|
|
TonyBe 06/06/95 Created
|
|
|
|
--*/
|
|
|
|
#include "wan.h"
|
|
|
|
#define __FILE_SIG__ UTIL_FILESIG
|
|
|
|
VOID
|
|
NdisWanCopyFromPacketToBuffer(
|
|
IN PNDIS_PACKET pNdisPacket,
|
|
IN ULONG Offset,
|
|
IN ULONG BytesToCopy,
|
|
OUT PUCHAR Buffer,
|
|
OUT PULONG BytesCopied
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
ULONG NdisBufferCount;
|
|
PNDIS_BUFFER CurrentBuffer;
|
|
PVOID VirtualAddress;
|
|
ULONG CurrentLength, AmountToMove;
|
|
ULONG LocalBytesCopied = 0, PacketLength;
|
|
|
|
*BytesCopied = 0;
|
|
|
|
//
|
|
// Take care of zero byte copy
|
|
//
|
|
if (!BytesToCopy) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Get the buffer count
|
|
//
|
|
NdisQueryPacket(pNdisPacket,
|
|
NULL,
|
|
&NdisBufferCount,
|
|
&CurrentBuffer,
|
|
&PacketLength);
|
|
|
|
//
|
|
// Could be a null packet
|
|
//
|
|
if (!NdisBufferCount ||
|
|
Offset == PacketLength) {
|
|
return;
|
|
}
|
|
|
|
|
|
NdisQueryBuffer(CurrentBuffer,
|
|
&VirtualAddress,
|
|
&CurrentLength);
|
|
|
|
while (LocalBytesCopied < BytesToCopy &&
|
|
LocalBytesCopied < PacketLength) {
|
|
|
|
//
|
|
// No more bytes left in this buffer
|
|
//
|
|
if (!CurrentLength) {
|
|
|
|
//
|
|
// Get the next buffer
|
|
//
|
|
NdisGetNextBuffer(CurrentBuffer,
|
|
&CurrentBuffer);
|
|
|
|
//
|
|
// End of the packet, copy what we can
|
|
//
|
|
if (CurrentBuffer == NULL) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
NdisQueryBuffer(CurrentBuffer,
|
|
&VirtualAddress,
|
|
&CurrentLength);
|
|
|
|
if (!CurrentLength) {
|
|
continue;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Get to the point where we can start copying
|
|
//
|
|
if (Offset) {
|
|
|
|
if (Offset > CurrentLength) {
|
|
|
|
//
|
|
// Not in this buffer, go to the next one
|
|
//
|
|
Offset -= CurrentLength;
|
|
CurrentLength = 0;
|
|
continue;
|
|
|
|
} else {
|
|
|
|
//
|
|
// At least some in this buffer
|
|
//
|
|
VirtualAddress = (PUCHAR)VirtualAddress + Offset;
|
|
CurrentLength -= Offset;
|
|
Offset = 0;
|
|
}
|
|
}
|
|
|
|
if (!CurrentLength) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// We can copy some data. If we need more data than is available
|
|
// in this buffer we can copy what we need and go back for more.
|
|
//
|
|
AmountToMove = (CurrentLength > (BytesToCopy - LocalBytesCopied)) ?
|
|
(BytesToCopy - LocalBytesCopied) : CurrentLength;
|
|
|
|
NdisMoveMemory(Buffer, VirtualAddress, AmountToMove);
|
|
|
|
Buffer = (PUCHAR)Buffer + AmountToMove;
|
|
|
|
VirtualAddress = (PUCHAR)VirtualAddress + AmountToMove;
|
|
|
|
LocalBytesCopied += AmountToMove;
|
|
|
|
CurrentLength -= AmountToMove;
|
|
}
|
|
|
|
*BytesCopied = LocalBytesCopied;
|
|
}
|
|
|
|
VOID
|
|
NdisWanCopyFromBufferToPacket(
|
|
PUCHAR Buffer,
|
|
ULONG BytesToCopy,
|
|
PNDIS_PACKET NdisPacket,
|
|
ULONG PacketOffset,
|
|
PULONG BytesCopied
|
|
)
|
|
{
|
|
PNDIS_BUFFER NdisBuffer;
|
|
ULONG NdisBufferCount, NdisBufferLength;
|
|
PVOID VirtualAddress;
|
|
ULONG LocalBytesCopied = 0;
|
|
|
|
*BytesCopied = 0;
|
|
|
|
//
|
|
// Make sure we actually want to do something
|
|
//
|
|
if (BytesToCopy == 0) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Get the buffercount of the packet
|
|
//
|
|
NdisQueryPacket(NdisPacket,
|
|
NULL,
|
|
&NdisBufferCount,
|
|
&NdisBuffer,
|
|
NULL);
|
|
|
|
//
|
|
// Make sure this is not a null packet
|
|
//
|
|
if (NdisBufferCount == 0) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Get first buffer and buffer length
|
|
//
|
|
NdisQueryBuffer(NdisBuffer,
|
|
&VirtualAddress,
|
|
&NdisBufferLength);
|
|
|
|
while (LocalBytesCopied < BytesToCopy) {
|
|
|
|
if (NdisBufferLength == 0) {
|
|
|
|
NdisGetNextBuffer(NdisBuffer,
|
|
&NdisBuffer);
|
|
|
|
if (NdisBuffer == NULL) {
|
|
break;
|
|
}
|
|
|
|
NdisQueryBuffer(NdisBuffer,
|
|
&VirtualAddress,
|
|
&NdisBufferLength);
|
|
|
|
continue;
|
|
}
|
|
|
|
if (PacketOffset != 0) {
|
|
|
|
if (PacketOffset > NdisBufferLength) {
|
|
|
|
PacketOffset -= NdisBufferLength;
|
|
|
|
NdisBufferLength = 0;
|
|
|
|
continue;
|
|
|
|
} else {
|
|
VirtualAddress = (PUCHAR)VirtualAddress + PacketOffset;
|
|
NdisBufferLength -= PacketOffset;
|
|
PacketOffset = 0;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Copy the data
|
|
//
|
|
{
|
|
ULONG AmountToMove;
|
|
ULONG AmountRemaining;
|
|
|
|
AmountRemaining = BytesToCopy - LocalBytesCopied;
|
|
|
|
AmountToMove = (NdisBufferLength < AmountRemaining) ?
|
|
NdisBufferLength : AmountRemaining;
|
|
|
|
NdisMoveMemory((PUCHAR)VirtualAddress,
|
|
Buffer,
|
|
AmountToMove);
|
|
|
|
Buffer += AmountToMove;
|
|
LocalBytesCopied += AmountToMove;
|
|
NdisBufferLength -= AmountToMove;
|
|
}
|
|
}
|
|
|
|
*BytesCopied = LocalBytesCopied;
|
|
}
|
|
|
|
BOOLEAN
|
|
IsLinkValid(
|
|
NDIS_HANDLE LinkHandle,
|
|
BOOLEAN CheckState,
|
|
PLINKCB *LinkCB
|
|
)
|
|
{
|
|
PLINKCB plcb;
|
|
LOCK_STATE LockState;
|
|
BOOLEAN Valid;
|
|
|
|
*LinkCB = NULL;
|
|
Valid = FALSE;
|
|
|
|
NdisAcquireReadWriteLock(&ConnTableLock, FALSE, &LockState);
|
|
|
|
do {
|
|
|
|
if (PtrToUlong(LinkHandle) > ConnectionTable->ulArraySize) {
|
|
break;
|
|
}
|
|
|
|
plcb = *(ConnectionTable->LinkArray + PtrToUlong(LinkHandle));
|
|
|
|
if (plcb == NULL) {
|
|
break;
|
|
}
|
|
|
|
NdisDprAcquireSpinLock(&plcb->Lock);
|
|
|
|
if (CheckState &&
|
|
(plcb->State != LINK_UP)) {
|
|
|
|
NdisDprReleaseSpinLock(&plcb->Lock);
|
|
break;
|
|
}
|
|
|
|
REF_LINKCB(plcb);
|
|
NdisDprReleaseSpinLock(&plcb->Lock);
|
|
|
|
*LinkCB = plcb;
|
|
|
|
Valid = TRUE;
|
|
|
|
} while (FALSE);
|
|
|
|
|
|
NdisReleaseReadWriteLock(&ConnTableLock, &LockState);
|
|
|
|
return (Valid);
|
|
}
|
|
|
|
BOOLEAN
|
|
IsBundleValid(
|
|
NDIS_HANDLE BundleHandle,
|
|
BOOLEAN CheckState,
|
|
PBUNDLECB *BundleCB
|
|
)
|
|
{
|
|
PBUNDLECB pbcb;
|
|
LOCK_STATE LockState;
|
|
BOOLEAN Valid;
|
|
|
|
*BundleCB = NULL;
|
|
Valid = FALSE;
|
|
|
|
NdisAcquireReadWriteLock(&ConnTableLock, FALSE, &LockState);
|
|
|
|
do {
|
|
if (PtrToUlong(BundleHandle) > ConnectionTable->ulArraySize) {
|
|
break;
|
|
}
|
|
|
|
pbcb = *(ConnectionTable->BundleArray + PtrToUlong(BundleHandle));
|
|
|
|
if (pbcb == NULL) {
|
|
break;
|
|
}
|
|
|
|
NdisDprAcquireSpinLock(&pbcb->Lock);
|
|
|
|
if (CheckState &&
|
|
(pbcb->State != BUNDLE_UP)) {
|
|
|
|
NdisDprReleaseSpinLock(&pbcb->Lock);
|
|
break;
|
|
}
|
|
|
|
REF_BUNDLECB(pbcb);
|
|
NdisDprReleaseSpinLock(&pbcb->Lock);
|
|
|
|
*BundleCB = pbcb;
|
|
|
|
Valid = TRUE;
|
|
|
|
} while (FALSE);
|
|
|
|
NdisReleaseReadWriteLock(&ConnTableLock, &LockState);
|
|
|
|
return (Valid);
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
AreLinkAndBundleValid(
|
|
NDIS_HANDLE LinkHandle,
|
|
BOOLEAN CheckState,
|
|
PLINKCB *LinkCB,
|
|
PBUNDLECB *BundleCB
|
|
)
|
|
{
|
|
PLINKCB plcb;
|
|
PBUNDLECB pbcb;
|
|
LOCK_STATE LockState;
|
|
BOOLEAN Valid;
|
|
|
|
*LinkCB = NULL;
|
|
*BundleCB = NULL;
|
|
Valid = FALSE;
|
|
|
|
NdisAcquireReadWriteLock(&ConnTableLock, FALSE, &LockState);
|
|
|
|
do {
|
|
|
|
if (PtrToUlong(LinkHandle) > ConnectionTable->ulArraySize) {
|
|
break;
|
|
}
|
|
|
|
plcb = *(ConnectionTable->LinkArray + PtrToUlong(LinkHandle));
|
|
|
|
if (plcb == NULL) {
|
|
break;
|
|
}
|
|
|
|
NdisDprAcquireSpinLock(&plcb->Lock);
|
|
|
|
if (CheckState &&
|
|
(plcb->State != LINK_UP)) {
|
|
|
|
NdisDprReleaseSpinLock(&plcb->Lock);
|
|
break;
|
|
}
|
|
|
|
pbcb = plcb->BundleCB;
|
|
|
|
if (pbcb == NULL) {
|
|
NdisDprReleaseSpinLock(&plcb->Lock);
|
|
break;
|
|
}
|
|
|
|
REF_LINKCB(plcb);
|
|
NdisDprReleaseSpinLock(&plcb->Lock);
|
|
|
|
NdisDprAcquireSpinLock(&pbcb->Lock);
|
|
REF_BUNDLECB(pbcb);
|
|
NdisDprReleaseSpinLock(&pbcb->Lock);
|
|
|
|
*LinkCB = plcb;
|
|
*BundleCB = pbcb;
|
|
|
|
Valid = TRUE;
|
|
|
|
} while (FALSE);
|
|
|
|
NdisReleaseReadWriteLock(&ConnTableLock, &LockState);
|
|
|
|
return (Valid);
|
|
}
|
|
|
|
//
|
|
// Called with BundleCB->Lock held
|
|
//
|
|
VOID
|
|
DoDerefBundleCBWork(
|
|
PBUNDLECB BundleCB
|
|
)
|
|
{
|
|
ASSERT(BundleCB->State == BUNDLE_GOING_DOWN);
|
|
ASSERT(BundleCB->OutstandingFrames == 0);
|
|
ASSERT(BundleCB->ulNumberOfRoutes == 0);
|
|
ASSERT(BundleCB->ulLinkCBCount == 0);
|
|
ReleaseBundleLock(BundleCB);
|
|
RemoveBundleFromConnectionTable(BundleCB);
|
|
NdisWanFreeBundleCB(BundleCB);
|
|
}
|
|
|
|
//
|
|
// Called with LinkCB->Lock held
|
|
//
|
|
VOID
|
|
DoDerefLinkCBWork(
|
|
PLINKCB LinkCB
|
|
)
|
|
{
|
|
PBUNDLECB _pbcb = LinkCB->BundleCB;
|
|
|
|
ASSERT(LinkCB->State == LINK_GOING_DOWN);
|
|
ASSERT(LinkCB->OutstandingFrames == 0);
|
|
NdisReleaseSpinLock(&LinkCB->Lock);
|
|
RemoveLinkFromBundle(_pbcb, LinkCB, FALSE);
|
|
RemoveLinkFromConnectionTable(LinkCB);
|
|
NdisWanFreeLinkCB(LinkCB);
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
VOID
|
|
DoDerefCmVcCBWork(
|
|
PCM_VCCB VcCB
|
|
)
|
|
{
|
|
InterlockedExchange((PLONG)&(VcCB)->State, CMVC_DEACTIVE);
|
|
NdisMCmDeactivateVc(VcCB->NdisVcHandle);
|
|
NdisMCmCloseCallComplete(NDIS_STATUS_SUCCESS,
|
|
VcCB->NdisVcHandle,
|
|
NULL);
|
|
}
|
|
|
|
//
|
|
// Called with ClAfSap->Lock held
|
|
//
|
|
VOID
|
|
DoDerefClAfSapCBWork(
|
|
PCL_AFSAPCB AfSapCB
|
|
)
|
|
{
|
|
NDIS_STATUS Status;
|
|
|
|
ASSERT(AfSapCB->Flags & SAP_REGISTERED);
|
|
|
|
if (AfSapCB->Flags & SAP_REGISTERED) {
|
|
|
|
AfSapCB->Flags &= ~(SAP_REGISTERED);
|
|
AfSapCB->Flags |= (SAP_DEREGISTERING);
|
|
|
|
NdisReleaseSpinLock(&AfSapCB->Lock);
|
|
|
|
Status = NdisClDeregisterSap(AfSapCB->SapHandle);
|
|
|
|
if (Status != NDIS_STATUS_PENDING) {
|
|
ClDeregisterSapComplete(Status, AfSapCB);
|
|
}
|
|
|
|
} else {
|
|
|
|
NdisReleaseSpinLock(&AfSapCB->Lock);
|
|
|
|
}
|
|
}
|
|
|
|
VOID
|
|
DerefVc(
|
|
PLINKCB LinkCB
|
|
)
|
|
{
|
|
//
|
|
// Ref applied when we sent the packet to the underlying
|
|
// miniport
|
|
//
|
|
LinkCB->VcRefCount--;
|
|
|
|
if ((LinkCB->ClCallState == CL_CALL_CLOSE_PENDING) &&
|
|
(LinkCB->VcRefCount == 0) ) {
|
|
|
|
NDIS_STATUS CloseStatus;
|
|
|
|
LinkCB->ClCallState = CL_CALL_CLOSED;
|
|
|
|
NdisReleaseSpinLock(&LinkCB->Lock);
|
|
|
|
CloseStatus =
|
|
NdisClCloseCall(LinkCB->NdisLinkHandle,
|
|
NULL,
|
|
NULL,
|
|
0);
|
|
|
|
if (CloseStatus != NDIS_STATUS_PENDING) {
|
|
ClCloseCallComplete(CloseStatus,
|
|
LinkCB,
|
|
NULL);
|
|
}
|
|
|
|
NdisAcquireSpinLock(&LinkCB->Lock);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
DeferredWorker(
|
|
PKDPC Dpc,
|
|
PVOID Context,
|
|
PVOID Arg1,
|
|
PVOID Arg2
|
|
)
|
|
{
|
|
NdisAcquireSpinLock(&DeferredWorkList.Lock);
|
|
|
|
while (!(IsListEmpty(&DeferredWorkList.List))) {
|
|
PLIST_ENTRY Entry;
|
|
PBUNDLECB BundleCB;
|
|
|
|
Entry = RemoveHeadList(&DeferredWorkList.List);
|
|
DeferredWorkList.ulCount--;
|
|
|
|
NdisReleaseSpinLock(&DeferredWorkList.Lock);
|
|
|
|
BundleCB =
|
|
CONTAINING_RECORD(Entry, BUNDLECB, DeferredLinkage);
|
|
|
|
AcquireBundleLock(BundleCB);
|
|
|
|
BundleCB->Flags &= ~DEFERRED_WORK_QUEUED;
|
|
|
|
//
|
|
// Do all of the deferred work items for this Bundle
|
|
//
|
|
SendPacketOnBundle(BundleCB);
|
|
|
|
//
|
|
// Deref for the ref applied when we inserted this item on
|
|
// the worker queue.
|
|
//
|
|
DEREF_BUNDLECB(BundleCB);
|
|
|
|
NdisAcquireSpinLock(&DeferredWorkList.Lock);
|
|
}
|
|
|
|
DeferredWorkList.TimerScheduled = FALSE;
|
|
|
|
NdisReleaseSpinLock(&DeferredWorkList.Lock);
|
|
}
|
|
|
|
NTSTATUS
|
|
TransformRegister(
|
|
PVOID ClientOpenContext,
|
|
ULONG CharsSize,
|
|
PTRANSFORM_CHARACTERISTICS Chars,
|
|
ULONG CapsSize,
|
|
PTRANSFORM_INFO Caps
|
|
)
|
|
{
|
|
PTRANSDRVCB TransDrvCB = (PTRANSDRVCB)ClientOpenContext;
|
|
PTRANSDRVCB tTransDrvCB;
|
|
PTRANSFORM_IE Ie = (PTRANSFORM_IE)(Caps->InfoElements);
|
|
PTRANSFORM_IE tIe;
|
|
UINT i, FoundCount = 0, MemoryNeeded = 0;
|
|
|
|
#if 0
|
|
InterlockedExchange((PLONG)&TransDrvCB->State, TRANSDRV_REGISTERING);
|
|
|
|
for (i = 0; i < Caps->InfoElementCount; i++) {
|
|
|
|
if (Ie->IEType == TRANS_PPP_COMPRESSION ||
|
|
Ie->IEType == TRANS_PPP_ENCRYPTION) {
|
|
//
|
|
// This is an IEType that we are interested in
|
|
// but we have some requirements...
|
|
// 1. It must support the framed interface unless it is
|
|
// MPPC/MPPE.
|
|
// 2. If we already have a driver registered that supports
|
|
// this scheme we will not add this in again.
|
|
// 3. We will give priority to drivers that have hardware
|
|
// assisted data transformation.
|
|
//
|
|
|
|
//
|
|
// Walk the transform driver list and see if
|
|
// this scheme is already registered by another
|
|
// driver. If it is, see if either has hardware
|
|
// support. If they have the same level of support
|
|
// just use the one currently registered. If the new
|
|
// ie has a higher level of support mark the old ie
|
|
// as not being used
|
|
//
|
|
NdisAcquireSpinLock(&TransformDrvList.Lock);
|
|
for (tTransDrvCB = (PTRANSDRVCB)TransformDrvList.List.Flink;
|
|
(PVOID)tTransDrvCB != (PVOID)&TransformDrvList.List;
|
|
tTransDrvCB = (PTRANSDRVCB)tTransDrvCB->Linkage.Flink) {
|
|
|
|
tIe = (PTRANSFORM_IE)tTransDrvCB->Caps->InfoElements;
|
|
for (i = 0; i < tTransDrvCB->Caps->InfoElementCount; i++) {
|
|
|
|
if (tIe->Flags & IE_IN_USE) {
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
NdisReleaseSpinLock(&TransformDrvList.Lock);
|
|
|
|
MemoryNeeded += Ie->IESize;
|
|
}
|
|
|
|
Ie = (PTRANSFORM_IE)((PUCHAR)Ie + Ie->IESize);
|
|
}
|
|
|
|
if (FoundCount == 0) {
|
|
return (STATUS_UNSUCCESSFUL);
|
|
}
|
|
|
|
NdisWanAllocateMemory(&TransDrvCB->Caps,
|
|
MemoryNeeded,
|
|
TRANSDRV_TAG);
|
|
|
|
if (TransDrvCB->Caps == NULL) {
|
|
return (STATUS_UNSUCCESSFUL);
|
|
}
|
|
|
|
TransDrvCB->Caps->InfoElementCount = FoundCount;
|
|
tIe = (PTRANSFORM_IE)(TransDrvCB->Caps->InfoElements);
|
|
|
|
for (i = 0; i < Caps->InfoElementCount; i++) {
|
|
|
|
if (Ie->IEType == TRANS_PPP_COMPRESSION ||
|
|
Ie->IEType == TRANS_PPP_ENCRYPTION) {
|
|
NdisMoveMemory(tIe, Ie, Ie->IESize);
|
|
}
|
|
|
|
Ie = (PTRANSFORM_IE)((PUCHAR)Ie + Ie->IESize);
|
|
tIe = (PTRANSFORM_IE)((PUCHAR)tIe + tIe->IESize);
|
|
}
|
|
|
|
NdisMoveMemory(&TransDrvCB->Chars, Chars, CharsSize);
|
|
#endif
|
|
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
|
|
VOID
|
|
TransformTxComplete(
|
|
NTSTATUS Status,
|
|
PVOID TxCtx,
|
|
PMDL InData,
|
|
PMDL OutData,
|
|
ULONG OutDataOffset,
|
|
ULONG OutDataLength
|
|
)
|
|
{
|
|
|
|
}
|
|
|
|
VOID
|
|
TransformRxComplete(
|
|
NTSTATUS Status,
|
|
PVOID RxCtx,
|
|
PMDL InData,
|
|
PMDL OutData,
|
|
ULONG OutDataOffset,
|
|
ULONG OutDataLength
|
|
)
|
|
{
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
TransformSendCtrlPacket(
|
|
PVOID TxCtx,
|
|
ULONG DataLength,
|
|
PUCHAR Data
|
|
)
|
|
{
|
|
|
|
return (STATUS_SUCCESS);
|
|
}
|
|
|
|
|
|
#ifdef NT
|
|
|
|
VOID
|
|
NdisWanStringToNdisString(
|
|
PNDIS_STRING pDestString,
|
|
PWSTR pSrcBuffer
|
|
)
|
|
{
|
|
PWSTR Dest, Src = pSrcBuffer;
|
|
NDIS_STRING SrcString;
|
|
|
|
NdisWanInitUnicodeString(&SrcString, pSrcBuffer);
|
|
NdisWanAllocateMemory(&pDestString->Buffer, SrcString.MaximumLength, NDISSTRING_TAG);
|
|
if (pDestString->Buffer == NULL) {
|
|
return;
|
|
}
|
|
pDestString->MaximumLength = SrcString.MaximumLength;
|
|
pDestString->Length = SrcString.Length;
|
|
NdisWanCopyUnicodeString(pDestString, &SrcString);
|
|
}
|
|
|
|
VOID
|
|
NdisWanInitUnicodeString(
|
|
OUT PUNICODE_STRING DestinationString,
|
|
IN PCWSTR SourceString OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The NdisWanInitUnicodeString function initializes an NT counted
|
|
unicode string. The DestinationString is initialized to point to
|
|
the SourceString and the Length and MaximumLength fields of
|
|
DestinationString are initialized to the length of the SourceString,
|
|
which is zero if SourceString is not specified.
|
|
|
|
Arguments:
|
|
|
|
DestinationString - Pointer to the counted string to initialize
|
|
|
|
SourceString - Optional pointer to a null terminated unicode string that
|
|
the counted string is to point to.
|
|
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Length;
|
|
|
|
DestinationString->Buffer = (PWSTR)SourceString;
|
|
if (ARGUMENT_PRESENT( SourceString )) {
|
|
Length = wcslen( SourceString ) * sizeof( WCHAR );
|
|
DestinationString->Length = (USHORT)Length;
|
|
DestinationString->MaximumLength = (USHORT)(Length + sizeof(UNICODE_NULL));
|
|
}
|
|
else {
|
|
DestinationString->MaximumLength = 0;
|
|
DestinationString->Length = 0;
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
NdisWanCopyUnicodeString(
|
|
OUT PUNICODE_STRING DestinationString,
|
|
IN PUNICODE_STRING SourceString OPTIONAL
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The NdisWanCopyUnicodeString function copies the SourceString
|
|
to the DestinationString. If SourceString is not specified,
|
|
then the Length field of DestinationString is set to zero. The
|
|
MaximumLength and Buffer fields of DestinationString are not
|
|
modified by this function.
|
|
|
|
The number of bytes copied from the SourceString is either the
|
|
Length of SourceString or the MaximumLength of DestinationString,
|
|
whichever is smaller.
|
|
|
|
Arguments:
|
|
|
|
DestinationString - Pointer to the destination string.
|
|
|
|
SourceString - Optional pointer to the source string.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UNALIGNED WCHAR *src, *dst;
|
|
ULONG n;
|
|
|
|
if (ARGUMENT_PRESENT(SourceString)) {
|
|
dst = DestinationString->Buffer;
|
|
src = SourceString->Buffer;
|
|
n = SourceString->Length;
|
|
if ((USHORT)n > DestinationString->MaximumLength) {
|
|
n = DestinationString->MaximumLength;
|
|
}
|
|
|
|
DestinationString->Length = (USHORT)n;
|
|
RtlCopyMemory(dst, src, n);
|
|
if (DestinationString->Length < DestinationString->MaximumLength) {
|
|
dst[n / sizeof(WCHAR)] = UNICODE_NULL;
|
|
}
|
|
|
|
} else {
|
|
DestinationString->Length = 0;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
NdisWanFreeNdisString(
|
|
PNDIS_STRING NdisString
|
|
)
|
|
{
|
|
if (NdisString->Buffer != NULL) {
|
|
NdisWanFreeMemory(NdisString->Buffer);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NdisWanAllocateAdapterName(
|
|
PNDIS_STRING Dest,
|
|
PNDIS_STRING Src
|
|
)
|
|
{
|
|
NdisWanAllocateMemory(&Dest->Buffer, Src->MaximumLength, NDISSTRING_TAG);
|
|
if (Dest->Buffer != NULL) {
|
|
Dest->MaximumLength = Src->MaximumLength;
|
|
Dest->Length = Src->Length;
|
|
RtlUpcaseUnicodeString(Dest, Src, FALSE);
|
|
}
|
|
}
|
|
|
|
BOOLEAN
|
|
NdisWanCompareNdisString(
|
|
PNDIS_STRING NdisString1,
|
|
PNDIS_STRING NdisString2
|
|
)
|
|
{
|
|
USHORT l1 = NdisString1->Length;
|
|
USHORT l2 = NdisString2->Length;
|
|
PWSTR s1 = NdisString1->Buffer;
|
|
PWSTR s2 = NdisString2->Buffer;
|
|
PWSTR EndCompare;
|
|
|
|
ASSERT(l1 != 0);
|
|
ASSERT(l2 != 0);
|
|
|
|
if (l1 == l2) {
|
|
|
|
EndCompare = (PWSTR)((PUCHAR)s1 + l1);
|
|
|
|
while (s1 < EndCompare) {
|
|
|
|
if (*s1++ != *s2++) {
|
|
return (FALSE);
|
|
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
//VOID
|
|
//NdisWanFreeNdisString(
|
|
// PNDIS_STRING NdisString
|
|
// )
|
|
//{
|
|
// NdisFreeMemory(NdisString->Buffer,
|
|
// NdisString->MaximumLength * sizeof(WCHAR),
|
|
// 0);
|
|
//}
|
|
|
|
VOID
|
|
NdisWanNdisStringToInteger(
|
|
PNDIS_STRING Source,
|
|
PULONG Value
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
PWSTR s = Source->Buffer;
|
|
ULONG Digit;
|
|
|
|
*Value = 0;
|
|
|
|
while (*s != UNICODE_NULL) {
|
|
|
|
if (*s >= L'0' && *s < L'9') {
|
|
Digit = *s - L'0';
|
|
} else if (*s >= L'A' && *s <= L'F') {
|
|
Digit = *s - L'A' + 10;
|
|
} else if (*s >= L'a' && *s <= L'f') {
|
|
Digit = *s - L'a' + 10;
|
|
} else {
|
|
break;
|
|
}
|
|
|
|
*Value = (*Value << 4) | Digit;
|
|
|
|
s++;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NdisWanCopyNdisString(
|
|
PNDIS_STRING Dest,
|
|
PNDIS_STRING Src
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
PWSTR SrcBuffer = Src->Buffer;
|
|
PWSTR DestBuffer = Dest->Buffer;
|
|
|
|
while (*SrcBuffer != UNICODE_NULL) {
|
|
|
|
*DestBuffer = *SrcBuffer;
|
|
|
|
SrcBuffer++;
|
|
DestBuffer++;
|
|
}
|
|
|
|
*DestBuffer = UNICODE_NULL;
|
|
|
|
Dest->Length = Src->Length;
|
|
|
|
}
|
|
|
|
VOID
|
|
BonDWorker(
|
|
PKDPC Dpc,
|
|
PVOID Context,
|
|
PVOID Arg1,
|
|
PVOID Arg2
|
|
)
|
|
{
|
|
PLIST_ENTRY Entry;
|
|
|
|
NdisAcquireSpinLock(&BonDWorkList.Lock);
|
|
|
|
for (Entry = BonDWorkList.List.Flink;
|
|
Entry != &BonDWorkList.List;
|
|
Entry = Entry->Flink) {
|
|
PBUNDLECB BundleCB;
|
|
|
|
BundleCB = CONTAINING_RECORD(Entry, BUNDLECB, BonDLinkage);
|
|
|
|
NdisReleaseSpinLock(&BonDWorkList.Lock);
|
|
|
|
AcquireBundleLock(BundleCB);
|
|
|
|
if (BundleCB->State != BUNDLE_UP ||
|
|
!(BundleCB->Flags & BOND_ENABLED)) {
|
|
ReleaseBundleLock(BundleCB);
|
|
NdisAcquireSpinLock(&BonDWorkList.Lock);
|
|
continue;
|
|
}
|
|
|
|
AgeSampleTable(&BundleCB->SUpperBonDInfo->SampleTable);
|
|
CheckUpperThreshold(BundleCB);
|
|
|
|
AgeSampleTable(&BundleCB->SLowerBonDInfo->SampleTable);
|
|
CheckLowerThreshold(BundleCB);
|
|
|
|
AgeSampleTable(&BundleCB->RUpperBonDInfo->SampleTable);
|
|
CheckUpperThreshold(BundleCB);
|
|
|
|
AgeSampleTable(&BundleCB->RLowerBonDInfo->SampleTable);
|
|
CheckUpperThreshold(BundleCB);
|
|
|
|
ReleaseBundleLock(BundleCB);
|
|
|
|
NdisAcquireSpinLock(&BonDWorkList.Lock);
|
|
}
|
|
|
|
NdisReleaseSpinLock(&BonDWorkList.Lock);
|
|
}
|
|
|
|
#if 0
|
|
VOID
|
|
CheckBonDInfo(
|
|
PKDPC Dpc,
|
|
PBUNDLECB BundleCB,
|
|
PVOID SysArg1,
|
|
PVOID SysArg2
|
|
)
|
|
{
|
|
if (!(BundleCB->Flags & BOND_ENABLED)) {
|
|
return;
|
|
}
|
|
|
|
AgeSampleTable(&BundleCB->SUpperBonDInfo.SampleTable);
|
|
CheckUpperThreshold(BundleCB);
|
|
|
|
AgeSampleTable(&BundleCB->SLowerBonDInfo.SampleTable);
|
|
CheckLowerThreshold(BundleCB);
|
|
|
|
AgeSampleTable(&BundleCB->RUpperBonDInfo.SampleTable);
|
|
CheckUpperThreshold(BundleCB);
|
|
|
|
AgeSampleTable(&BundleCB->RLowerBonDInfo.SampleTable);
|
|
CheckUpperThreshold(BundleCB);
|
|
}
|
|
#endif
|
|
|
|
VOID
|
|
AgeSampleTable(
|
|
PSAMPLE_TABLE SampleTable
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
WAN_TIME CurrentTime, TimeDiff;
|
|
ULONG HeadIndex = SampleTable->ulHead;
|
|
|
|
//
|
|
// Should return CurrentTime in 100ns units
|
|
//
|
|
NdisWanGetSystemTime(&CurrentTime);
|
|
|
|
//
|
|
// We will search through the sample indexing over samples that are more than
|
|
// one second older than the current time.
|
|
//
|
|
while (!IsSampleTableEmpty(SampleTable) ) {
|
|
PBOND_SAMPLE FirstSample;
|
|
|
|
FirstSample = &SampleTable->SampleArray[SampleTable->ulHead];
|
|
|
|
NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &FirstSample->TimeStamp);
|
|
|
|
if (NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SamplePeriod))
|
|
break;
|
|
|
|
SampleTable->ulCurrentSampleByteCount -= FirstSample->ulBytes;
|
|
|
|
ASSERT((LONG)SampleTable->ulCurrentSampleByteCount >= 0);
|
|
|
|
FirstSample->ulReferenceCount = 0;
|
|
|
|
if (++SampleTable->ulHead == SampleTable->ulSampleArraySize) {
|
|
SampleTable->ulHead = 0;
|
|
}
|
|
|
|
SampleTable->ulSampleCount--;
|
|
}
|
|
|
|
if (IsSampleTableEmpty(SampleTable)) {
|
|
ASSERT((LONG)SampleTable->ulCurrentSampleByteCount == 0);
|
|
SampleTable->ulHead = SampleTable->ulCurrent;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
UpdateSampleTable(
|
|
PSAMPLE_TABLE SampleTable,
|
|
ULONG Bytes
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
WAN_TIME CurrentTime, TimeDiff;
|
|
ULONG CurrentIndex = SampleTable->ulCurrent;
|
|
PBOND_SAMPLE CurrentSample = &SampleTable->SampleArray[CurrentIndex];
|
|
|
|
NdisWanGetSystemTime(&CurrentTime);
|
|
|
|
NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &CurrentSample->TimeStamp);
|
|
|
|
if (NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SampleRate) ||
|
|
IsSampleTableFull(SampleTable)) {
|
|
//
|
|
// Add this send on the previous sample
|
|
//
|
|
CurrentSample->ulBytes += Bytes;
|
|
CurrentSample->ulReferenceCount++;
|
|
} else {
|
|
ULONG NextIndex;
|
|
|
|
//
|
|
// We need a new sample
|
|
//
|
|
if (IsSampleTableEmpty(SampleTable)) {
|
|
NextIndex = SampleTable->ulHead;
|
|
ASSERT(NextIndex == SampleTable->ulCurrent);
|
|
} else {
|
|
NextIndex = SampleTable->ulCurrent + 1;
|
|
}
|
|
|
|
if (NextIndex == SampleTable->ulSampleArraySize) {
|
|
NextIndex = 0;
|
|
}
|
|
|
|
SampleTable->ulCurrent = NextIndex;
|
|
|
|
CurrentSample = &SampleTable->SampleArray[NextIndex];
|
|
CurrentSample->TimeStamp = CurrentTime;
|
|
CurrentSample->ulBytes = Bytes;
|
|
CurrentSample->ulReferenceCount = 1;
|
|
SampleTable->ulSampleCount++;
|
|
|
|
ASSERT(SampleTable->ulSampleCount <= SampleTable->ulSampleArraySize);
|
|
}
|
|
|
|
SampleTable->ulCurrentSampleByteCount += Bytes;
|
|
}
|
|
|
|
VOID
|
|
UpdateBandwidthOnDemand(
|
|
PBOND_INFO BonDInfo,
|
|
ULONG Bytes
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
PSAMPLE_TABLE SampleTable = &BonDInfo->SampleTable;
|
|
|
|
//
|
|
// Age and update the sample table
|
|
//
|
|
AgeSampleTable(SampleTable);
|
|
UpdateSampleTable(SampleTable, Bytes);
|
|
}
|
|
|
|
VOID
|
|
CheckUpperThreshold(
|
|
PBUNDLECB BundleCB
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
WAN_TIME CurrentTime, TimeDiff;
|
|
PBOND_INFO BonDInfo;
|
|
PSAMPLE_TABLE SampleTable;
|
|
ULONGLONG Bps;
|
|
BOOLEAN SSignal, RSignal;
|
|
|
|
//
|
|
// First check send side
|
|
//
|
|
BonDInfo = BundleCB->SUpperBonDInfo;
|
|
SSignal = FALSE;
|
|
SampleTable = &BonDInfo->SampleTable;
|
|
Bps = SampleTable->ulCurrentSampleByteCount;
|
|
|
|
//
|
|
// Switch on the current state
|
|
//
|
|
switch (BonDInfo->State) {
|
|
|
|
case BonDSignaled:
|
|
break;
|
|
|
|
case BonDIdle:
|
|
//
|
|
// We are currently below the upper threshold. If we
|
|
// go over the upperthreshold we will set the time and
|
|
// transition to the monitor state.
|
|
//
|
|
if (Bps >= BonDInfo->ulBytesThreshold) {
|
|
NdisWanGetSystemTime(&BonDInfo->StartTime);
|
|
BonDInfo->State = BonDMonitor;
|
|
NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("U-S: i -> m, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
|
|
}
|
|
break;
|
|
|
|
case BonDMonitor:
|
|
|
|
//
|
|
// We are currently in the monitor state which means that
|
|
// we have gone above the upper threshold. If we fall below
|
|
// the upper threshold we will go back to the idle state.
|
|
//
|
|
if (Bps < BonDInfo->ulBytesThreshold) {
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("U-S: m -> i, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
|
|
BonDInfo->State = BonDIdle;
|
|
|
|
} else {
|
|
|
|
NdisWanGetSystemTime(&CurrentTime);
|
|
|
|
NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &BonDInfo->StartTime);
|
|
|
|
if (!NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SamplePeriod)) {
|
|
|
|
SSignal = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Now check the receive side
|
|
//
|
|
BonDInfo = BundleCB->RUpperBonDInfo;
|
|
RSignal = FALSE;
|
|
SampleTable = &BonDInfo->SampleTable;
|
|
Bps = SampleTable->ulCurrentSampleByteCount;
|
|
|
|
switch (BonDInfo->State) {
|
|
|
|
case BonDSignaled:
|
|
break;
|
|
|
|
case BonDIdle:
|
|
//
|
|
// We are currently below the upper threshold. If we
|
|
// go over the upperthreshold we will set the time and
|
|
// transition to the monitor state.
|
|
//
|
|
if (Bps >= BonDInfo->ulBytesThreshold) {
|
|
NdisWanGetSystemTime(&BonDInfo->StartTime);
|
|
BonDInfo->State = BonDMonitor;
|
|
NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("U-R: i -> m, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
|
|
}
|
|
break;
|
|
|
|
case BonDMonitor:
|
|
|
|
//
|
|
// We are currently in the monitor state which means that
|
|
// we have gone above the upper threshold. If we fall below
|
|
// the upper threshold we will go back to the idle state.
|
|
//
|
|
if (Bps < BonDInfo->ulBytesThreshold) {
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("U-R: m -> i, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
|
|
BonDInfo->State = BonDIdle;
|
|
|
|
} else {
|
|
|
|
NdisWanGetSystemTime(&CurrentTime);
|
|
|
|
NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &BonDInfo->StartTime);
|
|
|
|
if (!NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SamplePeriod)) {
|
|
|
|
RSignal = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (SSignal || RSignal) {
|
|
|
|
//
|
|
// We have been above the threshold for time greater than the
|
|
// threshold sample period so we need to notify someone of this
|
|
// historic event!
|
|
//
|
|
CompleteThresholdEvent(BundleCB, BonDInfo->DataType, UPPER_THRESHOLD);
|
|
|
|
BundleCB->SUpperBonDInfo->State = BonDSignaled;
|
|
BundleCB->RUpperBonDInfo->State = BonDSignaled;
|
|
|
|
#if DBG
|
|
{
|
|
ULONGLONG util;
|
|
|
|
util = BundleCB->SUpperBonDInfo->SampleTable.ulCurrentSampleByteCount;
|
|
util *= 100;
|
|
util /= BundleCB->SUpperBonDInfo->ulBytesInSamplePeriod;
|
|
NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("U-S: Bps %I64d Threshold %I64d Util %I64d",
|
|
Bps, BundleCB->SUpperBonDInfo->ulBytesThreshold, util));
|
|
|
|
util = BundleCB->RUpperBonDInfo->SampleTable.ulCurrentSampleByteCount;
|
|
util *= 100;
|
|
util /= BundleCB->RUpperBonDInfo->ulBytesInSamplePeriod;
|
|
NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("U-R: Bps %I64d Threshold %I64d Util %I64d",
|
|
Bps, BundleCB->RUpperBonDInfo->ulBytesThreshold, util));
|
|
}
|
|
#endif
|
|
|
|
}
|
|
}
|
|
|
|
VOID
|
|
CheckLowerThreshold(
|
|
PBUNDLECB BundleCB
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
WAN_TIME CurrentTime, TimeDiff;
|
|
PBOND_INFO BonDInfo;
|
|
PSAMPLE_TABLE SampleTable;
|
|
ULONGLONG Bps;
|
|
BOOLEAN SSignal, RSignal;
|
|
|
|
if (!(BundleCB->Flags & BOND_ENABLED)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// First check send side
|
|
//
|
|
BonDInfo = BundleCB->SLowerBonDInfo;
|
|
SampleTable = &BonDInfo->SampleTable;
|
|
Bps = SampleTable->ulCurrentSampleByteCount;
|
|
SSignal = FALSE;
|
|
|
|
//
|
|
// Switch on the current state
|
|
//
|
|
switch (BonDInfo->State) {
|
|
|
|
case BonDIdle:
|
|
//
|
|
// We are currently above the lower threshold. If we
|
|
// go under the lowerthreshold we will set the time and
|
|
// transition to the monitor state.
|
|
//
|
|
if (Bps <= BonDInfo->ulBytesThreshold) {
|
|
NdisWanGetSystemTime(&BonDInfo->StartTime);
|
|
BonDInfo->State = BonDMonitor;
|
|
NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("L-S: i -> m, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
|
|
}
|
|
break;
|
|
|
|
case BonDMonitor:
|
|
|
|
//
|
|
// We are currently in the monitor state which means that
|
|
// we have gone below the lower threshold. If we climb above
|
|
// the lower threshold we will go back to the idle state.
|
|
//
|
|
if (Bps > BonDInfo->ulBytesThreshold) {
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("L-S: m -> i, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
|
|
BonDInfo->State = BonDIdle;
|
|
|
|
} else {
|
|
|
|
NdisWanGetSystemTime(&CurrentTime);
|
|
|
|
NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &BonDInfo->StartTime);
|
|
|
|
if (!NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SamplePeriod)) {
|
|
|
|
SSignal = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case BonDSignaled:
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Now check the receive side
|
|
//
|
|
BonDInfo = BundleCB->RLowerBonDInfo;
|
|
RSignal = FALSE;
|
|
SampleTable = &BonDInfo->SampleTable;
|
|
Bps = SampleTable->ulCurrentSampleByteCount;
|
|
|
|
switch (BonDInfo->State) {
|
|
|
|
case BonDIdle:
|
|
//
|
|
// We are currently above the lower threshold. If we
|
|
// go below the lowerthreshold we will set the time and
|
|
// transition to the monitor state.
|
|
//
|
|
if (Bps <= BonDInfo->ulBytesThreshold) {
|
|
NdisWanGetSystemTime(&BonDInfo->StartTime);
|
|
BonDInfo->State = BonDMonitor;
|
|
NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("L-R: i -> m, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
|
|
}
|
|
break;
|
|
|
|
case BonDMonitor:
|
|
|
|
//
|
|
// We are currently in the monitor state which means that
|
|
// we have gone below the lower threshold. If we climb above
|
|
// the lower threshold we will go back to the idle state.
|
|
//
|
|
if (Bps > BonDInfo->ulBytesThreshold) {
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("L-R: m -> i, %I64d-%I64d", Bps, BonDInfo->ulBytesThreshold));
|
|
BonDInfo->State = BonDIdle;
|
|
|
|
} else {
|
|
|
|
NdisWanGetSystemTime(&CurrentTime);
|
|
|
|
NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &BonDInfo->StartTime);
|
|
|
|
if (!NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SamplePeriod)) {
|
|
|
|
RSignal = TRUE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case BonDSignaled:
|
|
break;
|
|
}
|
|
|
|
if (SSignal && RSignal) {
|
|
//
|
|
// We have been above the threshold for time greater than the
|
|
// threshold sample period so we need to notify someone of this
|
|
// historic event!
|
|
//
|
|
CompleteThresholdEvent(BundleCB, BonDInfo->DataType, LOWER_THRESHOLD);
|
|
|
|
BundleCB->SLowerBonDInfo->State = BonDSignaled;
|
|
BundleCB->RLowerBonDInfo->State = BonDSignaled;
|
|
|
|
#if DBG
|
|
{
|
|
ULONGLONG util;
|
|
|
|
util = BundleCB->SLowerBonDInfo->SampleTable.ulCurrentSampleByteCount;
|
|
util *= 100;
|
|
util /= BundleCB->SLowerBonDInfo->ulBytesInSamplePeriod;
|
|
NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("L-S: Bps %I64d Threshold %I64d Util %I64d",
|
|
Bps, BundleCB->SLowerBonDInfo->ulBytesThreshold, util));
|
|
|
|
util = BundleCB->RLowerBonDInfo->SampleTable.ulCurrentSampleByteCount;
|
|
util *= 100;
|
|
util /= BundleCB->RLowerBonDInfo->ulBytesInSamplePeriod;
|
|
NdisWanDbgOut(DBG_TRACE, DBG_BACP, ("L-R: Bps %I64d Threshold %I64d Util %I64d",
|
|
Bps, BundleCB->RLowerBonDInfo->ulBytesThreshold, util));
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#endif // end of ifdef NT
|
|
|
|
#if DBG
|
|
VOID
|
|
InsertSendTrc(
|
|
PSEND_TRC_INFO SendTrcInfo,
|
|
ULONG DataLength,
|
|
PUCHAR Data
|
|
)
|
|
{
|
|
PWAN_TRC_EVENT NewTrcEvent;
|
|
PSEND_TRC_INFO TrcInfo;
|
|
|
|
if (WanTrcCount == 4096) {
|
|
NewTrcEvent = (PWAN_TRC_EVENT)
|
|
RemoveTailList(&WanTrcList);
|
|
|
|
NdisWanFreeMemory(NewTrcEvent->TrcInfo);
|
|
|
|
NdisZeroMemory(NewTrcEvent, sizeof(WAN_TRC_EVENT));
|
|
|
|
} else {
|
|
NdisWanAllocateMemory(&NewTrcEvent,
|
|
sizeof(WAN_TRC_EVENT),
|
|
WANTRCEVENT_TAG);
|
|
|
|
if (NewTrcEvent == NULL) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
WanTrcCount += 1;
|
|
}
|
|
|
|
|
|
#endif
|
|
|