From cd9af87cc16db4939c9de6c62c12d0dded9e6f8c Mon Sep 17 00:00:00 2001 From: jan Date: Tue, 16 May 2023 14:32:54 +0000 Subject: [PATCH] Use separate IFCAPs for LRO and TSO. This diff introduces separate capabilities for TCP offloading. We split this into LRO (large receive offloading) and TSO (TCP segmentation offloading). LRO can be turned on/off via tcprecvoffload option of ifconfig and is not inherited to sub interfaces. TSO is inherited by sub interfaces to signal this hardware offloading capability to the network stack. With tweaks from bluhm, claudio and dlg ok bluhm, claudio --- sbin/ifconfig/ifconfig.8 | 32 +++++++++++++++++++++----------- sbin/ifconfig/ifconfig.c | 10 +++++----- sys/dev/pci/if_ix.c | 14 +++++++------- sys/net/if.c | 35 +++++++++++++++-------------------- sys/net/if.h | 8 ++++---- sys/net/if_aggr.c | 5 ++++- sys/net/if_bridge.c | 6 +++--- sys/net/if_tpmr.c | 4 ++-- sys/net/if_veb.c | 4 ++-- sys/net/if_vlan.c | 30 +++--------------------------- sys/netinet/ip_carp.c | 4 ++-- 11 files changed, 68 insertions(+), 84 deletions(-) diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 index a236971f2b9..c635ede8b4d 100644 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ifconfig.8,v 1.394 2023/04/26 02:38:08 asou Exp $ +.\" $OpenBSD: ifconfig.8,v 1.395 2023/05/16 14:32:54 jan Exp $ .\" $NetBSD: ifconfig.8,v 1.11 1996/01/04 21:27:29 pk Exp $ .\" $FreeBSD: ifconfig.8,v 1.16 1998/02/01 07:03:29 steve Exp $ .\" @@ -31,7 +31,7 @@ .\" .\" @(#)ifconfig.8 8.4 (Berkeley) 6/1/94 .\" -.Dd $Mdocdate: April 26 2023 $ +.Dd $Mdocdate: May 16 2023 $ .Dt IFCONFIG 8 .Os .Sh NAME @@ -282,8 +282,18 @@ tag. As CSUM_TCPv4, but supports IPv6 datagrams. .It Sy CSUM_UDPv6 As above, for UDP. -.It Sy TSO -The device supports TCP segment offloading (TSO). +.It Sy LRO +The device supports TCP large receive offload (LRO). +.It Sy TSOv4 +The device supports IPv4 TCP segmentation offload (TSO). +TSO is used by default. +Use the +.Xr sysctl 8 +variable +.Va net.inet.tcp.tso +to disable this feature. +.It Sy TSOv6 +As above, for IPv6. .It Sy WOL The device supports Wake on LAN (WoL). .It Sy hardmtu @@ -491,25 +501,25 @@ Query and display information and diagnostics from GBIC and SFP modules installed in an interface. It is only supported by drivers implementing the necessary functionality on hardware which supports it. -.It Cm tso -Enable TCP segmentation offloading (TSO) if it's supported by the hardware; see +.It Cm tcprecvoffload +Enable TCP large receive offload (LRO) if it's supported by the hardware; see .Cm hwfeatures . -TSO enabled NICs modify received TCP/IP packets. +LRO enabled network interfaces modify received TCP/IP packets. This will also affect traffic of upper layer interfaces, such as .Xr vlan 4 , .Xr aggr 4 , and .Xr carp 4 . -It is not possible to use TSO with interfaces attached to a +It is not possible to use LRO with interfaces attached to a .Xr bridge 4 , .Xr veb 4 , or .Xr tpmr 4 . Changing this option will re-initialize the network interface. -.It Cm -tso -Disable TSO. -TSO is disabled by default. +.It Cm -tcprecvoffload +Disable LRO. +LRO is disabled by default. .It Cm up Mark an interface .Dq up . diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c index 0785b90f988..5dc9ea641ca 100644 --- a/sbin/ifconfig/ifconfig.c +++ b/sbin/ifconfig/ifconfig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ifconfig.c,v 1.463 2023/05/12 18:24:13 jan Exp $ */ +/* $OpenBSD: ifconfig.c,v 1.464 2023/05/16 14:32:54 jan Exp $ */ /* $NetBSD: ifconfig.c,v 1.40 1997/10/01 02:19:43 enami Exp $ */ /* @@ -126,7 +126,7 @@ #define HWFEATURESBITS \ "\024\1CSUM_IPv4\2CSUM_TCPv4\3CSUM_UDPv4" \ "\5VLAN_MTU\6VLAN_HWTAGGING\10CSUM_TCPv6" \ - "\11CSUM_UDPv6\17TSO\20WOL" + "\11CSUM_UDPv6\15TSOv4\16TSOv6\17LRO\20WOL" struct ifencap { unsigned int ife_flags; @@ -469,8 +469,8 @@ const struct cmd { { "-soii", IFXF_INET6_NOSOII, 0, setifxflags }, { "monitor", IFXF_MONITOR, 0, setifxflags }, { "-monitor", -IFXF_MONITOR, 0, setifxflags }, - { "tso", IFXF_TSO, 0, setifxflags }, - { "-tso", -IFXF_TSO, 0, setifxflags }, + { "tcprecvoffload", IFXF_LRO, 0, setifxflags }, + { "-tcprecvoffload", -IFXF_LRO, 0, setifxflags }, #ifndef SMALL { "hwfeatures", NEXTARG0, 0, printifhwfeatures }, { "metric", NEXTARG, 0, setifmetric }, @@ -674,7 +674,7 @@ const struct cmd { "\7RUNNING\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX" \ "\15LINK0\16LINK1\17LINK2\20MULTICAST" \ "\23AUTOCONF6TEMP\24MPLS\25WOL\26AUTOCONF6\27INET6_NOSOII" \ - "\30AUTOCONF4" "\31MONITOR" "\32TSO" + "\30AUTOCONF4" "\31MONITOR" "\32LRO" int getinfo(struct ifreq *, int); void getsock(int); diff --git a/sys/dev/pci/if_ix.c b/sys/dev/pci/if_ix.c index 870c3349fb3..8bf3ef49429 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.193 2023/04/28 10:18:57 bluhm Exp $ */ +/* $OpenBSD: if_ix.c,v 1.194 2023/05/16 14:32:54 jan Exp $ */ /****************************************************************************** @@ -1925,7 +1925,7 @@ ixgbe_setup_interface(struct ix_softc *sc) ifp->if_capabilities |= IFCAP_CSUM_IPv4; 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 @@ -2873,13 +2873,13 @@ ixgbe_initialize_receive_units(struct ix_softc *sc) hlreg |= IXGBE_HLREG0_JUMBOEN; 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 +2902,10 @@ ixgbe_initialize_receive_units(struct ix_softc *sc) 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 +3263,7 @@ ixgbe_setup_vlan_hw_support(struct ix_softc *sc) * 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; } diff --git a/sys/net/if.c b/sys/net/if.c index 855e5dfc9b4..ae1069b405a 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.696 2023/05/14 01:46:53 dlg Exp $ */ +/* $OpenBSD: if.c,v 1.697 2023/05/16 14:32:54 jan Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -2109,10 +2109,9 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p) error = ENOTSUP; } #endif - - if (ISSET(ifr->ifr_flags, IFXF_TSO) != - ISSET(ifp->if_xflags, IFXF_TSO)) - error = ifsettso(ifp, ISSET(ifr->ifr_flags, IFXF_TSO)); + if (ISSET(ifr->ifr_flags, IFXF_LRO) != + ISSET(ifp->if_xflags, IFXF_LRO)) + error = ifsetlro(ifp, ISSET(ifr->ifr_flags, IFXF_LRO)); if (error == 0) ifp->if_xflags = (ifp->if_xflags & IFXF_CANTCHANGE) | @@ -3153,37 +3152,33 @@ ifpromisc(struct ifnet *ifp, int pswitch) return (error); } -/* Set/clear TSO flag and restart interface if needed. */ +/* Set/clear LRO flag and restart interface if needed. */ int -ifsettso(struct ifnet *ifp, int on) +ifsetlro(struct ifnet *ifp, int on) { struct ifreq ifrq; int error = 0; int s = splnet(); + if (!ISSET(ifp->if_capabilities, IFCAP_LRO)) { + error = ENOTSUP; + goto out; + } + NET_ASSERT_LOCKED(); /* for ioctl */ KERNEL_ASSERT_LOCKED(); /* for if_flags */ - if (on && !ISSET(ifp->if_xflags, IFXF_TSO)) { - if (!ISSET(ifp->if_capabilities, IFCAP_TSO)) { - error = ENOTSUP; - goto out; - } + if (on && !ISSET(ifp->if_xflags, IFXF_LRO)) { if (ether_brport_isset(ifp)) { error = EBUSY; goto out; } - SET(ifp->if_xflags, IFXF_TSO); - } else if (!on && ISSET(ifp->if_xflags, IFXF_TSO)) - CLR(ifp->if_xflags, IFXF_TSO); + SET(ifp->if_xflags, IFXF_LRO); + } else if (!on && ISSET(ifp->if_xflags, IFXF_LRO)) + CLR(ifp->if_xflags, IFXF_LRO); else goto out; -#if NVLAN > 0 - /* Change TSO flag also on attached vlan(4) interfaces. */ - vlan_flags_from_parent(ifp, IFXF_TSO); -#endif - /* restart interface */ if (ISSET(ifp->if_flags, IFF_UP)) { /* go down for a moment... */ diff --git a/sys/net/if.h b/sys/net/if.h index c8c7ec5f03f..189ce873c12 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if.h,v 1.212 2023/05/15 16:34:56 bluhm Exp $ */ +/* $OpenBSD: if.h,v 1.213 2023/05/16 14:32:54 jan Exp $ */ /* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */ /* @@ -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] XXX missnamed, should be LRO */ +#define IFXF_LRO 0x200 /* [N] TCP large recv offload */ #define IFXF_CANTCHANGE \ (IFXF_MPSAFE|IFXF_CLONED) @@ -253,7 +253,7 @@ struct if_status_description { #define IFCAP_CSUM_UDPv6 0x00000100 /* can do IPv6/UDP checksums */ #define IFCAP_TSOv4 0x00001000 /* IPv4/TCP segment offload */ #define IFCAP_TSOv6 0x00002000 /* IPv6/TCP segment offload */ -#define IFCAP_TSO 0x00004000 /* XXX should be LRO */ +#define IFCAP_LRO 0x00004000 /* TCP large recv offload */ #define IFCAP_WOL 0x00008000 /* can do wake on lan */ #define IFCAP_CSUM_MASK (IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | \ @@ -546,7 +546,7 @@ void if_getdata(struct ifnet *, struct if_data *); void ifinit(void); int ifioctl(struct socket *, u_long, caddr_t, struct proc *); int ifpromisc(struct ifnet *, int); -int ifsettso(struct ifnet *, int); +int ifsetlro(struct ifnet *, int); struct ifg_group *if_creategroup(const char *); int if_addgroup(struct ifnet *, const char *); int if_delgroup(struct ifnet *, const char *); diff --git a/sys/net/if_aggr.c b/sys/net/if_aggr.c index a7a5ac9d7ea..5240643d93d 100644 --- a/sys/net/if_aggr.c +++ b/sys/net/if_aggr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_aggr.c,v 1.39 2022/02/05 03:56:16 dlg Exp $ */ +/* $OpenBSD: if_aggr.c,v 1.40 2023/05/16 14:32:54 jan Exp $ */ /* * Copyright (c) 2019 The University of Queensland @@ -2618,6 +2618,9 @@ aggr_update_capabilities(struct aggr_softc *sc) uint32_t capabilities = ~0; int set = 0; + /* Do not inherit LRO capabilities. */ + CLR(capabilities, IFCAP_LRO); + rw_enter_read(&sc->sc_lock); TAILQ_FOREACH(p, &sc->sc_ports, p_entry) { struct ifnet *ifp0 = p->p_ifp0; diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index a5ad2281a70..486b041bcfb 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bridge.c,v 1.367 2023/05/13 13:35:17 bluhm Exp $ */ +/* $OpenBSD: if_bridge.c,v 1.368 2023/05/16 14:32:54 jan Exp $ */ /* * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) @@ -338,7 +338,7 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) */ NET_LOCK(); - ifsettso(ifs, 0); + ifsetlro(ifs, 0); NET_UNLOCK(); bif->bridge_sc = sc; @@ -401,7 +401,7 @@ bridge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } NET_LOCK(); - ifsettso(ifs, 0); + ifsetlro(ifs, 0); NET_UNLOCK(); bif->bridge_sc = sc; diff --git a/sys/net/if_tpmr.c b/sys/net/if_tpmr.c index 9f2b2dec125..47bb4e5caa8 100644 --- a/sys/net/if_tpmr.c +++ b/sys/net/if_tpmr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_tpmr.c,v 1.32 2023/02/27 09:35:32 jan Exp $ */ +/* $OpenBSD: if_tpmr.c,v 1.33 2023/05/16 14:32:54 jan Exp $ */ /* * Copyright (c) 2019 The University of Queensland @@ -521,7 +521,7 @@ tpmr_add_port(struct tpmr_softc *sc, const struct ifbreq *req) goto put; } - ifsettso(ifp0, 0); + ifsetlro(ifp0, 0); p->p_ifp0 = ifp0; p->p_tpmr = sc; diff --git a/sys/net/if_veb.c b/sys/net/if_veb.c index c5f865b7154..df405678fa3 100644 --- a/sys/net/if_veb.c +++ b/sys/net/if_veb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_veb.c,v 1.30 2023/02/27 09:35:32 jan Exp $ */ +/* $OpenBSD: if_veb.c,v 1.31 2023/05/16 14:32:54 jan Exp $ */ /* * Copyright (c) 2021 David Gwynne @@ -1465,7 +1465,7 @@ veb_add_port(struct veb_softc *sc, const struct ifbreq *req, unsigned int span) goto put; } - ifsettso(ifp0, 0); + ifsetlro(ifp0, 0); p->p_ifp0 = ifp0; p->p_veb = sc; diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index 86bb5a757c9..d660232deb4 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vlan.c,v 1.214 2023/04/26 00:14:21 jan Exp $ */ +/* $OpenBSD: if_vlan.c,v 1.215 2023/05/16 14:32:54 jan Exp $ */ /* * Copyright 1998 Massachusetts Institute of Technology @@ -536,7 +536,8 @@ vlan_up(struct vlan_softc *sc) * Chips that can do hardware-assisted VLAN encapsulation, can * calculate the correct checksum for VLAN tagged packets. */ - ifp->if_capabilities = ifp0->if_capabilities & IFCAP_CSUM_MASK; + ifp->if_capabilities = ifp0->if_capabilities & + (IFCAP_CSUM_MASK | IFCAP_TSOv4 | IFCAP_TSOv6); } /* commit the sc */ @@ -560,9 +561,6 @@ vlan_up(struct vlan_softc *sc) /* configure the parent to handle packets for this vlan */ vlan_multi_apply(sc, ifp0, SIOCADDMULTI); - /* Inherit flags from parent interface. */ - vlan_flags_from_parent(ifp0, IFXF_TSO); - /* we're running now */ SET(ifp->if_flags, IFF_RUNNING); vlan_link_state(sc, ifp0->if_link_state, ifp0->if_baudrate); @@ -965,28 +963,6 @@ vlan_del_parent(struct vlan_softc *sc) return (0); } -void -vlan_flags_from_parent(struct ifnet *ifp0, int flags) -{ - struct vlan_softc *sc; - int i; - - for (i = 0; i < TAG_HASH_SIZE; i++) { - SMR_SLIST_FOREACH_LOCKED(sc, &vlan_tagh[i], sc_list) { - /* vlan and tso only works with hw tagging */ - if (!ISSET(ifp0->if_capabilities, IFCAP_VLAN_HWTAGGING)) - CLR(flags, IFXF_TSO); - - if (sc->sc_ifidx0 == ifp0->if_index) { - if (ISSET(ifp0->if_xflags, flags)) - SET(sc->sc_if.if_xflags, flags); - else - CLR(sc->sc_if.if_xflags, flags); - } - } - } -} - int vlan_set_compat(struct ifnet *ifp, struct ifreq *ifr) { diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index 519de95e450..064c4424910 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_carp.c,v 1.356 2023/03/08 04:43:09 guenther Exp $ */ +/* $OpenBSD: ip_carp.c,v 1.357 2023/05/16 14:32:54 jan Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff. All rights reserved. @@ -1693,7 +1693,7 @@ carp_set_ifp(struct carp_softc *sc, struct ifnet *ifp0) sc->sc_carpdevidx = ifp0->if_index; sc->sc_if.if_capabilities = ifp0->if_capabilities & - IFCAP_CSUM_MASK; + (IFCAP_CSUM_MASK | IFCAP_TSOv4 | IFCAP_TSOv6); SRPL_FOREACH_LOCKED(vr, cif, sc_list) { struct carp_vhost_entry *vrhead, *schead; -- 2.20.1