From: Moritz Buhl Subject: igc(4) tso To: tech@openbsd.org Cc: bket@openbsd.org, bluhm@openbsd.org, jan@openbsd.org Date: Wed, 1 May 2024 18:24:36 +0200 The VLAN_HWTAGGING diff is in snapshots for a while, I saw no additional feedback. How about adding TSO to igc(4) next? I ran thorough tests on bluhms' setup: http://bluhm.genua.de/netlink/results/2024-04-30T00%3A37%3A41Z/netlink.html and additional tests on my home router using pppoe(4) and vlan(4). ok? Index: dev/pci/if_igc.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_igc.c,v diff -u -p -r1.20 if_igc.c --- dev/pci/if_igc.c 12 Apr 2024 19:27:43 -0000 1.20 +++ dev/pci/if_igc.c 1 May 2024 16:16:29 -0000 @@ -44,10 +44,14 @@ #include #include +#include #include #include #include +#include +#include +#include #if NBPFILTER > 0 #include @@ -796,6 +800,7 @@ igc_setup_interface(struct igc_softc *sc ifp->if_capabilities |= IFCAP_CSUM_IPv4; ifp->if_capabilities |= IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4; ifp->if_capabilities |= IFCAP_CSUM_TCPv6 | IFCAP_CSUM_UDPv6; + ifp->if_capabilities |= IFCAP_TSOv4 | IFCAP_TSOv6; /* Initialize ifmedia structures. */ ifmedia_init(&sc->media, IFM_IMASK, igc_media_change, igc_media_status); @@ -993,8 +998,6 @@ igc_start(struct ifqueue *ifq) continue; } - olinfo_status = m->m_pkthdr.len << IGC_ADVTXD_PAYLEN_SHIFT; - bus_dmamap_sync(txr->txdma.dma_tag, map, 0, map->dm_mapsize, BUS_DMASYNC_PREWRITE); @@ -1007,6 +1010,9 @@ igc_start(struct ifqueue *ifq) prod++; prod &= mask; free--; + } else { + olinfo_status = + m->m_pkthdr.len << IGC_ADVTXD_PAYLEN_SHIFT; } for (i = 0; i < map->dm_nsegs; i++) { @@ -2025,12 +2031,15 @@ igc_tx_ctx_setup(struct tx_ring *txr, st { struct ether_extracted ext; struct igc_adv_tx_context_desc *txdesc; + uint32_t mss_l4len_idx = 0; uint32_t type_tucmd_mlhl = 0; uint32_t vlan_macip_lens = 0; int off = 0; - ether_extract_headers(mp, &ext); - vlan_macip_lens |= (sizeof(*ext.eh) << IGC_ADVTXD_MACLEN_SHIFT); + if (mp->m_pkthdr.csum_flags & M_TCP_TSO) + *olinfo_status = 0; + else + *olinfo_status = mp->m_pkthdr.len << IGC_ADVTXD_PAYLEN_SHIFT; /* * In advanced descriptors the vlan tag must @@ -2046,6 +2055,10 @@ igc_tx_ctx_setup(struct tx_ring *txr, st } #endif + ether_extract_headers(mp, &ext); + + vlan_macip_lens |= (sizeof(*ext.eh) << IGC_ADVTXD_MACLEN_SHIFT); + if (ext.ip4) { type_tucmd_mlhl |= IGC_ADVTXD_TUCMD_IPV4; if (ISSET(mp->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT)) { @@ -2056,6 +2069,9 @@ igc_tx_ctx_setup(struct tx_ring *txr, st } else if (ext.ip6) { type_tucmd_mlhl |= IGC_ADVTXD_TUCMD_IPV6; #endif + } else { + if (mp->m_pkthdr.csum_flags & M_TCP_TSO) + tcpstat_inc(tcps_outbadtso); } vlan_macip_lens |= ext.iphlen; @@ -2075,6 +2091,29 @@ igc_tx_ctx_setup(struct tx_ring *txr, st } } + if (mp->m_pkthdr.csum_flags & M_TCP_TSO) { + if (ext.tcp) { + uint32_t hdrlen, thlen, paylen, outlen; + + thlen = ext.tcphlen; + + outlen = mp->m_pkthdr.ph_mss; + mss_l4len_idx |= outlen << IGC_ADVTXD_MSS_SHIFT; + mss_l4len_idx |= thlen << IGC_ADVTXD_L4LEN_SHIFT; + + hdrlen = sizeof(*ext.eh) + ext.iphlen + thlen; + paylen = mp->m_pkthdr.len - hdrlen; + *olinfo_status |= paylen << IGC_ADVTXD_PAYLEN_SHIFT; + + *cmd_type_len |= IGC_ADVTXD_DCMD_TSE; + off = 1; + + tcpstat_add(tcps_outpkttso, + (paylen + outlen - 1) / outlen); + } else + tcpstat_inc(tcps_outbadtso); + } + if (off == 0) return 0; @@ -2085,7 +2124,7 @@ igc_tx_ctx_setup(struct tx_ring *txr, st htolem32(&txdesc->vlan_macip_lens, vlan_macip_lens); htolem32(&txdesc->type_tucmd_mlhl, type_tucmd_mlhl); htolem32(&txdesc->seqnum_seed, 0); - htolem32(&txdesc->mss_l4len_idx, 0); + htolem32(&txdesc->mss_l4len_idx, mss_l4len_idx); return 1; }