Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

464 lines
13 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. ntos\tdi\isn\fwd\packets.h
  5. Abstract:
  6. IPX Forwarder Driver packet allocator
  7. Author:
  8. Vadim Eydelman
  9. Revision History:
  10. --*/
  11. #ifndef _IPXFWD_PACKETS_
  12. #define _IPXFWD_PACKETS_
  13. // Forward structure prototypes
  14. struct _SEGMENT_LIST;
  15. typedef struct _SEGMENT_LIST SEGMENT_LIST, *PSEGMENT_LIST;
  16. struct _PACKET_SEGMENT;
  17. typedef struct _PACKET_SEGMENT PACKET_SEGMENT, *PPACKET_SEGMENT;
  18. struct _PACKET_TAG;
  19. typedef struct _PACKET_TAG PACKET_TAG, *PPACKET_TAG;
  20. // Forwarder data associated with each packet it allocates
  21. struct _PACKET_TAG {
  22. union {
  23. UCHAR PT_Identifier; // this should be IDENTIFIER_RIP
  24. PPACKET_TAG PT_Next; // link in packet segment
  25. };
  26. union {
  27. PVOID SEND_RESERVED[SEND_RESERVED_COMMON_SIZE]; // needed by ipx
  28. // for padding on ethernet
  29. PINTERFACE_CB PT_SourceIf; // Source interface reference needed
  30. // for spoofing keep-alives and
  31. // queuing connection requests
  32. };
  33. PPACKET_SEGMENT PT_Segment; // segment where it belongs
  34. LONGLONG PT_PerfCounter;
  35. ULONG PT_Flags;
  36. #define PT_NB_DESTROY 0x1 // NB packet to be not requeued
  37. #define PT_SOURCE_IF 0x2 // Spoofing packet with src if reference
  38. PUCHAR PT_Data; // Data buffer
  39. PNDIS_BUFFER PT_MacHdrBufDscr; // buffer descriptor for
  40. // mac header buffer required
  41. // by IPX
  42. PINTERFACE_CB PT_InterfaceReference; // points to the interface CB where
  43. // it is queued
  44. LIST_ENTRY PT_QueueLink; // links this packet in send queue
  45. IPX_LOCAL_TARGET PT_Target; // destination target for ipx
  46. // stack
  47. UCHAR PT_MacHeader[1];// Mac header buffer reserved for IPX
  48. };
  49. // Segment of preallocated packets complete with buffers
  50. struct _PACKET_SEGMENT {
  51. LIST_ENTRY PS_Link; // Link in segment list
  52. PSEGMENT_LIST PS_SegmentList; // Segment list we belong to
  53. PPACKET_TAG PS_FreeHead; // List of free packets in
  54. // this segment
  55. ULONG PS_BusyCount; // Count of packets allocated
  56. // from this segment
  57. NDIS_HANDLE PS_PacketPool; // Pool of NDIS packet
  58. // descriptors used by the
  59. // packets in this segment
  60. NDIS_HANDLE PS_BufferPool; // Pool of NDIS buffer
  61. // descriptors used by the
  62. // packets in this segment
  63. LONGLONG PS_FreeStamp; // Time when last packet was freed
  64. union {
  65. UCHAR PS_Buffers[1]; // Memory used by buffers
  66. LONGLONG PS_BuffersAlign;
  67. };
  68. };
  69. // List of segment with preallocated packets
  70. struct _SEGMENT_LIST {
  71. const ULONG SL_BlockSize; // Size of packet's buffer
  72. LIST_ENTRY SL_Head; // Head of the segment list
  73. ULONG SL_FreeCount; // Total number of free packets
  74. // in all segment in the list
  75. ULONG SL_BlockCount; // Number of packets per segment
  76. ULONG SL_LowCount; // Free count at which we
  77. // will preallocate new segment
  78. LONG SL_RefCount; // Number of consumers that are
  79. // using packets in this list
  80. BOOLEAN SL_TimerDpcPending;
  81. BOOLEAN SL_AllocatorPending;
  82. WORK_QUEUE_ITEM SL_Allocator; // Allocation work item
  83. KTIMER SL_Timer; // Timer to free unused segments
  84. KDPC SL_TimerDpc; // DPC of the timer of unused segments
  85. KSPIN_LOCK SL_Lock; // Access control
  86. };
  87. // The number of rcv packets per segment (config parameter)
  88. #define MIN_RCV_PKTS_PER_SEGMENT 8
  89. #define DEF_RCV_PKTS_PER_SEGMENT 64
  90. #define MAX_RCV_PKTS_PER_SEGMENT 256
  91. extern ULONG RcvPktsPerSegment;
  92. // Maximum size of memory that can be used to allocate packets (config
  93. // param). 0 means no limit
  94. extern ULONG MaxRcvPktsPoolSize;
  95. // There are currently three known frame sizes: ethernet-1500,
  96. // token ring 4k - 4500, token ring 16k - 17986
  97. #define FRAME_SIZE_VARIATIONS 3
  98. // List of packet segments for Ethernet packets
  99. extern SEGMENT_LIST ListEther;
  100. // List of packet segments for Token Ring 4K packets
  101. extern SEGMENT_LIST ListTR4;
  102. // List of packet segments for Token Ring 16K packets
  103. extern SEGMENT_LIST ListTR16;
  104. // Mapping from src and destination packet size requirments
  105. // to the appropriate segment list
  106. extern PSEGMENT_LIST SegmentMap[FRAME_SIZE_VARIATIONS][FRAME_SIZE_VARIATIONS];
  107. // Timeout for unused segment
  108. extern const LONGLONG SegmentTimeout;
  109. extern KSPIN_LOCK AllocatorLock;
  110. /*++
  111. *******************************************************************
  112. 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
  113. Routine Description:
  114. Initializes packet allocator
  115. Arguments:
  116. None
  117. Return Value:
  118. None
  119. *******************************************************************
  120. --*/
  121. // VOID
  122. // InitializePacketAllocator (
  123. // void
  124. // );
  125. #define InitializePacketAllocator() { \
  126. KeInitializeSpinLock(&AllocatorLock); \
  127. InitializeSegmentList(&ListEther); \
  128. InitializeSegmentList(&ListTR4); \
  129. InitializeSegmentList(&ListTR16); \
  130. }
  131. /*++
  132. *******************************************************************
  133. D e l e t e P a c k e t A l l o c a t o r
  134. Routine Description:
  135. Disposes of all resources in packet allocator
  136. Arguments:
  137. None
  138. Return Value:
  139. None
  140. *******************************************************************
  141. --*/
  142. // VOID
  143. // DeletePacketAllocator (
  144. // void
  145. // );
  146. #define DeletePacketAllocator() { \
  147. DeleteSegmentList(&ListEther); \
  148. DeleteSegmentList(&ListTR4); \
  149. DeleteSegmentList(&ListTR16); \
  150. }
  151. /*++
  152. *******************************************************************
  153. A l l o c a t e P a c k e t
  154. Routine Description:
  155. Allocate packet for source - destination combination
  156. Arguments:
  157. srcListId - identifies max frame size for source interface
  158. dstListId - identifies max frame size for destination
  159. packet - receives pointer to allocated packet or NULL if allocation
  160. fails
  161. Return Value:
  162. None
  163. *******************************************************************
  164. --*/
  165. // VOID
  166. // AllocatePacket (
  167. // IN INT srcListId,
  168. // IN INT dstListId,
  169. // OUT PPACKET_TAG packet
  170. // );
  171. #define AllocatePacket(srcListId,dstListId,packet) { \
  172. PSEGMENT_LIST list; \
  173. ASSERT ((srcListId>=0) && (srcListId<FRAME_SIZE_VARIATIONS)); \
  174. ASSERT ((dstListId>=0) && (dstListId<FRAME_SIZE_VARIATIONS)); \
  175. list = SegmentMap[srcListId][dstListId]; \
  176. AllocatePacketFromList(list,packet); \
  177. }
  178. /*++
  179. *******************************************************************
  180. D u p l i c a t e P a c k e t
  181. Routine Description:
  182. Duplicates packet
  183. Arguments:
  184. src - source packet
  185. dst - receives pointer to duplicated packet or NUUL if operation
  186. failed
  187. Return Value:
  188. None
  189. *******************************************************************
  190. --*/
  191. // VOID
  192. // DuplicatePacket (
  193. // IN PPACKET_TAG src
  194. // OUT PPACKET_TAG dst
  195. // );
  196. #define DuplicatePacket(src,dst) { \
  197. PSEGMENT_LIST list; \
  198. list = src->PT_Segment->PS_SegmentList; \
  199. AllocatePacketFromList(list,dst); \
  200. }
  201. /*++
  202. *******************************************************************
  203. A l l o c a t e P a c k e t F r o m L i s t
  204. Routine Description:
  205. Allocate packet from specified packet segment list
  206. Arguments:
  207. list - list from which to allocate
  208. packet - receives pointer to allocated packet or NULL if allocation
  209. fails
  210. Return Value:
  211. None
  212. *******************************************************************
  213. --*/
  214. // VOID
  215. // AllocatePacketFromList (
  216. // IN PSEGMENT_LIST list
  217. // OUT PPACKET_TAG packet
  218. // );
  219. #define AllocatePacketFromList(list,packet) { \
  220. PPACKET_SEGMENT segment; \
  221. KIRQL oldIRQL; \
  222. KeAcquireSpinLock (&list->SL_Lock, &oldIRQL); \
  223. do { \
  224. if (list->SL_FreeCount>0) { \
  225. segment = CONTAINING_RECORD (list->SL_Head.Flink, \
  226. PACKET_SEGMENT, PS_Link); \
  227. while (segment->PS_FreeHead==NULL) { \
  228. segment = CONTAINING_RECORD (segment->PS_Link.Flink, \
  229. PACKET_SEGMENT, PS_Link); \
  230. ASSERT (&segment->PS_Link!=&list->SL_Head); \
  231. } \
  232. list->SL_FreeCount -= 1; \
  233. if ((list->SL_FreeCount<list->SL_LowCount) \
  234. && !list->SL_AllocatorPending \
  235. && EnterForwarder ()) { \
  236. list->SL_AllocatorPending = TRUE; \
  237. ExQueueWorkItem (&list->SL_Allocator, DelayedWorkQueue);\
  238. } \
  239. } \
  240. else { \
  241. segment = CreateSegment (list); \
  242. if (segment!=NULL) { \
  243. InsertTailList (&list->SL_Head, &segment->PS_Link); \
  244. segment->PS_SegmentList = list; \
  245. list->SL_FreeCount = list->SL_BlockCount-1; \
  246. } \
  247. else { \
  248. packet = NULL; \
  249. break; \
  250. } \
  251. } \
  252. packet = segment->PS_FreeHead; \
  253. segment->PS_FreeHead = packet->PT_Next; \
  254. segment->PS_BusyCount += 1; \
  255. packet->PT_Identifier = IDENTIFIER_RIP; \
  256. packet->PT_Flags = 0; \
  257. } \
  258. while (FALSE); \
  259. KeReleaseSpinLock (&list->SL_Lock, oldIRQL); \
  260. }
  261. /*++
  262. *******************************************************************
  263. F r e e P a c k e t
  264. Routine Description:
  265. Free allocated packet
  266. Arguments:
  267. packet - packet to free
  268. Return Value:
  269. None
  270. *******************************************************************
  271. --*/
  272. // VOID
  273. // FreePacket (
  274. // IN PPACKET_TAG packet
  275. // );
  276. #define FreePacket(packet) { \
  277. PPACKET_SEGMENT segment=packet->PT_Segment; \
  278. PSEGMENT_LIST list; \
  279. KIRQL oldIRQL; \
  280. list = segment->PS_SegmentList; \
  281. KeAcquireSpinLock (&list->SL_Lock, &oldIRQL); \
  282. packet->PT_Next = segment->PS_FreeHead; \
  283. segment->PS_FreeHead = packet; \
  284. list->SL_FreeCount += 1; \
  285. segment->PS_BusyCount -= 1; \
  286. if (segment->PS_BusyCount==0) { \
  287. if (list->SL_TimerDpcPending) { \
  288. KeQuerySystemTime ((PLARGE_INTEGER)&segment->PS_FreeStamp); \
  289. KeReleaseSpinLock (&list->SL_Lock, oldIRQL);\
  290. } \
  291. else if (EnterForwarder ()) { \
  292. list->SL_TimerDpcPending = TRUE; \
  293. KeReleaseSpinLock (&list->SL_Lock, oldIRQL);\
  294. KeSetTimer (&list->SL_Timer, \
  295. *((PLARGE_INTEGER)&SegmentTimeout), \
  296. &list->SL_TimerDpc); \
  297. } \
  298. else { \
  299. KeReleaseSpinLock (&list->SL_Lock, oldIRQL);\
  300. } \
  301. } \
  302. else { \
  303. KeReleaseSpinLock (&list->SL_Lock, oldIRQL); \
  304. } \
  305. }
  306. /*++
  307. *******************************************************************
  308. C r e a t e S e g m e n t
  309. Routine Description:
  310. Allocates and initializes packet segment
  311. Arguments:
  312. list - segment list to which new segment will be added
  313. Return Value:
  314. Pointer to allocated segment, NULL if fails
  315. *******************************************************************
  316. --*/
  317. PPACKET_SEGMENT
  318. CreateSegment (
  319. PSEGMENT_LIST list
  320. );
  321. /*++
  322. *******************************************************************
  323. D e l e t e S e g m e n t
  324. Routine Description:
  325. Frees packet segment
  326. Arguments:
  327. segment - segment to free
  328. Return Value:
  329. None
  330. *******************************************************************
  331. --*/
  332. VOID
  333. DeleteSegment (
  334. PPACKET_SEGMENT segment
  335. );
  336. /*++
  337. *******************************************************************
  338. R e g i s t e r P a c k e t C o n s u m e r
  339. Routine Description:
  340. Registers a consumer (bound interface) of packets of the
  341. given size
  342. Arguments:
  343. pktsize - maximum size of packets needed
  344. listId - buffer to return packet list id where packets
  345. of required size are located
  346. Return Value:
  347. STATUS_SUCCESS - registration succeded
  348. STATUS_INSUFFICIENT_RESOURCES - not enogh resources to register
  349. *******************************************************************
  350. --*/
  351. NTSTATUS
  352. RegisterPacketConsumer (
  353. IN ULONG pktsize,
  354. OUT INT *listID
  355. );
  356. /*++
  357. *******************************************************************
  358. D e r e g i s t e r P a c k e t C o n s u m e r
  359. Routine Description:
  360. Deregisters a consumer (bound interface) of packets of the
  361. given size
  362. Arguments:
  363. listId - packet list id used by the consumer
  364. Return Value:
  365. None
  366. *******************************************************************
  367. --*/
  368. VOID
  369. DeregisterPacketConsumer (
  370. IN INT listID
  371. );
  372. /*++
  373. *******************************************************************
  374. I n i t i a l i z e S e g m e n t L i s t
  375. Routine Description:
  376. Initializes list of packet segments
  377. Arguments:
  378. list - list to initalize
  379. Return Value:
  380. None
  381. *******************************************************************
  382. --*/
  383. VOID
  384. InitializeSegmentList(
  385. PSEGMENT_LIST list
  386. );
  387. /*++
  388. *******************************************************************
  389. D e l e t e S e g m e n t L i s t
  390. Routine Description:
  391. Deletes list of packet segments
  392. Arguments:
  393. list - list to delete
  394. Return Value:
  395. None
  396. *******************************************************************
  397. --*/
  398. VOID
  399. DeleteSegmentList (
  400. PSEGMENT_LIST list
  401. );
  402. #endif
  403.