接收段合并 (RSC) 卸载

接收数据时,TCP/IP 堆栈中的大多数层必须单独查看每个段的标头信息。 当在接收大量数据时,这将产生大量的开销。

接收段合并 (RSC) 可合并一系列接收段并指示 TCP/IP 堆栈将它们合并成一个合并段,从而减少此开销。 TCP/IP 堆栈中的上层只需要查看整个序列的一个标头。

在硬件中支持 RSC 的网络接口卡 (NIC) 可以大幅提高接收路径性能。 它还可以减少主机 CPU 利用率,因为它使得协议层无需在软件中执行 RSC。

有关 RSC 的更多详细信息,请参阅接收段合并概述

从版本 2.5 开始,NetAdapterCX 还支持 UDP RSC (URO)。 有关更多详细信息,请参阅 UDP RSC 卸载 (URO)

用于控制 RSC 卸载的 INF 关键字

NetAdapterCx 会检查注册表关键字,并在启用活动卸载功能时遵循这些关键字。 驱动程序无需执行任何其他操作。

RSC 的标准化 INF 关键字中指定的 RSC 关键字可用于通过注册表项设置启用/禁用 RSC 卸载。

关键字值必须属于类型 REG_SZ

配置 RSC 卸载

客户端驱动程序首先在网络适配器初始化期间播发其硬件的 RSC 功能。 在启动网络适配器之前,可能会在其 EvtDevicePrepareHardware 回调中发生这种情况。

若要配置 RSC 功能,客户端驱动程序:

  1. 分配 NET_ADAPTER_OFFLOAD_RSC_CAPABILITIES 结构。

  2. 调用 NET_ADAPTER_OFFLOAD_RSC_CAPABILITIES_INIT 来初始化结构。

  3. 调用 NetAdapterOffloadSetRscCapabilities 来向 NetAdapterCx 注册结构。

在调用 NET_ADAPTER_OFFLOAD_RSC_CAPABILITIES_INIT 期间,客户端驱动程序提供指向 EVT_NET_ADAPTER_OFFLOAD_SET_RSC 回调的指针。 如果活动卸载功能发生变化,系统稍后将调用此回调。

用于指示硬件 RSC 功能的规则

  1. 对于 NIC 中没有硬件支持的任何类型的流量,客户端驱动程序不得执行软件 RSC。

以下规则适用于 NET_ADAPTER_OFFLOAD_RSC_CAPABILITIES 结构:

  1. NetAdapterOffloadLayer3FlagIPv4NoOptionsNetAdapterOffloadLayer3FlagIPv6NoExtensionsLayer3Flags 字段的唯一有效值。 这些标志分别表示 IPv4 和 IPv6 支持。

  2. NetAdapterOffloadLayer4FlagTcpNoOptionsNetAdapterOffloadLayer4FlagUdpLayer4Flags 字段的唯一有效值。 这些标志分别表示 TCP 和 UDP 支持。

  3. 如果设置了 NetAdapterOffloadLayer4FlagTcpNoOptions 标志,则必须设置第 3 层标志。

  4. TcpTimestampOption 字段为可选。 客户端驱动程序会在调用 NET_ADAPTER_OFFLOAD_RSC_CAPABILITIES_INIT 之后以及调用 NetAdapterOffloadSetRscCapabilities 之前设置此字段,以指示 NIC 是否支持 TCP 时间戳选项。

以下示例演示客户端驱动程序设置其 RSC 硬件卸载功能的可能方式。

VOID
MyAdapterSetRscOffloadCapabilities(
    NETADAPTER NetAdapter
)
{
    // Configure the hardware's RSC offload capabilities
    NET_ADAPTER_OFFLOAD_RSC_CAPABILITIES rscOffloadCapabilities;
    NET_ADAPTER_OFFLOAD_RSC_CAPABILITIES_INIT(
        &rscOffloadCapabilities,
        NetAdapterOffloadLayer3FlagIPv4NoOptions | NetAdapterOffloadLayer3FlagIPv6NoExtensions,
        NetAdapterOffloadLayer4FlagTcpNoOptions,
        MyEvtAdapterOffloadSetRsc);
    rscOffloadCapabilities.TcpTimestampOption = FALSE;

    // Set the current RSC offload capabilities and register the callback for future changes in active capabilities
    NetAdapterOffloadSetRscCapabilities(NetAdapter, &rscOffloadCapabilities);
}

更新 RSC 硬件卸载

如果 TCP/IP 堆栈或上层协议驱动程序请求更改网络适配器的活动 RSC 功能,NetAdapterCx 将调用在 NET_ADAPTER_OFFLOAD_RSC_CAPABILITIES 中注册的客户端驱动程序 EVT_NET_ADAPTER_OFFLOAD_SET_RSC 回调。 在此回调中,系统将在 NETOFFLOAD 对象中提供更新的功能,客户端驱动程序可以查询该对象以更新其卸载功能。

客户端驱动程序可以调用以下函数来确定已启的 RSC 卸载:

以下示例演示客户端驱动程序可如何更新其 RSC 卸载功能:

VOID
MyEvtAdapterOffloadSetRsc(
    NETADAPTER NetAdapter,
    NETOFFLOAD Offload
)
{
    PMY_NET_ADAPTER_CONTEXT adapterContext = NetvAdapterGetContext(NetAdapter);

    // Store the updated information in the context
    adapterContext->IsRscIPv4Enabled = NetOffloadIsTcpRscIPv4Enabled(Offload);
    adapterContext->IsRscIPv6Enabled = NetOffloadIsTcpRscIPv6Enabled(Offload);
    adapterContext->IsRscTcpTimestampOptionEnabled = NetOffloadIsRscTcpTimestampOptionEnabled(Offload);
}

UDP RSC Offload (URO)

URO 可用于合并接收 UDP 段。 NIC 可以将来自同一流且符合一组规则的 UDP 数据报组合到逻辑上连续的缓冲区中。 然后,这些组合数据报将作为单个大型数据包指示给 Windows 网络堆栈。 有关 URO 规则的信息,请参阅用于合并 UDP 数据包的规则

用于控制 URO 的 INF 关键字中指定的 URO 关键字可用于利用注册表项设置启用/禁用 URO。

NetAdapterCx 客户端驱动程序可以使用现有 RSC 结构和 RSC API for URO。 若要配置 URO,客户端驱动程序必须将 NET_ADAPTER_OFFLOAD_RSC_CAPABILITIES 结构中的 Layer4Flags 字段设置为 NetAdapterOffloadLayer4FlagUdp

URO 行为镜像 RSC,但有一个例外。 当 EVT_NET_ADAPTER_OFFLOAD_SET_RSC 回调禁用 URO 时,驱动程序必须指示现有合并段,并等至所有未完成的 URO 指示完成。 此方法可确保回调返回后没有 URO 指示处于活动状态。