windows-nt/Source/XPSP1/NT/net/qos/inc/pktsched.h
2020-09-26 16:20:57 +08:00

576 lines
16 KiB
C

/*++
Copyright (c) 1996-1999 Microsoft Corporation
Module Name:
pktsched.h
Abstract:
defines for packet scheduler component interface
Author:
Revision History:
--*/
#ifndef _PKTSCHED_H_
#define _PKTSCHED_H_
//
// forwards
//
/*
typedef struct _PSI_INFO;
typedef struct _PS_PROFILE;
typedef struct _PS_PIPE_CONTEXT;
typedef struct _PS_FLOW_CONTEXT;
typedef struct _PS_DEBUG_INFO;
*/
//
// Component registration function exported by PSched
//
//
// Context info passed to each component during pipe initialization. The PS
// allocates one PS_PIPE_CONTEXT struct for each component. The size of an
// individual component's struct is indicated by the component during registration,
// and must be at least as large as sizeof(PS_PIPE_CONTEXT).
// Each component's context area begins with the struct defined below, and the
// component-specific data follows.
//
// Note : This structure has to be word aligned.
//
typedef struct _PS_PIPE_CONTEXT {
// NextComponentContext - Pointer to next component's pipe-specific data
// PrevComponentContext - Pointer to previous component's pipe-specific data
// NextComponent - Function info about next component in pipeline
// PacketReservedOffset - Offset to packet reserved bytes for this component
struct _PS_PIPE_CONTEXT *NextComponentContext;
struct _PS_PIPE_CONTEXT *PrevComponentContext;
struct _PSI_INFO *NextComponent;
ULONG PacketReservedOffset;
} PS_PIPE_CONTEXT, *PPS_PIPE_CONTEXT;
//
// Context info passed to each component during flow initialization. The PS
// allocates one PS_FLOW_CONTEXT struct for each component. The size of an
// individual component's struct is indicated by the component during registration,
// and must be at least as large as sizeof(PS_FLOW_CONTEXT).
// Each component's context area begins with the struct defined below, and the
// component-specific data follows.
//
typedef struct _PS_FLOW_CONTEXT {
// NextComponentContext - Pointer to next component's flow-specific data
// PrevComponentContext - Pointer to previous component's flow-specific data
struct _PS_FLOW_CONTEXT *NextComponentContext;
struct _PS_FLOW_CONTEXT *PrevComponentContext;
} PS_FLOW_CONTEXT, *PPS_FLOW_CONTEXT, PS_CLASS_MAP_CONTEXT, *PPS_CLASS_MAP_CONTEXT;
//
// Packet Information Block. This structure can be found
// at offset zero from the packet's ProtocolReserved area.
//
typedef struct _PACKET_INFO_BLOCK {
// SchedulerLinks - Linkage in scheduling component list
// PacketLength - Length of packet, non including MAC header
// ConformanceTime - Token Bucket Conformance Time
// DelayTime - Time at which packet is eligible for sending
// FlowContext - Flow context area for the convenience of the scheduling
// components. May be used by the scheduling component
// while the packet is being processed by that component.
// ClassMapContext - Class Map context area for convenience of scheduling
// components. May be used by the scheduling component
// when the packet is being processed by that component.
// IpHdr - points to the IP transport header. This is used by the
// sequencer to stamp the IP packet with the non conforming
// TOS byte. We store a pointer here because we have already
// done the dirty work of getting to the buffer in MpSend.
// This will be 0 for non IP packets, in which case the
// sequencer need not do anything.
// IPPrecedenceByteNonConforming - The TOS setting for non conforming packets.
// UserPriorityNonConforming - 802.1p setting for non conforming packets.
LIST_ENTRY SchedulerLinks;
ULONG PacketLength;
LARGE_INTEGER ConformanceTime;
LARGE_INTEGER DelayTime;
HANDLE FlowContext;
HANDLE ClassMapContext;
ULONG IPHeaderOffset;
IPHeader *IPHdr;
PNDIS_PACKET NdisPacket;
UCHAR TOSNonConforming;
UCHAR UserPriorityNonConforming;
} PACKET_INFO_BLOCK, *PPACKET_INFO_BLOCK;
//
// Prototypes for PS routines made available to scheduling components.
//
typedef VOID
(*PS_DROP_PACKET)(
IN HANDLE PsPipeContext,
IN HANDLE PsFlowContext,
IN PNDIS_PACKET Packet,
IN NDIS_STATUS Status
);
typedef HANDLE
(*PS_NDIS_PIPE_HANDLE)(
IN HANDLE PsPipeContext
);
typedef HANDLE
(*PS_NDIS_FLOW_HANDLE)(
IN HANDLE PsFlowContext
);
typedef VOID
(*PS_GET_TIMER_INFO)(
OUT PULONG TimerResolution // Timer resolution in system time units
);
typedef struct _PS_PROCS {
PS_DROP_PACKET DropPacket;
PS_NDIS_PIPE_HANDLE NdisPipeHandle;
PS_GET_TIMER_INFO GetTimerInfo;
} PS_PROCS, *PPS_PROCS;
//
// Upcall information passed to next component
//
typedef VOID
(*PSU_SEND_COMPLETE)(
IN PPS_PIPE_CONTEXT PipeContext,
IN PNDIS_PACKET Packet
);
typedef struct _PS_UPCALLS {
PSU_SEND_COMPLETE SendComplete;
PPS_PIPE_CONTEXT PipeContext;
} PS_UPCALLS, *PPS_UPCALLS;
//
// Pipe parameters
//
typedef struct _PS_PIPE_PARAMETERS {
// Bandwidth - In bytes/sec
// MTUSize - Maximum frame size
// HeaderSize - Number of bytes in header
// Flags - See below
// MaxOutstandingSends - Maximum sends that can be pending concurrently
// SDModeControlledLoad - Default handling of non-conforming controlled load traffic
// SDModeGuaranteed - Default handling of non-conforming guaranteed service traffic
// SDModeNetworkControl - Default handling of non-conforming NetworkControl service traffic
// SDModeQualitative - Default handling of non-conforming Qualitative service traffic
// RegistryPath - Pointer to the registry path of that interface. Can be used to read reg params.
ULONG Bandwidth;
ULONG MTUSize;
ULONG HeaderSize;
ULONG Flags;
ULONG MaxOutstandingSends;
ULONG SDModeControlledLoad;
ULONG SDModeGuaranteed;
ULONG SDModeNetworkControl;
ULONG SDModeQualitative;
PNDIS_STRING RegistryPath;
// Need this to let the scheduling components to know what kind of medium it is //
NDIS_MEDIUM MediaType; // Wan Or anything else
} PS_PIPE_PARAMETERS, *PPS_PIPE_PARAMETERS;
// Pipe flags
#define PS_DISABLE_DRR 2
#define PS_INTERMEDIATE_SYS 4
//
// function typedefs for the scheduler entry points
//
typedef NDIS_STATUS
(*PS_INITIALIZE_PIPE)(
IN HANDLE PsPipeContext,
IN PPS_PIPE_PARAMETERS PipeParameters,
IN PPS_PIPE_CONTEXT ComponentPipeContext,
IN PPS_PROCS PsProcs,
IN PPS_UPCALLS Upcalls
);
typedef NDIS_STATUS
(*PS_MODIFY_PIPE)(
IN PPS_PIPE_CONTEXT PipeContext,
IN PPS_PIPE_PARAMETERS PipeParameters
);
typedef VOID
(*PS_DELETE_PIPE)(
IN PPS_PIPE_CONTEXT PipeContext
);
typedef NDIS_STATUS
(*PS_CREATE_FLOW)(
IN PPS_PIPE_CONTEXT PipeContext,
IN HANDLE PsFlowContext,
IN PCO_CALL_PARAMETERS CallParameters,
IN PPS_FLOW_CONTEXT ComponentFlowContext
);
typedef NDIS_STATUS
(*PS_MODIFY_FLOW)(
IN PPS_PIPE_CONTEXT PipeContext,
IN PPS_FLOW_CONTEXT FlowContext,
IN PCO_CALL_PARAMETERS CallParameters
);
typedef VOID
(*PS_DELETE_FLOW)(
IN PPS_PIPE_CONTEXT PipeContext,
IN PPS_FLOW_CONTEXT FlowContext
);
typedef VOID
(*PS_EMPTY_FLOW)(
IN PPS_PIPE_CONTEXT PipeContext,
IN PPS_FLOW_CONTEXT FlowContext
);
typedef BOOLEAN
(*PS_SUBMIT_PACKET)(
IN PPS_PIPE_CONTEXT PipeContext,
IN PPS_FLOW_CONTEXT FlowContext,
IN PPS_CLASS_MAP_CONTEXT ClassMapContext,
IN PPACKET_INFO_BLOCK PktInfo);
typedef BOOLEAN
(*PS_RECEIVE_PACKET)(
IN PPS_PIPE_CONTEXT PipeContext,
IN PPS_FLOW_CONTEXT FlowContext,
IN PPS_CLASS_MAP_CONTEXT ClassMapContext,
IN PNDIS_PACKET Packet,
IN NDIS_MEDIUM Medium
);
typedef BOOLEAN
(*PS_RECEIVE_INDICATION)(
IN PPS_PIPE_CONTEXT PipeContext,
IN PPS_FLOW_CONTEXT FlowContext,
IN PPS_CLASS_MAP_CONTEXT ClassMapContext,
IN PVOID HeaderBuffer,
IN UINT HeaderBufferSize,
IN PVOID LookAheadBuffer,
IN UINT LookAheadBufferSize,
IN UINT PacketSize,
IN UINT TransportHeaderOffset
);
typedef VOID
(*PS_SET_INFORMATION) (
IN PPS_PIPE_CONTEXT PipeContext,
IN PPS_FLOW_CONTEXT FlowContext,
IN NDIS_OID Oid,
IN ULONG BufferSize,
IN PVOID Buffer
);
typedef VOID
(*PS_QUERY_INFORMATION) (
IN PPS_PIPE_CONTEXT PipeContext,
IN PPS_FLOW_CONTEXT FlowContext,
IN NDIS_OID Oid,
IN ULONG BufferSize,
IN PVOID Buffer,
IN OUT PULONG BytesWritten,
IN OUT PULONG BytesNeeded,
IN OUT PNDIS_STATUS Status);
typedef NDIS_STATUS
(*PS_CREATE_CLASS_MAP) (
IN PPS_PIPE_CONTEXT PipeContext,
IN HANDLE PsClassMapContext,
IN PTC_CLASS_MAP_FLOW ClassMap,
IN PPS_CLASS_MAP_CONTEXT ComponentClassMapContext
);
typedef NDIS_STATUS
(*PS_DELETE_CLASS_MAP) (
IN PPS_PIPE_CONTEXT PipeContext,
IN PPS_CLASS_MAP_CONTEXT
);
/* End Prototypes */
//
// Scheduling component registration structure.
//
#define PS_COMPONENT_CURRENT_VERSION 1
typedef struct _PSI_INFO {
LIST_ENTRY Links;
BOOLEAN Registered;
BOOLEAN AddIn;
USHORT Version;
NDIS_STRING ComponentName;
ULONG PacketReservedLength;
ULONG PipeContextLength;
ULONG FlowContextLength;
ULONG ClassMapContextLength;
ULONG SupportedOidsLength;
NDIS_OID *SupportedOidList;
ULONG SupportedGuidsLength;
NDIS_GUID *SupportedGuidList;
PS_INITIALIZE_PIPE InitializePipe;
PS_MODIFY_PIPE ModifyPipe;
PS_DELETE_PIPE DeletePipe;
PS_CREATE_FLOW CreateFlow;
PS_MODIFY_FLOW ModifyFlow;
PS_DELETE_FLOW DeleteFlow;
PS_EMPTY_FLOW EmptyFlow;
PS_SUBMIT_PACKET SubmitPacket;
PS_RECEIVE_PACKET ReceivePacket;
PS_RECEIVE_INDICATION ReceiveIndication;
PS_SET_INFORMATION SetInformation;
PS_QUERY_INFORMATION QueryInformation;
PS_CREATE_CLASS_MAP CreateClassMap;
PS_DELETE_CLASS_MAP DeleteClassMap;
} PSI_INFO, *PPSI_INFO;
//
// Profile registration structure
//
#define MAX_COMPONENT_PER_PROFILE 10
typedef struct _PS_PROFILE {
LIST_ENTRY Links;
USHORT UnregisteredAddInCnt;
NDIS_STRING ProfileName;
UINT ComponentCnt;
// Allocate an extra slot for the StubComponent
PPSI_INFO ComponentList[MAX_COMPONENT_PER_PROFILE + 1];
} PS_PROFILE, *PPS_PROFILE;
//
// Debugging support for add-in components
//
typedef VOID
(*PS_GET_CURRENT_TIME) (PLARGE_INTEGER SysTime);
typedef VOID
(*PS_LOGSTRING_PROC) (
IN char *format,
...
);
typedef VOID
(*PS_LOGSCHED_PROC) (
IN ULONG SchedulerComponent,
IN ULONG Action,
IN PVOID VC,
IN PNDIS_PACKET Packet,
IN ULONG PacketLength,
IN ULONG Priority,
IN LONGLONG ArrivalTime,
IN LONGLONG ConformanceTime,
IN ULONG PacketsInComponent,
IN ULONG BytesInComponent
);
typedef VOID
(*PS_LOGREC_PROC) (
IN ULONG ComponentId,
IN PVOID RecordData,
IN ULONG RecordLength
);
typedef ULONG
(*PS_GETID_PROC) (
VOID);
typedef struct _PS_DEBUG_INFO {
PULONG DebugLevel;
PULONG DebugMask;
PULONG LogTraceLevel;
PULONG LogTraceMask;
ULONG LogId;
PS_GET_CURRENT_TIME GetCurrentTime;
PS_LOGSTRING_PROC LogString;
PS_LOGSCHED_PROC LogSched;
PS_LOGREC_PROC LogRec;
} PS_DEBUG_INFO, *PPS_DEBUG_INFO;
NDIS_STATUS RegisterPsComponent( PPSI_INFO PsiComponentInfo, ULONG Size ,
PPS_DEBUG_INFO Dbg);
//
// VOID
// InsertEntryList(
// PLIST_ENTRY Entry,
// PLIST_ENTRY EntryToInsert
// );
//
// insert EntryToInsert just after Entry
//
#define InsertEntryList( Entry, EntryToInsert ) { \
(EntryToInsert)->Flink = (Entry)->Flink; \
(Entry)->Flink = (EntryToInsert); \
(EntryToInsert)->Blink = (EntryToInsert)->Flink->Blink; \
(EntryToInsert)->Flink->Blink = (EntryToInsert); \
}
#define ARP_802_ADDR_LENGTH 6 // Length of an 802 address.
#define ARP_ETYPE_IP 0x800
typedef struct _ETH_HEADER {
UCHAR DestAddr[ARP_802_ADDR_LENGTH];
UCHAR SrcAddr[ARP_802_ADDR_LENGTH];
USHORT Type;
} ETH_HEADER, *PETH_HEADER;
_inline
IPHeader *
GetIpHeader(ULONG TransportHeaderOffset, PNDIS_PACKET pNdisPacket)
{
PVOID pAddr;
PNDIS_BUFFER pNdisBuf1, pNdisBuf2;
UINT Len;
pNdisBuf1 = pNdisPacket->Private.Head;
NdisQueryBuffer(pNdisBuf1, &pAddr, &Len);
while(Len <= TransportHeaderOffset) {
//
// Transport header is not in this buffer,
// try the next buffer
//
TransportHeaderOffset -= Len;
NdisGetNextBuffer(pNdisBuf1, &pNdisBuf2);
ASSERT(pNdisBuf2);
NdisQueryBuffer(pNdisBuf2, &pAddr, &Len);
pNdisBuf1 = pNdisBuf2;
}
return (IPHeader *)(((PUCHAR)pAddr) + TransportHeaderOffset);
}
//
// Set TOS byte and recalculate checksum
// Use incremental checksum update
// RFCs 1071, 1141, 1624
//
//
// RFC : 1624
// HC' = ~(~HC + ~m + m');
// HC - old checksum, m - old value, m' - new value
//
#define SET_TOS_XSUM(Packet, pIpHdr, tos) { \
PNDIS_PACKET_EXTENSION _PktExt; \
NDIS_TCP_IP_CHECKSUM_PACKET_INFO _ChkPI; \
_PktExt = NDIS_PACKET_EXTENSION_FROM_PACKET((Packet)); \
_ChkPI.Value = PtrToUlong(_PktExt->NdisPacketInfo[TcpIpChecksumPacketInfo]); \
if(_ChkPI.Transmit.NdisPacketIpChecksum) { \
(pIpHdr)->iph_tos = ((pIpHdr)->iph_tos & PS_IP_DS_CODEPOINT_MASK) | (tos); \
} \
else { \
USHORT _old, _new; \
ULONG _sum; \
_old = *(USHORT *)(pIpHdr); \
(pIpHdr)->iph_tos = ((pIpHdr)->iph_tos & PS_IP_DS_CODEPOINT_MASK) | (tos); \
_new = *(USHORT *)(pIpHdr); \
_sum = ((~(pIpHdr)->iph_xsum) & 0xffff) + ((~_old) & 0xffff) + _new; \
_sum = (_sum & 0xffff) + (_sum >> 16); \
_sum += (_sum >> 16); \
(pIpHdr)->iph_xsum = (ushort) ((~_sum) & 0xffff); \
} \
}
//
// Number of OS time units per second
//
#define OS_TIME_SCALE 10000000
//
// convert from OS's 100 ns to millisecs
//
#define OS_TIME_TO_MILLISECS(_time) ((_time)/10000)
_inline VOID
PsGetCurrentTime(
PLARGE_INTEGER SysTime
)
/*++
Routine Description:
Get the current system time
Arguments:
Comments:
1. We need something that always increases - Hence we cannot use NdisGetCurrentSystemTime or
KeQueryCurrentSystem time. Those APIs can return decreasing times (daylight savings, date/time, etc).
Return Value:
System time (in base OS time units)
--*/
{
#if defined(PERF_COUNTER)
LARGE_INTEGER Now;
LARGE_INTEGER Frequency;
Now = KeQueryPerformanceCounter(&Frequency);
SysTime->QuadPart = (Now.QuadPart * OS_TIME_SCALE) / Frequency.QuadPart;
#else
//
// We used to use KeQueryTickCount() with KeQueryTimeIncrement(). But, if we are driving the clock at a lower
// resolution, then we cannot use KeQueryTickCount, because this will always return the time based on the
// maximum resolution. Therefore, we use KeQueryInterruptTime().
//
SysTime->QuadPart = KeQueryInterruptTime();
#endif
}
#endif /* _PKTSCHED_H_ */
/* end pktsched.h */