Hi,

I merged jan@'s ix(4) TSO diff with my software TSO diff.  It seems
to work.

# netstat -s -p tcp | grep TSO
                1 output TSO packet software chopped
                1824861 output TSO packets hardware processed
                31668597 output TSO packets generated
                83 output TSO packets dropped

Do not set ifconfig ix tso, this flag does not work correctly.
Hardware TSO is enabled if the hardware interface supports it.  To
disable TSO globally, use sysctl net.inet.tcp.tso=0.

I have tested it with this interface types.
ix0 at pci3 dev 0 function 0 "Intel 82598AF" rev 0x01, msix, 4 queues, address 
00:1b:21:0d:db:8f
ix1 at pci4 dev 0 function 0 "Intel 82599" rev 0x01, msix, 4 queues, address 
00:1b:21:c5:19:50
ix5 at pci13 dev 0 function 0 "Intel 82599" rev 0x01, msix, 4 queues, address 
90:e2:ba:d6:28:ac

Feel free to try other ix interfaces.  pf route-to should work, but
I have not tested it.

I have not yet investigated where the dropped counter 83 comes from.
If you see that also, please report what you did.

bluhm

Index: dev/pci/if_ix.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/if_ix.c,v
retrieving revision 1.193
diff -u -p -r1.193 if_ix.c
--- dev/pci/if_ix.c     28 Apr 2023 10:18:57 -0000      1.193
+++ dev/pci/if_ix.c     12 May 2023 22:43:04 -0000
@@ -1924,8 +1924,9 @@ ixgbe_setup_interface(struct ix_softc *s
        ifp->if_capabilities |= IFCAP_CSUM_TCPv6 | IFCAP_CSUM_UDPv6;
        ifp->if_capabilities |= IFCAP_CSUM_IPv4;
 
+       ifp->if_capabilities |= IFCAP_TSOv4 | IFCAP_TSOv6;
        if (sc->hw.mac.type != ixgbe_mac_82598EB)
-               ifp->if_capabilities |= IFCAP_TSO;
+               ifp->if_capabilities |= IFCAP_LRO;
 
        /*
         * Specify the media types supported by this sc and register
@@ -2344,6 +2345,7 @@ ixgbe_initialize_transmit_units(struct i
        int              i;
        uint64_t         tdba;
        uint32_t         txctrl;
+       uint32_t         hlreg;
 
        /* Setup the Base and Length of the Tx Descriptor Ring */
 
@@ -2405,6 +2407,11 @@ ixgbe_initialize_transmit_units(struct i
                rttdcs &= ~IXGBE_RTTDCS_ARBDIS;
                IXGBE_WRITE_REG(hw, IXGBE_RTTDCS, rttdcs);
        }
+
+       /* Enable TCP/UDP padding when using TSO */
+       hlreg = IXGBE_READ_REG(hw, IXGBE_HLREG0);
+       hlreg |= IXGBE_HLREG0_TXPADEN;
+       IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg);
 }
 
 /*********************************************************************
@@ -2473,16 +2480,18 @@ ixgbe_free_transmit_buffers(struct tx_ri
  **********************************************************************/
 
 static inline int
-ixgbe_csum_offload(struct mbuf *mp, uint32_t *vlan_macip_lens,
-    uint32_t *type_tucmd_mlhl, uint32_t *olinfo_status)
+ixgbe_tx_offload(struct mbuf *mp, uint32_t *vlan_macip_lens,
+    uint32_t *type_tucmd_mlhl, uint32_t *olinfo_status, uint32_t *cmd_type_len,
+    uint32_t *mss_l4len_idx)
 {
        struct ether_extracted ext;
        int offload = 0;
-       uint32_t iphlen;
+       uint32_t ethlen, iphlen;
 
        ether_extract_headers(mp, &ext);
+       ethlen = sizeof(*ext.eh);
 
-       *vlan_macip_lens |= (sizeof(*ext.eh) << IXGBE_ADVTXD_MACLEN_SHIFT);
+       *vlan_macip_lens |= (ethlen << IXGBE_ADVTXD_MACLEN_SHIFT);
 
        if (ext.ip4) {
                iphlen = ext.ip4->ip_hl << 2;
@@ -2500,6 +2509,8 @@ ixgbe_csum_offload(struct mbuf *mp, uint
                *type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;
 #endif
        } else {
+               if (mp->m_pkthdr.csum_flags & M_TCP_TSO)
+                       tcpstat_inc(tcps_outbadtso);
                return offload;
        }
 
@@ -2519,6 +2530,32 @@ ixgbe_csum_offload(struct mbuf *mp, uint
                }
        }
 
+       if (mp->m_pkthdr.csum_flags & M_TCP_TSO) {
+               if (ext.tcp) {
+                       uint32_t pktlen, hdrlen, thlen, outlen;
+
+                       thlen = ext.tcp->th_off << 2;
+
+                       *mss_l4len_idx |= (uint32_t)(mp->m_pkthdr.ph_mss
+                           << IXGBE_ADVTXD_MSS_SHIFT);
+                       *mss_l4len_idx |= thlen << IXGBE_ADVTXD_L4LEN_SHIFT;
+
+                       hdrlen = ethlen + iphlen + thlen;
+                       pktlen = mp->m_pkthdr.len - hdrlen;
+                       CLR(*olinfo_status, IXGBE_ADVTXD_PAYLEN_MASK
+                           << IXGBE_ADVTXD_PAYLEN_SHIFT);
+                       *olinfo_status |= pktlen << IXGBE_ADVTXD_PAYLEN_SHIFT;
+
+                       *cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
+                       offload = 1;
+
+                       outlen = hdrlen + mp->m_pkthdr.ph_mss;
+                       tcpstat_add(tcps_outpkttso,
+                           (pktlen + outlen - 1) / outlen);
+               } else
+                       tcpstat_inc(tcps_outbadtso);
+       }
+
        return offload;
 }
 
@@ -2529,6 +2566,7 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, 
        struct ixgbe_adv_tx_context_desc *TXD;
        struct ixgbe_tx_buf *tx_buffer;
        uint32_t vlan_macip_lens = 0, type_tucmd_mlhl = 0;
+       uint32_t mss_l4len_idx = 0;
        int     ctxd = txr->next_avail_desc;
        int     offload = 0;
 
@@ -2544,8 +2582,8 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, 
        }
 #endif
 
-       offload |= ixgbe_csum_offload(mp, &vlan_macip_lens, &type_tucmd_mlhl,
-           olinfo_status);
+       offload |= ixgbe_tx_offload(mp, &vlan_macip_lens, &type_tucmd_mlhl,
+           olinfo_status, cmd_type_len, &mss_l4len_idx);
 
        if (!offload)
                return (0);
@@ -2559,7 +2597,7 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, 
        TXD->vlan_macip_lens = htole32(vlan_macip_lens);
        TXD->type_tucmd_mlhl = htole32(type_tucmd_mlhl);
        TXD->seqnum_seed = htole32(0);
-       TXD->mss_l4len_idx = htole32(0);
+       TXD->mss_l4len_idx = htole32(mss_l4len_idx);
 
        tx_buffer->m_head = NULL;
        tx_buffer->eop_index = -1;
@@ -2868,18 +2906,20 @@ ixgbe_initialize_receive_units(struct ix
        }
        IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
 
-       /* Always enable jumbo frame reception */
        hlreg = IXGBE_READ_REG(hw, IXGBE_HLREG0);
+       /* Always enable jumbo frame reception */
        hlreg |= IXGBE_HLREG0_JUMBOEN;
+       /* Always enable CRC stripping */
+       hlreg |= IXGBE_HLREG0_RXCRCSTRP;
        IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg);
 
-       if (ISSET(ifp->if_xflags, IFXF_TSO)) {
+       if (ISSET(ifp->if_xflags, IFXF_LRO)) {
                rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
 
                /* This field has to be set to zero. */
                rdrxctl &= ~IXGBE_RDRXCTL_RSCFRSTSIZE;
 
-               /* Enable TSO Receive Offloading */
+               /* RSC Coalescing on ACK Change */
                rdrxctl |= IXGBE_RDRXCTL_RSCACKC;
                rdrxctl |= IXGBE_RDRXCTL_FCOE_WRFIX;
 
@@ -2902,10 +2942,10 @@ ixgbe_initialize_receive_units(struct ix
                srrctl = bufsz | IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
                IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(i), srrctl);
 
-               if (ISSET(ifp->if_xflags, IFXF_TSO)) {
+               if (ISSET(ifp->if_xflags, IFXF_LRO)) {
                        rdrxctl = IXGBE_READ_REG(&sc->hw, IXGBE_RSCCTL(i));
 
-                       /* Enable TSO Receive Side Coalescing */
+                       /* Enable Receive Side Coalescing */
                        rdrxctl |= IXGBE_RSCCTL_RSCEN;
                        rdrxctl |= IXGBE_RSCCTL_MAXDESC_16;
 
@@ -3263,7 +3303,7 @@ ixgbe_setup_vlan_hw_support(struct ix_so
         * We have to disable VLAN striping when using TCP offloading, due to a
         * firmware bug.
         */
-       if (ISSET(ifp->if_xflags, IFXF_TSO)) {
+       if (ISSET(ifp->if_xflags, IFXF_LRO)) {
                sc->vlan_stripping = 0;
                return;
        }
Index: dev/pci/ixgbe.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/ixgbe.h,v
retrieving revision 1.33
diff -u -p -r1.33 ixgbe.h
--- dev/pci/ixgbe.h     8 Feb 2022 03:38:00 -0000       1.33
+++ dev/pci/ixgbe.h     12 May 2023 20:54:28 -0000
@@ -60,12 +60,18 @@
 
 #include <net/if.h>
 #include <net/if_media.h>
+#include <net/route.h>
 #include <net/toeplitz.h>
 
+struct tdb;
+
 #include <netinet/in.h>
 #include <netinet/if_ether.h>
 #include <netinet/ip.h>
 #include <netinet/ip6.h>
+#include <netinet/tcp.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
 
 #if NBPFILTER > 0
 #include <net/bpf.h>
Index: dev/pci/ixgbe_type.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/ixgbe_type.h,v
retrieving revision 1.36
diff -u -p -r1.36 ixgbe_type.h
--- dev/pci/ixgbe_type.h        9 Jan 2022 05:42:56 -0000       1.36
+++ dev/pci/ixgbe_type.h        12 May 2023 20:54:28 -0000
@@ -3355,6 +3355,7 @@ struct ixgbe_adv_tx_context_desc {
 /* 1st&Last TSO-full iSCSI PDU */
 #define IXGBE_ADVTXD_POPTS_ISCO_FULL   0x00001800
 #define IXGBE_ADVTXD_POPTS_RSV         0x00002000 /* POPTS Reserved */
+#define IXGBE_ADVTXD_PAYLEN_MASK       0x0003FFFF /* Adv desc PAYLEN */
 #define IXGBE_ADVTXD_PAYLEN_SHIFT      14 /* Adv desc PAYLEN shift */
 #define IXGBE_ADVTXD_MACLEN_SHIFT      9  /* Adv ctxt desc mac len shift */
 #define IXGBE_ADVTXD_VLAN_SHIFT                16  /* Adv ctxt vlan tag shift 
*/
Index: net/if.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/if.h,v
retrieving revision 1.211
diff -u -p -r1.211 if.h
--- net/if.h    7 Mar 2023 20:09:48 -0000       1.211
+++ net/if.h    12 May 2023 20:54:28 -0000
@@ -231,7 +231,7 @@ struct if_status_description {
 #define IFXF_INET6_NOSOII      0x40    /* [N] don't do RFC 7217 */
 #define        IFXF_AUTOCONF4          0x80    /* [N] v4 autoconf (aka dhcp) 
enabled */
 #define        IFXF_MONITOR            0x100   /* [N] only used for bpf */
-#define        IFXF_TSO                0x200   /* [N] TCP segment offloading */
+#define        IFXF_LRO                0x200   /* [N] TCP large recv offload */
 
 #define        IFXF_CANTCHANGE \
        (IFXF_MPSAFE|IFXF_CLONED)
@@ -251,11 +251,17 @@ struct if_status_description {
 #define        IFCAP_VLAN_HWTAGGING    0x00000020      /* hardware VLAN tag 
support */
 #define        IFCAP_CSUM_TCPv6        0x00000080      /* can do IPv6/TCP 
checksums */
 #define        IFCAP_CSUM_UDPv6        0x00000100      /* can do IPv6/UDP 
checksums */
-#define        IFCAP_TSO               0x00004000      /* TCP segment 
offloading */
+#define        IFCAP_LRO               0x00001000      /* TCP large recv 
offload */
+#define        IFCAP_TSOv4             0x00002000      /* TCP segmentation 
offload */
+#define        IFCAP_TSOv6             0x00004000      /* TCP segmentation 
offload */
 #define        IFCAP_WOL               0x00008000      /* can do wake on lan */
 
 #define IFCAP_CSUM_MASK                (IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | \
     IFCAP_CSUM_UDPv4 | IFCAP_CSUM_TCPv6 | IFCAP_CSUM_UDPv6)
+
+/* XXX feature flags are misnamed */
+#define IFCAP_TSO      IFCAP_LRO
+#define IFXF_TSO       IFXF_LRO
 
 /* symbolic names for terminal (per-protocol) CTL_IFQ_ nodes */
 #define IFQCTL_LEN 1
Index: net/pf.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v
retrieving revision 1.1178
diff -u -p -r1.1178 pf.c
--- net/pf.c    10 May 2023 12:07:16 -0000      1.1178
+++ net/pf.c    12 May 2023 20:54:28 -0000
@@ -6561,15 +6561,9 @@ pf_route(struct pf_pdesc *pd, struct pf_
                goto done;
        }
 
-       if (ISSET(m0->m_pkthdr.csum_flags, M_TCP_TSO) &&
-           m0->m_pkthdr.ph_mss <= ifp->if_mtu) {
-               if (tcp_chopper(m0, &ml, ifp, m0->m_pkthdr.ph_mss) ||
-                   if_output_ml(ifp, &ml, sintosa(dst), rt))
-                       goto done;
-               tcpstat_inc(tcps_outswtso);
+       if (tcp_if_output_tso(ifp, &m0, sintosa(dst), rt,
+           IFCAP_TSOv4, ifp->if_mtu) || m0 == NULL)
                goto done;
-       }
-       CLR(m0->m_pkthdr.csum_flags, M_TCP_TSO);
 
        /*
         * Too large for interface; fragment if possible.
@@ -6604,7 +6598,6 @@ void
 pf_route6(struct pf_pdesc *pd, struct pf_state *st)
 {
        struct mbuf             *m0;
-       struct mbuf_list         ml;
        struct sockaddr_in6     *dst, sin6;
        struct rtentry          *rt = NULL;
        struct ip6_hdr          *ip6;
@@ -6702,15 +6695,9 @@ pf_route6(struct pf_pdesc *pd, struct pf
                goto done;
        }
 
-       if (ISSET(m0->m_pkthdr.csum_flags, M_TCP_TSO) &&
-           m0->m_pkthdr.ph_mss <= ifp->if_mtu) {
-               if (tcp_chopper(m0, &ml, ifp, m0->m_pkthdr.ph_mss) ||
-                   if_output_ml(ifp, &ml, sin6tosa(dst), rt))
-                       goto done;
-               tcpstat_inc(tcps_outswtso);
+       if (tcp_if_output_tso(ifp, &m0, sin6tosa(dst), rt,
+           IFCAP_TSOv6, ifp->if_mtu) || m0 == NULL)
                goto done;
-       }
-       CLR(m0->m_pkthdr.csum_flags, M_TCP_TSO);
 
        ip6stat_inc(ip6s_cantfrag);
        if (st->rt != PF_DUPTO)
Index: netinet/in.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in.h,v
retrieving revision 1.143
diff -u -p -r1.143 in.h
--- netinet/in.h        10 May 2023 12:07:16 -0000      1.143
+++ netinet/in.h        12 May 2023 20:58:17 -0000
@@ -779,6 +779,7 @@ int    in_broadcast(struct in_addr, u_in
 int       in_canforward(struct in_addr);
 int       in_cksum(struct mbuf *, int);
 int       in4_cksum(struct mbuf *, u_int8_t, int, int);
+void      in_hdr_cksum_out(struct mbuf *, struct ifnet *);
 void      in_proto_cksum_out(struct mbuf *, struct ifnet *);
 int       in_ifcap_cksum(struct mbuf *, struct ifnet *, int);
 void      in_ifdetach(struct ifnet *);
Index: netinet/ip_output.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.385
diff -u -p -r1.385 ip_output.c
--- netinet/ip_output.c 10 May 2023 12:07:16 -0000      1.385
+++ netinet/ip_output.c 12 May 2023 21:18:07 -0000
@@ -467,15 +467,10 @@ sendit:
                goto done;
        }
 
-       if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO) &&
-           m->m_pkthdr.ph_mss <= mtu) {
-               if ((error = tcp_chopper(m, &ml, ifp, m->m_pkthdr.ph_mss)) ||
-                   (error = if_output_ml(ifp, &ml, sintosa(dst), ro->ro_rt)))
-                       goto done;
-               tcpstat_inc(tcps_outswtso);
+       error = tcp_if_output_tso(ifp, &m, sintosa(dst), ro->ro_rt,
+           IFCAP_TSOv4, mtu);
+       if (error || m == NULL)
                goto done;
-       }
-       CLR(m->m_pkthdr.csum_flags, M_TCP_TSO);
 
        /*
         * Too large for interface; fragment if possible.
@@ -1822,6 +1817,21 @@ ip_mloopback(struct ifnet *ifp, struct m
        }
 }
 
+void
+in_hdr_cksum_out(struct mbuf *m, struct ifnet *ifp)
+{
+       struct ip *ip = mtod(m, struct ip *);
+
+       ip->ip_sum = 0;
+       if (ifp && in_ifcap_cksum(m, ifp, IFCAP_CSUM_IPv4)) {
+               SET(m->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT);
+       } else {
+               ipstat_inc(ips_outswcsum);
+               ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
+               CLR(m->m_pkthdr.csum_flags, M_IPV4_CSUM_OUT);
+       }
+}
+
 /*
  *     Compute significant parts of the IPv4 checksum pseudo-header
  *     for use in a delayed TCP/UDP checksum calculation.
@@ -1894,10 +1904,15 @@ in_proto_cksum_out(struct mbuf *m, struc
                u_int16_t csum = 0, offset;
 
                offset = ip->ip_hl << 2;
-               if (m->m_pkthdr.csum_flags & (M_TCP_CSUM_OUT|M_UDP_CSUM_OUT))
+               if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO)) {
+                       csum = in_cksum_phdr(ip->ip_src.s_addr,
+                           ip->ip_dst.s_addr, htonl(ip->ip_p));
+               } else if (ISSET(m->m_pkthdr.csum_flags,
+                   M_TCP_CSUM_OUT|M_UDP_CSUM_OUT)) {
                        csum = in_cksum_phdr(ip->ip_src.s_addr,
                            ip->ip_dst.s_addr, htonl(ntohs(ip->ip_len) -
                            offset + ip->ip_p));
+               }
                if (ip->ip_p == IPPROTO_TCP)
                        offset += offsetof(struct tcphdr, th_sum);
                else if (ip->ip_p == IPPROTO_UDP)
Index: netinet/tcp_output.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_output.c,v
retrieving revision 1.136
diff -u -p -r1.136 tcp_output.c
--- netinet/tcp_output.c        10 May 2023 12:07:16 -0000      1.136
+++ netinet/tcp_output.c        12 May 2023 22:12:25 -0000
@@ -80,6 +80,7 @@
 #include <sys/kernel.h>
 
 #include <net/if.h>
+#include <net/if_var.h>
 #include <net/route.h>
 #if NPF > 0
 #include <net/pfvar.h>
@@ -753,7 +754,7 @@ send:
 
        /* Enable TSO and specify the size of the resulting segments. */
        if (tso) {
-               m->m_pkthdr.csum_flags |= M_TCP_TSO;
+               SET(m->m_pkthdr.csum_flags, M_TCP_TSO);
                m->m_pkthdr.ph_mss = tp->t_maxseg;
        }
 
@@ -1358,5 +1359,47 @@ tcp_chopper(struct mbuf *m0, struct mbuf
  bad:
        tcpstat_inc(tcps_outbadtso);
        ml_purge(ml);
+       return error;
+}
+
+int
+tcp_if_output_tso(struct ifnet *ifp, struct mbuf **mp, struct sockaddr *dst,
+    struct rtentry *rt, uint32_t ifcap, u_int mtu)
+{
+       struct mbuf_list ml;
+       int error;
+
+       /* caller must fail later or fragment */
+       if (!ISSET((*mp)->m_pkthdr.csum_flags, M_TCP_TSO))
+               return 0;
+       if ((*mp)->m_pkthdr.ph_mss > mtu) {
+               CLR((*mp)->m_pkthdr.csum_flags, M_TCP_TSO);
+               return 0;
+       }
+
+       /* network interface hardware will do TSO */
+       if (in_ifcap_cksum(*mp, ifp, ifcap)) {
+               if (ISSET(ifcap, IFCAP_TSOv4)) {
+                       in_hdr_cksum_out(*mp, ifp);
+                       in_proto_cksum_out(*mp, ifp);
+               }
+               if (ISSET(ifcap, IFCAP_TSOv6))
+                       in6_proto_cksum_out(*mp, ifp);
+               if ((error = ifp->if_output(ifp, *mp, dst, rt))) {
+                       tcpstat_inc(tcps_outbadtso);
+                       goto done;
+               }
+               tcpstat_inc(tcps_outhwtso);
+               goto done;
+       }
+
+       /* as fallback do TSO in software */
+       if ((error = tcp_chopper(*mp, &ml, ifp, (*mp)->m_pkthdr.ph_mss)) ||
+           (error = if_output_ml(ifp, &ml, dst, rt)))
+               goto done;
+       tcpstat_inc(tcps_outswtso);
+
+ done:
+       *mp = NULL;
        return error;
 }
Index: netinet/tcp_var.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_var.h,v
retrieving revision 1.164
diff -u -p -r1.164 tcp_var.h
--- netinet/tcp_var.h   10 May 2023 12:07:16 -0000      1.164
+++ netinet/tcp_var.h   12 May 2023 20:54:28 -0000
@@ -719,6 +719,8 @@ struct tcpcb *
 void    tcp_notify(struct inpcb *, int);
 int     tcp_output(struct tcpcb *);
 int     tcp_chopper(struct mbuf *, struct mbuf_list *, struct ifnet *, u_int);
+int     tcp_if_output_tso(struct ifnet *, struct mbuf **, struct sockaddr *,
+           struct rtentry *, uint32_t, u_int);
 void    tcp_pulloutofband(struct socket *, u_int, struct mbuf *, int);
 int     tcp_reass(struct tcpcb *, struct tcphdr *, struct mbuf *, int *);
 void    tcp_rscale(struct tcpcb *, u_long);
Index: netinet6/ip6_output.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.275
diff -u -p -r1.275 ip6_output.c
--- netinet6/ip6_output.c       10 May 2023 12:07:17 -0000      1.275
+++ netinet6/ip6_output.c       12 May 2023 22:11:38 -0000
@@ -706,15 +706,10 @@ reroute:
                goto done;
        }
 
-       if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO) &&
-           m->m_pkthdr.ph_mss <= mtu) {
-               if ((error = tcp_chopper(m, &ml, ifp, m->m_pkthdr.ph_mss)) ||
-                   (error = if_output_ml(ifp, &ml, sin6tosa(dst), ro->ro_rt)))
-                       goto done;
-               tcpstat_inc(tcps_outswtso);
+       error = tcp_if_output_tso(ifp, &m, sin6tosa(dst), ro->ro_rt,
+           IFCAP_TSOv6, mtu);
+       if (error || m == NULL)
                goto done;
-       }
-       CLR(m->m_pkthdr.csum_flags, M_TCP_TSO);
 
        /*
         * try to fragment the packet.  case 1-b
@@ -2715,8 +2710,13 @@ in6_proto_cksum_out(struct mbuf *m, stru
                u_int16_t csum;
 
                offset = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
-               csum = in6_cksum_phdr(&ip6->ip6_src, &ip6->ip6_dst,
-                   htonl(m->m_pkthdr.len - offset), htonl(nxt));
+               if (ISSET(m->m_pkthdr.csum_flags, M_TCP_TSO)) {
+                       csum = in6_cksum_phdr(&ip6->ip6_src, &ip6->ip6_dst,
+                           htonl(0), htonl(nxt));
+               } else {
+                       csum = in6_cksum_phdr(&ip6->ip6_src, &ip6->ip6_dst,
+                           htonl(m->m_pkthdr.len - offset), htonl(nxt));
+               }
                if (nxt == IPPROTO_TCP)
                        offset += offsetof(struct tcphdr, th_sum);
                else if (nxt == IPPROTO_UDP)

Reply via email to