Download raw body.
vmx(4): TCP/UDP checksum offloading
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 */
vmx(4): TCP/UDP checksum offloading