Generic Segmentation Offload

Generic Segmentation Offload (GSO) collectively represents Large Send Offload (LSO) and UDP Send Offload (USO).

Client drivers can offload the segmentation of TCP/UDP packets that are larger than the maximum transmission unit (MTU) of the network medium. Drivers must indicate this capability to NetAdapterCx using the GSO APIs.

INF keywords for controlling GSO

NetAdapterCx checks the registry keywords and honors them when enabling the active offload capabilities. The driver doesn't need to take any further action.

The LSO keywords specified in Using Registry Values to Enable and Disable Task Offloading can be used to enable/disable the LSO offload with a registry key setting.

The USO keywords specified in UDP Segmentation Offload (USO) can be used to enable/disable the USO offload with a registry key setting.

The keyword values must be of type REG_SZ.

Configuring GSO

Client drivers first advertise their hardware's GSO capabilities during net adapter initialization. This might occur within their EvtDevicePrepareHardware callback before starting a net adapter.

To configure GSO, the client driver:

  1. Allocates a NET_ADAPTER_OFFLOAD_GSO_CAPABILITIES structure.

  2. Calls NET_ADAPTER_OFFLOAD_GSO_CAPABILITIES_INIT to initialize the structure.

  3. Calls NetAdapterOffloadSetGsoCapabilities to register the structure with NetAdapterCx.

During the call to NET_ADAPTER_OFFLOAD_GSO_CAPABILITIES_INIT the client driver provides a pointer to the EVT_NET_ADAPTER_OFFLOAD_SET_GSO callback. The system invokes this callback later if active offload capabilities change.

Rules for indicating hardware GSO capabilities

The following rules apply to the NET_ADAPTER_OFFLOAD_GSO_CAPABILITIES structure:

  1. The driver must set the Layer3Flags and Layer4Flags.

  2. If the NIC supports LSO, the driver must populate the Layer4Flags field with the NetAdapterOffloadLayer4FlagTcpWithoutOptions TCP flag.

  3. If the NIC supports USO, the driver must populate the Layer4Flags field with the NetAdapterOffloadLayer4FlagUdp UDP flag.

  4. MaximumOffloadSize and MinimumSegmentCount are mandatory fields.

  5. The Layer4OffsetLimit field is optional. If the OS sends a packet with a header offset larger than the specified limit, it won't ask for GSO to be performed.

  6. IP/TCP packets without options/extensions must be supported if options/extensions are supported.

This example shows how a client driver might set up its hardware offload capabilities.

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);
}

Updating hardware offloads

If the TCP/IP stack or an overlying protocol driver requests a change to the net adapter's active capabilities, NetAdapterCx invokes the client driver's EVT_NET_ADAPTER_OFFLOAD_SET_GSO callback that was registered during adapter initialization. In this function, the system supplies updated capabilities in the NETOFFLOAD object which the client driver queries to update its offload capabilities.

Client drivers can call the following functions to determine which offloads are enabled:

The following example example shows how a client driver might update its GSO offload capabilities:

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);
}