Index | Thread | Search

From:
Alexander Bluhm <bluhm@openbsd.org>
Subject:
Re: ice(4) Tx checksum offloading
To:
tech@openbsd.org
Date:
Thu, 22 May 2025 22:23:04 +0900

Download raw body.

Thread
On Tue, May 20, 2025 at 10:13:42PM +0200, Stefan Sperling wrote:
> This patch adds support for Tx checksum offloading to the ice(4) driver.
> 
> As with the earlier Rx patch, I have tested this diff both with and
> without ice-ddp firmware loaded. It seems to work in both cases.
> 
> The only case where software checksumming is still being used is when
> I send iperf UDP packets over IPv6. Offloading UDP checkums works in
> the IPv4 case, though, per counters shown by netstat -s.
> Does this indicate a bug in this diff? Or is the IPv6 stack deciding to
> clear M_UDP_CSUM_OUT in some cases for some reason? I could not yet see
> anything wrong comparing my changes to ixl(4) and to FreeBSD ice(4).

Works for me.  I don't see software checksumming counters going up.
Please commit, and I can have an eye on this in more test cases.

OK bluhm@

> M  sys/dev/pci/if_ice.c  |  23+  6-
> 
> 1 file changed, 23 insertions(+), 6 deletions(-)
> 
> commit - 2e4fc07e79d7ea65b71425f1af53c3c7c9d88bb3
> commit + 0f813f93bd053e12f651681399505c576b4cc14e
> blob - ed64ea74bb85a0d5c2750114ed461c94028f295e
> blob + 7cb43b5931c74d075d351458dff0c13b70c582ed
> --- sys/dev/pci/if_ice.c
> +++ sys/dev/pci/if_ice.c
> @@ -84,6 +84,7 @@
>  
>  #include <netinet/in.h>
>  #include <netinet/if_ether.h>
> +#include <netinet/udp.h>
>  
>  #define STRUCT_HACK_VAR_LEN
>  
> @@ -13683,18 +13684,31 @@ ice_tx_setup_offload(struct mbuf *m0, struct ice_tx_qu
>  	hlen = ext.iphlen;
>  
>  	if (ext.ip4) {
> -		/* TODO: ipv4 checksum offload */
> -		offload |= ICE_TX_DESC_CMD_IIPT_IPV4 << ICE_TXD_QW1_CMD_S;
> +		if (ISSET(m0->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT))
> +			offload |= ICE_TX_DESC_CMD_IIPT_IPV4_CSUM <<
> +			    ICE_TXD_QW1_CMD_S;
> +		else
> +			offload |= ICE_TX_DESC_CMD_IIPT_IPV4 <<
> +			    ICE_TXD_QW1_CMD_S;
>  	} else if (ext.ip6)
>  		offload |= ICE_TX_DESC_CMD_IIPT_IPV6 << ICE_TXD_QW1_CMD_S;
> +	else
> +		return offload;
>  
>  	offload |= ((ETHER_HDR_LEN >> 1) << ICE_TX_DESC_LEN_MACLEN_S) <<
>  	    ICE_TXD_QW1_OFFSET_S;
> -	if (ext.ip4 || ext.ip6)
> -		offload |= ((hlen >> 2) << ICE_TX_DESC_LEN_IPLEN_S) <<
> -		    ICE_TXD_QW1_OFFSET_S;
> +	offload |= ((hlen >> 2) << ICE_TX_DESC_LEN_IPLEN_S) <<
> +	    ICE_TXD_QW1_OFFSET_S;
>  
> -	/* TODO: enable offloading features */
> +	if (ext.tcp && ISSET(m0->m_pkthdr.csum_flags, M_TCP_CSUM_OUT)) {
> +		offload |= ICE_TX_DESC_CMD_L4T_EOFT_TCP << ICE_TXD_QW1_CMD_S;
> +		offload |= ((uint64_t)(ext.tcphlen >> 2) <<
> +		    ICE_TX_DESC_LEN_L4_LEN_S) << ICE_TXD_QW1_OFFSET_S;
> +	} else if (ext.udp && ISSET(m0->m_pkthdr.csum_flags, M_UDP_CSUM_OUT)) {
> +		offload |= ICE_TX_DESC_CMD_L4T_EOFT_UDP << ICE_TXD_QW1_CMD_S;
> +		offload |= ((uint64_t)(sizeof(*ext.udp) >> 2) <<
> +		    ICE_TX_DESC_LEN_L4_LEN_S) << ICE_TXD_QW1_OFFSET_S;
> +	}
>  
>  	return offload;
>  }
> @@ -29809,6 +29823,9 @@ ice_attach_hook(struct device *self)
>  #if NVLAN > 0
>  	ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
>  #endif
> +	ifp->if_capabilities |= IFCAP_CSUM_IPv4 |
> +	    IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4 |
> +	    IFCAP_CSUM_TCPv6 | IFCAP_CSUM_UDPv6;
>  
>  	if_attach(ifp);
>  	ether_ifattach(ifp);