Hi, Claudio@ mentioned the idea to use TSO and LRO on the loopback interface to transfer TCP faster.
I see a performance effect with this diff, but more importantly it gives us more test coverage. Currently LRO on lo(4) is default off. Future plan is: - Fix some corner cases for LRO/TSO with TCP path-MTU discovery and IP forwarding when LRO is enabled. - Enable LRO/TSO for lo(4) and ix(4) per default. - Jan@ commits his ixl(4) TSO diff. ok for lo(4) LRO/TSO with default off? bluhm Index: sys/net/if.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/net/if.c,v retrieving revision 1.700 diff -u -p -r1.700 if.c --- sys/net/if.c 12 Jun 2023 21:19:54 -0000 1.700 +++ sys/net/if.c 23 Jun 2023 15:48:27 -0000 @@ -106,6 +106,9 @@ #ifdef MROUTING #include <netinet/ip_mroute.h> #endif +#include <netinet/tcp.h> +#include <netinet/tcp_timer.h> +#include <netinet/tcp_var.h> #ifdef INET6 #include <netinet6/in6_var.h> @@ -802,12 +805,29 @@ if_input_local(struct ifnet *ifp, struct * is now incorrect, will be calculated before sending. */ keepcksum = m->m_pkthdr.csum_flags & (M_IPV4_CSUM_OUT | - M_TCP_CSUM_OUT | M_UDP_CSUM_OUT | M_ICMP_CSUM_OUT); + M_TCP_CSUM_OUT | M_UDP_CSUM_OUT | M_ICMP_CSUM_OUT | + M_TCP_TSO); m_resethdr(m); m->m_flags |= M_LOOP | keepflags; m->m_pkthdr.csum_flags = keepcksum; m->m_pkthdr.ph_ifidx = ifp->if_index; m->m_pkthdr.ph_rtableid = ifp->if_rdomain; + + if (ISSET(keepcksum, M_TCP_TSO) && m->m_pkthdr.len > ifp->if_mtu) { + if (ifp->if_mtu > 0 && + ((af == AF_INET && + ISSET(ifp->if_capabilities, IFCAP_TSOv4)) || + (af == AF_INET6 && + ISSET(ifp->if_capabilities, IFCAP_TSOv6)))) { + tcpstat_inc(tcps_inswlro); + tcpstat_add(tcps_inpktlro, + (m->m_pkthdr.len + ifp->if_mtu - 1) / ifp->if_mtu); + } else { + tcpstat_inc(tcps_inbadlro); + m_freem(m); + return (EPROTONOSUPPORT); + } + } if (ISSET(keepcksum, M_TCP_CSUM_OUT)) m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK; Index: sys/net/if_loop.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/net/if_loop.c,v retrieving revision 1.94 diff -u -p -r1.94 if_loop.c --- sys/net/if_loop.c 5 Jun 2023 11:35:46 -0000 1.94 +++ sys/net/if_loop.c 23 Jun 2023 15:48:27 -0000 @@ -175,7 +175,8 @@ loop_clone_create(struct if_clone *ifc, ifp->if_xflags = IFXF_CLONED; ifp->if_capabilities = IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4 | - IFCAP_CSUM_TCPv6 | IFCAP_CSUM_UDPv6; + IFCAP_CSUM_TCPv6 | IFCAP_CSUM_UDPv6 | + IFCAP_LRO; ifp->if_rtrequest = lortrequest; ifp->if_ioctl = loioctl; ifp->if_input = loinput; @@ -281,6 +282,10 @@ loioctl(struct ifnet *ifp, u_long cmd, c switch (cmd) { case SIOCSIFFLAGS: + if (ISSET(ifp->if_xflags, IFXF_LRO)) + SET(ifp->if_capabilities, IFCAP_TSOv4 | IFCAP_TSOv6); + else + CLR(ifp->if_capabilities, IFCAP_TSOv4 | IFCAP_TSOv6); break; case SIOCSIFADDR: Index: sys/netinet/tcp_usrreq.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_usrreq.c,v retrieving revision 1.219 diff -u -p -r1.219 tcp_usrreq.c --- sys/netinet/tcp_usrreq.c 23 May 2023 09:16:16 -0000 1.219 +++ sys/netinet/tcp_usrreq.c 23 Jun 2023 15:48:27 -0000 @@ -1340,6 +1340,7 @@ tcp_sysctl_tcpstat(void *oldp, size_t *o ASSIGN(tcps_outhwtso); ASSIGN(tcps_outpkttso); ASSIGN(tcps_outbadtso); + ASSIGN(tcps_inswlro); ASSIGN(tcps_inhwlro); ASSIGN(tcps_inpktlro); ASSIGN(tcps_inbadlro); Index: sys/netinet/tcp_var.h =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_var.h,v retrieving revision 1.167 diff -u -p -r1.167 tcp_var.h --- sys/netinet/tcp_var.h 23 May 2023 09:16:16 -0000 1.167 +++ sys/netinet/tcp_var.h 23 Jun 2023 15:48:27 -0000 @@ -447,6 +447,7 @@ struct tcpstat { u_int32_t tcps_outhwtso; /* output tso processed by hardware */ u_int32_t tcps_outpkttso; /* packets generated by tso */ u_int32_t tcps_outbadtso; /* output tso failed, packet dropped */ + u_int32_t tcps_inswlro; /* input lro on pseudo device */ u_int32_t tcps_inhwlro; /* input lro from hardware */ u_int32_t tcps_inpktlro; /* packets coalesced by hardware lro */ u_int32_t tcps_inbadlro; /* input bad lro packets */ @@ -628,6 +629,7 @@ enum tcpstat_counters { tcps_outhwtso, tcps_outpkttso, tcps_outbadtso, + tcps_inswlro, tcps_inhwlro, tcps_inpktlro, tcps_inbadlro, Index: usr.bin/netstat/inet.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/usr.bin/netstat/inet.c,v retrieving revision 1.176 diff -u -p -r1.176 inet.c --- usr.bin/netstat/inet.c 23 May 2023 09:16:16 -0000 1.176 +++ usr.bin/netstat/inet.c 23 Jun 2023 15:55:55 -0000 @@ -439,9 +439,12 @@ tcp_stats(char *name) p(tcps_inswcsum, "\t\t%u packet%s software-checksummed\n"); p(tcps_rcvbadsig, "\t\t%u bad/missing md5 checksum%s\n"); p(tcps_rcvgoodsig, "\t\t%llu good md5 checksum%s\n"); + p(tcps_inswlro, + "\t\t%u input LRO packet%s passed through pseudo device\n"); p(tcps_inhwlro, "\t\t%u input LRO generated packet%s from hardware\n"); - p(tcps_inpktlro, "\t\t%u input LRO coalesced packet%s by hardware\n"); - p(tcps_inbadlro, "\t\t%u input bad LRO packet%s\n"); + p(tcps_inpktlro, + "\t\t%u input LRO coalesced packet%s by network device\n"); + p(tcps_inbadlro, "\t\t%u input bad LRO packet%s dropped\n"); p(tcps_connattempt, "\t%u connection request%s\n"); p(tcps_accepts, "\t%u connection accept%s\n"); p(tcps_connects, "\t%u connection%s established (including accepts)\n");