windows-nt/Source/XPSP1/NT/net/rras/ndis/ndiswan/cm.c

512 lines
13 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1990-1997 Microsoft Corporation
Module Name:
cm.c
Abstract:
This file contains the functions that implement the ndiswan
NDIS 5.0 call manager interface. These functions are used by the
ndiswan miniport and NDIS 5.0 clients.
Author:
Tony Bell (TonyBe) January 9, 1997
Environment:
Kernel Mode
Revision History:
TonyBe 01/09/97 Created
--*/
#include "wan.h"
#include "traffic.h"
#include "ntddtc.h"
#define __FILE_SIG__ CM_FILESIG
NDIS_STATUS
CmCreateVc(
IN NDIS_HANDLE ProtocolAfContext,
IN NDIS_HANDLE NdisVcHandle,
OUT PNDIS_HANDLE ProtocolVcContext
)
{
PCM_AFSAPCB AfSapCB = (PCM_AFSAPCB)ProtocolAfContext;
PCM_VCCB CmVcCB;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmCreateVc: Enter"));
CmVcCB =
NdisWanAllocateCmVcCB(AfSapCB, NdisVcHandle);
if (CmVcCB == NULL) {
return (NDIS_STATUS_RESOURCES);
}
*ProtocolVcContext = CmVcCB;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmCreateVc: Exit"));
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
CmDeleteVc(
IN NDIS_HANDLE ProtocolVcContext
)
{
PCM_VCCB CmVcCB;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmDeleteVc: Enter"));
CmVcCB = (PCM_VCCB)ProtocolVcContext;
ASSERT(CmVcCB->RefCount == 0);
NdisWanFreeCmVcCB(CmVcCB);
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmDeleteVc: Exit"));
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
CmOpenAf(
IN NDIS_HANDLE CallMgrBindingContext,
IN PCO_ADDRESS_FAMILY AddressFamily,
IN NDIS_HANDLE NdisAfHandle,
OUT PNDIS_HANDLE CallMgrAfContext
)
{
PMINIPORTCB MiniportCB = (PMINIPORTCB)CallMgrBindingContext;
PCM_AFSAPCB AfSapCB;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmOpenAf: Enter"));
if (AddressFamily->AddressFamily != CO_ADDRESS_FAMILY_PPP) {
return (NDIS_STATUS_FAILURE);
}
AfSapCB =
NdisWanAllocateCmAfSapCB(MiniportCB);
if (AfSapCB == NULL) {
return (NDIS_STATUS_RESOURCES);
}
*CallMgrAfContext = (NDIS_HANDLE)AfSapCB;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmOpenAf: Exit"));
return(NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
CmCloseAf(
IN NDIS_HANDLE CallMgrAfContext
)
{
PCM_AFSAPCB AfSapCB = (PCM_AFSAPCB)CallMgrAfContext;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmCloseAf: Enter"));
NdisWanFreeCmAfSapCB(AfSapCB);
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmCloseAf: Exit"));
return(NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
CmRegisterSap(
IN NDIS_HANDLE CallMgrAfContext,
IN PCO_SAP Sap,
IN NDIS_HANDLE NdisSapHandle,
OUT PNDIS_HANDLE CallMgrSapContext
)
{
PMINIPORTCB MiniportCB = (PMINIPORTCB)CallMgrAfContext;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmRegisterSap: Enter SapType %d", Sap->SapType));
*CallMgrSapContext = CallMgrAfContext;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmRegisterSap: Exit"));
return(NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
CmDeregisterSap(
IN NDIS_HANDLE CallMgrSapContext
)
{
PCM_AFSAPCB AfSapCB = (PCM_AFSAPCB)CallMgrSapContext;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmDeregisterSap: Enter"));
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmDeregisterSap: Exit"));
return(NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
CmMakeCall(
IN NDIS_HANDLE CallMgrVcContext,
IN OUT PCO_CALL_PARAMETERS CallParameters,
IN NDIS_HANDLE NdisPartyHandle OPTIONAL,
OUT PNDIS_HANDLE CallMgrPartyContext OPTIONAL
)
{
PBUNDLECB BundleCB;
PPROTOCOLCB ProtocolCB;
PCM_VCCB CmVcCB;
PCO_CALL_MANAGER_PARAMETERS CallMgrParams;
PCO_MEDIA_PARAMETERS MediaParams;
PCO_SPECIFIC_PARAMETERS SpecificParams;
LPQOS_WAN_MEDIA QosMedia;
LPQOS_OBJECT_HDR QoSObject;
LONG ParamsLength;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmMakeCall: Enter"));
CmVcCB = (PCM_VCCB)CallMgrVcContext;
CallMgrParams =
CallParameters->CallMgrParameters;
MediaParams =
CallParameters->MediaParameters;
SpecificParams = &MediaParams->MediaSpecific;
if (SpecificParams->ParamType != PARAM_TYPE_GQOS_INFO) {
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_CM,
("CmMakeCall: Not a QOS Vc! ParamType %x", SpecificParams->ParamType));
return (NDIS_STATUS_FAILURE);
}
QosMedia = (LPQOS_WAN_MEDIA)SpecificParams->Parameters;
//
// Need to check the flowspec for bandwidth
//
do {
ULONG_PTR BIndex, PIndex;
//
// Get the protocolcb
//
GetNdisWanIndices(QosMedia->LinkId, BIndex, PIndex);
if (!IsBundleValid((NDIS_HANDLE)BIndex,
TRUE,
&BundleCB)) {
Status = NDIS_STATUS_FAILURE;
break;
}
AcquireBundleLock(BundleCB);
PROTOCOLCB_FROM_PROTOCOLH(BundleCB, ProtocolCB, PIndex);
if (ProtocolCB == NULL ||
ProtocolCB == (PVOID)RESERVED_PROTOCOLCB ||
ProtocolCB->State != PROTOCOL_ROUTED) {
ReleaseBundleLock(BundleCB);
Status = NDIS_STATUS_FAILURE;
break;
}
//
// If we don't have multilink or if we have encryption then we can not
// do isslow
//
if (!(BundleCB->FramingInfo.SendFramingBits & PPP_MULTILINK_FRAMING) ||
(BundleCB->SendFlags & DO_ENCRYPTION)) {
CmVcCB->FlowClass = 0;
} else {
if (QosMedia->ISSLOW == 1) {
CmVcCB->FlowClass = MAX_MCML;
BundleCB->Flags |= QOS_ENABLED;
} else {
CmVcCB->FlowClass = 0;
}
}
#ifdef USE_QOS_WORKER
NdisInitializeWorkItem(&BundleCB->QoSWorkItem,
QoSSendFragments,
BundleCB);
#endif
SetBundleFlags(BundleCB);
NdisWanDbgOut(DBG_INFO, DBG_CM, ("MakeCall Vc/Protocol %p/%p %d/%d",
CmVcCB, ProtocolCB, CmVcCB->State, ProtocolCB->State));
NdisWanDbgOut(DBG_INFO, DBG_CM, ("Setting FlowClass %x Isslow %d",
CmVcCB->FlowClass, QosMedia->ISSLOW));
REF_CMVCCB(CmVcCB);
CmVcCB->ProtocolCB = ProtocolCB;
InsertTailList(&ProtocolCB->VcList, &CmVcCB->Linkage);
REF_PROTOCOLCB(ProtocolCB);
ReleaseBundleLock(BundleCB);
InterlockedExchange((PLONG)&CmVcCB->State, CMVC_ACTIVE);
NdisMCmActivateVc(CmVcCB->NdisVcHandle, CallParameters);
} while (FALSE);
//
// Deref for ref applied in IsBundleValid
//
DEREF_BUNDLECB(BundleCB);
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmMakeCall: Exit"));
return(Status);
}
NDIS_STATUS
CmCloseCall(
IN NDIS_HANDLE CallMgrVcContext,
IN NDIS_HANDLE CallMgrPartyContext OPTIONAL,
IN PVOID CloseData OPTIONAL,
IN UINT Size OPTIONAL
)
{
PPROTOCOLCB ProtocolCB;
PBUNDLECB BundleCB;
PCM_VCCB CmVcCB;
BOOLEAN DisableQoS = TRUE;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmCloseCall: Enter"));
CmVcCB = (PCM_VCCB)CallMgrVcContext;
ProtocolCB =
CmVcCB->ProtocolCB;
BundleCB =
ProtocolCB->BundleCB;
AcquireBundleLock(BundleCB);
if (CmVcCB->State != CMVC_CLOSE_DISPATCHED) {
RemoveEntryList(&CmVcCB->Linkage);
}
//
// Walk the Vc list and see if there are any
// ISSLOW Vc's. If there are not then disable QOS
//
{
PCM_VCCB _vc;
_vc = (PCM_VCCB)ProtocolCB->VcList.Flink;
while ((PVOID)_vc != (PVOID)&ProtocolCB->VcList) {
if (_vc->FlowClass == MAX_MCML) {
DisableQoS = FALSE;
break;
}
_vc = (PCM_VCCB)_vc->Linkage.Flink;
}
}
NdisWanDbgOut(DBG_INFO, DBG_CM, ("CloseCall Vc/Protocol %p/%p %d/%d",
CmVcCB, ProtocolCB, CmVcCB->State, ProtocolCB->State));
InterlockedExchange((PLONG)&CmVcCB->State, CMVC_CLOSING);
DEREF_CMVCCB(CmVcCB);
DEREF_PROTOCOLCB(ProtocolCB);
if (DisableQoS && BundleCB != NULL) {
BundleCB->Flags &= ~QOS_ENABLED;
}
ReleaseBundleLock(BundleCB);
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmCloseCall: Exit"));
return(NDIS_STATUS_PENDING);
}
NDIS_STATUS
CmModifyCallQoS(
IN NDIS_HANDLE CallMgrVcContext,
IN PCO_CALL_PARAMETERS CallParameters
)
{
PCM_VCCB CmVcCB;
PCO_CALL_MANAGER_PARAMETERS CallMgrParams;
PCO_MEDIA_PARAMETERS MediaParams;
PCO_SPECIFIC_PARAMETERS SpecificParams;
LPQOS_WAN_MEDIA QosMedia;
LPQOS_OBJECT_HDR QoSObject;
PBUNDLECB BundleCB;
PPROTOCOLCB ProtocolCB;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmModifyCallQos: Enter"));
CmVcCB = (PCM_VCCB)CallMgrVcContext;
CallMgrParams =
CallParameters->CallMgrParameters;
MediaParams =
CallParameters->MediaParameters;
SpecificParams = &MediaParams->MediaSpecific;
if (SpecificParams->ParamType != PARAM_TYPE_GQOS_INFO) {
NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_CM,
("CmMakeCall: Not a QOS Vc! ParamType %x", SpecificParams->ParamType));
return (NDIS_STATUS_SUCCESS);
}
QosMedia = (LPQOS_WAN_MEDIA)SpecificParams->Parameters;
ProtocolCB = CmVcCB->ProtocolCB;
if (ProtocolCB == NULL) {
return (NDIS_STATUS_SUCCESS);
}
BundleCB = ProtocolCB->BundleCB;
if (BundleCB == NULL) {
return (NDIS_STATUS_SUCCESS);
}
AcquireBundleLock(BundleCB);
//
// If we don't have multilink or if we have encryption then we can not
// do isslow
//
if (!(BundleCB->FramingInfo.SendFramingBits & PPP_MULTILINK_FRAMING) ||
(BundleCB->SendFlags & DO_ENCRYPTION))
{
CmVcCB->FlowClass = 0;
} else {
if (QosMedia->ISSLOW == 1) {
CmVcCB->FlowClass = MAX_MCML;
BundleCB->Flags |= QOS_ENABLED;
} else {
CmVcCB->FlowClass = 0;
// Walk the Vc list and see if there are any
// ISSLOW Vc's. If there are not then disable QOS
{
PCM_VCCB _vc;
BOOLEAN DisableQoS = TRUE;
_vc = (PCM_VCCB)ProtocolCB->VcList.Flink;
while ((PVOID)_vc != (PVOID)&ProtocolCB->VcList) {
if (_vc->FlowClass == MAX_MCML) {
DisableQoS = FALSE;
break;
}
_vc = (PCM_VCCB)_vc->Linkage.Flink;
}
if (DisableQoS) {
BundleCB->Flags &= ~QOS_ENABLED;
}
}
}
}
SetBundleFlags(BundleCB);
ReleaseBundleLock(BundleCB);
NdisWanDbgOut(DBG_DEATH, DBG_CM, ("Updating FlowClass %x for Vc/Protocol %p/%p, Isslow %d",
CmVcCB->FlowClass, CmVcCB, CmVcCB->ProtocolCB, QosMedia->ISSLOW));
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmModifyCallQos: Exit"));
return(NDIS_STATUS_SUCCESS);
}
VOID
CmIncomingCallComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE CallMgrVcContext,
IN PCO_CALL_PARAMETERS CallParameters
)
{
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmIncomingCallComplete: Enter"));
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmIncomingCallComplete: Exit"));
}
VOID
CmActivateVcComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE CallMgrVcContext,
IN PCO_CALL_PARAMETERS CallParameters
)
{
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmActivateVcComplete: Enter"));
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmActivateVcComplete: Exit"));
}
VOID
CmDeactivateVcComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE CallMgrVcContext
)
{
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmDeactivateVcComplete: Enter"));
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmDeactivateVcComplete: Exit"));
}
NDIS_STATUS
CmRequest(
IN NDIS_HANDLE ProtocolAfContext,
IN NDIS_HANDLE ProtocolVcContext OPTIONAL,
IN NDIS_HANDLE ProtocolPartyContext OPTIONAL,
IN OUT PNDIS_REQUEST NdisRequest
)
{
NDIS_STATUS Status;
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmRequest: Enter"));
Status =
NdisWanCoOidProc((PMINIPORTCB)ProtocolAfContext,
(PCM_VCCB)ProtocolVcContext,
NdisRequest);
NdisWanDbgOut(DBG_TRACE, DBG_CM, ("CmRequest: Exit Status: 0x%x", Status));
return(Status);
}