1027 lines
25 KiB
C
1027 lines
25 KiB
C
/*++
|
|
|
|
Copyright (c) 1990-1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Indicate.c
|
|
|
|
Abstract:
|
|
|
|
This file contains procedures to handle indications from the
|
|
WAN Miniport drivers.
|
|
|
|
|
|
Author:
|
|
|
|
Tony Bell (TonyBe) June 06, 1995
|
|
|
|
Environment:
|
|
|
|
Kernel Mode
|
|
|
|
Revision History:
|
|
|
|
TonyBe 06/06/95 Created
|
|
|
|
--*/
|
|
|
|
#include "wan.h"
|
|
|
|
#define __FILE_SIG__ INDICATE_FILESIG
|
|
|
|
VOID
|
|
NdisWanLineUpIndication(
|
|
POPENCB OpenCB,
|
|
PUCHAR Buffer,
|
|
ULONG BufferSize
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
NdisWanLineupIndication
|
|
|
|
Routine Description:
|
|
|
|
This routine is called when a WAN Miniport driver has a new connetion
|
|
become active or when the status of an active connection changes. If
|
|
this is a new connection the routine creates a LinkCB, and a BundleCB
|
|
for the new connection. If this is for an already active connetion the
|
|
connection info is updated.
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PLINKCB LinkCB = NULL;
|
|
PBUNDLECB BundleCB = NULL;
|
|
NDIS_STATUS Status;
|
|
PNDIS_MAC_LINE_UP LineUpInfo = (PNDIS_MAC_LINE_UP)Buffer;
|
|
BOOLEAN EmptyList;
|
|
|
|
if (BufferSize < sizeof(NDIS_MAC_LINE_UP)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Is this for a new connetion?
|
|
//
|
|
if (LineUpInfo->NdisLinkContext == NULL) {
|
|
|
|
//
|
|
// This is a new connection!
|
|
//
|
|
|
|
//
|
|
// Get a linkcb
|
|
//
|
|
LinkCB = NdisWanAllocateLinkCB(OpenCB, LineUpInfo->SendWindow);
|
|
|
|
if (LinkCB == NULL) {
|
|
|
|
//
|
|
// Error getting LinkCB!
|
|
//
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
LinkCB->NdisLinkHandle = LineUpInfo->NdisLinkHandle;
|
|
LinkCB->ConnectionWrapperID = LineUpInfo->ConnectionWrapperID;
|
|
|
|
//
|
|
// Get a bundlecb
|
|
//
|
|
BundleCB = NdisWanAllocateBundleCB();
|
|
|
|
if (BundleCB == NULL) {
|
|
|
|
//
|
|
// Error getting BundleCB!
|
|
//
|
|
|
|
NdisWanFreeLinkCB(LinkCB);
|
|
|
|
return;
|
|
}
|
|
|
|
AcquireBundleLock(BundleCB);
|
|
|
|
//
|
|
// Copy LineUpInfo to Link LineUpInfo
|
|
//
|
|
/* NdisMoveMemory((PUCHAR)&LinkCB->LineUpInfo,
|
|
(PUCHAR)LineUpInfo,
|
|
sizeof(NDIS_MAC_LINE_UP));
|
|
*/
|
|
//
|
|
// If a linkspeed is not reported we are
|
|
// assuming 28.8K as the slowest...
|
|
//
|
|
if (LineUpInfo->LinkSpeed == 0) {
|
|
LineUpInfo->LinkSpeed = 288;
|
|
}
|
|
|
|
//
|
|
// Take 1/100bps to Bps without rolling over
|
|
//
|
|
{
|
|
ULONGLONG temp;
|
|
ULONG value;
|
|
|
|
temp = LineUpInfo->LinkSpeed;
|
|
temp *= 100;
|
|
temp /= 8;
|
|
|
|
//
|
|
// Check for rollover
|
|
//
|
|
value = (ULONG)temp;
|
|
|
|
if (value == 0) {
|
|
value = 0xFFFFFFFF/8;
|
|
}
|
|
|
|
LinkCB->SFlowSpec.TokenRate =
|
|
LinkCB->SFlowSpec.PeakBandwidth =
|
|
LinkCB->RFlowSpec.TokenRate =
|
|
LinkCB->RFlowSpec.PeakBandwidth = (ULONG)value;
|
|
}
|
|
|
|
LinkCB->SFlowSpec.MaxSduSize =
|
|
(OpenCB->WanInfo.MaxFrameSize > glMaxMTU) ?
|
|
glMaxMTU : OpenCB->WanInfo.MaxFrameSize;
|
|
|
|
LinkCB->RFlowSpec.MaxSduSize = glMRRU;
|
|
|
|
//
|
|
// Add LinkCB to BundleCB
|
|
//
|
|
AddLinkToBundle(BundleCB, LinkCB);
|
|
|
|
ReleaseBundleLock(BundleCB);
|
|
|
|
//
|
|
// Place BundleCB in active connection table
|
|
//
|
|
if (NULL == InsertBundleInConnectionTable(BundleCB)) {
|
|
//
|
|
// Error inserting link in ConnectionTable
|
|
//
|
|
RemoveLinkFromBundle(BundleCB, LinkCB, FALSE);
|
|
NdisWanFreeLinkCB(LinkCB);
|
|
NdisWanFreeBundleCB(BundleCB);
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Place LinkCB in active connection table
|
|
//
|
|
if (NULL == InsertLinkInConnectionTable(LinkCB)) {
|
|
//
|
|
// Error inserting bundle in connectiontable
|
|
//
|
|
RemoveLinkFromBundle(BundleCB, LinkCB, FALSE);
|
|
NdisWanFreeLinkCB(LinkCB);
|
|
NdisWanFreeBundleCB(BundleCB);
|
|
|
|
return;
|
|
}
|
|
|
|
LineUpInfo->NdisLinkContext = LinkCB->hLinkHandle;
|
|
|
|
} else {
|
|
|
|
do {
|
|
|
|
//
|
|
// This is an already existing connetion
|
|
//
|
|
if (!AreLinkAndBundleValid(LineUpInfo->NdisLinkContext,
|
|
TRUE,
|
|
&LinkCB,
|
|
&BundleCB)) {
|
|
#if DBG
|
|
DbgPrint("NDISWAN: LineUp on unknown LinkContext %x\n",
|
|
LineUpInfo->NdisLinkContext);
|
|
DbgBreakPoint();
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
AcquireBundleLock(BundleCB);
|
|
|
|
if (LineUpInfo->LinkSpeed == 0) {
|
|
LineUpInfo->LinkSpeed = 288;
|
|
}
|
|
|
|
//
|
|
// Take 1/100bps to Bps
|
|
//
|
|
{
|
|
ULONGLONG temp;
|
|
|
|
temp = LineUpInfo->LinkSpeed;
|
|
temp *= 100;
|
|
temp /= 8;
|
|
|
|
LinkCB->SFlowSpec.TokenRate =
|
|
LinkCB->SFlowSpec.PeakBandwidth =
|
|
LinkCB->RFlowSpec.TokenRate =
|
|
LinkCB->RFlowSpec.PeakBandwidth = (ULONG)temp;
|
|
}
|
|
|
|
LinkCB->SendWindow = (LineUpInfo->SendWindow > OpenCB->WanInfo.MaxTransmit ||
|
|
LineUpInfo->SendWindow == 0) ?
|
|
OpenCB->WanInfo.MaxTransmit : LineUpInfo->SendWindow;
|
|
|
|
//
|
|
// If the new sendwindow is set smaller then the
|
|
// current # of outstanding frames then we have to
|
|
// close the sendwindow for the link and reduce the
|
|
// number of sending links that the bundle sees.
|
|
//
|
|
// If the new sendwindow is set larger then the
|
|
// current # of outstanding frames and the sendwindow
|
|
// is currently closed, we need to open the sendwindow
|
|
// and increase the number of sending links that the
|
|
// bundle sees.
|
|
//
|
|
if (LinkCB->LinkActive) {
|
|
if (LinkCB->SendWindow <= LinkCB->OutstandingFrames) {
|
|
if (LinkCB->SendWindowOpen) {
|
|
LinkCB->SendWindowOpen = FALSE;
|
|
BundleCB->SendingLinks -= 1;
|
|
}
|
|
} else if (!LinkCB->SendWindowOpen) {
|
|
LinkCB->SendWindowOpen = TRUE;
|
|
BundleCB->SendingLinks += 1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Update BundleCB info
|
|
//
|
|
UpdateBundleInfo(BundleCB);
|
|
|
|
//
|
|
// Deref's for the ref's applied when we mapped the
|
|
// context into the control blocks
|
|
//
|
|
DEREF_BUNDLECB_LOCKED(BundleCB);
|
|
DEREF_LINKCB(LinkCB);
|
|
|
|
} while ( 0 );
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
NdisWanLineDownIndication(
|
|
POPENCB OpenCB,
|
|
PUCHAR Buffer,
|
|
ULONG BufferSize
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
PNDIS_MAC_LINE_DOWN LineDownInfo = (PNDIS_MAC_LINE_DOWN)Buffer;
|
|
PLINKCB LinkCB;
|
|
PBUNDLECB BundleCB;
|
|
PRECV_DESC RecvDesc;
|
|
ULONG i;
|
|
|
|
if (!AreLinkAndBundleValid(LineDownInfo->NdisLinkContext,
|
|
TRUE,
|
|
&LinkCB,
|
|
&BundleCB)) {
|
|
#if DBG
|
|
DbgPrint("NDISWAN: LineDown on unknown LinkContext %x\n",
|
|
LineDownInfo->NdisLinkContext);
|
|
DbgBreakPoint();
|
|
#endif
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Link is now going down
|
|
//
|
|
NdisAcquireSpinLock(&LinkCB->Lock);
|
|
|
|
LinkCB->State = LINK_GOING_DOWN;
|
|
|
|
//
|
|
// Deref for the ref applied in AreLinkAndBundleValid. We don't
|
|
// have to go through the full deref code as we know that the
|
|
// ref applied at lineup will hold the block around.
|
|
//
|
|
LinkCB->RefCount--;
|
|
|
|
NdisReleaseSpinLock(&LinkCB->Lock);
|
|
|
|
NdisAcquireSpinLock(&IoRecvList.Lock);
|
|
|
|
RecvDesc = (PRECV_DESC)IoRecvList.DescList.Flink;
|
|
|
|
while ((PVOID)RecvDesc != (PVOID)&IoRecvList.DescList) {
|
|
PRECV_DESC Next;
|
|
|
|
Next = (PRECV_DESC)RecvDesc->Linkage.Flink;
|
|
|
|
if (RecvDesc->LinkCB == LinkCB) {
|
|
|
|
RemoveEntryList(&RecvDesc->Linkage);
|
|
|
|
LinkCB->RecvDescCount--;
|
|
|
|
IoRecvList.ulDescCount--;
|
|
|
|
NdisWanFreeRecvDesc(RecvDesc);
|
|
}
|
|
|
|
RecvDesc = Next;
|
|
}
|
|
|
|
NdisReleaseSpinLock(&IoRecvList.Lock);
|
|
|
|
//
|
|
// Flush the Bundle's fragment send queues that
|
|
// have sends pending on this link
|
|
//
|
|
AcquireBundleLock(BundleCB);
|
|
|
|
for (i = 0; i < MAX_MCML; i++) {
|
|
PSEND_DESC SendDesc;
|
|
PSEND_FRAG_INFO FragInfo;
|
|
|
|
FragInfo = &BundleCB->SendFragInfo[i];
|
|
|
|
SendDesc = (PSEND_DESC)FragInfo->FragQueue.Flink;
|
|
|
|
while ((PVOID)SendDesc != (PVOID)&FragInfo->FragQueue) {
|
|
|
|
if (SendDesc->LinkCB == LinkCB) {
|
|
PSEND_DESC NextSendDesc;
|
|
|
|
NextSendDesc = (PSEND_DESC)SendDesc->Linkage.Flink;
|
|
|
|
RemoveEntryList(&SendDesc->Linkage);
|
|
|
|
FragInfo->FragQueueDepth--;
|
|
|
|
(*LinkCB->SendHandler)(SendDesc);
|
|
|
|
SendDesc = NextSendDesc;
|
|
} else {
|
|
SendDesc = (PSEND_DESC)SendDesc->Linkage.Flink;
|
|
}
|
|
}
|
|
}
|
|
|
|
UpdateBundleInfo(BundleCB);
|
|
|
|
ReleaseBundleLock(BundleCB);
|
|
|
|
//
|
|
// For the ref from the lineup
|
|
//
|
|
DEREF_LINKCB(LinkCB);
|
|
|
|
//
|
|
// Deref for the ref applied in AreLinkAndBundleValid
|
|
//
|
|
DEREF_BUNDLECB(BundleCB);
|
|
}
|
|
|
|
|
|
VOID
|
|
NdisWanFragmentIndication(
|
|
POPENCB OpenCB,
|
|
PUCHAR Buffer,
|
|
ULONG BufferSize
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
ULONG Errors;
|
|
PLINKCB LinkCB;
|
|
PBUNDLECB BundleCB;
|
|
|
|
PNDIS_MAC_FRAGMENT FragmentInfo =
|
|
(PNDIS_MAC_FRAGMENT)Buffer;
|
|
|
|
if (!AreLinkAndBundleValid(FragmentInfo->NdisLinkContext,
|
|
TRUE,
|
|
&LinkCB,
|
|
&BundleCB)) {
|
|
#if DBG
|
|
DbgPrint("NDISWAN: Status indication after link has gone down LinkContext %x\n",
|
|
FragmentInfo->NdisLinkContext);
|
|
DbgBreakPoint();
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
Errors = FragmentInfo->Errors;
|
|
|
|
AcquireBundleLock(BundleCB);
|
|
|
|
if (Errors & WAN_ERROR_CRC) {
|
|
LinkCB->Stats.CRCErrors++;
|
|
BundleCB->Stats.CRCErrors++;
|
|
}
|
|
|
|
if (Errors & WAN_ERROR_FRAMING) {
|
|
LinkCB->Stats.FramingErrors++;
|
|
BundleCB->Stats.FramingErrors++;
|
|
}
|
|
|
|
if (Errors & WAN_ERROR_HARDWAREOVERRUN) {
|
|
LinkCB->Stats.SerialOverrunErrors++;
|
|
BundleCB->Stats.SerialOverrunErrors++;
|
|
}
|
|
|
|
if (Errors & WAN_ERROR_BUFFEROVERRUN) {
|
|
LinkCB->Stats.BufferOverrunErrors++;
|
|
BundleCB->Stats.BufferOverrunErrors++;
|
|
}
|
|
|
|
if (Errors & WAN_ERROR_TIMEOUT) {
|
|
LinkCB->Stats.TimeoutErrors++;
|
|
BundleCB->Stats.TimeoutErrors++;
|
|
}
|
|
|
|
if (Errors & WAN_ERROR_ALIGNMENT) {
|
|
LinkCB->Stats.AlignmentErrors++;
|
|
BundleCB->Stats.AlignmentErrors++;
|
|
}
|
|
|
|
//
|
|
// Deref's for the ref's applied in AreLinkAndBundleValid
|
|
//
|
|
DEREF_BUNDLECB_LOCKED(BundleCB);
|
|
DEREF_LINKCB(LinkCB);
|
|
}
|
|
|
|
VOID
|
|
NdisCoWanFragmentIndication(
|
|
PLINKCB LinkCB,
|
|
PBUNDLECB BundleCB,
|
|
PUCHAR Buffer,
|
|
ULONG BufferSize
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
ULONG Errors;
|
|
PNDIS_WAN_CO_FRAGMENT FragmentInfo =
|
|
(PNDIS_WAN_CO_FRAGMENT)Buffer;
|
|
|
|
Errors = FragmentInfo->Errors;
|
|
|
|
AcquireBundleLock(BundleCB);
|
|
|
|
if (Errors & WAN_ERROR_CRC) {
|
|
LinkCB->Stats.CRCErrors++;
|
|
BundleCB->Stats.CRCErrors++;
|
|
}
|
|
|
|
if (Errors & WAN_ERROR_FRAMING) {
|
|
LinkCB->Stats.FramingErrors++;
|
|
BundleCB->Stats.FramingErrors++;
|
|
}
|
|
|
|
if (Errors & WAN_ERROR_HARDWAREOVERRUN) {
|
|
LinkCB->Stats.SerialOverrunErrors++;
|
|
BundleCB->Stats.SerialOverrunErrors++;
|
|
}
|
|
|
|
if (Errors & WAN_ERROR_BUFFEROVERRUN) {
|
|
LinkCB->Stats.BufferOverrunErrors++;
|
|
BundleCB->Stats.BufferOverrunErrors++;
|
|
}
|
|
|
|
if (Errors & WAN_ERROR_TIMEOUT) {
|
|
LinkCB->Stats.TimeoutErrors++;
|
|
BundleCB->Stats.TimeoutErrors++;
|
|
}
|
|
|
|
if (Errors & WAN_ERROR_ALIGNMENT) {
|
|
LinkCB->Stats.AlignmentErrors++;
|
|
BundleCB->Stats.AlignmentErrors++;
|
|
}
|
|
|
|
ReleaseBundleLock(BundleCB);
|
|
}
|
|
|
|
VOID
|
|
NdisCoWanLinkParamChange(
|
|
PLINKCB LinkCB,
|
|
PBUNDLECB BundleCB,
|
|
PUCHAR Buffer,
|
|
ULONG BufferSize
|
|
)
|
|
{
|
|
PWAN_CO_LINKPARAMS LinkParams =
|
|
(PWAN_CO_LINKPARAMS)Buffer;
|
|
|
|
if (BufferSize < sizeof(WAN_CO_LINKPARAMS)) {
|
|
return;
|
|
}
|
|
|
|
AcquireBundleLock(BundleCB);
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_INDICATE,
|
|
("LinkParamChange: SendWindow %d XmitSpeed %d RecvSpeed %d",
|
|
LinkParams->SendWindow, LinkParams->TransmitSpeed, LinkParams->ReceiveSpeed));
|
|
|
|
LinkCB->SendWindow = LinkParams->SendWindow;
|
|
|
|
//
|
|
// If the new sendwindow is set smaller then the
|
|
// current # of outstanding frames then we have to
|
|
// close the sendwindow for the link and reduce the
|
|
// number of sending links that the bundle sees.
|
|
//
|
|
// If the new sendwindow is set larger then the
|
|
// current # of outstanding frames and the sendwindow
|
|
// is currently closed, we need to open the sendwindow
|
|
// and increase the number of sending links that the
|
|
// bundle sees.
|
|
//
|
|
if (LinkCB->LinkActive) {
|
|
if (LinkCB->SendWindow <= LinkCB->OutstandingFrames) {
|
|
if (LinkCB->SendWindowOpen) {
|
|
LinkCB->SendWindowOpen = FALSE;
|
|
BundleCB->SendingLinks -= 1;
|
|
}
|
|
} else if (!LinkCB->SendWindowOpen) {
|
|
LinkCB->SendWindowOpen = TRUE;
|
|
BundleCB->SendingLinks += 1;
|
|
}
|
|
}
|
|
|
|
LinkCB->SFlowSpec.PeakBandwidth =
|
|
LinkParams->TransmitSpeed;
|
|
|
|
LinkCB->RFlowSpec.PeakBandwidth =
|
|
LinkParams->ReceiveSpeed;
|
|
|
|
if (LinkCB->SFlowSpec.PeakBandwidth == 0) {
|
|
LinkCB->SFlowSpec.PeakBandwidth = 28800 / 8;
|
|
}
|
|
|
|
if (LinkCB->RFlowSpec.PeakBandwidth == 0) {
|
|
LinkCB->RFlowSpec.PeakBandwidth = LinkCB->SFlowSpec.PeakBandwidth;
|
|
}
|
|
|
|
UpdateBundleInfo(BundleCB);
|
|
|
|
ReleaseBundleLock(BundleCB);
|
|
}
|
|
|
|
VOID
|
|
UpdateBundleInfo(
|
|
PBUNDLECB BundleCB
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Expects the BundleCB->Lock to be held!
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
PLINKCB LinkCB;
|
|
ULONG SlowestSSpeed, FastestSSpeed;
|
|
ULONG SlowestRSpeed, FastestRSpeed;
|
|
PPROTOCOLCB ProtocolCB;
|
|
PFLOWSPEC BSFlowSpec, BRFlowSpec;
|
|
ULONG i;
|
|
ULONG SmallestSDU;
|
|
LIST_ENTRY TempList;
|
|
|
|
BSFlowSpec = &BundleCB->SFlowSpec;
|
|
BRFlowSpec = &BundleCB->RFlowSpec;
|
|
|
|
SlowestSSpeed = FastestSSpeed = 0;
|
|
SlowestRSpeed = FastestRSpeed = 0;
|
|
SmallestSDU = 0;
|
|
BSFlowSpec->TokenRate = 0;
|
|
BSFlowSpec->PeakBandwidth = 0;
|
|
BRFlowSpec->TokenRate = 0;
|
|
BRFlowSpec->PeakBandwidth = 0;
|
|
BundleCB->SendWindow = 0;
|
|
BundleCB->State = BUNDLE_GOING_DOWN;
|
|
|
|
if (BundleCB->ulLinkCBCount != 0) {
|
|
//
|
|
// Currently only using the SendSide FastestSpeed so
|
|
// just get it from the head of the list.
|
|
//
|
|
FastestSSpeed =
|
|
((PLINKCB)(BundleCB->LinkCBList.Flink))->SFlowSpec.PeakBandwidth;
|
|
SmallestSDU =
|
|
((PLINKCB)(BundleCB->LinkCBList.Flink))->SFlowSpec.MaxSduSize;
|
|
|
|
//
|
|
// If a link has a speed that is less than the minimum
|
|
// link bandwidth (% of the fastests link speed) it is flaged
|
|
// as not sending and does not count as a sending link.
|
|
//
|
|
|
|
BundleCB->SendingLinks = 0;
|
|
BundleCB->SendResources = 0;
|
|
|
|
for (LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
|
|
(PVOID)LinkCB != (PVOID)&BundleCB->LinkCBList;
|
|
LinkCB = (PLINKCB)LinkCB->Linkage.Flink) {
|
|
ULONGLONG n, d, temp;
|
|
PFLOWSPEC LSFlowSpec = &LinkCB->SFlowSpec;
|
|
PFLOWSPEC LRFlowSpec = &LinkCB->RFlowSpec;
|
|
|
|
if (LinkCB->State == LINK_UP) {
|
|
BundleCB->State = BUNDLE_UP;
|
|
}
|
|
|
|
n = LSFlowSpec->PeakBandwidth;
|
|
n *= 100;
|
|
d = FastestSSpeed;
|
|
temp = n/d;
|
|
|
|
|
|
LinkCB->LinkActive = ((ULONG)temp > glMinLinkBandwidth) ?
|
|
TRUE : FALSE;
|
|
|
|
if (LinkCB->LinkActive) {
|
|
|
|
BundleCB->SendResources += LinkCB->SendResources;
|
|
BundleCB->SendWindow += LinkCB->SendWindow;
|
|
if (LinkCB->SendWindowOpen) {
|
|
BundleCB->SendingLinks += 1;
|
|
}
|
|
|
|
BSFlowSpec->PeakBandwidth += LSFlowSpec->PeakBandwidth;
|
|
BRFlowSpec->PeakBandwidth += LRFlowSpec->PeakBandwidth;
|
|
}
|
|
|
|
if (LinkCB->SFlowSpec.MaxSduSize < SmallestSDU) {
|
|
SmallestSDU = LinkCB->SFlowSpec.MaxSduSize;
|
|
}
|
|
}
|
|
|
|
BundleCB->SFlowSpec.MaxSduSize = SmallestSDU;
|
|
|
|
//
|
|
// Now calculate the % bandwidth that each links contributes to the
|
|
// bundle. If a link has a speed that is less than the minimum
|
|
// link bandwidth (% of the fastests link speed) it is flaged
|
|
// as not sending and does not count as a sending link.
|
|
//
|
|
for (LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
|
|
(PVOID)LinkCB != (PVOID)&BundleCB->LinkCBList;
|
|
LinkCB = (PLINKCB)LinkCB->Linkage.Flink) {
|
|
ULONGLONG n, d, temp;
|
|
PFLOWSPEC LSFlowSpec = &LinkCB->SFlowSpec;
|
|
PFLOWSPEC LRFlowSpec = &LinkCB->RFlowSpec;
|
|
|
|
//
|
|
// Do sending side
|
|
//
|
|
n = LSFlowSpec->PeakBandwidth;
|
|
n *= 100;
|
|
d = BSFlowSpec->PeakBandwidth;
|
|
temp = n/d;
|
|
|
|
LinkCB->SBandwidth = (temp > 0) ? (ULONG)temp : 1;
|
|
|
|
//
|
|
// Do receiving side
|
|
//
|
|
n = LRFlowSpec->PeakBandwidth;
|
|
n *= 100;
|
|
d = BRFlowSpec->PeakBandwidth;
|
|
temp = n/d;
|
|
|
|
LinkCB->RBandwidth = (temp > 0) ? (ULONG)temp : 1;
|
|
|
|
}
|
|
|
|
BundleCB->NextLinkToXmit =
|
|
(PLINKCB)BundleCB->LinkCBList.Flink;
|
|
|
|
//
|
|
// Update the BandwidthOnDemand information
|
|
//
|
|
if (BundleCB->Flags & BOND_ENABLED) {
|
|
PBOND_INFO BonDInfo;
|
|
ULONGLONG SecondsInSamplePeriod;
|
|
ULONGLONG BytesPerSecond;
|
|
ULONGLONG BytesInSamplePeriod;
|
|
ULONGLONG temp;
|
|
|
|
BonDInfo = BundleCB->SUpperBonDInfo;
|
|
|
|
SecondsInSamplePeriod =
|
|
BonDInfo->ulSecondsInSamplePeriod;
|
|
|
|
BytesPerSecond =
|
|
BundleCB->SFlowSpec.PeakBandwidth;
|
|
|
|
BytesInSamplePeriod =
|
|
BytesPerSecond * SecondsInSamplePeriod;
|
|
|
|
temp = BonDInfo->usPercentBandwidth;
|
|
temp *= BytesInSamplePeriod;
|
|
temp /= 100;
|
|
|
|
BonDInfo->ulBytesThreshold = (ULONG)temp;
|
|
|
|
BonDInfo = BundleCB->SLowerBonDInfo;
|
|
|
|
SecondsInSamplePeriod =
|
|
BonDInfo->ulSecondsInSamplePeriod;
|
|
|
|
BytesPerSecond =
|
|
BundleCB->SFlowSpec.PeakBandwidth;
|
|
|
|
BytesInSamplePeriod =
|
|
BytesPerSecond * SecondsInSamplePeriod;
|
|
|
|
temp = BonDInfo->usPercentBandwidth;
|
|
temp *= BytesInSamplePeriod;
|
|
temp /= 100;
|
|
|
|
BonDInfo->ulBytesThreshold = (ULONG)temp;
|
|
|
|
BonDInfo = BundleCB->RUpperBonDInfo;
|
|
|
|
SecondsInSamplePeriod =
|
|
BonDInfo->ulSecondsInSamplePeriod;
|
|
|
|
BytesPerSecond =
|
|
BundleCB->RFlowSpec.PeakBandwidth;
|
|
|
|
BytesInSamplePeriod =
|
|
BytesPerSecond * SecondsInSamplePeriod;
|
|
|
|
temp = BonDInfo->usPercentBandwidth;
|
|
temp *= BytesInSamplePeriod;
|
|
temp /= 100;
|
|
|
|
BonDInfo->ulBytesThreshold = (ULONG)temp;
|
|
|
|
BonDInfo = BundleCB->RLowerBonDInfo;
|
|
|
|
SecondsInSamplePeriod =
|
|
BonDInfo->ulSecondsInSamplePeriod;
|
|
|
|
BytesPerSecond =
|
|
BundleCB->RFlowSpec.PeakBandwidth;
|
|
|
|
BytesInSamplePeriod =
|
|
BytesPerSecond * SecondsInSamplePeriod;
|
|
|
|
temp = BonDInfo->usPercentBandwidth;
|
|
temp *= BytesInSamplePeriod;
|
|
temp /= 100;
|
|
|
|
BonDInfo->ulBytesThreshold = (ULONG)temp;
|
|
}
|
|
}
|
|
|
|
//
|
|
// We need to do a new lineup to all routed protocols
|
|
//
|
|
ProtocolCB = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
|
|
|
|
InitializeListHead(&TempList);
|
|
|
|
while ((PVOID)ProtocolCB != (PVOID)&BundleCB->ProtocolCBList) {
|
|
|
|
REF_PROTOCOLCB(ProtocolCB);
|
|
|
|
InsertHeadList(&TempList, &ProtocolCB->RefLinkage);
|
|
|
|
ProtocolCB =
|
|
(PPROTOCOLCB)ProtocolCB->Linkage.Flink;
|
|
}
|
|
|
|
while (!IsListEmpty(&TempList)) {
|
|
PLIST_ENTRY Entry;
|
|
|
|
Entry =
|
|
RemoveHeadList(&TempList);
|
|
|
|
ProtocolCB = CONTAINING_RECORD(Entry, PROTOCOLCB, RefLinkage);
|
|
|
|
if (BundleCB->State == BUNDLE_UP) {
|
|
ReleaseBundleLock(BundleCB);
|
|
|
|
DoLineUpToProtocol(ProtocolCB);
|
|
|
|
AcquireBundleLock(BundleCB);
|
|
} else {
|
|
//
|
|
// Our link count has gone to 0. This means
|
|
// that we can not send any packets. Flush the
|
|
// queues and don't accept any more sends from
|
|
// the transports.
|
|
//
|
|
FlushProtocolPacketQueue(ProtocolCB);
|
|
}
|
|
|
|
DEREF_PROTOCOLCB(ProtocolCB);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
AddLinkToBundle(
|
|
IN PBUNDLECB BundleCB,
|
|
IN PLINKCB LinkCB
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
UINT Class;
|
|
|
|
//
|
|
// Insert the links so that they are ordered with the fastest
|
|
// sending link at the head of the list
|
|
//
|
|
if (IsListEmpty(&BundleCB->LinkCBList) ||
|
|
(LinkCB->SFlowSpec.PeakBandwidth >=
|
|
((PLINKCB)(BundleCB->LinkCBList.Flink))->SFlowSpec.PeakBandwidth)) {
|
|
|
|
//
|
|
// The list was either empty or this link is a bigger pipe
|
|
// than anything else on the bundle
|
|
//
|
|
InsertHeadList(&BundleCB->LinkCBList, &LinkCB->Linkage);
|
|
|
|
} else if ((LinkCB->SFlowSpec.PeakBandwidth <=
|
|
((PLINKCB)(BundleCB->LinkCBList.Blink))->SFlowSpec.PeakBandwidth)) {
|
|
|
|
//
|
|
// This link is a smaller pipe than anything else
|
|
// on the bundle.
|
|
//
|
|
InsertTailList(&(BundleCB->LinkCBList), &(LinkCB->Linkage));
|
|
|
|
} else {
|
|
PLINKCB Current, Next;
|
|
BOOLEAN Inserted = FALSE;
|
|
|
|
//
|
|
// We need to find where this link belongs in the list!
|
|
//
|
|
Current = (PLINKCB)BundleCB->LinkCBList.Flink;
|
|
Next = (PLINKCB)Current->Linkage.Flink;
|
|
|
|
while ((PVOID)Next != (PVOID)&BundleCB->LinkCBList) {
|
|
|
|
if (LinkCB->SFlowSpec.PeakBandwidth <= Current->SFlowSpec.PeakBandwidth &&
|
|
LinkCB->SFlowSpec.PeakBandwidth >= Next->SFlowSpec.PeakBandwidth) {
|
|
|
|
LinkCB->Linkage.Flink = (PLIST_ENTRY)Next;
|
|
LinkCB->Linkage.Blink = (PLIST_ENTRY)Current;
|
|
|
|
Current->Linkage.Flink =
|
|
Next->Linkage.Blink =
|
|
(PLIST_ENTRY)LinkCB;
|
|
|
|
Inserted = TRUE;
|
|
break;
|
|
}
|
|
|
|
Current = Next;
|
|
Next = (PLINKCB)Next->Linkage.Flink;
|
|
}
|
|
|
|
if (!Inserted) {
|
|
InsertTailList(&(BundleCB->LinkCBList), &(LinkCB->Linkage));
|
|
}
|
|
}
|
|
|
|
BundleCB->ulLinkCBCount++;
|
|
|
|
LinkCB->BundleCB = BundleCB;
|
|
|
|
for (Class = 0; Class < MAX_MCML; Class++) {
|
|
PLINK_RECV_INFO LinkRecvInfo;
|
|
PBUNDLE_RECV_INFO BundleRecvInfo;
|
|
|
|
LinkRecvInfo = &LinkCB->RecvInfo[Class];
|
|
BundleRecvInfo = &BundleCB->RecvInfo[Class];
|
|
|
|
LinkRecvInfo->LastSeqNumber =
|
|
BundleRecvInfo->MinSeqNumber;
|
|
}
|
|
|
|
//
|
|
// Update BundleCB info
|
|
//
|
|
UpdateBundleInfo(BundleCB);
|
|
|
|
REF_BUNDLECB(BundleCB);
|
|
}
|
|
|
|
VOID
|
|
RemoveLinkFromBundle(
|
|
IN PBUNDLECB BundleCB,
|
|
IN PLINKCB LinkCB,
|
|
IN BOOLEAN Locked
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Expects the BundleCB->Lock to be held! Returns with the
|
|
lock released!
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
|
|
if (!Locked) {
|
|
AcquireBundleLock(BundleCB);
|
|
}
|
|
|
|
//
|
|
// Remove link from the bundle
|
|
//
|
|
RemoveEntryList(&LinkCB->Linkage);
|
|
|
|
LinkCB->BundleCB = NULL;
|
|
|
|
BundleCB->ulLinkCBCount--;
|
|
BundleCB->SendingLinks--;
|
|
|
|
//
|
|
// Update BundleCB info
|
|
//
|
|
UpdateBundleInfo(BundleCB);
|
|
|
|
//
|
|
// Deref for ref applied when we added this linkcb to
|
|
// the bundle
|
|
//
|
|
DEREF_BUNDLECB_LOCKED(BundleCB);
|
|
}
|