Use separate IFCAPs for LRO and TSO.
authorjan <jan@openbsd.org>
Tue, 16 May 2023 14:32:54 +0000 (14:32 +0000)
committerjan <jan@openbsd.org>
Tue, 16 May 2023 14:32:54 +0000 (14:32 +0000)
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
sbin/ifconfig/ifconfig.c
sys/dev/pci/if_ix.c
sys/net/if.c
sys/net/if.h
sys/net/if_aggr.c
sys/net/if_bridge.c
sys/net/if_tpmr.c
sys/net/if_veb.c
sys/net/if_vlan.c
sys/netinet/ip_carp.c

index a236971..c635ede 100644 (file)
@@ -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 .
index 0785b90..5dc9ea6 100644 (file)
@@ -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 $      */
 
 /*
 #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);
index 870c334..8bf3ef4 100644 (file)
@@ -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;
        }
index 855e5df..ae1069b 100644 (file)
@@ -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... */
index c8c7ec5..189ce87 100644 (file)
@@ -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 *);
index a7a5ac9..5240643 100644 (file)
@@ -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;
index a5ad228..486b041 100644 (file)
@@ -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;
index 9f2b2de..47bb4e5 100644 (file)
@@ -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;
index c5f865b..df40567 100644 (file)
@@ -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 <dlg@openbsd.org>
@@ -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;
index 86bb5a7..d660232 100644 (file)
@@ -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)
 {
index 519de95..064c442 100644 (file)
@@ -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;