Download raw body.
vmx(4): TCP/UDP checksum offloading
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@
>
> bye,
> Jan
>
> 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 9 Feb 2024 19:44:51 -0000
> @@ -37,6 +37,7 @@
> #include <netinet/in.h>
> #include <netinet/if_ether.h>
> #include <netinet/ip.h>
> +#include <netinet/ip6.h>
> #include <netinet/tcp.h>
> #include <netinet/udp.h>
>
> @@ -400,10 +401,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 +1401,57 @@ 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)
> + hdrlen += ext.ip4->ip_hl << 2;
> + else if (ext.ip6)
> + hdrlen += sizeof(*ext.ip6);
> +
> + 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 +1523,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