576 lines
16 KiB
C
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 */
|