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

/*++
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);
}
#ifdef NT
VOID
NdisWanStringToNdisString(
PNDIS_STRING pDestString,
PWSTR pSrcBuffer
)
{
PWSTR Dest, Src = pSrcBuffer;
NDIS_STRING SrcString;
NdisInitUnicodeString(&SrcString, pSrcBuffer);
NdisWanAllocateMemory(&pDestString->Buffer, SrcString.MaximumLength, NDISSTRING_TAG);
if (pDestString->Buffer == NULL) {
return;
}
pDestString->MaximumLength = SrcString.MaximumLength;
pDestString->Length = SrcString.Length;
RtlCopyUnicodeString(pDestString, &SrcString);
}
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);
}
}
//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