From: Alexander Bluhm Subject: Re: vmx(4): TCP/UDP checksum offloading To: jan@openbsd.org Cc: Jonathan Matthew , tech@openbsd.org Date: Thu, 15 Feb 2024 14:17:37 +0100 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 */