The actual packet payload of an NET_BUFFER
is a subset of the payload of the entire MDL chain. The packet might not start at the beginning of the MDL chain, and the packet might not end at the end of the MDL chain.
Therefore, in the most general case, you'll actually need to remove some MDLs from the end of the NET_BUFFER
, before you append your new MDL. Let me give a specific example:
NET_BUFFER
* DataOffset=300 bytes
* DataLength=200 bytes
* MdlChain=[200 bytes]->[200 bytes]->[300 bytes]->[200 bytes]
So in this example, the NET_BUFFER
points to an MDL chain with 4 MDLs in it. Let's look at the buffers in ASCII-art:
0 100 200 300 400 500 600 700 800 900
| | | | | | | | | |
[ First MDL ][ Second MDL ][ Third MDL ][ Fourth MDL ]
↑ ↑ [ Packet ] ↑
| | |
| | ↑ ↑ |
| | | | |
MdlChain | DataOffset DataLength End-of-MDL-chain
|
CurrentMdl
As hopefully the diagram illustrates, the actual packet payload is only spread across the second & third MDLs. Both the first & fourth MDLs are completely ignored. So if you want to append data to the packet, you need to:
- Remove all MDLs from the end of the MDL chain, where the last byte of the MDL's buffer isn't part of the logical packet buffer. (In the example above, remove both the third & fourth MDLs).
- Allocate a new buffer that's big enough to hold your data, plus any actual packet payload you deleted from step #1 above. (In the example, you'd have to allocate an extra 100 bytes, to hold the first 100 bytes from the third MDL.)
- Chain your new MDL to the end of the chain.
- Increment
NET_BUFFER::DataLength
.
- Give the packet to NDIS.
Here's a diagram of what the packet will look like after finishing step 3:
0 100 200 300 400 500 600 700 800 900
| | | | | | | | | |
[ First MDL ][ Second MDL ][ Your MDL ]
↑ ↑ [ Packet ] ↑
| | |
| | ↑ ↑ |
| | | | |
MdlChain | DataOffset DataLength |
| |
CurrentMdl End-of-MDL-chain
Then after step #4:
0 100 200 300 400 500 600 700 800 900
| | | | | | | | | |
[ First MDL ][ Second MDL ][ Your MDL ]
↑ ↑ [ Packet ]
| |
| | ↑ ↑
| | | |
MdlChain | DataOffset DataLength
| |
CurrentMdl End-of-MDL-chain
When the packet is completed back to your driver, you need to undo the modifications you made earlier:
- Decrement
DataLength
.
- Remove the MDL you added.
- Free the MDL you added.
- Restore the original MDLs you removed.