From f3378d78b5d0bc06ce577390d250d05225f9c875 Mon Sep 17 00:00:00 2001 From: jan Date: Thu, 1 Jun 2023 09:05:33 +0000 Subject: [PATCH] Enable forwarding of ix(4) LRO Pakets via TSO 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 | 44 +++++++++++++++++++++++++++++++------- sys/netinet6/ip6_forward.c | 13 ++++++++--- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/sys/dev/pci/if_ix.c b/sys/dev/pci/if_ix.c index 98815b51d62..b250ee48df8 100644 --- a/sys/dev/pci/if_ix.c +++ b/sys/dev/pci/if_ix.c @@ -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); diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c index 56c6dd93b49..85a7e913406 100644 --- a/sys/netinet6/ip6_forward.c +++ b/sys/netinet6/ip6_forward.c @@ -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 $ */ /* @@ -63,8 +63,10 @@ #include #include #include -#include #endif +#include +#include +#include /* * 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); -- 2.20.1