an 的实际数据包有效NET_BUFFER
负载是整个 MDL 链的有效负载的子集。数据包可能不会在 MDL 链的开头开始,并且数据包可能不会在 MDL 链的末尾结束。
因此,在最一般的情况下,您实际上需要NET_BUFFER
在添加新的 MDL 之前从 . 让我举一个具体的例子:
NET_BUFFER
* DataOffset=300 bytes
* DataLength=200 bytes
* MdlChain=[200 bytes]->[200 bytes]->[300 bytes]->[200 bytes]
所以在这个例子中,NET_BUFFER
指向一个包含 4 个 MDL 的 MDL 链。让我们看看 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
如希望的图所示,实际的数据包有效负载仅分布在第二个和第三个 MDL 中。第一个和第四个 MDL 都被完全忽略。因此,如果要将数据附加到数据包中,则需要:
- 从 MDL 链的末尾删除所有 MDL,其中 MDL 缓冲区的最后一个字节不是逻辑数据包缓冲区的一部分。(在上面的示例中,删除第三个和第四个 MDL)。
- 分配一个足够大的新缓冲区来保存您的数据,以及您从上面的第 1 步中删除的任何实际数据包有效负载。(在示例中,您必须分配额外的 100 个字节来保存第三个 MDL 的前 100 个字节。)
- 将您的新 MDL 链接到链的末尾。
- 增量
NET_BUFFER::DataLength
。
- 将数据包交给 NDIS。
这是完成步骤 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
然后在第 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
当数据包完成返回驱动程序后,您需要撤消之前所做的修改:
- 减量
DataLength
。
- 删除您添加的 MDL。
- 释放您添加的 MDL。
- 恢复您删除的原始 MDL。