|
|
Using Custom Queues forNET_BUFFER_LIST Management
IntroductionOften the task to be performed in a NDIS 6 FilterSendNetBufferLists callback involves sorting the singly-linked list of NBLs based on packet inspection. One issue in performing this task is how to keep track of the NBLs as you sort them in an efficient and simple way. This topic expands on some structures and MACROs that are included in some of the Microsoft WDK NDIS 6 samples that may be helpful in managing NBLs as you sort them. The originals are found in the WDK "filter" and "e100bex" samples (now deprecated), with some "glorification" added by PCAUSA. NBL_QUEUE_HEADER StructureA simple header structure is used for custom queuing of NBLs:
In reality this is just the head of a singly-linked list with an auxiliary field that tracks the NBL at the tail of the list.
Macros for NBL_QUEUE ManagementA few MACROs are provided to simplify the queuing process. They include:
There are a few others. These MACROs are defined on the
NBL_QUEUE page.
Example of NBL_QUEUE UseIn a simple case there may be two operations to be performed:
In this case simply define two queues in your FilterSendNetBufferLists callback: // NBLs to passthrough to lower-level miniport NDF_NBL_QUEUE_HEADER NblDropQueue; // NBLs to return to higher-level protocol by send completionAnd initialize them before using them:
Early in the do{} loop when processing individual NBLs you need to fetch the next NBL (because you'll be yanking it out of the original list) and also zap the NBL next field (so queuing this one won't drag along those chained behind it...). Something like this:
pNextNetBufferList = NET_BUFFER_LIST_NEXT_NBL (pCurrentNetBufferList); // Unlink NBLs Following The Original NBL NET_BUFFER_LIST_NEXT_NBL(pCurrentNetBufferList) = NULL; Now as you examine the current NBL (that's out of scope of this document...) you would decide somewhere whether to pass or block the packet:
if( BlockNbl ) { // Block This NetBufferList NDF_INSERT_TAIL_NBL_QUEUE( &NblDropQueue, pCurrentNetBufferList ); goto MoveToNextNbl; } else { // Passthrough Send This NetBufferList NDF_INSERT_TAIL_NBL_QUEUE( &NblSendQueue, pCurrentNetBufferList ); goto MoveToNextNbl; } Where MoveToNextNbl is a label at the tail of your per-NBL do{} loop: // Move to the Next NetBufferList pCurrentNetBufferList = pNextNetBufferList; } After you exit your per-NBL do{} loop you would process the two queues: // Send Passthrough NetBufferLists if( NDF_GET_NBL_QUEUE_HEAD( &NblSendQueue ) ) Some PCAUSA drivers have many more queues. For example, an impairment generator might have: // NBLs to passthrough to lower-level miniport NDF_NBL_QUEUE_HEADER NblDropQueue; // NBLs to return to higher-level protocol by send completionNDF_NBL_QUEUE_HEADER NblDelayQueue; // NBLs to delay before sending to lower-level miniport NDF_NBL_QUEUE_HEADER NblMangleQueue; // NBLs to mangle before sending to lower-level miniportI hope that this is helpful to some of you.
| ||||||||||||||
|
PCAUSA Home
· Privacy Statement ·
Products · Ordering · Support ·
Utilities ·
Resources
|