Checksum and TCP Segmentation Offloading

Jump to: navigation, search

Table of Contents


General Description

Some devices support a combination of receive checksum offload, send checksum offload, and/or TCP segmentation offload for different type of packets. The stack can be configured on a per interface basis to take advantage of the offload hardware capabilities.

Compile-time Configuration

First, some macros need to be defined to enable all of the offload capabilities in the stack as shown below.

Run-time Configuration

When one or both of these macros are enabled, at run time, when an interface is opened, the stack will query the corresponding driver (calling the driver IOCTL with TM_DEV_IOCTL_OFFLOAD_GET) for its offload capabilities, and then will let the driver know of the driver's offload capabilities (with the driver IOCTL TM_DEV_IOCTL_OFFLOAD_SET). Offloading should only be performed by the driver according to the driver's offload capabilities as set in the driver IOCTL call with TM_DEV_IOCTL_OFFLOAD_SET.

Recv Checksum Offload

When the recv offload macro is enabled, the driver recv functions take an extra parameter that should be ignored by drivers that do not support offload, and that should be filled in by the drivers that do support offload as explained below.

Send Checksum Offload/TCP Segmentation Offload

When the send offload macro is enabled, for drivers that support send and/or TCP segmentation offload, then the driver should supply a scattered send single call for the driver send routine as explained in Chapter 4: Integrating Turbo Treck Real-Time Protocols Into Your Environment.


Related Macros

Reception: Checksum Offload

To enable the recv checksum offload add the following macro definition to <trsystem.h>:

#define TM_DEV_RECV_OFFLOAD

In that case all driver recv functions take an extra parameter. If the driver does not support offloading, then it ignores the extra parameter.

Transmission: Checksum and TCP Segmentation Offload

To enable the send checksum and TCP segmentation offload add the following macro definition to <trsystem.h>:

#define TM_DEV_SEND_OFFLOAD

Transmission: TM_USE_DRV_ONE_SCAT_SEND Macro

Note that when TM_DEF_SEND_OFFLOAD is defined, then the macro TM_USE_DRV_ONE_SCAT_SEND is automatically defined, because to be able to use send checksum offload/TCP segmentation offload on a device, the driver needs to supply the single send call per frame function as explained in Adding a Device Driver.


Run-time Configuration

Device Driver IOCTL Function

Driver IOCTL with TM_DEV_IOCTL_OFFLOAD_GET Flag

When the user opens the interface, and if one of the 2 offload macros has been defined, then the stack will call the driver IOCTL function with the TM_DEV_IOCTL_OFFLOAD_GET flag to get the offload capabilities of the device driver. A pointer to an offload structure is passed as 3rd parameter. The offload structure is initialized by the driver.

Upon return, the device driver will set one or more of the below flags in the offloadFlags field of the ttDevIoctlOffloadStruct structure to indicate what the device supports.

Driver IOCTL with TM_DEV_IOCTL_OFFLOAD_SET Flag

After having called the device driver IOCTL with the TM_DEV_IOCTL_OFFLOAD_GET flag, and if that function returns TM_ENOERROR, then the stack will immediately call the device driver IOCTL function with the TM_DEV_IOCTL_OFFLOAD_SET flag passing the pointer to the offload structure with its fields as set by the device driver. When this function is called, the driver and the stack have both agreed on what offload capabilities they both support.

The stack will let the driver know which of the above flags returned by TM_DEV_IOCTL_OFFLOAD_GET it will support in the offloadFlags field of the ttDevIoctlOffloadStruct structure to indicate what the device should support.

Driver IOCTL Offload Structure

A pointer to the following structure is passed as 3rd parameter of the device driver IOCTL:

typedef struct tsDevIoctlOffloadStruct
{
    ttUser16Bit offloadFlags;
    ttUser16Bit offloadMaxSize;
} ttDevIoctlOffloadStruct;
typedef ttDevIoctlOffloadStruct TM_FAR * ttDevIoctlOffloadPtr;


Members

  • (ttUser16Bit) offloadFlags
    One or more bits set to indicate the offload capabilities of the driver as described below.
  • (ttUser16Bit) offloadMaxSize
    Maximum size of a TCP packet (including IP header and Ethernet header) that the driver can segment.


Flags

  • TM_DEVO_PACKET_RECV_CHKSUM_COMPUTE
    Legacy: Device calculates recv checksum on the entire packet (hardware will append the recv checksum on the entire packet (minus the MAC layer) at the end of the data in network byte order. Note that some drivers append the checksum in little endian order; in this case the recv checksum should be flipped by the driver.
  • TM_DEVO_IP_RECV_CHKSUM_VALIDATE
    Hardware validates the recv IPv4 header checksum
  • TM_DEVO_TCP_RECV_CHKSUM_VALIDATE
    Hardware validates the recv TCP header checksum
  • TM_DEVO_UDP_RECV_CHKSUM_VALIDATE
    Hardware validates the recv UDP header checksum
  • TM_DEVO_ICMP6_RECV_CHKSUM_VALIDATE
    Hardware validates the ICMPv6 header checksum
  • TM_DEVO_DITCH_BAD_CHECKSUM_PACKETS
    Device driver will not pass up the stack packets that have bad checksums.
  • TM_DEVO_TCP_CHKSUM_OFFLOAD
    Device supports TCP checksum offload only (no segmentation offload)
  • TM_DEVO_UDP_CHKSUM_OFFLOAD
    Device supports UDP checksum offload
  • TM_DEVO_ICMP6_CHKSUM_OFFLOAD
    Device supports ICMPV6 checksum offload
  • TM_DEVO_IP_CHKSUM_OFFLOAD
    Device supports IPv4 checksum offload
  • TM_DEVO_TCP_SEGMENT_OFFLOAD_V4
    Device supports TCP Segmentation offload for IPv4 packets, note that, whenever TCP segment is enabled, TM_DEVO_IP_CHKSUM_OFFLOAD is enabled automatically.
  • TM_DEVO_TCP_SEGMENT_OFFLOAD_V6
    Device supports TCP Segmentation offload for IPv6 packets



Recv Checksum Offload

The stack will support different degrees of device checksum capabilities. Some devices are only capable of computing a checksum on the entire packet (legacy). Others are able to completely validate the IPv4 header checksum, TCP header checksum, etc. To get that information from the driver, the driver recv function has been modified to take an extra parameter.

Modified Driver Recv Function

When TM_DEV_RECV_OFFLOAD is enabled, then the driver recv function takes an extra parameter, a pointer to a recv offload structure:


int devRecv (
ttUserInterface interfaceHandle,
char ** dataPtr,
int * dataLength,
ttUserBufferPtr userBufferHandlePtr,
ttDevRecvOffloadPtr devRecvOffloadPtr
);


Modified Driver Scattered Recv Function

When TM_DEV_RECV_OFFLOAD is enabled, then the driver scattered recv function takes an extra parameter, a pointer to a recv offload structure:


int devRecv (
ttUserInterface interfaceHandle,
ttDruBlockPtrPtr uDevBlockPtrPtr,
int * uDevBlockCountPtr,
int * flagPtr,
ttDevRecvOffloadPtr devRecvOffloadPtr
);


Recv Offload Structure

typedef struct tsDevRecvOffloadStruct
{
/*
 * One of more of the TM_DEVOR_XXX flags as defined below.
 */
    ttUser16Bit devoRFlags;
/* Recv checksum as computed by the board */
    ttUser16Bit devoRecvXsum;
/* Offset to start of checksum computation */
    ttUser16Bit devoRecvXsumOffset;
/* Checksum done on this amount of data */
    ttUser16Bit devoRecvXsumLength;
} ttDevRecvOffloadStruct;
typedef ttDevRecvOffloadStruct TM_FAR * ttDevRecvOffloadPtr;


Members

  • (ttUser16Bit) devoRFlags
    One of more of the TM_DEVOR_XXX flags as defined below.
  • (ttUser16Bit) devoRecvXsum
    Recv checksum as computed by the hardware in network byte order (legacy).
  • (ttUser16Bit) devoRecvXsumOffset
    Offset to start of checksum computation (legacy).
  • (ttUser16Bit) devoRecvXsumLength
    Checksum done on this amount of data (legacy).


Note Note: In case the hardware supports legacy recv checksum hardware computation, the device driver will need to copy:
  1. The hardware checksum in the 'devoRecvXsum' field in network byte order
  2. The offset from the beginning of the packet to where the hardware checksum computation started in the 'devoRecvXsumOffset' field
  3. The length of the data that was checksum'ed in the 'devoRecvXsumLength' field.


Flags

  • TM_DEVOR_PACKET_RECV_CHKSUM_COMPUTED
    recv checksum has been computed (legacy)
  • TM_DEVOR_IP_RECV_CHKSUM_VALIDATED
    recv IP header checksum has been validated
  • TM_DEVOR_TCP_RECV_CHKSUM_VALIDATED
    recv TCP header checksum has been validated
  • TM_DEVOR_UDP_RECV_CHKSUM_VALIDATED
    recv TCP header checksum has been validated
  • TM_DEVOR_ICMP6_RECV_CHKSUM_VALIDATED
    recv TCP header checksum has been validated
  • TM_DEVOR_IP_RECV_CHKSUM_FAILED
    recv IPv4 header checksum failed
  • TM_DEVOR_TCP_RECV_CHKSUM_FAILED
    recv TCP header checksum failed
  • TM_DEVOR_UDP_RECV_CHKSUM_FAILED
    recv UDP header checksum failed
  • TM_DEVOR_ICMP6_RECV_CHKSUM_FAILED
    recv ICMPv6 header checksum failed



Transmission

When data is sent to the device driver, the stack needs to indicate to the device driver what checksum computations have been made, and information about TCP segmentation offload. That information is conveyed in a ttDevSendOffloadStruct structure as shown below.

The stack will pre-compute the pseudo header checksum for TCP, UDP, and ICMPv6 packets in the checksum field. It will indicate to the board the offset to that field in the packet, offset to first byte of data, and last byte of data to be checksum'ed. Note that if the board supports TCP segmentation, and TCP is sending a segment bigger than the MSS, then the stack will indicate to the board that TCP segmentation needs to be performed. In that case the pseudo-header checksum does not include the length. Also in that case, three additional fields are filled in by the stack as shown below.

If the board supports IP header checksum, the stack will not compute the IP header checksum, and will indicate to the board the offset to the IP header checksum, to the first byte of the IP header, and last byte of the IP header.

Single Send Call Driver Function

The driver needs to support the single send call driver function.

Modified ttUserPacket Structure

The single send call driver function takes a ttUserPacketPtr parameter. The ttUserPacket structure takes an additional field used to convey the offload performed on the packet. It is a pointer to a ttDevSendOffloadStruct.

#define trsocket.h
 
/*
 * Data type used for the linked list of packets passed to the device
 * driver single call scattered send function prototype.
 */
typedef struct tsUserPacket
{
/* Next tsUserPacket for scattered data  */
/*    struct tsUserPacket TM_FAR   *pktuLinkNextPtr; */
    void               TM_FAR   *pktuLinkNextPtr;
/* Pointer to data */
    ttUser8BitPtr                pktuLinkDataPtr;
#ifdef TM_DSP
/* byte offset of start of data, in word pointed to by pktuLinkDataPtr */
    int                          pktuLinkDataByteOffset;
#endif /* TM_DSP */
#if defined(TM_DEV_SEND_OFFLOAD) || defined(TM_DEV_RECV_OFFLOAD)
    ttUserVoidPtr                pktuDevOffloadPtr;
#endif /* TM_DEV_SEND_OFFLOAD || TM_DEV_RECV_OFFLOAD */
/* Size of data pointed by pktuLinkDataPtr */
    ttPktLen                     pktuLinkDataLength;
/*
 * Total packet length (of chained scattered data). Valid in first link
 * only
 */
    ttPktLen                     pktuChainDataLength;
/*
 * Number of links linked to this one (not including this one).
 * Valid in first link only.
 */
    int                          pktuLinkExtraCount;
#ifdef TM_USE_USER_PARAM
/* User-defined data */
    ttUserGenericUnion           pktuUserParam;
#endif /* TM_USE_USER_PARAM */
} ttUserPacket;
 
typedef ttUserPacket TM_FAR * ttUserPacketPtr;


Device Send Offload Structure

In ttUserPacket, the pktuDevOffloadPtr points to the following structure:

typedef struct tsDevSendOffloadStruct
{
/*
 * One of more of the device offload flags as defined in the
 * TM_DEV_IOCTL_OFFLOAD_SET tfIoctlInterface().
 * Note that a TM_DEVO_TCP_SEGMENT_OFFLOAD_V4 flag, indicates an IPv4 protocol
 * and a TM_DEVO_TCP_SEGMENT_OFFLOAD_V6 indicates an IPv6 protocol (needed for
 * segmentation)
 */
    ttUser16Bit devoFlags;
/* TCP/IP or UDP/IP header length to be used in each frame */
    ttUser16Bit devoFrameHdrLen;
/* Total TCP payload (used in segmentation) not including header */
    ttUser32Bit devoPayload;
/* Maximum TCP or UDP payload segment per frame not including header */
    ttUser16Bit devoFramePayload;
/* UDP/TCP header checksum */
    ttUser16Bit devoTucss; /* offset to first byte to be included in Xsum */
    ttUser16Bit devoTucso; /* Offset to Xsum field */
    ttUser16Bit devoTucse; /* Offset to last byte to be in included in Xsum */
#ifdef TM_USE_IPV4
/* IP header checksum */
    ttUser16Bit devoIpcss; /* offset to first byte to be included in Xsum */
    ttUser16Bit devoIpcso; /* Offset to Xsum field */
    ttUser16Bit devoIpcse; /* Offset to last byte to be in included in Xsum */
#endif /* TM_USE_IPV4 */
} ttDevSendOffloadStruct;
 
typedef ttDevSendOffloadStruct TM_FAR * ttDevSendOffloadPtr;


Members

  • (ttUser16Bit) devoFlags
    One of more of the device offload flags as shown below.
  • (ttUser16Bit) devoFrameHdrLen
    TCP/IP header length to be used in each frame (segmentation).
  • (ttUser32Bit) devoPayload
    Total TCP payload not including header (segmentation).
  • (ttUser16Bit) devoFramePayload
    Maximum TCP payload segment per frame not including header (segmentation).
  • (ttUser16Bit) devoTucss
    UDP/TCP/ICMPV6 header checksum: offset to first byte to be included in Xsum.
  • (ttUser16Bit) devoTucso
    UDP/TCP/ICMPV6 header checksum: Offset to Xsum field.
  • (ttUser16Bit) devoTucse
    UDP/TCP/ICMPV6 header checksum: Offset to last byte to be in included in Xsum. Note that 0 means offset to last byte of the entire packet.
  • (ttUser16Bit) devoIpcss
    IPv4 header checksum: offset to first byte to be included in Xsum.
  • (ttUser16Bit) devoIpcso
    IPv4 header checksum: Offset to Xsum field.
  • (ttUser16Bit) devoIpcse
    IPv4 header checksum: Offset to last byte to be in included in Xsum.


Flags

  • TM_DEVO_TCP_CHKSUM_OFFLOAD
    TCP checksum is to be offloaded (no segmentation offload)
  • TM_DEVO_UDP_CHKSUM_OFFLOAD
    UDP checksum is to be offloaded
  • TM_DEVO_ICMP6_CHKSUM_OFFLOAD
    ICMPV6 checksum is to be offloaded
  • TM_DEVO_IP_CHKSUM_OFFLOAD
    IPv4 checksum is to be offloaded
  • TM_DEVO_TCP_SEGMENT_OFFLOAD_V4
    TCP Segmentation offload for IPv4 packets. Note that whenever TCP segment is enabled, TM_DEVO_IP_CHKSUM_OFFLOAD is enabled automatically.
  • TM_DEVO_TCP_SEGMENT_OFFLOAD_V6
    TCP Segmentation offload for IPv6 packet



Examples

The source code contains one driver that support different degrees of offloading capabilities:


Board Type of Offload Supported Location
Intel Xscale 80321 Recv checksum validation source/drivers/8254x/tr8254x.c
Recv checksum computation if TM_DEVO_PACKET_RECV_CHKSUM_COMPUTE is set in the offloadFlags field of the ttDevIoctlOffloadStruct structure when the stack calls the driver IOCTL with the TM_DEV_IOCTL_OFFLOAD_SET flag parameter. Note that the stack will set the flags retrieved from the driver IOCTL function call with TM_DEV_IOCTL_OFFLOAD_GET. So this happens if TM_DEVO_PACKET_RECV_CHKSUM_COMPUTE is set in the offladFlags field of the ttDevIoctlOffloadStruct structure in the driver IOCTL function.
TCP segmentation if the macro TM_LEGACY_OFFLOAD is not defined in that driver.
TCP/UDP/ICMPv6 checksum offload.
IP header checksum offload if the macro TM_LEGACY_OFFLOAD is not defined in that driver.


Table of Contents