|
|
/*++
Copyright (c) 1999, Microsoft Corporation
Module Name:
qosminfo.c
Abstract:
The file contains global and interface config functions for QOS Mgr protocol.
Revision History:
--*/
#include "pchqosm.h"
#pragma hdrstop
DWORD WINAPI QosmGetGlobalInfo ( IN PVOID GlobalInfo, IN OUT PULONG BufferSize, OUT PULONG InfoSize )
/*++
Routine Description:
Returns the global config info for this protocol.
Arguments:
See corr header file.
Return Value: Status of the operation --*/
{ PIPQOS_GLOBAL_CONFIG GlobalConfig; DWORD Status;
//
// Validate all input params before reading the global info
//
if (BufferSize == NULL) { return ERROR_INVALID_PARAMETER; }
ACQUIRE_GLOBALS_READ_LOCK();
do { *InfoSize = Globals.ConfigSize;
if ((*BufferSize < *InfoSize) || (GlobalInfo == NULL)) { //
// Either the size was too small or there was no storage
//
Trace1(CONFIG, "GetGlobalInfo: Buffer size too small: %u", *BufferSize);
*BufferSize = *InfoSize;
Status = ERROR_INSUFFICIENT_BUFFER;
break; }
*BufferSize = *InfoSize;
GlobalConfig = (PIPQOS_GLOBAL_CONFIG) GlobalInfo;
CopyMemory(GlobalConfig, Globals.GlobalConfig, *InfoSize);
Status = NO_ERROR; } while (FALSE);
RELEASE_GLOBALS_READ_LOCK();
return Status; }
DWORD WINAPI QosmSetGlobalInfo ( IN PVOID GlobalInfo, IN ULONG InfoSize )
/*++
Routine Description:
Sets the global config info for this protocol.
Arguments:
See corr header file.
Return Value: Status of the operation --*/
{ PIPQOS_GLOBAL_CONFIG GlobalConfig; DWORD Status;
//
// Update the global config information.
//
ACQUIRE_GLOBALS_WRITE_LOCK();
do { GlobalConfig = AllocMemory(InfoSize);
if (GlobalConfig == NULL) { Status = ERROR_NOT_ENOUGH_MEMORY; break; }
//
// Copy the new config information
//
CopyMemory(GlobalConfig, GlobalInfo, InfoSize);
Globals.ConfigSize = InfoSize;
//
// Set up rest of the global state
//
if (GlobalConfig->LoggingLevel <= IPQOS_LOGGING_INFO) { Globals.LoggingLevel = GlobalConfig->LoggingLevel; }
//
// Cleanup old global information
//
if (Globals.GlobalConfig) { FreeMemory(Globals.GlobalConfig); }
Globals.GlobalConfig = GlobalConfig;
Status = NO_ERROR; } while (FALSE);
RELEASE_GLOBALS_WRITE_LOCK();
return Status; }
DWORD WINAPI QosmGetInterfaceInfo ( IN QOSMGR_INTERFACE_ENTRY *Interface, IN PVOID InterfaceInfo, IN OUT PULONG BufferSize, OUT PULONG InfoSize )
/*++
Routine Description:
Gets the inteface config info for this protocol for this interface.
Arguments:
See corr header file.
Return Value: Status of the operation
--*/
{ PIPQOS_IF_CONFIG InterfaceConfig; DWORD Status;
//
// Validate all input params before reading interface info
//
if (BufferSize == NULL) { return ERROR_INVALID_PARAMETER; }
ACQUIRE_INTERFACE_READ_LOCK(Interface);
do { *InfoSize = Interface->ConfigSize;
if ((*BufferSize < *InfoSize) || (InterfaceInfo == NULL)) { //
// Either the size was too small or there was no storage
//
Trace1(CONFIG, "GetInterfaceInfo: Buffer size too small: %u", *BufferSize);
*BufferSize = *InfoSize;
Status = ERROR_INSUFFICIENT_BUFFER;
break; }
*BufferSize = *InfoSize;
InterfaceConfig = (PIPQOS_IF_CONFIG) InterfaceInfo;
CopyMemory(InterfaceConfig, Interface->InterfaceConfig, *InfoSize);
Status = NO_ERROR; } while (FALSE);
RELEASE_INTERFACE_READ_LOCK(Interface);
return Status; }
DWORD WINAPI QosmSetInterfaceInfo ( IN QOSMGR_INTERFACE_ENTRY *Interface, IN PVOID InterfaceInfo, IN ULONG InfoSize )
/*++
Routine Description:
Sets the interface config info for this protocol on this interface.
Arguments:
See corr header file.
Return Value: Status of the operation --*/
{ PIPQOS_IF_CONFIG InterfaceConfig; PIPQOS_IF_FLOW FlowConfig; PQOSMGR_FLOW_ENTRY Flow; UINT i; PLIST_ENTRY p, q; PTC_GEN_FLOW FlowInfo; ULONG FlowSize; HANDLE FlowHandle; DWORD Status;
//
// Update the interface config information.
//
ACQUIRE_INTERFACE_WRITE_LOCK(Interface);
do { //
// Allocate memory to store new config
//
InterfaceConfig = AllocMemory(InfoSize);
if (InterfaceConfig == NULL) { Status = ERROR_NOT_ENOUGH_MEMORY; break; }
//
// Copy the new config information
//
CopyMemory(InterfaceConfig, InterfaceInfo, InfoSize);
Interface->ConfigSize = InfoSize;
//
// Set up rest of interface state
//
if (Interface->State != InterfaceConfig->QosState) { if (InterfaceConfig->QosState == IPQOS_STATE_DISABLED) { //
// Disable all flows on this interface
//
; } else { //
// Renable all flows on this interface
//
; }
Interface->State = InterfaceConfig->QosState; }
//
// Update the flow information on if
//
//
// First mark all flows as needing refresh
//
for (p = Interface->FlowList.Flink; p != &Interface->FlowList; p = p->Flink) { Flow = CONTAINING_RECORD(p, QOSMGR_FLOW_ENTRY, OnInterfaceLE);
ASSERT(!(Flow->Flags & FLOW_FLAG_DELETE));
Flow->Flags |= FLOW_FLAG_DELETE; }
//
// If we do not have an TC interface handle,
// we delete all flows as they are obsolete
//
if (Interface->TciIfHandle) { //
// Set each flow if it has changed from before
//
FlowConfig = IPQOS_GET_FIRST_FLOW_ON_IF(InterfaceConfig);
for (i = 0; i < InterfaceConfig->NumFlows; i++) { //
// Search for a flow with the same name
//
for (p = Interface->FlowList.Flink; p != &Interface->FlowList; p = p->Flink) { Flow = CONTAINING_RECORD(p, QOSMGR_FLOW_ENTRY, OnInterfaceLE);
if (!_wcsicmp(Flow->FlowName, FlowConfig->FlowName)) { break; } }
if (p == &Interface->FlowList) { //
// No flow by this name - add new one
//
Flow = NULL; }
//
// Get a flow info from description
//
Status = GetFlowFromDescription(&FlowConfig->FlowDesc, &FlowInfo, &FlowSize);
if (Status == NO_ERROR) { do { if ((Flow) && (FlowSize == Flow->FlowSize) && (EqualMemory(FlowInfo, Flow->FlowInfo, FlowSize))) { //
// No change in the flow info yet,
// this flow still remains valid
//
Flow->Flags &= ~FLOW_FLAG_DELETE;
Status = ERROR_ALREADY_EXISTS;
break; }
if (Flow) { //
// Flow info changed - modify flow
//
Status = TcModifyFlow(Flow->TciFlowHandle, FlowInfo);
if (Status != NO_ERROR) { break; }
Flow->Flags &= ~FLOW_FLAG_DELETE;
//
// Update cached flow info
//
FreeMemory(Flow->FlowInfo); Flow->FlowInfo = FlowInfo; Flow->FlowSize = FlowSize; } else { //
// Add the new flow using the TC API
//
Status = TcAddFlow(Interface->TciIfHandle, NULL, 0, FlowInfo, &FlowHandle);
if (Status != NO_ERROR) { break; }
//
// Addition of a new flow in TC
//
Flow = AllocMemory(sizeof(QOSMGR_FLOW_ENTRY));
if (Flow == NULL) { Status = TcDeleteFlow(FlowHandle);
ASSERT(Status);
Status = ERROR_NOT_ENOUGH_MEMORY;
break; }
//
// Initialize flow and insert in list
//
Flow->TciFlowHandle = FlowHandle;
Flow->Flags = 0;
Flow->FlowInfo = FlowInfo; Flow->FlowSize = FlowSize;
wcscpy(Flow->FlowName, FlowConfig->FlowName);
InsertTailList(p, &Flow->OnInterfaceLE); } } while (FALSE); if (Status != NO_ERROR) { FreeMemory(FlowInfo); } }
//
// Move to the next flow in config
//
FlowConfig = IPQOS_GET_NEXT_FLOW_ON_IF(FlowConfig); } }
//
// Cleanup all flows that are obsolete
//
for (p = Interface->FlowList.Flink; p != &Interface->FlowList; p = q) { Flow = CONTAINING_RECORD(p, QOSMGR_FLOW_ENTRY, OnInterfaceLE);
q = p->Flink;
if (Flow->Flags & FLOW_FLAG_DELETE) { //
// Delete the flow from the TC API
//
Status = TcDeleteFlow(Flow->TciFlowHandle);
if (Status != NO_ERROR) { Flow->Flags &= ~FLOW_FLAG_DELETE;
continue; }
//
// Remove flow from this flow list
//
RemoveEntryList(p);
//
// Free the flow and its resources
//
if (Flow->FlowInfo) { FreeMemory(Flow->FlowInfo); }
FreeMemory(Flow); } }
//
// Cleanup old interface information
//
if (Interface->InterfaceConfig) { FreeMemory(Interface->InterfaceConfig); }
Interface->InterfaceConfig = InterfaceConfig;
Status = NO_ERROR; } while (FALSE);
RELEASE_INTERFACE_WRITE_LOCK(Interface);
return Status; }
DWORD GetFlowFromDescription( IN PIPQOS_NAMED_FLOW FlowDesc, OUT PTC_GEN_FLOW *FlowInfo, OUT ULONG *FlowSize ) { FLOWSPEC *CurrFlowspec; FLOWSPEC SendFlowspec; FLOWSPEC RecvFlowspec; FLOWSPEC *Flowspec; PTC_GEN_FLOW Flow; QOS_OBJECT_HDR *QosObject; PWCHAR FlowspecName; PWCHAR QosObjectName; PUCHAR CopyAtPtr; ULONG ObjectsLength; ULONG i;
#if 1
//
// Check for the existence of sending flowspec
//
if (FlowDesc->SendingFlowspecName[0] == L'\0') { return ERROR_INVALID_DATA; } #endif
//
// Get the sending and receiving flowspecs
//
for (i = 0; i < 2; i++) { if (i) { FlowspecName = FlowDesc->RecvingFlowspecName; CurrFlowspec = &RecvFlowspec; } else { FlowspecName = FlowDesc->SendingFlowspecName; CurrFlowspec = &SendFlowspec; }
FillMemory(CurrFlowspec, sizeof(FLOWSPEC), QOS_NOT_SPECIFIED);
if (FlowspecName[0] != L'\0') { Flowspec = GetFlowspecFromGlobalConfig(FlowspecName);
if (Flowspec == NULL) { return ERROR_INVALID_DATA; }
*CurrFlowspec = *Flowspec; } }
//
// Calculate the size of the TC_GEN_FLOW block
//
QosObjectName = IPQOS_GET_FIRST_OBJECT_NAME_ON_NAMED_FLOW(FlowDesc);
ObjectsLength = 0;
for (i = 0; i < FlowDesc->NumTcObjects; i++) { //
// Get object's description in global info
//
QosObject = GetQosObjectFromGlobalConfig(QosObjectName);
if (QosObject == NULL) { //
// Incomplete description
//
return ERROR_INVALID_DATA; }
ObjectsLength += QosObject->ObjectLength;
QosObjectName= IPQOS_GET_NEXT_OBJECT_NAME_ON_NAMED_FLOW(QosObjectName); }
*FlowSize = FIELD_OFFSET(TC_GEN_FLOW, TcObjects) + ObjectsLength;
*FlowInfo = Flow = AllocMemory(*FlowSize);
if (Flow == NULL) { return ERROR_NOT_ENOUGH_MEMORY; }
//
// Fill in the flow information now
//
Flow->ReceivingFlowspec = RecvFlowspec;
Flow->SendingFlowspec = SendFlowspec;
Flow->TcObjectsLength = ObjectsLength;
//
// Repeat the loop above filling info
//
QosObjectName = IPQOS_GET_FIRST_OBJECT_NAME_ON_NAMED_FLOW(FlowDesc);
CopyAtPtr = (PUCHAR) &Flow->TcObjects[0];
for (i = 0; i < FlowDesc->NumTcObjects; i++) { //
// Get object's description in global info
//
QosObject = GetQosObjectFromGlobalConfig(QosObjectName);
// We just checked above for its existence
ASSERT(QosObject != NULL);
CopyMemory(CopyAtPtr, QosObject, QosObject->ObjectLength);
CopyAtPtr += QosObject->ObjectLength;
QosObjectName= IPQOS_GET_NEXT_OBJECT_NAME_ON_NAMED_FLOW(QosObjectName); }
return NO_ERROR; }
FLOWSPEC * GetFlowspecFromGlobalConfig( IN PWCHAR FlowspecName ) { IPQOS_NAMED_FLOWSPEC *Flowspec; UINT i;
Flowspec = IPQOS_GET_FIRST_FLOWSPEC_IN_CONFIG(Globals.GlobalConfig);
for (i = 0; i < Globals.GlobalConfig->NumFlowspecs; i++) { if (!_wcsicmp(Flowspec->FlowspecName, FlowspecName)) { break; }
Flowspec = IPQOS_GET_NEXT_FLOWSPEC_IN_CONFIG(Flowspec); }
if (i < Globals.GlobalConfig->NumFlowspecs) { return &Flowspec->FlowspecDesc; }
return NULL; }
QOS_OBJECT_HDR * GetQosObjectFromGlobalConfig( IN PWCHAR QosObjectName ) { IPQOS_NAMED_QOSOBJECT *QosObject; UINT i;
QosObject = IPQOS_GET_FIRST_QOSOBJECT_IN_CONFIG(Globals.GlobalConfig);
for (i = 0; i < Globals.GlobalConfig->NumQosObjects; i++) { if (!_wcsicmp(QosObject->QosObjectName, QosObjectName)) { break; }
QosObject = IPQOS_GET_NEXT_QOSOBJECT_IN_CONFIG(QosObject); }
if (i < Globals.GlobalConfig->NumFlowspecs) { return &QosObject->QosObjectHdr; }
return NULL; }
|