From e9542ffc3660d6c3ee05e9a84a3d6649d1e7711a Mon Sep 17 00:00:00 2001 From: jan Date: Thu, 15 Feb 2024 13:24:45 +0000 Subject: [PATCH] vmx(4): Add TCP/UDP Checksum Offloading for IPv4/6 ok jmatthew@, bluhm@ --- sys/dev/pci/if_vmx.c | 67 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 11 deletions(-) diff --git a/sys/dev/pci/if_vmx.c b/sys/dev/pci/if_vmx.c index 4a9c762350b..7a3c772e250 100644 --- a/sys/dev/pci/if_vmx.c +++ b/sys/dev/pci/if_vmx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vmx.c,v 1.80 2024/02/09 15:22:41 jan Exp $ */ +/* $OpenBSD: if_vmx.c,v 1.81 2024/02/15 13:24:45 jan Exp $ */ /* * Copyright (c) 2013 Tsubai Masanari @@ -400,10 +400,12 @@ vmxnet3_attach(struct device *parent, struct device *self, void *aux) 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; @@ -1397,6 +1399,55 @@ vmx_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map, struct mbuf *m) BUS_DMA_STREAMING | BUS_DMA_NOWAIT)); } +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) { @@ -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 */ -- 2.20.1