|
|
/*++
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
|