Index | Thread | Search

From:
Alexander Bluhm <alexander.bluhm@gmx.net>
Subject:
Re: vmx(4): TCP/UDP checksum offloading
To:
jan@openbsd.org
Cc:
Jonathan Matthew <jonathan@d14n.org>, tech@openbsd.org
Date:
Thu, 15 Feb 2024 14:17:37 +0100

Download raw body.

Thread
On Thu, Feb 15, 2024 at 10:46:18AM +0100, jan@openbsd.org wrote:
> On Thu, Feb 15, 2024 at 01:12:18PM +1000, Jonathan Matthew wrote:
> > On Fri, Feb 09, 2024 at 10:04:37PM +0100, jan@openbsd.org wrote:
> > > Hi,
> > > 
> > > This diff implements the TCP/UDP checksum offloading for vmx(4).
> > > I tested it on ESXi 8.0 with OpenBSD and Linux guests.
> > > 
> > > ok?
> > 
> > This looks better than the diff I was working on.
> > ok jmatthew@
> 
> Thanks for your review.  I adjust the diff with bluhm's ext.iphlen
> feature from yesterday and remove the include of ip6.h.
> 
> ok?

OK bluhm@

> Index: dev/pci/if_vmx.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/if_vmx.c,v
> diff -u -p -r1.80 if_vmx.c
> --- dev/pci/if_vmx.c	9 Feb 2024 15:22:41 -0000	1.80
> +++ dev/pci/if_vmx.c	15 Feb 2024 09:36:49 -0000
> @@ -400,10 +400,12 @@ vmxnet3_attach(struct device *parent, st
>  	ifp->if_watchdog = vmxnet3_watchdog;
>  	ifp->if_hardmtu = VMXNET3_MAX_MTU;
>  	ifp->if_capabilities = IFCAP_VLAN_MTU;
> -#if 0
> -	if (sc->sc_ds->upt_features & UPT1_F_CSUM)
> +
> +	if (sc->sc_ds->upt_features & UPT1_F_CSUM) {
>  		ifp->if_capabilities |= IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4;
> -#endif
> +		ifp->if_capabilities |= IFCAP_CSUM_TCPv6 | IFCAP_CSUM_UDPv6;
> +	}
> +
>  #if NVLAN > 0
>  	if (sc->sc_ds->upt_features & UPT1_F_VLAN)
>  		ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
> @@ -1398,6 +1400,55 @@ vmx_load_mbuf(bus_dma_tag_t dmat, bus_dm
>  }
>  
>  void
> +vmxnet3_tx_offload(struct vmxnet3_txdesc *sop, struct mbuf *m)
> +{
> +	struct ether_extracted ext;
> +	uint32_t offset = 0;
> +	uint32_t hdrlen;
> +
> +	/*
> +	 * VLAN Offload
> +	 */
> +
> +#if NVLAN > 0
> +	if (ISSET(m->m_flags, M_VLANTAG)) {
> +		sop->tx_word3 |= htole32(VMXNET3_TX_VTAG_MODE);
> +		sop->tx_word3 |= htole32((m->m_pkthdr.ether_vtag &
> +		    VMXNET3_TX_VLANTAG_M) << VMXNET3_TX_VLANTAG_S);
> +	}
> +#endif
> +
> +	/*
> +	 * Checksum Offload
> +	 */
> +
> +	if (!ISSET(m->m_pkthdr.csum_flags, M_TCP_CSUM_OUT) &&
> +	    !ISSET(m->m_pkthdr.csum_flags, M_UDP_CSUM_OUT))
> +		return;
> +
> +	ether_extract_headers(m, &ext);
> +
> +	hdrlen = sizeof(*ext.eh);
> +	if (ext.evh)
> +		hdrlen = sizeof(*ext.evh);
> +
> +	if (ext.ip4 || ext.ip6)
> +		hdrlen += ext.iphlen;
> +
> +	if (ext.tcp)
> +		offset = hdrlen + offsetof(struct tcphdr, th_sum);
> +	else if (ext.udp)
> +		offset = hdrlen + offsetof(struct udphdr, uh_sum);
> +
> +	hdrlen &= VMXNET3_TX_HLEN_M;
> +	offset &= VMXNET3_TX_OP_M;
> +
> +	sop->tx_word3 |= htole32(VMXNET3_OM_CSUM << VMXNET3_TX_OM_S);
> +	sop->tx_word3 |= htole32(hdrlen << VMXNET3_TX_HLEN_S);
> +	sop->tx_word2 |= htole32(offset << VMXNET3_TX_OP_S);
> +}
> +
> +void
>  vmxnet3_start(struct ifqueue *ifq)
>  {
>  	struct ifnet *ifp = ifq->ifq_if;
> @@ -1469,13 +1520,7 @@ vmxnet3_start(struct ifqueue *ifq)
>  		}
>  		txd->tx_word3 = htole32(VMXNET3_TX_EOP | VMXNET3_TX_COMPREQ);
>  
> -#if NVLAN > 0
> -		if (ISSET(m->m_flags, M_VLANTAG)) {
> -			sop->tx_word3 |= htole32(VMXNET3_TX_VTAG_MODE);
> -			sop->tx_word3 |= htole32((m->m_pkthdr.ether_vtag &
> -			    VMXNET3_TX_VLANTAG_M) << VMXNET3_TX_VLANTAG_S);
> -		}
> -#endif
> +		vmxnet3_tx_offload(sop, m);
>  
>  		ring->prod = prod;
>  		/* Change the ownership by flipping the "generation" bit */