windows-nt/Source/XPSP1/NT/net/nwlink/fwd/packets.h
2020-09-26 16:20:57 +08:00

465 lines
13 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
ntos\tdi\isn\fwd\packets.h
Abstract:
IPX Forwarder Driver packet allocator
Author:
Vadim Eydelman
Revision History:
--*/
#ifndef _IPXFWD_PACKETS_
#define _IPXFWD_PACKETS_
// Forward structure prototypes
struct _SEGMENT_LIST;
typedef struct _SEGMENT_LIST SEGMENT_LIST, *PSEGMENT_LIST;
struct _PACKET_SEGMENT;
typedef struct _PACKET_SEGMENT PACKET_SEGMENT, *PPACKET_SEGMENT;
struct _PACKET_TAG;
typedef struct _PACKET_TAG PACKET_TAG, *PPACKET_TAG;
// Forwarder data associated with each packet it allocates
struct _PACKET_TAG {
union {
UCHAR PT_Identifier; // this should be IDENTIFIER_RIP
PPACKET_TAG PT_Next; // link in packet segment
};
union {
PVOID SEND_RESERVED[SEND_RESERVED_COMMON_SIZE]; // needed by ipx
// for padding on ethernet
PINTERFACE_CB PT_SourceIf; // Source interface reference needed
// for spoofing keep-alives and
// queuing connection requests
};
PPACKET_SEGMENT PT_Segment; // segment where it belongs
LONGLONG PT_PerfCounter;
ULONG PT_Flags;
#define PT_NB_DESTROY 0x1 // NB packet to be not requeued
#define PT_SOURCE_IF 0x2 // Spoofing packet with src if reference
PUCHAR PT_Data; // Data buffer
PNDIS_BUFFER PT_MacHdrBufDscr; // buffer descriptor for
// mac header buffer required
// by IPX
PINTERFACE_CB PT_InterfaceReference; // points to the interface CB where
// it is queued
LIST_ENTRY PT_QueueLink; // links this packet in send queue
IPX_LOCAL_TARGET PT_Target; // destination target for ipx
// stack
UCHAR PT_MacHeader[1];// Mac header buffer reserved for IPX
};
// Segment of preallocated packets complete with buffers
struct _PACKET_SEGMENT {
LIST_ENTRY PS_Link; // Link in segment list
PSEGMENT_LIST PS_SegmentList; // Segment list we belong to
PPACKET_TAG PS_FreeHead; // List of free packets in
// this segment
ULONG PS_BusyCount; // Count of packets allocated
// from this segment
NDIS_HANDLE PS_PacketPool; // Pool of NDIS packet
// descriptors used by the
// packets in this segment
NDIS_HANDLE PS_BufferPool; // Pool of NDIS buffer
// descriptors used by the
// packets in this segment
LONGLONG PS_FreeStamp; // Time when last packet was freed
union {
UCHAR PS_Buffers[1]; // Memory used by buffers
LONGLONG PS_BuffersAlign;
};
};
// List of segment with preallocated packets
struct _SEGMENT_LIST {
const ULONG SL_BlockSize; // Size of packet's buffer
LIST_ENTRY SL_Head; // Head of the segment list
ULONG SL_FreeCount; // Total number of free packets
// in all segment in the list
ULONG SL_BlockCount; // Number of packets per segment
ULONG SL_LowCount; // Free count at which we
// will preallocate new segment
LONG SL_RefCount; // Number of consumers that are
// using packets in this list
BOOLEAN SL_TimerDpcPending;
BOOLEAN SL_AllocatorPending;
WORK_QUEUE_ITEM SL_Allocator; // Allocation work item
KTIMER SL_Timer; // Timer to free unused segments
KDPC SL_TimerDpc; // DPC of the timer of unused segments
KSPIN_LOCK SL_Lock; // Access control
};
// The number of rcv packets per segment (config parameter)
#define MIN_RCV_PKTS_PER_SEGMENT 8
#define DEF_RCV_PKTS_PER_SEGMENT 64
#define MAX_RCV_PKTS_PER_SEGMENT 256
extern ULONG RcvPktsPerSegment;
// Maximum size of memory that can be used to allocate packets (config
// param). 0 means no limit
extern ULONG MaxRcvPktsPoolSize;
// There are currently three known frame sizes: ethernet-1500,
// token ring 4k - 4500, token ring 16k - 17986
#define FRAME_SIZE_VARIATIONS 3
// List of packet segments for Ethernet packets
extern SEGMENT_LIST ListEther;
// List of packet segments for Token Ring 4K packets
extern SEGMENT_LIST ListTR4;
// List of packet segments for Token Ring 16K packets
extern SEGMENT_LIST ListTR16;
// Mapping from src and destination packet size requirments
// to the appropriate segment list
extern PSEGMENT_LIST SegmentMap[FRAME_SIZE_VARIATIONS][FRAME_SIZE_VARIATIONS];
// Timeout for unused segment
extern const LONGLONG SegmentTimeout;
extern KSPIN_LOCK AllocatorLock;
/*++
*******************************************************************
I n i t i a l i z e P a c k e t A l l o c a t o r
Routine Description:
Initializes packet allocator
Arguments:
None
Return Value:
None
*******************************************************************
--*/
// VOID
// InitializePacketAllocator (
// void
// );
#define InitializePacketAllocator() { \
KeInitializeSpinLock(&AllocatorLock); \
InitializeSegmentList(&ListEther); \
InitializeSegmentList(&ListTR4); \
InitializeSegmentList(&ListTR16); \
}
/*++
*******************************************************************
D e l e t e P a c k e t A l l o c a t o r
Routine Description:
Disposes of all resources in packet allocator
Arguments:
None
Return Value:
None
*******************************************************************
--*/
// VOID
// DeletePacketAllocator (
// void
// );
#define DeletePacketAllocator() { \
DeleteSegmentList(&ListEther); \
DeleteSegmentList(&ListTR4); \
DeleteSegmentList(&ListTR16); \
}
/*++
*******************************************************************
A l l o c a t e P a c k e t
Routine Description:
Allocate packet for source - destination combination
Arguments:
srcListId - identifies max frame size for source interface
dstListId - identifies max frame size for destination
packet - receives pointer to allocated packet or NULL if allocation
fails
Return Value:
None
*******************************************************************
--*/
// VOID
// AllocatePacket (
// IN INT srcListId,
// IN INT dstListId,
// OUT PPACKET_TAG packet
// );
#define AllocatePacket(srcListId,dstListId,packet) { \
PSEGMENT_LIST list; \
ASSERT ((srcListId>=0) && (srcListId<FRAME_SIZE_VARIATIONS)); \
ASSERT ((dstListId>=0) && (dstListId<FRAME_SIZE_VARIATIONS)); \
list = SegmentMap[srcListId][dstListId]; \
AllocatePacketFromList(list,packet); \
}
/*++
*******************************************************************
D u p l i c a t e P a c k e t
Routine Description:
Duplicates packet
Arguments:
src - source packet
dst - receives pointer to duplicated packet or NUUL if operation
failed
Return Value:
None
*******************************************************************
--*/
// VOID
// DuplicatePacket (
// IN PPACKET_TAG src
// OUT PPACKET_TAG dst
// );
#define DuplicatePacket(src,dst) { \
PSEGMENT_LIST list; \
list = src->PT_Segment->PS_SegmentList; \
AllocatePacketFromList(list,dst); \
}
/*++
*******************************************************************
A l l o c a t e P a c k e t F r o m L i s t
Routine Description:
Allocate packet from specified packet segment list
Arguments:
list - list from which to allocate
packet - receives pointer to allocated packet or NULL if allocation
fails
Return Value:
None
*******************************************************************
--*/
// VOID
// AllocatePacketFromList (
// IN PSEGMENT_LIST list
// OUT PPACKET_TAG packet
// );
#define AllocatePacketFromList(list,packet) { \
PPACKET_SEGMENT segment; \
KIRQL oldIRQL; \
KeAcquireSpinLock (&list->SL_Lock, &oldIRQL); \
do { \
if (list->SL_FreeCount>0) { \
segment = CONTAINING_RECORD (list->SL_Head.Flink, \
PACKET_SEGMENT, PS_Link); \
while (segment->PS_FreeHead==NULL) { \
segment = CONTAINING_RECORD (segment->PS_Link.Flink, \
PACKET_SEGMENT, PS_Link); \
ASSERT (&segment->PS_Link!=&list->SL_Head); \
} \
list->SL_FreeCount -= 1; \
if ((list->SL_FreeCount<list->SL_LowCount) \
&& !list->SL_AllocatorPending \
&& EnterForwarder ()) { \
list->SL_AllocatorPending = TRUE; \
ExQueueWorkItem (&list->SL_Allocator, DelayedWorkQueue);\
} \
} \
else { \
segment = CreateSegment (list); \
if (segment!=NULL) { \
InsertTailList (&list->SL_Head, &segment->PS_Link); \
segment->PS_SegmentList = list; \
list->SL_FreeCount = list->SL_BlockCount-1; \
} \
else { \
packet = NULL; \
break; \
} \
} \
packet = segment->PS_FreeHead; \
segment->PS_FreeHead = packet->PT_Next; \
segment->PS_BusyCount += 1; \
packet->PT_Identifier = IDENTIFIER_RIP; \
packet->PT_Flags = 0; \
} \
while (FALSE); \
KeReleaseSpinLock (&list->SL_Lock, oldIRQL); \
}
/*++
*******************************************************************
F r e e P a c k e t
Routine Description:
Free allocated packet
Arguments:
packet - packet to free
Return Value:
None
*******************************************************************
--*/
// VOID
// FreePacket (
// IN PPACKET_TAG packet
// );
#define FreePacket(packet) { \
PPACKET_SEGMENT segment=packet->PT_Segment; \
PSEGMENT_LIST list; \
KIRQL oldIRQL; \
list = segment->PS_SegmentList; \
KeAcquireSpinLock (&list->SL_Lock, &oldIRQL); \
packet->PT_Next = segment->PS_FreeHead; \
segment->PS_FreeHead = packet; \
list->SL_FreeCount += 1; \
segment->PS_BusyCount -= 1; \
if (segment->PS_BusyCount==0) { \
if (list->SL_TimerDpcPending) { \
KeQuerySystemTime ((PLARGE_INTEGER)&segment->PS_FreeStamp); \
KeReleaseSpinLock (&list->SL_Lock, oldIRQL);\
} \
else if (EnterForwarder ()) { \
list->SL_TimerDpcPending = TRUE; \
KeReleaseSpinLock (&list->SL_Lock, oldIRQL);\
KeSetTimer (&list->SL_Timer, \
*((PLARGE_INTEGER)&SegmentTimeout), \
&list->SL_TimerDpc); \
} \
else { \
KeReleaseSpinLock (&list->SL_Lock, oldIRQL);\
} \
} \
else { \
KeReleaseSpinLock (&list->SL_Lock, oldIRQL); \
} \
}
/*++
*******************************************************************
C r e a t e S e g m e n t
Routine Description:
Allocates and initializes packet segment
Arguments:
list - segment list to which new segment will be added
Return Value:
Pointer to allocated segment, NULL if fails
*******************************************************************
--*/
PPACKET_SEGMENT
CreateSegment (
PSEGMENT_LIST list
);
/*++
*******************************************************************
D e l e t e S e g m e n t
Routine Description:
Frees packet segment
Arguments:
segment - segment to free
Return Value:
None
*******************************************************************
--*/
VOID
DeleteSegment (
PPACKET_SEGMENT segment
);
/*++
*******************************************************************
R e g i s t e r P a c k e t C o n s u m e r
Routine Description:
Registers a consumer (bound interface) of packets of the
given size
Arguments:
pktsize - maximum size of packets needed
listId - buffer to return packet list id where packets
of required size are located
Return Value:
STATUS_SUCCESS - registration succeded
STATUS_INSUFFICIENT_RESOURCES - not enogh resources to register
*******************************************************************
--*/
NTSTATUS
RegisterPacketConsumer (
IN ULONG pktsize,
OUT INT *listID
);
/*++
*******************************************************************
D e r e g i s t e r P a c k e t C o n s u m e r
Routine Description:
Deregisters a consumer (bound interface) of packets of the
given size
Arguments:
listId - packet list id used by the consumer
Return Value:
None
*******************************************************************
--*/
VOID
DeregisterPacketConsumer (
IN INT listID
);
/*++
*******************************************************************
I n i t i a l i z e S e g m e n t L i s t
Routine Description:
Initializes list of packet segments
Arguments:
list - list to initalize
Return Value:
None
*******************************************************************
--*/
VOID
InitializeSegmentList(
PSEGMENT_LIST list
);
/*++
*******************************************************************
D e l e t e S e g m e n t L i s t
Routine Description:
Deletes list of packet segments
Arguments:
list - list to delete
Return Value:
None
*******************************************************************
--*/
VOID
DeleteSegmentList (
PSEGMENT_LIST list
);
#endif