windows网络适配器驱动开发-网环元素管理

📅 2026/7/12 19:48:09 👁️ 阅读次数 📝 编程学习
windows网络适配器驱动开发-网环元素管理

网环元素管理

按照本主题中的指南在网络数据传输期间管理NET_RING结构及其元素。本主题中的规则描述了在不同的数据路径方案下,客户端驱动程序可以修改哪些 net ring 元素的成员以及何时可以修改,并提供了客户端驱动程序在使用这些结构时应牢记的一般信息。

重要

客户端驱动程序应在开发的所有阶段遵循这些方向。如果在使用驱动程序验证程序进行测试时客户端驱动程序不遵循这些指示,驱动程序验证程序会报告冲突,并在测试的设备上触发 bug 检查。


NET_RING

启动NET_RING的父数据包队列时,环中的所有索引将初始化为 0。

下表描述了客户端驱动程序可以修改的 net ring 成员:

字段允许修改客户端驱动程序
OSReserved1
ElementStride
NumberOfElements
ElementIndexMask
EndIndex
OSReserved0
OSReserved2
BeginIndex是(必需)
NextIndex是(可选)> 注意:框架永远不会读取NextIndex
Scratch是(可选)> 注意:框架永远不会读取Scratch
Buffer

客户端驱动程序不得修改此结构中的任何只读成员,在调用EvtPacketQueueAdvance时,也绝不应将BeginIndex增加到超过EndIndex

有关 net 环中的索引所有权的详细信息,请参阅net 环简介


NET_PACKET

NET_PACKET中的字段对数据路径运行的不同上下文敏感。是否设置数据包的Ignore字段以及驱动程序是在接收(Rx)还是传输(Tx)数据包,会影响应用于该数据包的规则集。

下表为每种场景中的驱动程序提供指引:

Rx 或 TxIgnore字段被设置由…注释
Rx客户端驱动程序在 Rx 期间,客户端驱动程序会根据需要设置Ignore,框架会读取它。客户端驱动程序无需在 Rx 期间随时读取Ignore

如果客户端驱动程序在 Rx 期间设置Ignore字段,则:
• 取消未成功编程到硬件的任何数据包的 Rx 操作时,客户端驱动程序必须写入Ignore字段。有关更多信息,请参阅使用网环取消网络数据
• 客户端驱动程序不得将资源与数据包相关联,因为它们不会被释放。

如果客户端驱动程序在 Rx 期间未设置Ignore字段,则:
• 客户端驱动程序必须填充FragmentIndexFragmentCountLayout中的所有字段。
FragmentIndex必须介于片段环中的BeginIndex(包含)和EndIndex(不包含)之间。
FragmentCount不能超过片段环中BeginIndex(包含)和EndIndex(不包含)之间的片段数量。

如果客户端驱动程序移动相应的片段环BeginIndex
• 客户端驱动程序必须移动数据包环BeginIndex
• 调用EvtPacketQueueAdvance后,如果客户端驱动程序递增数据包环BeginIndex,则驱动程序还必须将片段环BeginIndex递增,以越过该数据包的片段。换句话说,片段环BeginIndex应移动到上一数据包片段的EndIndex
TxNetAdapterCx在 Tx 期间
• 客户端驱动程序不得修改除Scratch以外的任何数据包中的任何字段。
• 客户端驱动程序可以读取Ignore的值,但绝不能写入它
• 如果忽略 Tx 数据包,驱动程序不得读取任何字段,除非有必要读取Scratch

关于Ignore字段的简要回顾

在 NetAdapterCx 数据路径中,Ignore字段用于标记应被跳过的数据包:

  • Tx(传输)场景Ignore由 NetAdapterCx 框架设置,用于指示驱动程序应跳过该数据包的传输(例如,数据包已被上层取消)。驱动程序仅可读取此字段。

  • Rx(接收)场景Ignore由客户端驱动程序在取消操作期间设置,用于指示框架应忽略该数据包(例如,该数据包从未真正被硬件填充)。驱动程序负责写入此字段,框架负责读取并执行相应操作。


NET_PACKET 布局(Layout)字段

在 Rx 操作期间,NET_PACKETLayout字段受以下规则的约束:

规则编号约束条件
1Reserved0之外的所有字段都必须由客户端驱动程序初始化。
2如果Layer2Type设置为NetPacketLayer2TypeEthernet,则Layer2HeaderLength必须为14 或更高
3如果Layer2Type设置为NetPacketLayer2TypeNull,则必须将Layer2HeaderLength设置为0
4如果Layer3Type是 IPv4 类型,则Layer3HeaderLength必须为20 或更高
5如果Layer3Type是 IPv6 类型,则Layer3HeaderLength必须为40 或更高
6如果Layer4Type设置为Tcp,则Layer4HeaderLength必须为40 或更高
7如果Layer4Type设置为Udp,则Layer4HeaderLength必须为8 或更高
8层类型字段必须位于适当的枚举范围内。

注意:Tx 期间不使用Layout字段。


NET_FRAGMENT

NET_FRAGMENT字段规则取决于驱动程序是接收还是传输,以及片段缓冲区是由驱动程序还是框架附加到数据包:

Rx 或 Tx注释
Rx• 客户端驱动程序无法写入OsReserved_Bounced字段。
如果驱动程序未附加缓冲区Capacity不得修改,而ValidLengthOffset必须修改。
如果驱动程序正在附加缓冲区CapacityValidLengthOffset都必须修改。
Offset + ValidLength必须小于Capacity
Tx• 客户端驱动程序不能修改Scratch以外的任何字段。

关键规则速查表

操作场景BeginIndexNextIndexScratchIgnore(读)Ignore(写)Layout 字段片段字段
Tx - 正常只读可写可写可读❌ 禁止不使用只读(除 Scratch)
Tx - 取消可写可写可写可读❌ 禁止不使用只读(除 Scratch)
Rx - 正常可写只读可写不读取不写入必须初始化可写(见上表)
Rx - 取消可写只读可写不读取必须写入无需初始化可写