Introduce Large Receive Offloading of TCP segment offloading for ix(4). It is
authorjan <jan@openbsd.org>
Mon, 27 Jun 2022 15:11:23 +0000 (15:11 +0000)
committerjan <jan@openbsd.org>
Mon, 27 Jun 2022 15:11:23 +0000 (15:11 +0000)
disabled by default.  Also add a tso option to ifconfig(8) to enable and
disable this feature.

ok deraadt

sbin/ifconfig/ifconfig.8
sbin/ifconfig/ifconfig.c
sys/dev/pci/if_ix.c
sys/dev/pci/if_ix.h
sys/net/if.c
sys/net/if.h

index cc5a699..4daccdb 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: ifconfig.8,v 1.382 2022/05/14 07:22:10 denis Exp $
+.\"    $OpenBSD: ifconfig.8,v 1.383 2022/06/27 15:11:23 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: May 14 2022 $
+.Dd $Mdocdate: June 27 2022 $
 .Dt IFCONFIG 8
 .Os
 .Sh NAME
@@ -279,6 +279,8 @@ 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 WOL
 The device supports Wake on LAN (WoL).
 .It Sy hardmtu
@@ -486,6 +488,22 @@ 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 its supported by the hardware; see
+.Cm hwfeatures .
+TSO enabled NICs modify received TCP/IP packets.
+This will also affect traffic of upper layer interfaces
+.Po
+e.g.,
+.Xr vlan 4 ,
+.Xr aggr 4 ,
+.Xr carp 4 ,
+etc.
+.Pc .
+Changing this option will re-initialize the network interface.
+.It Cm -tso
+Disable TSO.
+TSO is disabled by default.
 .It Cm up
 Mark an interface
 .Dq up .
index ed05d8f..ea3b29d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ifconfig.c,v 1.454 2022/04/07 16:41:13 naddy Exp $    */
+/*     $OpenBSD: ifconfig.c,v 1.455 2022/06/27 15:11:23 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\20WOL"
+       "\11CSUM_UDPv6\17TSO\20WOL"
 
 struct ifencap {
        unsigned int     ife_flags;
@@ -470,6 +470,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 },
 #ifndef SMALL
        { "hwfeatures", NEXTARG0,       0,              printifhwfeatures },
        { "metric",     NEXTARG,        0,              setifmetric },
@@ -673,7 +675,7 @@ const struct        cmd {
        "\7RUNNING\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX"    \
        "\15LINK0\16LINK1\17LINK2\20MULTICAST"                          \
        "\23AUTOCONF6TEMP\24MPLS\25WOL\26AUTOCONF6\27INET6_NOSOII"      \
-       "\30AUTOCONF4" "\31MONITOR"
+       "\30AUTOCONF4" "\31MONITOR" "\32TSO"
 
 int    getinfo(struct ifreq *, int);
 void   getsock(int);
index 924b605..cb23303 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_ix.c,v 1.185 2022/03/15 11:22:10 jan Exp $ */
+/*     $OpenBSD: if_ix.c,v 1.186 2022/06/27 15:11:23 jan Exp $ */
 
 /******************************************************************************
 
@@ -160,8 +160,6 @@ void        ixgbe_dma_free(struct ix_softc *, struct ixgbe_dma_alloc *);
 static int
        ixgbe_tx_ctx_setup(struct tx_ring *, struct mbuf *, uint32_t *,
            uint32_t *);
-int    ixgbe_tso_setup(struct tx_ring *, struct mbuf *, uint32_t *,
-           uint32_t *);
 void   ixgbe_set_ivar(struct ix_softc *, uint8_t, uint8_t, int8_t);
 void   ixgbe_configure_ivars(struct ix_softc *);
 uint8_t        *ixgbe_mc_array_itr(struct ixgbe_hw *, uint8_t **, uint32_t *);
@@ -1924,6 +1922,9 @@ ixgbe_setup_interface(struct ix_softc *sc)
        ifp->if_capabilities |= IFCAP_CSUM_TCPv6 | IFCAP_CSUM_UDPv6;
        ifp->if_capabilities |= IFCAP_CSUM_IPv4;
 
+       if (sc->hw.mac.type != ixgbe_mac_82598EB)
+               ifp->if_capabilities |= IFCAP_TSO;
+
        /*
         * Specify the media types supported by this sc and register
         * callbacks to update media and link information
@@ -2868,9 +2869,10 @@ fail:
 void
 ixgbe_initialize_receive_units(struct ix_softc *sc)
 {
+       struct ifnet    *ifp = &sc->arpcom.ac_if;
        struct rx_ring  *rxr = sc->rx_rings;
        struct ixgbe_hw *hw = &sc->hw;
-       uint32_t        bufsz, fctrl, srrctl, rxcsum;
+       uint32_t        bufsz, fctrl, srrctl, rxcsum, rdrxctl;
        uint32_t        hlreg;
        int             i;
 
@@ -2894,6 +2896,19 @@ 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)) {
+               rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
+
+               /* This field has to be set to zero. */
+               rdrxctl &= ~IXGBE_RDRXCTL_RSCFRSTSIZE;
+
+               /* Enable TSO Receive Offloading */
+               rdrxctl |= IXGBE_RDRXCTL_RSCACKC;
+               rdrxctl |= IXGBE_RDRXCTL_FCOE_WRFIX;
+
+               IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
+       }
+
        bufsz = (sc->rx_mbuf_sz - ETHER_ALIGN) >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
 
        for (i = 0; i < sc->num_queues; i++, rxr++) {
@@ -2910,6 +2925,16 @@ 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)) {
+                       rdrxctl = IXGBE_READ_REG(&sc->hw, IXGBE_RSCCTL(i));
+
+                       /* Enable TSO Receive Side Coalescing */
+                       rdrxctl |= IXGBE_RSCCTL_RSCEN;
+                       rdrxctl |= IXGBE_RSCCTL_MAXDESC_16;
+
+                       IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(i), rdrxctl);
+               }
+
                /* Setup the HW Rx Head and Tail Descriptor Pointers */
                IXGBE_WRITE_REG(hw, IXGBE_RDH(i), 0);
                IXGBE_WRITE_REG(hw, IXGBE_RDT(i), 0);
@@ -3175,7 +3200,7 @@ ixgbe_rxeof(struct rx_ring *rxr)
                        sendmp = mp;
                        sendmp->m_pkthdr.len = mp->m_len;
 #if NVLAN > 0
-                       if (staterr & IXGBE_RXD_STAT_VP) {
+                       if (sc->vlan_stripping && staterr & IXGBE_RXD_STAT_VP) {
                                sendmp->m_pkthdr.ether_vtag = vtag;
                                sendmp->m_flags |= M_VLANTAG;
                        }
@@ -3248,8 +3273,20 @@ ixgbe_rx_checksum(uint32_t staterr, struct mbuf * mp, uint32_t ptype)
 void
 ixgbe_setup_vlan_hw_support(struct ix_softc *sc)
 {
-       uint32_t        ctrl;
-       int             i;
+       struct ifnet    *ifp = &sc->arpcom.ac_if;
+       uint32_t         ctrl;
+       int              i;
+
+       /*
+        * We have to disable VLAN striping when using TCP offloading, due to a
+        * firmware bug.
+        */
+       if (ISSET(ifp->if_xflags, IFXF_TSO)) {
+               sc->vlan_stripping = 0;
+               return;
+       }
+
+       sc->vlan_stripping = 1;
 
        /*
         * A soft reset zero's out the VFTA, so
index fdae408..41d7561 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_ix.h,v 1.44 2022/01/09 05:42:52 jsg Exp $  */
+/*     $OpenBSD: if_ix.h,v 1.45 2022/06/27 15:11:23 jan Exp $  */
 
 /******************************************************************************
 
@@ -225,6 +225,7 @@ struct ix_softc {
        struct ifmedia          media;
        struct intrmap          *sc_intrmap;
        int                     if_flags;
+       int                     vlan_stripping;
 
        uint16_t                num_vlans;
        uint16_t                num_queues;
index 58af573..c12943d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if.c,v 1.653 2022/06/07 22:18:34 sashan Exp $ */
+/*     $OpenBSD: if.c,v 1.654 2022/06/27 15:11:23 jan Exp $    */
 /*     $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $  */
 
 /*
@@ -2019,6 +2019,38 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p)
                        ifr->ifr_flags &= ~IFXF_WOL;
                        error = ENOTSUP;
                }
+
+               if (ISSET(ifp->if_capabilities, IFCAP_TSO) &&
+                   ISSET(ifr->ifr_flags, IFXF_TSO) !=
+                   ISSET(ifp->if_xflags, IFXF_TSO)) {
+                       struct ifreq ifrq;
+
+                       s = splnet();
+
+                       if (ISSET(ifr->ifr_flags, IFXF_TSO))
+                               ifp->if_xflags |= IFXF_TSO;
+                       else
+                               ifp->if_xflags &= ~IFXF_TSO;
+
+                       NET_ASSERT_LOCKED();    /* for ioctl */
+                       KERNEL_ASSERT_LOCKED(); /* for if_flags */
+
+                       if (ISSET(ifp->if_flags, IFF_UP)) {
+                               /* go down for a moment... */
+                               ifp->if_flags &= ~IFF_UP;
+                               ifrq.ifr_flags = ifp->if_flags;
+                               (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS,
+                                   (caddr_t)&ifrq);
+
+                               /* ... and up again */
+                               ifp->if_flags |= IFF_UP;
+                               ifrq.ifr_flags = ifp->if_flags;
+                               (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS,
+                                   (caddr_t)&ifrq);
+                       }
+
+                       splx(s);
+               }
 #endif
 
                if (error == 0)
index 42d0328..278679b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if.h,v 1.208 2021/03/11 19:53:40 florian Exp $        */
+/*     $OpenBSD: if.h,v 1.209 2022/06/27 15:11:23 jan Exp $    */
 /*     $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $  */
 
 /*
@@ -231,6 +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] TCP segment offloading */
 
 #define        IFXF_CANTCHANGE \
        (IFXF_MPSAFE|IFXF_CLONED)
@@ -250,6 +251,7 @@ struct if_status_description {
 #define        IFCAP_VLAN_HWTAGGING    0x00000020      /* hardware VLAN tag support */
 #define        IFCAP_CSUM_TCPv6        0x00000080      /* can do IPv6/TCP checksums */
 #define        IFCAP_CSUM_UDPv6        0x00000100      /* can do IPv6/UDP checksums */
+#define        IFCAP_TSO               0x00004000      /* TCP segment offloading */
 #define        IFCAP_WOL               0x00008000      /* can do wake on lan */
 
 #define IFCAP_CSUM_MASK                (IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 | \