第二部分:NetAdapterCx 接收端缩放(RSS)------ 功能设置与回调实现
四、设置 RSS 功能
若要在 NetAdapterCx 中开始使用 RSS,客户端驱动程序需要在启动网络适配器时执行以下步骤:
-
使用 NET_ADAPTER_RECEIVE_SCALING_CAPABILITIES 结构告知系统硬件的 RSS 功能和约束。
-
通过调用 NET_ADAPTER_RECEIVE_SCALING_CAPABILITIES_INIT 初始化功能结构。
-
在初始化 RSS 功能结构时,设置结构的 RSS 回调成员,以注册四个回调函数的实现:
-
EvtNetAdapterReceiveScalingEnable:启用 RSS
-
EvtNetAdapterReceiveScalingDisable:禁用 RSS
-
EvtNetAdapterReceiveScalingSetHashSecretKey:设置哈希密钥
-
EvtNetAdapterReceiveScalingSetIndirectionEntries:移动间接表条目
-
根据需要设置 RSS 功能结构的 SynchronizeSetIndirectionEntries 成员。
-
将初始化的 RSS 功能结构传递给 NetAdapterSetReceiveScalingCapabilities 方法。
注意:NetAdapterSetReceiveScalingCapabilities 必须在调用 NetAdapterStart 之前调用。
五、启用和禁用 RSS
设置 RSS 功能后,系统将继续执行驱动程序的通电顺序。完成创建数据路径队列的最后一步后,NetAdapterCx 开始调用驱动程序的 RSS 回调。此时,系统可根据需要启用和禁用 RSS。
重要提示:启用或禁用 RSS 时,驱动程序不应清除或重置间接表。框架将设置初始间接表状态。
5.1 启用 RSS
NetAdapterCx 通过调用驱动程序的 EvtNetAdapterReceiveScalingEnable 回调来启用 RSS。
该回调函数的原型如下:
NTSTATUS EvtNetAdapterReceiveScalingEnable(
NETADAPTER Adapter,
NET_ADAPTER_RECEIVE_SCALING_HASH_TYPE HashType,
NET_ADAPTER_RECEIVE_SCALING_PROTOCOL_TYPE ProtocolType
);
参数说明:
-
Adapter:NETADAPTER 对象,由客户端驱动程序在之前调用 NetAdapterCreate 时获得。
-
HashType:指定 NIC 用于计算入站数据包哈希值的 RSS 哈希函数类型。
-
ProtocolType:指定支持 RSS 的 NIC 在计算 RSS 哈希值时必须使用的接收网络数据部分。
在此回调的上下文中,客户端驱动程序通常通过设置硬件中的相应控制位来启用 RSS。
代码示例(来自官方文档):
NTSTATUS MyEvtNetAdapterReceiveScalingEnable(
_In_ NETADAPTER Adapter,
_In_ NET_ADAPTER_RECEIVE_SCALING_HASH_TYPE HashType,
_In_ NET_ADAPTER_RECEIVE_SCALING_PROTOCOL_TYPE ProtocolType
)
{
NTSTATUS status = STATUS_SUCCESS;
UNREFERENCED_PARAMETER(HashType);
UINT32 controlBitsEnable = MY_RSS_MULTI_CPU_ENABLE | MY_RSS_HASH_BITS_ENABLE;
// 如果协议类型包含 IPv4,设置相应的控制位
if (ProtocolType & NET_ADAPTER_RECEIVE_SCALING_PROTOCOL_TYPE_IPV4) {
// 设置 IPv4 相关的 RSS 控制位
}
// 将控制位写入硬件寄存器
// ...
return status;
}
重要提示:客户端驱动程序不应在其 EvtNetAdapterReceiveScalingEnable 回调中清除或重置间接表。
5.2 禁用 RSS
NetAdapterCx 通过调用驱动程序的 EvtNetAdapterReceiveScalingDisable 回调来禁用 RSS。
在此回调中,客户端驱动程序通常需要禁用之前在 EvtNetAdapterReceiveScalingEnable 中设置的硬件控制位。
重要提示:与启用回调类似,客户端驱动程序不应从其 EvtNetAdapterReceiveScalingDisable 回调中清除或重置间接表。
六、设置哈希密钥
启用 RSS 后,NetAdapterCx 调用 EvtNetAdapterReceiveScalingSetHashSecretKey 回调,为驱动程序提供 NIC 在验证哈希计算时应使用的哈希密钥。
RSS 运行时,如果哈希密钥发生更改,可以随时调用此回调函数。
NET_ADAPTER_RECEIVE_SCALING_HASH_SECRET_KEY 结构包含用于验证 RSS 哈希计算的密钥数据。
在此回调中,NIC 客户端驱动程序将提供的哈希密钥编程到硬件中,以供 RSS 哈希计算使用。
七、移动间接表条目
当 RSS 在系统上运行时,上层协议驱动程序会监视处理器工作负荷,并维护一个将接收队列映射到处理器的间接表。当协议驱动程序需要在 RSS 中重新平衡处理器工作负荷时,它会首先计算每个间接表条目到新处理器的新映射。
然后,协议驱动程序将此信息传递给 NetAdapterCx,NetAdapterCx 在内部将处理器编号映射到 NIC 接收队列 ID。
NetAdapterCx 将新的重定向表存储在 NET_ADAPTER_RECEIVE_SCALING_INDIRECTION_ENTRIES 结构中,其中的条目与接收队列 ID 相关联,并在调用 EvtNetAdapterReceiveScalingSetIndirectionEntries 回调函数时将该结构传递给驱动程序。
NET_ADAPTER_RECEIVE_SCALING_INDIRECTION_ENTRIES 是一个由 NET_ADAPTER_RECEIVE_SCALING_INDIRECTION_ENTRY 结构构成的数组,每个结构表示间接表中一个条目的移动。
每个 NET_ADAPTER_RECEIVE_SCALING_INDIRECTION_ENTRY 结构包含:
-
该条目在间接表中的哈希索引
-
要将条目分配到的新的接收队列
-
一个状态字段,指示该单个移动是否成功
在此回调中,驱动程序需要将 NIC 间接寻址表中的每个条目移动到指定的接收队列。将索引条目分配给硬件接收队列的方法取决于 NIC 的设计及其包含的接收队列数。