Implement and enable TSO in vmx(4)
authorjan <jan@openbsd.org>
Tue, 2 Apr 2024 20:59:48 +0000 (20:59 +0000)
committerjan <jan@openbsd.org>
Tue, 2 Apr 2024 20:59:48 +0000 (20:59 +0000)
Tested with IPv4/IPv6 and vlan(4).

ok jmatthew@

sys/dev/pci/if_vmx.c

index d94e052..81bb083 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_vmx.c,v 1.82 2024/02/29 22:09:33 jan Exp $ */
+/*     $OpenBSD: if_vmx.c,v 1.83 2024/04/02 20:59:48 jan Exp $ */
 
 /*
  * Copyright (c) 2013 Tsubai Masanari
 #include <net/if.h>
 #include <net/toeplitz.h>
 #include <net/if_media.h>
+#include <net/route.h>
 
 #include <netinet/in.h>
 #include <netinet/if_ether.h>
 #include <netinet/ip.h>
 #include <netinet/tcp.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
 #include <netinet/udp.h>
 
 #include <machine/bus.h>
@@ -407,6 +410,8 @@ vmxnet3_attach(struct device *parent, struct device *self, void *aux)
                ifp->if_capabilities |= IFCAP_CSUM_TCPv6 | IFCAP_CSUM_UDPv6;
        }
 
+       ifp->if_capabilities |= IFCAP_TSOv4 | IFCAP_TSOv6;
+
 #if NVLAN > 0
        if (sc->sc_ds->upt_features & UPT1_F_VLAN)
                ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
@@ -579,8 +584,8 @@ vmxnet3_alloc_txring(struct vmxnet3_softc *sc, int queue, int intr)
        comp_ring->txcd = VMX_DMA_KVA(&comp_ring->dmamem);
 
        for (idx = 0; idx < NTXDESC; idx++) {
-               if (bus_dmamap_create(sc->sc_dmat, JUMBO_LEN, NTXSEGS,
-                   VMXNET3_TX_LEN_M + 1, 0, BUS_DMA_NOWAIT, &ring->dmap[idx]))
+               if (bus_dmamap_create(sc->sc_dmat, MAXMCLBYTES, NTXSEGS,
+                   VMXNET3_TX_LEN_M, 0, BUS_DMA_NOWAIT, &ring->dmap[idx]))
                        return -1;
        }
 
@@ -1440,13 +1445,41 @@ vmxnet3_tx_offload(struct vmxnet3_txdesc *sop, struct mbuf *m)
                offset = hdrlen + offsetof(struct tcphdr, th_sum);
        else if (ext.udp)
                offset = hdrlen + offsetof(struct udphdr, uh_sum);
+       else
+               return;
+
+       if (!ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO)) {
+               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);
 
+               return;
+       }
+
+       /*
+        * TCP Segmentation Offload
+        */
+
+       if (ext.tcp == NULL) {
+               tcpstat_inc(tcps_outbadtso);
+               return;
+       }
+
+       if (ext.ip4)
+               ext.ip4->ip_sum = 0;
+
+       hdrlen += ext.tcphlen;
        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(VMXNET3_OM_TSO << VMXNET3_TX_OM_S);
        sop->tx_word3 |= htole32(hdrlen << VMXNET3_TX_HLEN_S);
-       sop->tx_word2 |= htole32(offset << VMXNET3_TX_OP_S);
+       sop->tx_word2 |= htole32(m->m_pkthdr.ph_mss << VMXNET3_TX_OP_S);
+
+       tcpstat_add(tcps_outpkttso, (m->m_pkthdr.len - hdrlen +
+           m->m_pkthdr.ph_mss - 1) / m->m_pkthdr.ph_mss);
 }
 
 void