1531 lines
40 KiB
C
1531 lines
40 KiB
C
/*++
|
|
|
|
|
|
Copyright (c) 1996-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
wansup.c
|
|
|
|
Abstract:
|
|
|
|
support for ndiswan
|
|
|
|
Author:
|
|
|
|
Yoram Bernet (yoramb) 29-Oct-1997
|
|
Rajesh Sundaram (rajeshsu) 01-Aug-1998
|
|
|
|
Environment:
|
|
|
|
Kernel Mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "psched.h"
|
|
#pragma hdrstop
|
|
|
|
/* External */
|
|
|
|
/* Static */
|
|
|
|
//
|
|
// Should be defined in ndis.h. Put it here for now.
|
|
//
|
|
|
|
#define UNKNOWN_PROTOCOL_TYPE (USHORT) -1
|
|
|
|
NDIS_STATUS
|
|
CleanWanLink(PADAPTER Adapter,
|
|
PPS_WAN_LINK WanLink);
|
|
|
|
NDIS_STATUS
|
|
WanHandleISSLOW(
|
|
IN PGPC_CLIENT_VC Vc,
|
|
IN PCO_CALL_PARAMETERS CallParameters);
|
|
|
|
VOID
|
|
PsWanMungeAddress(PUSHORT id, USHORT Index)
|
|
{
|
|
*id = Index;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
DeleteInterfaceForNdisWan(
|
|
IN PADAPTER Adapter,
|
|
IN PVOID StatusBuffer,
|
|
IN UINT StatusBufferSize
|
|
)
|
|
{
|
|
PNDIS_WAN_LINE_DOWN LineDownBuff;
|
|
PLIST_ENTRY NextWanLink;
|
|
PPS_WAN_LINK WanLink;
|
|
NDIS_STATUS Status = NDIS_STATUS_FAILURE;
|
|
|
|
LineDownBuff = (PNDIS_WAN_LINE_DOWN)StatusBuffer;
|
|
|
|
PsDbgOut(DBG_TRACE, DBG_WAN,
|
|
("[DeleteInterfaceForNdisWan]: Linedown for remote address %02X:%02X:%02X:%02X:%02X:%02X \n",
|
|
LineDownBuff->RemoteAddress[0],
|
|
LineDownBuff->RemoteAddress[1],
|
|
LineDownBuff->RemoteAddress[2],
|
|
LineDownBuff->RemoteAddress[3],
|
|
LineDownBuff->RemoteAddress[4],
|
|
LineDownBuff->RemoteAddress[5]));
|
|
|
|
|
|
//
|
|
// Walk the List & remove the WanLink
|
|
//
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
NextWanLink = Adapter->WanLinkList.Flink;
|
|
|
|
while(NextWanLink != &Adapter->WanLinkList) {
|
|
|
|
WanLink = CONTAINING_RECORD(NextWanLink, PS_WAN_LINK, Linkage);
|
|
|
|
//
|
|
// We cannot compare the LocalAddress, because NDISWAN initially
|
|
// passes us 0 for the LocalAddress in the LINE_UP
|
|
// The LocalAddress is for Wanarp to store its context which it
|
|
// sends down to NDISWAN. NDISWAN then sends this context back
|
|
// to us as LocalAddress in LINE_DOWN. So, we have to ignore
|
|
// the LocalAddress in the LINE_DOWN.
|
|
//
|
|
|
|
if(NdisEqualMemory(WanLink->OriginalRemoteMacAddress,
|
|
LineDownBuff->RemoteAddress,
|
|
sizeof(LineDownBuff->RemoteAddress)))
|
|
{
|
|
//
|
|
// Get rid of the wanlink from the list.
|
|
//
|
|
g_WanLinkTable[WanLink->UniqueIndex] = 0;
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
//
|
|
// Munge the s-mac and r-mac so that wanarp can clean correctly.
|
|
//
|
|
PsWanMungeAddress((PUSHORT)&LineDownBuff->RemoteAddress[0],
|
|
WanLink->UniqueIndex);
|
|
|
|
PsWanMungeAddress((PUSHORT)&LineDownBuff->LocalAddress[0],
|
|
(USHORT)(*(PUSHORT)&WanLink->OriginalLocalMacAddress[0]));
|
|
|
|
Status = CleanWanLink(Adapter, WanLink);
|
|
|
|
NdisMIndicateStatus(Adapter->PsNdisHandle,
|
|
NDIS_STATUS_WAN_LINE_DOWN,
|
|
StatusBuffer,
|
|
StatusBufferSize);
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
NextWanLink = NextWanLink->Flink;
|
|
}
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
PsDbgOut(DBG_CRITICAL_ERROR, DBG_WAN,
|
|
("[DeleteInterfaceForNdisWan]: Could not find wanlink for Remote Mac: (%02X:%02X:%02X:%02X:%02X:%02X) \n",
|
|
LineDownBuff->RemoteAddress[0],
|
|
LineDownBuff->RemoteAddress[1],
|
|
LineDownBuff->RemoteAddress[2],
|
|
LineDownBuff->RemoteAddress[3],
|
|
LineDownBuff->RemoteAddress[4],
|
|
LineDownBuff->RemoteAddress[5]));
|
|
|
|
return Status;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PsWanGenerateUniqueIndex(
|
|
PPS_WAN_LINK WanLink
|
|
)
|
|
{
|
|
PADAPTER Adapter = WanLink->Adapter;
|
|
NDIS_STATUS Status = NDIS_STATUS_FAILURE;
|
|
USHORT size, Index, i, j;
|
|
PULONG_PTR NewTable;
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
for(i=0, Index = g_NextWanIndex;
|
|
i < g_WanTableSize;
|
|
i++)
|
|
{
|
|
if(g_WanLinkTable[Index] == 0)
|
|
{
|
|
//
|
|
// We got a free slot.
|
|
//
|
|
|
|
g_WanLinkTable[Index] = (ULONG_PTR)WanLink;
|
|
WanLink->UniqueIndex = Index;
|
|
|
|
//
|
|
// Assume that the next one is free.
|
|
//
|
|
g_NextWanIndex ++;
|
|
g_NextWanIndex = g_NextWanIndex % g_WanTableSize;
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
Index ++;
|
|
|
|
Index = Index % g_WanTableSize;
|
|
}
|
|
|
|
//
|
|
// We could not find a slot to insert the wanlink. Grow the table
|
|
// and copy the existing table.
|
|
//
|
|
|
|
size = (g_WanTableSize + WAN_TABLE_INCREMENT) * sizeof(ULONG_PTR);
|
|
|
|
PsAllocatePool(NewTable, size, WanTableTag);
|
|
|
|
if(!NewTable)
|
|
{
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
NdisZeroMemory(NewTable, size);
|
|
|
|
NdisMoveMemory(NewTable, g_WanLinkTable, g_WanTableSize * sizeof(ULONG_PTR));
|
|
|
|
PsFreePool(g_WanLinkTable);
|
|
|
|
g_WanLinkTable = NewTable;
|
|
|
|
//
|
|
//
|
|
//
|
|
g_WanLinkTable[g_WanTableSize] = (ULONG_PTR)WanLink;
|
|
|
|
WanLink->UniqueIndex = g_WanTableSize;
|
|
|
|
g_NextWanIndex = g_WanTableSize + 1;
|
|
|
|
g_WanTableSize += WAN_TABLE_INCREMENT;
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
DeleteWanLink(
|
|
PVOID Instance,
|
|
BOOLEAN AdapterLocked)
|
|
{
|
|
PPS_WAN_LINK WanLink = (PPS_WAN_LINK)Instance;
|
|
if(WanLink->pDiffServMapping)
|
|
{
|
|
PsFreePool(WanLink->pDiffServMapping);
|
|
}
|
|
|
|
if(WanLink->ShutdownMask & SHUTDOWN_DELETE_PIPE)
|
|
{
|
|
(*WanLink->PsComponent->DeletePipe)(WanLink->PsPipeContext);
|
|
}
|
|
|
|
if(WanLink->ShutdownMask & SHUTDOWN_FREE_PS_CONTEXT)
|
|
{
|
|
PsFreePool(WanLink->PsPipeContext);
|
|
}
|
|
|
|
if(WanLink->InstanceName.Buffer) {
|
|
|
|
PsFreePool(WanLink->InstanceName.Buffer);
|
|
}
|
|
|
|
if(WanLink->MpDeviceName.Buffer){
|
|
|
|
PsFreePool(WanLink->MpDeviceName.Buffer);
|
|
}
|
|
|
|
if(AdapterLocked)
|
|
{
|
|
RemoveEntryList(&WanLink->Linkage);
|
|
}
|
|
else
|
|
{
|
|
PS_LOCK(&WanLink->Adapter->Lock);
|
|
|
|
RemoveEntryList(&WanLink->Linkage);
|
|
|
|
PS_UNLOCK(&WanLink->Adapter->Lock);
|
|
}
|
|
|
|
NdisFreeSpinLock(&WanLink->Lock);
|
|
|
|
PsFreePool(WanLink);
|
|
|
|
}
|
|
|
|
NDIS_STATUS
|
|
CreateInterfaceForNdisWan(
|
|
IN PADAPTER Adapter,
|
|
IN PVOID StatusBuffer,
|
|
IN UINT StatusBufferSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Creates a TC interface to represent an underlying WAN link.
|
|
|
|
Arguments:
|
|
|
|
Adapter - the adapter on which the link is being created.
|
|
StatusBuffer - the buffer from NDISWAN.
|
|
StatusBufferSize - the length of the buffer.
|
|
|
|
Return Values:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PNDIS_WAN_LINE_UP LineUpBuff;
|
|
PPS_WAN_LINK WanLink;
|
|
PLIST_ENTRY NextWanLink;
|
|
NDIS_STATUS Status;
|
|
PIP_WAN_LINKUP_INFO RouterInfo;
|
|
NTSTATUS NtStatus;
|
|
LARGE_INTEGER Increment = {0, 1};
|
|
LARGE_INTEGER Index;
|
|
PGPC_CLIENT_VC Vc;
|
|
UCHAR ZeroAddress[] = {0, 0, 0, 0, 0, 0};
|
|
NDIS_HANDLE LineUpHandle;
|
|
int i,j;
|
|
|
|
LineUpBuff = (PNDIS_WAN_LINE_UP)StatusBuffer;
|
|
|
|
//
|
|
// Check for MultiLink:
|
|
//
|
|
// The first link up will have a ZeroLocal Address, in this case, we create a new QoS interface.
|
|
// All subsequent lineups will have a non-zero LocalAddress. If the link is being updated, we
|
|
// only need to update the linkspeed on the existing interface.
|
|
//
|
|
|
|
if(!(NdisEqualMemory(LineUpBuff->LocalAddress, ZeroAddress, 6)))
|
|
{
|
|
//
|
|
// Get the exisiting WanLink
|
|
//
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
NextWanLink = Adapter->WanLinkList.Flink;
|
|
|
|
while(NextWanLink != &Adapter->WanLinkList) {
|
|
|
|
WanLink = CONTAINING_RECORD(NextWanLink, PS_WAN_LINK, Linkage);
|
|
|
|
if(NdisEqualMemory(WanLink->OriginalRemoteMacAddress,
|
|
LineUpBuff->RemoteAddress,
|
|
sizeof(LineUpBuff->RemoteAddress)))
|
|
{
|
|
REFADD(&Adapter->RefCount, 'WANU');
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
PsDbgOut(DBG_TRACE, DBG_WAN,
|
|
("[CreateInterfaceForNdisWan]: Link speed of WanLink 0x%x has changed "
|
|
"from %d to %d \n", WanLink, WanLink->LinkSpeed, LineUpBuff->LinkSpeed));
|
|
|
|
WanLink->LinkSpeed = LineUpBuff->LinkSpeed;
|
|
|
|
UpdateWanLinkBandwidthParameters(WanLink);
|
|
|
|
TcIndicateInterfaceChange(Adapter, WanLink, NDIS_STATUS_INTERFACE_CHANGE);
|
|
|
|
//
|
|
// Munge s-mac and d-mac and send to wanarp.
|
|
//
|
|
PsWanMungeAddress((PUSHORT)&LineUpBuff->RemoteAddress[0],
|
|
WanLink->UniqueIndex);
|
|
|
|
PsWanMungeAddress((PUSHORT)&LineUpBuff->LocalAddress[0],
|
|
(USHORT)(*(PUSHORT)&WanLink->OriginalLocalMacAddress[0]));
|
|
|
|
NdisMIndicateStatus(Adapter->PsNdisHandle,
|
|
NDIS_STATUS_WAN_LINE_UP,
|
|
StatusBuffer,
|
|
StatusBufferSize);
|
|
|
|
REFDEL(&Adapter->RefCount, FALSE, 'WANU');
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
NextWanLink = NextWanLink->Flink;
|
|
}
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
PsDbgOut(DBG_FAILURE, DBG_WAN,
|
|
("[CreateInterfaceForNdisWan]: Got a change notification, but could not find wanlink "
|
|
"Remote Mac: (%02X:%02X:%02X:%02X:%02X:%02X) \n",
|
|
LineUpBuff->RemoteAddress[0],
|
|
LineUpBuff->RemoteAddress[1],
|
|
LineUpBuff->RemoteAddress[2],
|
|
LineUpBuff->RemoteAddress[3],
|
|
LineUpBuff->RemoteAddress[4],
|
|
LineUpBuff->RemoteAddress[5]));
|
|
|
|
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
//
|
|
// Create an internal representation of the link.
|
|
//
|
|
|
|
PsAllocatePool(WanLink,
|
|
sizeof(PS_WAN_LINK),
|
|
WanLinkTag);
|
|
|
|
if(WanLink == NULL)
|
|
{
|
|
|
|
PsDbgOut(DBG_FAILURE,
|
|
DBG_WAN,
|
|
("[CreateInterfaceForNdisWan]: Adapter %08X, couldn't create WanLink\n",
|
|
Adapter));
|
|
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// Initialize the wanlink.
|
|
//
|
|
|
|
NdisZeroMemory(WanLink, sizeof(PS_WAN_LINK));
|
|
WanLink->Adapter = Adapter;
|
|
|
|
REFINIT(&WanLink->RefCount, WanLink, DeleteWanLink);
|
|
REFADD(&WanLink->RefCount, 'WANU');
|
|
PS_INIT_SPIN_LOCK(&WanLink->Lock);
|
|
|
|
//
|
|
// Link the SausageLink on the link list.
|
|
//
|
|
|
|
NdisInterlockedIncrement(&Adapter->WanLinkCount);
|
|
|
|
NdisInterlockedInsertHeadList(&Adapter->WanLinkList,
|
|
&WanLink->Linkage,
|
|
&Adapter->Lock.Lock);
|
|
|
|
//
|
|
// Update the LinkSpeed and create a pipe off the wanlink.
|
|
//
|
|
WanLink->RawLinkSpeed = LineUpBuff->LinkSpeed;
|
|
WanLink->LinkSpeed = ( WanLink->RawLinkSpeed / 8 ) * 100;
|
|
|
|
|
|
Status = UpdateWanLinkBandwidthParameters(WanLink);
|
|
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
PsDbgOut(DBG_FAILURE,
|
|
DBG_WAN,
|
|
("[CreateInterfaceForNdisWan]: Adapter %08X, UpdateWanLinkBandwidthParameters failed with %08X",
|
|
Adapter, Status));
|
|
|
|
REFDEL(&WanLink->RefCount, FALSE, 'WANU');
|
|
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Extract the network addresses from the protocol part
|
|
// of the status buffer. Update the network layer address list
|
|
// which is held on the adapter.
|
|
//
|
|
|
|
switch(LineUpBuff->ProtocolType)
|
|
{
|
|
|
|
case PROTOCOL_IP:
|
|
|
|
RouterInfo = (PIP_WAN_LINKUP_INFO) LineUpBuff->ProtocolBuffer;
|
|
|
|
WanLink->DialUsage = RouterInfo->duUsage;
|
|
WanLink->ProtocolType = LineUpBuff->ProtocolType;
|
|
WanLink->LocalIpAddress = RouterInfo->dwLocalAddr;
|
|
WanLink->RemoteIpAddress = RouterInfo->dwRemoteAddr;
|
|
WanLink->LocalIpxAddress = 0;
|
|
WanLink->RemoteIpxAddress = 0;
|
|
break;
|
|
|
|
default:
|
|
|
|
//
|
|
// Unknown address type. We'll create a manageable
|
|
// entity, but - we don't know how to represent its
|
|
// addresses. Therefore, we also don't know how to
|
|
// format traffic control filters for it. So - it
|
|
// probably won't be particualrly useful. At least it
|
|
// lets the user see that there is an interface.
|
|
//
|
|
|
|
WanLink->ProtocolType = UNKNOWN_PROTOCOL_TYPE;
|
|
WanLink->LocalIpAddress = 0;
|
|
WanLink->RemoteIpAddress = 0;
|
|
WanLink->LocalIpxAddress = 0;
|
|
WanLink->RemoteIpxAddress = 0;
|
|
}
|
|
|
|
PsAllocatePool(WanLink->InstanceName.Buffer,
|
|
Adapter->WMIInstanceName.Length + WanPrefix.Length + INSTANCE_ID_SIZE,
|
|
PsMiscTag);
|
|
|
|
if(!WanLink->InstanceName.Buffer)
|
|
{
|
|
PsDbgOut(DBG_FAILURE,
|
|
DBG_WAN,
|
|
("[CreateInterfaceForNdisWan]: Adapter %08X, could not allocate memory for instance name \n",
|
|
Adapter));
|
|
|
|
REFDEL(&WanLink->RefCount, FALSE, 'WANU');
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
if((Status = PsWanGenerateUniqueIndex(WanLink)) != NDIS_STATUS_SUCCESS)
|
|
{
|
|
PsDbgOut(DBG_FAILURE,
|
|
DBG_WAN,
|
|
("[CreateInterfaceForNdisWan]: Adapter %08X, PsWanGenerateUniqueIndex failed with Status %08X \n",
|
|
Adapter, Status));
|
|
|
|
REFDEL(&WanLink->RefCount, FALSE, 'WANU');
|
|
return Status;
|
|
}
|
|
|
|
Index.QuadPart = WanLink->UniqueIndex;
|
|
NtStatus = GenerateInstanceName(&WanPrefix,
|
|
Adapter,
|
|
&Index,
|
|
&WanLink->InstanceName);
|
|
|
|
|
|
//
|
|
// Copy the DeviceName
|
|
//
|
|
WanLink->MpDeviceName.MaximumLength = LineUpBuff->DeviceName.MaximumLength;
|
|
|
|
PsAllocatePool(WanLink->MpDeviceName.Buffer,
|
|
WanLink->MpDeviceName.MaximumLength,
|
|
PsMiscTag);
|
|
|
|
if(!WanLink->MpDeviceName.Buffer)
|
|
{
|
|
PsDbgOut(DBG_FAILURE,
|
|
DBG_WAN,
|
|
("[CreateInterfaceForNdisWan]: Adapter %08X, could not allocate memory for device name \n",
|
|
Adapter));
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
g_WanLinkTable[WanLink->UniqueIndex] = 0;
|
|
|
|
REFDEL(&WanLink->RefCount, TRUE, 'WANU');
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
|
|
NdisZeroMemory(WanLink->MpDeviceName.Buffer, WanLink->MpDeviceName.MaximumLength);
|
|
|
|
|
|
Status = CreateBestEffortVc(Adapter,
|
|
&WanLink->BestEffortVc,
|
|
WanLink);
|
|
|
|
if(Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
PsDbgOut(DBG_FAILURE,
|
|
DBG_WAN,
|
|
("[CreateInterfaceForNdisWan]: Adapter %08X, could not create BestEffort Vc, status %08X",
|
|
Adapter, Status));
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
g_WanLinkTable[WanLink->UniqueIndex] = 0;
|
|
|
|
REFDEL(&WanLink->RefCount, TRUE, 'WANU');
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Create 2 BEVCS and make the NextVc as the first one.
|
|
WanLink->NextVc = 0;
|
|
|
|
for( i = 0; i < BEVC_LIST_LEN; i++)
|
|
{
|
|
|
|
Status = CreateBestEffortVc(Adapter,
|
|
&WanLink->BeVcList[i],
|
|
WanLink);
|
|
|
|
if(Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
PsDbgOut(DBG_FAILURE,
|
|
DBG_WAN,
|
|
("[CreateInterfaceForNdisWan]: Adapter %08X, could not create BestEffort Vc, status %08X",
|
|
Adapter, Status));
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
g_WanLinkTable[WanLink->UniqueIndex] = 0;
|
|
|
|
for( j = 0; j < i; j++ )
|
|
{
|
|
PS_LOCK_DPC(&WanLink->BeVcList[j].Lock);
|
|
|
|
InternalCloseCall(&WanLink->BeVcList[j]);
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
}
|
|
|
|
PS_LOCK_DPC(&WanLink->BestEffortVc.Lock);
|
|
|
|
InternalCloseCall(&WanLink->BestEffortVc);
|
|
|
|
REFDEL(&WanLink->RefCount, TRUE, 'WANU');
|
|
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Copy the original Remote Addresses and munge it.
|
|
//
|
|
|
|
NdisMoveMemory(&WanLink->OriginalRemoteMacAddress,
|
|
&LineUpBuff->RemoteAddress,
|
|
6);
|
|
|
|
PsWanMungeAddress((PUSHORT) &LineUpBuff->RemoteAddress[0], WanLink->UniqueIndex);
|
|
|
|
NdisMIndicateStatus(Adapter->PsNdisHandle,
|
|
NDIS_STATUS_WAN_LINE_UP,
|
|
StatusBuffer,
|
|
StatusBufferSize);
|
|
|
|
//
|
|
// Fail if wanarp has failed the line up
|
|
//
|
|
|
|
*((ULONG UNALIGNED *)(&LineUpHandle)) =
|
|
*((ULONG UNALIGNED *)(&LineUpBuff->LocalAddress[2]));
|
|
|
|
if (LineUpHandle == NULL)
|
|
{
|
|
PsDbgOut(DBG_FAILURE, DBG_WAN,
|
|
("[ClStatusIndication]: wanarp has failed the lineup. "
|
|
"Remote Address (%02X:%02X:%02X:%02X:%02X:%02X) \n",
|
|
LineUpBuff->RemoteAddress[0],
|
|
LineUpBuff->RemoteAddress[1],
|
|
LineUpBuff->RemoteAddress[2],
|
|
LineUpBuff->RemoteAddress[3],
|
|
LineUpBuff->RemoteAddress[4],
|
|
LineUpBuff->RemoteAddress[5]));
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
g_WanLinkTable[WanLink->UniqueIndex] = 0;
|
|
|
|
for( j = 0; j < BEVC_LIST_LEN; j++ )
|
|
{
|
|
PS_LOCK_DPC(&WanLink->BeVcList[j].Lock);
|
|
|
|
InternalCloseCall(&WanLink->BeVcList[j]);
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
}
|
|
|
|
PS_LOCK_DPC(&WanLink->BestEffortVc.Lock);
|
|
|
|
InternalCloseCall(&WanLink->BestEffortVc);
|
|
|
|
REFDEL(&WanLink->RefCount, FALSE, 'WANU');
|
|
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If wanarp has succeeded the lineup, we cannot get a zero local mac address.
|
|
//
|
|
PsAssert(!(NdisEqualMemory(LineUpBuff->LocalAddress, ZeroAddress, 6)));
|
|
}
|
|
|
|
//
|
|
// Copy the device name that wanarp has filled in.
|
|
//
|
|
|
|
WanLink->MpDeviceName.Length = LineUpBuff->DeviceName.Length;
|
|
NdisMoveMemory(WanLink->MpDeviceName.Buffer,
|
|
LineUpBuff->DeviceName.Buffer,
|
|
LineUpBuff->DeviceName.Length);
|
|
|
|
//
|
|
// Munge the smac address. Remember the original one that wanarp gave us.
|
|
//
|
|
|
|
NdisMoveMemory(&WanLink->OriginalLocalMacAddress,
|
|
&LineUpBuff->LocalAddress,
|
|
6);
|
|
|
|
PsWanMungeAddress((PUSHORT)&LineUpBuff->LocalAddress[0], WanLink->UniqueIndex);
|
|
|
|
//
|
|
// Create the headers that have to be slapped on the send/recv path.
|
|
//
|
|
NdisMoveMemory(&WanLink->SendHeader.DestAddr[0],
|
|
WanLink->OriginalRemoteMacAddress,
|
|
ARP_802_ADDR_LENGTH);
|
|
|
|
NdisMoveMemory(&WanLink->SendHeader.SrcAddr[0] ,
|
|
LineUpBuff->LocalAddress,
|
|
ARP_802_ADDR_LENGTH);
|
|
|
|
NdisMoveMemory(&WanLink->RecvHeader.DestAddr[0],
|
|
WanLink->OriginalLocalMacAddress,
|
|
ARP_802_ADDR_LENGTH);
|
|
|
|
NdisMoveMemory(&WanLink->RecvHeader.SrcAddr[0],
|
|
LineUpBuff->RemoteAddress,
|
|
ARP_802_ADDR_LENGTH);
|
|
|
|
//
|
|
// Unmunge the remote address in the lineup buff now.
|
|
//
|
|
PsWanMungeAddress((PUSHORT)&LineUpBuff->RemoteAddress[0],
|
|
(USHORT)(*(PUSHORT)WanLink->OriginalRemoteMacAddress));
|
|
|
|
|
|
//
|
|
// We are ready to recv and send packets.
|
|
//
|
|
|
|
PS_LOCK(&WanLink->Lock);
|
|
|
|
WanLink->State = WanStateOpen;
|
|
|
|
PS_UNLOCK(&WanLink->Lock);
|
|
|
|
PsScheduleInterfaceIdWorkItem(Adapter, WanLink);
|
|
|
|
//
|
|
// Indicate the new interface up to the TCI. We indicate both the
|
|
// addition of a new interface and the addresses available on it.
|
|
// The address descriptors indicated for WAN interfaces differ from
|
|
// those indicated for LAN interfaces. WAN interfaces include a
|
|
// destination network layer address, as well as a source address.
|
|
//
|
|
|
|
TcIndicateInterfaceChange(Adapter, WanLink, NDIS_STATUS_INTERFACE_UP);
|
|
|
|
|
|
PsDbgOut(DBG_TRACE, DBG_WAN,
|
|
("[CreateInterfaceForNdisWan]: Created WanLink 0x%x, Remote Address (%02X:%02X:%02X:%02X:%02X:%02X) \n",
|
|
WanLink,
|
|
LineUpBuff->RemoteAddress[0],
|
|
LineUpBuff->RemoteAddress[1],
|
|
LineUpBuff->RemoteAddress[2],
|
|
LineUpBuff->RemoteAddress[3],
|
|
LineUpBuff->RemoteAddress[4],
|
|
LineUpBuff->RemoteAddress[5]));
|
|
|
|
return(NDIS_STATUS_SUCCESS);
|
|
|
|
}
|
|
|
|
NDIS_STATUS
|
|
OpenWanAddressFamily(
|
|
IN PADAPTER Adapter,
|
|
IN PCO_ADDRESS_FAMILY WanAddressFamily
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Establish the binding between the PS miniport, NDISWAN and the
|
|
NDISWAN call manager.
|
|
|
|
Arguments:
|
|
|
|
Adapter - pointer to adapter
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
NDIS_CLIENT_CHARACTERISTICS WanClCharacteristics;
|
|
NDIS_STATUS Status;
|
|
|
|
WanClCharacteristics.MajorVersion = 5;
|
|
WanClCharacteristics.MinorVersion = 0;
|
|
WanClCharacteristics.Reserved = 0;
|
|
|
|
WanClCharacteristics.ClCreateVcHandler = WanCreateVc;
|
|
WanClCharacteristics.ClDeleteVcHandler = WanDeleteVc;
|
|
WanClCharacteristics.ClOpenAfCompleteHandler = WanOpenAddressFamilyComplete;
|
|
WanClCharacteristics.ClCloseAfCompleteHandler = WanCloseAddressFamilyComplete;
|
|
WanClCharacteristics.ClRegisterSapCompleteHandler = WanRegisterSapComplete;
|
|
WanClCharacteristics.ClDeregisterSapCompleteHandler = WanDeregisterSapComplete;
|
|
WanClCharacteristics.ClMakeCallCompleteHandler = WanMakeCallComplete;
|
|
WanClCharacteristics.ClModifyCallQoSCompleteHandler = WanModifyCallComplete;
|
|
WanClCharacteristics.ClCloseCallCompleteHandler = WanCloseCallComplete;
|
|
WanClCharacteristics.ClAddPartyCompleteHandler = WanAddPartyComplete;
|
|
WanClCharacteristics.ClDropPartyCompleteHandler = WanDropPartyComplete;
|
|
WanClCharacteristics.ClIncomingCallHandler = WanIncomingCall;
|
|
WanClCharacteristics.ClIncomingCallQoSChangeHandler = WanIncomingCallQoSChange;
|
|
WanClCharacteristics.ClIncomingCloseCallHandler = WanIncomingCloseCall;
|
|
WanClCharacteristics.ClIncomingDropPartyHandler = WanIncomingDropParty;
|
|
WanClCharacteristics.ClCallConnectedHandler = WanCallConnected;
|
|
WanClCharacteristics.ClRequestHandler = WanCoRequest;
|
|
WanClCharacteristics.ClRequestCompleteHandler = WanCoRequestComplete;
|
|
|
|
PsDbgOut(DBG_TRACE,
|
|
DBG_WAN | DBG_INIT,
|
|
("[OpenWanAddressFamily]: Adapter %08X \n", Adapter));
|
|
|
|
Status = NdisClOpenAddressFamily(Adapter->LowerMpHandle,
|
|
WanAddressFamily,
|
|
Adapter,
|
|
&WanClCharacteristics,
|
|
sizeof(WanClCharacteristics),
|
|
&Adapter->WanCmHandle);
|
|
|
|
if(Status != NDIS_STATUS_PENDING)
|
|
{
|
|
WanOpenAddressFamilyComplete(Status,
|
|
Adapter,
|
|
Adapter->WanCmHandle);
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // OpenWanAddressFamily
|
|
|
|
|
|
VOID
|
|
WanOpenAddressFamilyComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolAfContext,
|
|
IN NDIS_HANDLE NdisAfHandle
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Complete a call to NdisClOpenAddressFamily.
|
|
|
|
Arguments:
|
|
|
|
see the DDK
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PADAPTER Adapter = (PADAPTER)ProtocolAfContext;
|
|
|
|
|
|
if(Status != NDIS_STATUS_SUCCESS){
|
|
|
|
PsDbgOut(DBG_CRITICAL_ERROR,
|
|
DBG_WAN,
|
|
("[WanOpenAddressFamilyComplete]: Adapter %08X, open failed %08X\n",
|
|
Adapter, Status));
|
|
|
|
PsAdapterWriteEventLog(
|
|
EVENT_PS_REGISTER_ADDRESS_FAMILY_FAILED,
|
|
0,
|
|
&Adapter->MpDeviceName,
|
|
sizeof(Status),
|
|
&Status);
|
|
|
|
return;
|
|
}
|
|
else{
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
Adapter->WanBindingState |= WAN_ADDR_FAMILY_OPEN;
|
|
|
|
Adapter->ShutdownMask |= SHUTDOWN_CLOSE_WAN_ADDR_FAMILY;
|
|
|
|
Adapter->WanCmHandle = NdisAfHandle;
|
|
|
|
Adapter->FinalStatus = Status;
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
PsDbgOut(DBG_TRACE,
|
|
DBG_WAN | DBG_INIT,
|
|
("[WanOpenAddressFamilyComplete]: Adapter %08X, Status = %x\n",
|
|
Adapter,
|
|
Status));
|
|
}
|
|
|
|
} // WanOpenAddressFamilyComplete
|
|
|
|
VOID
|
|
WanMakeCallComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolVcContext,
|
|
IN NDIS_HANDLE NdisPartyHandle,
|
|
IN OUT PCO_CALL_PARAMETERS CallParameters
|
|
)
|
|
{
|
|
PGPC_CLIENT_VC Vc = (PGPC_CLIENT_VC) ProtocolVcContext;
|
|
PADAPTER Adapter = Vc->Adapter;
|
|
|
|
PsStructAssert(Adapter);
|
|
|
|
//
|
|
// Common code to complete both synchronous and asynchronous
|
|
// returns from WanMakeCall. Note that, unless there is a WAN
|
|
// adapter, CmMakeCall will always complete synchronously.
|
|
//
|
|
|
|
if(Status != NDIS_STATUS_SUCCESS){
|
|
|
|
//
|
|
// We probably at least succeeeded in creating a VC in NDISWAN.
|
|
// If we did, we should delete it here. We may have failed however,
|
|
// because we could not create the VC, in which case, we have
|
|
// nothing to delete.
|
|
//
|
|
|
|
if(Vc->NdisWanVcHandle){
|
|
|
|
NdisCoDeleteVc(Vc->NdisWanVcHandle);
|
|
|
|
Vc->NdisWanVcHandle = NULL;
|
|
}
|
|
}
|
|
|
|
CompleteMakeCall(Vc,
|
|
CallParameters,
|
|
Status);
|
|
}
|
|
|
|
VOID
|
|
WanModifyCallComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolVcContext,
|
|
IN OUT PCO_CALL_PARAMETERS CallParameters
|
|
)
|
|
{
|
|
PGPC_CLIENT_VC Vc = (PGPC_CLIENT_VC)ProtocolVcContext;
|
|
PADAPTER Adapter = Vc->Adapter;
|
|
|
|
PsStructAssert(Adapter);
|
|
|
|
//
|
|
// Common code to complete both synchronous and asynchronous
|
|
// returns from WanModifyCall.
|
|
//
|
|
|
|
if(Status != NDIS_STATUS_SUCCESS) {
|
|
|
|
//
|
|
// We changed some of the ISSLOW stuff - Time to revert back
|
|
//
|
|
|
|
WanHandleISSLOW(Vc, Vc->CallParameters);
|
|
}
|
|
|
|
ModifyCallComplete(Vc, CallParameters, Status);
|
|
}
|
|
|
|
|
|
VOID
|
|
WanCloseAddressFamilyComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolBindingContext
|
|
)
|
|
{
|
|
PADAPTER Adapter = (PADAPTER)ProtocolBindingContext;
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
Adapter->WanBindingState &= ~WAN_ADDR_FAMILY_OPEN;
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
WanCreateVc(
|
|
IN NDIS_HANDLE ProtocolAfContext,
|
|
IN NDIS_HANDLE NdisVcHandle,
|
|
OUT PNDIS_HANDLE ProtocolVcContext
|
|
)
|
|
{
|
|
DEBUGCHK;
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
WanDeleteVc(
|
|
IN NDIS_HANDLE ProtocolVcContext
|
|
)
|
|
{
|
|
DEBUGCHK;
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
VOID
|
|
WanRegisterSapComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolSapContext,
|
|
IN PCO_SAP Sap,
|
|
IN NDIS_HANDLE NdisSapHandle
|
|
)
|
|
{
|
|
DEBUGCHK;
|
|
}
|
|
|
|
VOID
|
|
WanDeregisterSapComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolSapContext
|
|
)
|
|
{
|
|
DEBUGCHK;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
WanIncomingCall(
|
|
IN NDIS_HANDLE ProtocolSapContext,
|
|
IN NDIS_HANDLE ProtocolVcContext,
|
|
IN OUT PCO_CALL_PARAMETERS CallParameters
|
|
)
|
|
{
|
|
DEBUGCHK;
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
VOID
|
|
WanAddPartyComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolPartyContext,
|
|
IN NDIS_HANDLE NdisPartyHandle,
|
|
IN PCO_CALL_PARAMETERS CallParameters
|
|
)
|
|
{
|
|
DEBUGCHK;
|
|
}
|
|
|
|
VOID
|
|
WanDropPartyComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolPartyContext
|
|
)
|
|
{
|
|
DEBUGCHK;
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
WanHandleISSLOW(
|
|
IN PGPC_CLIENT_VC Vc,
|
|
IN PCO_CALL_PARAMETERS CallParameters
|
|
)
|
|
{
|
|
LONG ParamsLength;
|
|
LPQOS_OBJECT_HDR QoSObject;
|
|
PADAPTER Adapter = Vc->Adapter;
|
|
PCO_MEDIA_PARAMETERS CallMgrParams = CallParameters->MediaParameters;
|
|
ULONGLONG i,j,k;
|
|
|
|
//
|
|
// See if this is an ISSLOW flow.
|
|
//
|
|
ParamsLength = (LONG)CallMgrParams->MediaSpecific.Length;
|
|
QoSObject = (LPQOS_OBJECT_HDR)CallMgrParams->MediaSpecific.Parameters;
|
|
|
|
//
|
|
// By default, this is not an ISSLOW flow.
|
|
//
|
|
|
|
Vc->Flags &= ~GPC_ISSLOW_FLOW;
|
|
|
|
while(ParamsLength > 0){
|
|
|
|
if(QoSObject->ObjectType == QOS_OBJECT_WAN_MEDIA)
|
|
{
|
|
LPQOS_WAN_MEDIA WanMedia = (LPQOS_WAN_MEDIA)QoSObject;
|
|
|
|
WanMedia->ISSLOW = FALSE;
|
|
|
|
//
|
|
// See if the flow is an ISSLOW flow. If the TokenRate of the flow
|
|
// is under ISSLOW TokenRate and the PacketSize is under MaxPacketSize
|
|
// Then we qualify this as ISSLOW flows.
|
|
//
|
|
// If a wanlink's linkspeed is greater than a certain amount, we don't run issow over it.
|
|
//
|
|
|
|
if((Vc->WanLink->LinkSpeed <= Adapter->ISSLOWLinkSpeed) &&
|
|
(CallParameters->CallMgrParameters->Transmit.ServiceType != SERVICETYPE_BESTEFFORT))
|
|
{
|
|
i = (ULONG) Adapter->ISSLOWTokenRate * (ULONG) CallParameters->CallMgrParameters->Transmit.MaxSduSize;
|
|
j = (ULONG) Adapter->ISSLOWPacketSize * (ULONG) CallParameters->CallMgrParameters->Transmit.TokenRate;
|
|
k = (ULONG) Adapter->ISSLOWTokenRate * (ULONG)Adapter->ISSLOWPacketSize;
|
|
|
|
if((i+j)<k)
|
|
{
|
|
WanMedia->ISSLOW = TRUE;
|
|
|
|
PsDbgOut(DBG_TRACE, DBG_WAN,
|
|
("[WanHandleISSLOW]: Vc %08X is an ISSLOW VC (TokenRate = %d, PacketSize = %d \n",
|
|
Vc, CallParameters->CallMgrParameters->Transmit.TokenRate,
|
|
CallParameters->CallMgrParameters->Transmit.MaxSduSize));
|
|
|
|
//
|
|
// The MaxSDUSize is normally a measure of the latency requirements of -that- flow
|
|
// For audio codes, MaxSDUSize = f(Latency requirements, unit size);
|
|
//
|
|
// But, we don't want to chop these into very small fragments. Therefore, we have
|
|
// an upper bound and pick the maximum.
|
|
//
|
|
|
|
if(CallParameters->CallMgrParameters->Transmit.MaxSduSize > Adapter->ISSLOWFragmentSize)
|
|
{
|
|
Vc->ISSLOWFragmentSize = CallParameters->CallMgrParameters->Transmit.MaxSduSize;
|
|
}
|
|
else
|
|
{
|
|
Vc->ISSLOWFragmentSize = Adapter->ISSLOWFragmentSize;
|
|
}
|
|
|
|
Vc->Flags |= GPC_ISSLOW_FLOW;
|
|
|
|
PsDbgOut(DBG_TRACE, DBG_WAN,
|
|
("[WanHandleISSLOW]: Adapter %08X, ISSLOW Vc %08X, FragmentSize = %d bytes \n",
|
|
Adapter, Vc, Vc->ISSLOWFragmentSize));
|
|
|
|
}
|
|
else
|
|
{
|
|
PsDbgOut(DBG_TRACE, DBG_WAN,
|
|
("[WanHandleISSLOW]: Non ISSLOW Vc %08X. ISSLOW TokenRate %d, "
|
|
"ISSLOW Packet Size %d, VC TokenRate %d, VC Packet Size %d \n",
|
|
Vc, Adapter->ISSLOWTokenRate,
|
|
Adapter->ISSLOWPacketSize,
|
|
CallParameters->CallMgrParameters->Transmit.TokenRate,
|
|
CallParameters->CallMgrParameters->Transmit.MaxSduSize));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PsDbgOut(DBG_TRACE, DBG_WAN,
|
|
("[WanHandleISSLOW]: Non ISSLOW Vc %08X. (servicetype == B/E "
|
|
" or WAN LinkSpeed %d < ISSLOW LinkSpeed %d \n",
|
|
Vc, Vc->WanLink->LinkSpeed, Adapter->ISSLOWLinkSpeed));
|
|
}
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
else {
|
|
|
|
if(
|
|
((LONG)QoSObject->ObjectLength <= 0) ||
|
|
((LONG)QoSObject->ObjectLength > ParamsLength)
|
|
){
|
|
|
|
return(QOS_STATUS_TC_OBJECT_LENGTH_INVALID);
|
|
}
|
|
|
|
ParamsLength -= QoSObject->ObjectLength;
|
|
QoSObject = (LPQOS_OBJECT_HDR)((UINT_PTR)QoSObject +
|
|
QoSObject->ObjectLength);
|
|
|
|
}
|
|
}
|
|
|
|
return NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
WanMakeCall(
|
|
IN PGPC_CLIENT_VC Vc,
|
|
IN OUT PCO_CALL_PARAMETERS CallParameters
|
|
)
|
|
{
|
|
NDIS_STATUS Status;
|
|
PADAPTER Adapter;
|
|
|
|
Adapter = Vc->Adapter;
|
|
PsStructAssert(Adapter);
|
|
|
|
//
|
|
// Handle ISSLOW
|
|
//
|
|
WanHandleISSLOW(Vc, CallParameters);
|
|
|
|
//
|
|
// Create a VC in the Wan adapter.
|
|
//
|
|
Vc->NdisWanVcHandle = NULL;
|
|
|
|
Status = NdisCoCreateVc(Adapter->LowerMpHandle,
|
|
Adapter->WanCmHandle,
|
|
Vc,
|
|
&Vc->NdisWanVcHandle);
|
|
|
|
PsAssert(Status != NDIS_STATUS_PENDING);
|
|
|
|
if(Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
Vc->NdisWanVcHandle = 0;
|
|
|
|
PsDbgOut(DBG_FAILURE, DBG_WAN,
|
|
("[WanMakeCall]: cannot create VC. Status = %d\n", Status));
|
|
|
|
WanMakeCallComplete(Status, Vc, NULL, CallParameters);
|
|
}
|
|
else
|
|
{
|
|
Status = NdisClMakeCall(Vc->NdisWanVcHandle, CallParameters, NULL, NULL);
|
|
|
|
if(Status != NDIS_STATUS_PENDING){
|
|
|
|
WanMakeCallComplete(Status, Vc, NULL, CallParameters);
|
|
}
|
|
}
|
|
|
|
return (NDIS_STATUS_PENDING);
|
|
}
|
|
|
|
VOID
|
|
WanCloseCall(
|
|
IN PGPC_CLIENT_VC Vc
|
|
)
|
|
{
|
|
NDIS_STATUS Status;
|
|
|
|
//
|
|
// Issue a CloseCall to the WAN call manager.
|
|
//
|
|
|
|
PsAssert(Vc->NdisWanVcHandle);
|
|
|
|
Status = NdisClCloseCall(Vc->NdisWanVcHandle,
|
|
NULL,
|
|
NULL,
|
|
0);
|
|
|
|
if(Status != NDIS_STATUS_PENDING)
|
|
{
|
|
WanCloseCallComplete(Status,
|
|
Vc,
|
|
Vc->CallParameters);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
WanCloseCallComplete(
|
|
NDIS_STATUS Status,
|
|
NDIS_HANDLE ProtocolVcContext,
|
|
PCO_CALL_PARAMETERS CallParameters
|
|
)
|
|
{
|
|
PGPC_CLIENT_VC Vc = (PGPC_CLIENT_VC) ProtocolVcContext;
|
|
|
|
Status = NdisCoDeleteVc(Vc->NdisWanVcHandle);
|
|
|
|
PsAssert(Status != NDIS_STATUS_PENDING);
|
|
|
|
Vc->NdisWanVcHandle = 0;
|
|
|
|
CmDeleteVc(Vc);
|
|
|
|
}
|
|
|
|
NDIS_STATUS
|
|
WanModifyCall(
|
|
IN PGPC_CLIENT_VC Vc,
|
|
IN OUT PCO_CALL_PARAMETERS CallParameters
|
|
)
|
|
{
|
|
NDIS_STATUS Status;
|
|
|
|
WanHandleISSLOW(Vc, CallParameters);
|
|
|
|
PsAssert(Vc->NdisWanVcHandle);
|
|
|
|
Status = NdisClModifyCallQoS(Vc->NdisWanVcHandle, CallParameters);
|
|
|
|
if(Status != NDIS_STATUS_PENDING)
|
|
{
|
|
WanModifyCallComplete(Status, Vc, CallParameters);
|
|
}
|
|
|
|
return NDIS_STATUS_PENDING;
|
|
}
|
|
|
|
VOID
|
|
AskWanLinksToClose(PADAPTER Adapter)
|
|
{
|
|
|
|
PLIST_ENTRY NextWanLink;
|
|
PPS_WAN_LINK WanLink;
|
|
|
|
PsDbgOut(DBG_TRACE, DBG_WAN,
|
|
("[AskWanLinksToClose]: Adapter %08X - All wanlinks are closing \n", Adapter));
|
|
|
|
//
|
|
// Walk the List & remove the WanLink
|
|
//
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
while(!IsListEmpty(&Adapter->WanLinkList)) {
|
|
|
|
NextWanLink = RemoveHeadList(&Adapter->WanLinkList);
|
|
|
|
WanLink = CONTAINING_RECORD(NextWanLink, PS_WAN_LINK, Linkage);
|
|
|
|
//
|
|
// Get rid of the wanlink from the list.
|
|
//
|
|
g_WanLinkTable[WanLink->UniqueIndex] = 0;
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
CleanWanLink(Adapter, WanLink);
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
}
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
return;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
CleanWanLink(PADAPTER Adapter,
|
|
PPS_WAN_LINK WanLink)
|
|
{
|
|
PLIST_ENTRY NextVc;
|
|
PGPC_CLIENT_VC Vc;
|
|
PUSHORT id;
|
|
int j;
|
|
|
|
PsDbgOut(DBG_TRACE, DBG_WAN, ("[CleanWanLink]: WanLink 0x%x is going down \n", WanLink));
|
|
|
|
TcIndicateInterfaceChange(Adapter, WanLink, NDIS_STATUS_INTERFACE_DOWN);
|
|
|
|
PS_LOCK(&WanLink->Lock);
|
|
|
|
WanLink->State = WanStateClosing;
|
|
|
|
PS_UNLOCK(&WanLink->Lock);
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
//
|
|
// Make sure to delete Be Vc1 also..
|
|
|
|
for( j = 0; j < BEVC_LIST_LEN; j++ )
|
|
{
|
|
PS_LOCK_DPC(&WanLink->BeVcList[j].Lock);
|
|
|
|
InternalCloseCall(&WanLink->BeVcList[j]);
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
}
|
|
|
|
PS_LOCK_DPC(&WanLink->BestEffortVc.Lock);
|
|
|
|
InternalCloseCall(&WanLink->BestEffortVc);
|
|
|
|
NdisInterlockedDecrement(&Adapter->WanLinkCount);
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
//
|
|
// Clean up all the GPC VCs on the WanLink;
|
|
//
|
|
|
|
NextVc = Adapter->GpcClientVcList.Flink;
|
|
|
|
while(NextVc != &Adapter->GpcClientVcList)
|
|
{
|
|
|
|
Vc = CONTAINING_RECORD(NextVc, GPC_CLIENT_VC, Linkage);
|
|
|
|
NextVc = NextVc->Flink;
|
|
|
|
PsAssert(Vc);
|
|
|
|
if(Vc->WanLink == WanLink)
|
|
{
|
|
|
|
PS_LOCK_DPC(&Vc->Lock);
|
|
|
|
if(Vc->ClVcState == CL_INTERNAL_CLOSE_PENDING || Vc->Flags & INTERNAL_CLOSE_REQUESTED)
|
|
{
|
|
// We have already closed this Vc. Let's move on.
|
|
|
|
PS_UNLOCK_DPC(&Vc->Lock);
|
|
}
|
|
else
|
|
{
|
|
|
|
InternalCloseCall(Vc);
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
//
|
|
// Sigh. We can't really get hold to the NextVc in a reliable manner. When we call
|
|
// InternalCloseCall on the Vc, it releases the Adapter Lock (since it might have to
|
|
// make calls into NDIS). Now, in this window, the next Vc could go away, and we
|
|
// could point to a stale Vc. So, we start at the head of the list.
|
|
// Note that this can never lead to a infinite loop, since we don't process the
|
|
// internal close'd VCs repeatedly.
|
|
//
|
|
|
|
NextVc = Adapter->GpcClientVcList.Flink;
|
|
}
|
|
}
|
|
}
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
REFDEL(&WanLink->RefCount, FALSE, 'WANU');
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
WanIncomingCallQoSChange(
|
|
IN NDIS_HANDLE ProtocolVcContext,
|
|
IN PCO_CALL_PARAMETERS CallParameters
|
|
)
|
|
{
|
|
DEBUGCHK;
|
|
}
|
|
|
|
VOID
|
|
WanIncomingCloseCall(
|
|
IN NDIS_STATUS CloseStatus,
|
|
IN NDIS_HANDLE ProtocolVcContext,
|
|
IN PVOID CloseData OPTIONAL,
|
|
IN UINT Size OPTIONAL
|
|
)
|
|
{
|
|
PGPC_CLIENT_VC Vc = (PGPC_CLIENT_VC) ProtocolVcContext;
|
|
|
|
PsAssert(Vc);
|
|
|
|
CheckLLTag(Vc, GpcClientVc);
|
|
|
|
PS_LOCK(&Vc->Adapter->Lock);
|
|
|
|
PS_LOCK_DPC(&Vc->Lock);
|
|
|
|
InternalCloseCall(Vc);
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
WanIncomingDropParty(
|
|
IN NDIS_STATUS DropStatus,
|
|
IN NDIS_HANDLE ProtocolPartyContext,
|
|
IN PVOID CloseData OPTIONAL,
|
|
IN UINT Size OPTIONAL
|
|
)
|
|
{
|
|
DEBUGCHK;
|
|
}
|
|
|
|
VOID
|
|
WanCallConnected(
|
|
IN NDIS_HANDLE ProtocolPartyContext
|
|
)
|
|
{
|
|
DEBUGCHK;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
WanCoRequest(
|
|
IN NDIS_HANDLE ProtocolAfContext,
|
|
IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
|
|
IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
|
|
IN OUT PNDIS_REQUEST NdisRequest
|
|
)
|
|
{
|
|
DEBUGCHK;
|
|
return NDIS_STATUS_INVALID_OID;
|
|
}
|
|
|
|
VOID
|
|
WanCoRequestComplete(
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolAfContext,
|
|
IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
|
|
IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
|
|
IN PNDIS_REQUEST NdisRequest
|
|
)
|
|
{
|
|
ClRequestComplete(ProtocolAfContext,
|
|
NdisRequest,
|
|
Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
UpdateWanLinkBandwidthParameters(PPS_WAN_LINK WanLink)
|
|
{
|
|
//
|
|
// Called any time the link speed is updated. This
|
|
// function generates the adapter link speed and the
|
|
// and non-best-effort rate limits, both in bytes per second.
|
|
//
|
|
|
|
PsUpdateLinkSpeed(WanLink->Adapter,
|
|
WanLink->RawLinkSpeed,
|
|
&WanLink->RemainingBandWidth,
|
|
&WanLink->LinkSpeed,
|
|
&WanLink->NonBestEffortLimit,
|
|
&WanLink->Lock);
|
|
|
|
return UpdateWanSchedulingPipe(WanLink);
|
|
}
|