Enable forwarding of ix(4) LRO Pakets via TSO
authorjan <jan@openbsd.org>
Thu, 1 Jun 2023 09:05:33 +0000 (09:05 +0000)
committerjan <jan@openbsd.org>
Thu, 1 Jun 2023 09:05:33 +0000 (09:05 +0000)
Also fix ip6_forwarding of TSO packets with tcp_if_output_tso().

With a lot of testing from Hrvoje Popovski
and a lot of tweaks from bluhm@

ok bluhm@

sys/dev/pci/if_ix.c
sys/netinet6/ip6_forward.c

index 98815b5..b250ee4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_ix.c,v 1.196 2023/05/23 09:16:16 jan Exp $ */
+/*     $OpenBSD: if_ix.c,v 1.197 2023/06/01 09:05:33 jan Exp $ */
 
 /******************************************************************************
 
@@ -3245,6 +3245,8 @@ ixgbe_rxeof(struct rx_ring *rxr)
                        sendmp = NULL;
                        mp->m_next = nxbuf->buf;
                } else { /* Sending this frame? */
+                       uint16_t pkts;
+
                        ixgbe_rx_checksum(staterr, sendmp);
 
                        if (hashtype != IXGBE_RXDADV_RSSTYPE_NONE) {
@@ -3252,19 +3254,45 @@ ixgbe_rxeof(struct rx_ring *rxr)
                                SET(sendmp->m_pkthdr.csum_flags, M_FLOWID);
                        }
 
-                       if (sendmp->m_pkthdr.ph_mss == 1)
-                               sendmp->m_pkthdr.ph_mss = 0;
+                       pkts = sendmp->m_pkthdr.ph_mss;
+                       sendmp->m_pkthdr.ph_mss = 0;
 
-                       if (sendmp->m_pkthdr.ph_mss > 0) {
+                       if (pkts > 1) {
                                struct ether_extracted ext;
-                               uint16_t pkts = sendmp->m_pkthdr.ph_mss;
+                               uint32_t hdrlen, paylen;
 
+                               /* Calculate header size. */
                                ether_extract_headers(sendmp, &ext);
-                               if (ext.tcp)
+                               hdrlen = sizeof(*ext.eh);
+                               if (ext.ip4)
+                                       hdrlen += ext.ip4->ip_hl << 2;
+                               if (ext.ip6)
+                                       hdrlen += sizeof(*ext.ip6);
+                               if (ext.tcp) {
+                                       hdrlen += ext.tcp->th_off << 2;
                                        tcpstat_inc(tcps_inhwlro);
-                               else
+                                       tcpstat_add(tcps_inpktlro, pkts);
+                               } else {
                                        tcpstat_inc(tcps_inbadlro);
-                               tcpstat_add(tcps_inpktlro, pkts);
+                               }
+
+                               /*
+                                * If we gonna forward this packet, we have to
+                                * mark it as TSO, set a correct mss,
+                                * and recalculate the TCP checksum.
+                                */
+                               paylen = sendmp->m_pkthdr.len - hdrlen;
+                               if (ext.tcp && paylen >= pkts) {
+                                       SET(sendmp->m_pkthdr.csum_flags,
+                                           M_TCP_TSO);
+                                       sendmp->m_pkthdr.ph_mss = paylen / pkts;
+                               }
+                               if (ext.tcp &&
+                                   ISSET(sendmp->m_pkthdr.csum_flags,
+                                   M_TCP_CSUM_IN_OK)) {
+                                       SET(sendmp->m_pkthdr.csum_flags,
+                                           M_TCP_CSUM_OUT);
+                               }
                        }
 
                        ml_enqueue(&ml, sendmp);
index 56c6dd9..85a7e91 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip6_forward.c,v 1.109 2023/04/05 13:56:31 kn Exp $    */
+/*     $OpenBSD: ip6_forward.c,v 1.110 2023/06/01 09:05:33 jan Exp $   */
 /*     $KAME: ip6_forward.c,v 1.75 2001/06/29 12:42:13 jinmei Exp $    */
 
 /*
 #include <netinet/ip_ah.h>
 #include <netinet/ip_esp.h>
 #include <netinet/udp.h>
-#include <netinet/tcp.h>
 #endif
+#include <netinet/tcp.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
 
 /*
  * Forward a packet.  If some error occurs return the sender
@@ -316,7 +318,11 @@ reroute:
                goto reroute;
        }
 #endif
-       in6_proto_cksum_out(m, ifp);
+
+       error = tcp_if_output_tso(ifp, &m, sin6tosa(sin6), rt, IFCAP_TSOv6,
+           ifp->if_mtu);
+       if (error || m == NULL)
+               goto freecopy;
 
        /* Check the size after pf_test to give pf a chance to refragment. */
        if (m->m_pkthdr.len > ifp->if_mtu) {
@@ -327,6 +333,7 @@ reroute:
                goto out;
        }
 
+       in6_proto_cksum_out(m, ifp);
        error = ifp->if_output(ifp, m, sin6tosa(sin6), rt);
        if (error) {
                ip6stat_inc(ip6s_cantforward);