泛型分段卸载

通用分段卸载 (GSO) 共同表示 大型发送卸载 (LSO) UDP 发送卸载 (USO)

客户端驱动程序可以卸载大于网络媒体的最大传输单元 (MTU) 的 TCP/UDP 数据包分段。 驱动程序必须使用 GSO API 向 NetAdapterCx 指示此功能。

用于控制 GSO 的 INF 关键字

NetAdapterCx 检查注册表关键字,并在启用活动卸载功能时遵循它们。 驱动程序无需执行任何进一步操作。

使用注册表值启用和禁用任务卸载中指定的 LSO 关键字可用于使用注册表项设置启用/禁用 LSO 卸载。

UDP 分段卸载 (USO) 中指定的 USO 关键字可用于使用注册表项设置启用/禁用 USO 卸载。

关键字 (keyword) 值的类型必须为 REG_SZ

配置 GSO

客户端驱动程序在 Net 适配器初始化期间首先播发其硬件的 GSO 功能。 在启动 net 适配器之前,这可能在其 EvtDevicePrepareHardware 回调中发生。

若要配置 GSO,客户端驱动程序:

  1. 分配 NET_ADAPTER_OFFLOAD_GSO_CAPABILITIES 结构。

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

  3. 调用 NetAdapterOffloadSetGsoCapabilities 将结构注册到 NetAdapterCx。

在调用 NET_ADAPTER_OFFLOAD_GSO_CAPABILITIES_INIT 客户端驱动程序提供指向 EVT_NET_ADAPTER_OFFLOAD_SET_GSO 回调的指针。 如果活动卸载功能发生更改,系统稍后会调用此回调。

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

以下规则适用于 NET_ADAPTER_OFFLOAD_GSO_CAPABILITIES 结构:

  1. 驱动程序必须设置 Layer3FlagsLayer4Flags

  2. 如果 NIC 支持 LSO,驱动程序必须使用 TCP 标志填充 Layer4Flags 字段 NetAdapterOffloadLayer4FlagTcpWithoutOptions

  3. 如果 NIC 支持 USO,驱动程序必须使用 UDP 标志填充 Layer4Flags 字段 NetAdapterOffloadLayer4FlagUdp

  4. MaximumOffloadSizeMinimumSegmentCount 是必填字段。

  5. Layer4OffsetLimit 字段是可选的。 如果 OS 发送标头偏移量大于指定限制的数据包,则不会要求执行 GSO。

  6. 如果支持选项/扩展,则必须支持没有选项/扩展的 IP/TCP 数据包。

此示例演示客户端驱动程序如何设置其硬件卸载功能。

VOID
MyAdapterSetOffloadCapabilities(
    NETADAPTER NetAdapter
)
{
    // Configure the hardware's GSO offload capabilities
    NET_ADAPTER_OFFLOAD_GSO_CAPABILITIES gsoOffloadCapabilities;

    auto const layer3Flags = NetAdapterOffloadLayer3FlagIPv4NoOptions |
        NetAdapterOffloadLayer3FlagIPv4WithOptions |
        NetAdapterOffloadLayer3FlagIPv6NoExtensions |
        NetAdapterOffloadLayer3FlagIPv6WithExtensions;

    auto const layer4Flags = NetAdapterOffloadLayer4FlagTcpNoOptions |
        NetAdapterOffloadLayer4FlagTcpWithOptions;
        NetAdapterOffloadLayer4FlagUdp;

    NET_ADAPTER_OFFLOAD_GSO_CAPABILITIES_INIT(
        &gsoOffloadCapabilities,
        layer3Flags,
        layer4Flags,
        MY_GSO_OFFLOAD_MAX_SIZE,
        MY_GSO_OFFLOAD_MIN_SEGMENT_COUNT,
        EvtAdapterOffloadSetGso);

    gsoOffloadCapabilities.Layer4OffsetLimit = 127;

    // Set the current GSO offload capabilities and register the callback for future changes in active capabilities
    NetAdapterOffloadSetGsoCapabilities(NetAdapter, &gsoOffloadCapabilities);
}

更新硬件卸载

如果 TCP/IP 堆栈或过度的协议驱动程序请求更改网络适配器的活动功能,NetAdapterCx 会调用在适配器初始化期间注册的客户端驱动程序 EVT_NET_ADAPTER_OFFLOAD_SET_GSO 回调。 在此函数中,系统在 NETOFFLOAD 对象中提供更新的功能,客户端驱动程序将查询该对象以更新其卸载功能。

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

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

VOID
MyEvtAdapterOffloadSetGso(
	NETADAPTER NetAdapter,
	NETOFFLOAD Offload
)
{
	PMY_NET_ADAPTER_CONTEXT adapterContext = MyGetNetAdapterContext(NetAdapter);

	// Store the updated information in the context
	adapterContext->LSOv4 = NetOffloadIsLsoIPv4Enabled(Offload) ? 
		GsoOffloadEnabled : GsoOffloadDisabled;
	adapterContext->LSOv6 = NetOffloadIsLsoIPv6Enabled(Offload) ?
		GsoOffloadEnabled : GsoOffloadDisabled;
	adapterContext->USOv4 = NetOffloadIsUsoIPv4Enabled(Offload) ? 
		GsoOffloadEnabled : GsoOffloadDisabled;
	adapterContext->USOv6 = NetOffloadIsUsoIPv6Enabled(Offload) ?
		GsoOffloadEnabled : GsoOffloadDisabled;

	// Enable hardware checksum if LSO/USO is enabled
	MyUpdateHardwareChecksum(adapterContext);
}