- When your driver starts (DriverEntry), or when your filter attaches to a miniport (FilterAttach), allocate a NET_BUFFER_LIST (NBL) pool with
NdisAllocateNetBufferListPool
. For typical usage, you'll want to get one NET_BUFFER (NB) automatically with each NBL, so set fAllocateNetBuffer=TRUE
. If you want NDIS to allocate the data payload buffers for you, also give a non-zero DataSize. If you already have the packet payload in some other buffer, you can transmit faster by pointing the NB at the existing MDL, but this is also more complex to code up.
- To send a packet, allocate a new NBL from
NdisAllocateNetBufferAndNetBufferList
. Put your FilterModuleHandle into NBL->SourceHandle. Assign NB->DataLength and copy in the data. Call NdisFSendNetBufferLists on your new NBL. Do not touch the NBL until it's returned back to you.
- Eventually, NDIS will return the NBL back to you via
FilterSendNetBufferListsComplete
. Note that all NBLs come through there in one jumbled linked list -- both your own NBLs, as well as any NBLs you just passed through from above. So you have to slice the linked list based on NBL->SourceHandle: if the SourceHandle is yours, take the NBL out of the stream and free it via NdisFreeNetBufferList. Otherwise, if the NBL is not yours, continue propagating it along by calling NdisFSendNetBufferListsComplete.
- Do not allow FilterPause to complete until all the NBLs you originated have been returned to you. You can do this any way you want, but the usual approach is to add some refcounting to the send and sendcomplete paths. You are not required to worry about any NBLs that you didn't create.
When you're creating NBLs, you can use !ndiskd.nbl
to double-check your work. It can detect a variety of errors. There's a likely problem with the NBL if ndiskd reports any field in red text.