The branch main has been updated by gallatin:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=713ceb99b68568232bf9895bbe1811797bfde63c

commit 713ceb99b68568232bf9895bbe1811797bfde63c
Author:     Andrew Gallatin <galla...@freebsd.org>
AuthorDate: 2022-07-28 14:36:22 +0000
Commit:     Andrew Gallatin <galla...@freebsd.org>
CommitDate: 2022-07-28 14:39:00 +0000

    lagg: fix lagg ifioctl after SIOCSIFCAPNV
    
    Lagg was broken by SIOCSIFCAPNV when all underlying devices
    support SIOCSIFCAPNV.  This change updates lagg to work with
    SIOCSIFCAPNV and if_capabilities2.
    
    Reviewed by: kib, hselasky
    Sponsored by: Netflix
    Differential Revision: https://reviews.freebsd.org/D35865
---
 sys/net/if_lagg.c | 62 +++++++++++++++++++++++++++++++++++++++----------------
 sys/net/if_lagg.h |  1 +
 2 files changed, 45 insertions(+), 18 deletions(-)

diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c
index 3894b6d55cea..8e273c4ed391 100644
--- a/sys/net/if_lagg.c
+++ b/sys/net/if_lagg.c
@@ -157,7 +157,7 @@ static void     lagg_ratelimit_query(struct ifnet *,
 #endif
 static int     lagg_setmulti(struct lagg_port *);
 static int     lagg_clrmulti(struct lagg_port *);
-static int     lagg_setcaps(struct lagg_port *, int cap);
+static void    lagg_setcaps(struct lagg_port *, int cap, int cap2);
 static int     lagg_setflag(struct lagg_port *, int, int,
                    int (*func)(struct ifnet *, int));
 static int     lagg_setflags(struct lagg_port *, int status);
@@ -664,17 +664,20 @@ static void
 lagg_capabilities(struct lagg_softc *sc)
 {
        struct lagg_port *lp;
-       int cap, ena, pena;
+       int cap, cap2, ena, ena2, pena, pena2;
        uint64_t hwa;
        struct ifnet_hw_tsomax hw_tsomax;
 
        LAGG_XLOCK_ASSERT(sc);
 
        /* Get common enabled capabilities for the lagg ports */
-       ena = ~0;
-       CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
+       ena = ena2 = ~0;
+       CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
                ena &= lp->lp_ifp->if_capenable;
-       ena = (ena == ~0 ? 0 : ena);
+               ena2 &= lp->lp_ifp->if_capenable2;
+       }
+       if (CK_SLIST_FIRST(&sc->sc_ports) == NULL)
+               ena = ena2 = 0;
 
        /*
         * Apply common enabled capabilities back to the lagg ports.
@@ -682,30 +685,36 @@ lagg_capabilities(struct lagg_softc *sc)
         */
        do {
                pena = ena;
+               pena2 = ena2;
                CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
-                       lagg_setcaps(lp, ena);
+                       lagg_setcaps(lp, ena, ena2);
                        ena &= lp->lp_ifp->if_capenable;
+                       ena2 &= lp->lp_ifp->if_capenable2;
                }
-       } while (pena != ena);
+       } while (pena != ena || pena2 != ena2);
 
        /* Get other capabilities from the lagg ports */
-       cap = ~0;
+       cap = cap2 = ~0;
        hwa = ~(uint64_t)0;
        memset(&hw_tsomax, 0, sizeof(hw_tsomax));
        CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
                cap &= lp->lp_ifp->if_capabilities;
+               cap2 &= lp->lp_ifp->if_capabilities2;
                hwa &= lp->lp_ifp->if_hwassist;
                if_hw_tsomax_common(lp->lp_ifp, &hw_tsomax);
        }
-       cap = (cap == ~0 ? 0 : cap);
-       hwa = (hwa == ~(uint64_t)0 ? 0 : hwa);
+       if (CK_SLIST_FIRST(&sc->sc_ports) == NULL)
+               cap = cap2 = hwa = 0;
 
        if (sc->sc_ifp->if_capabilities != cap ||
            sc->sc_ifp->if_capenable != ena ||
+           sc->sc_ifp->if_capenable2 != ena2 ||
            sc->sc_ifp->if_hwassist != hwa ||
            if_hw_tsomax_update(sc->sc_ifp, &hw_tsomax) != 0) {
                sc->sc_ifp->if_capabilities = cap;
+               sc->sc_ifp->if_capabilities2 = cap2;
                sc->sc_ifp->if_capenable = ena;
+               sc->sc_ifp->if_capenable2 = ena2;
                sc->sc_ifp->if_hwassist = hwa;
                getmicrotime(&sc->sc_ifp->if_lastchange);
 
@@ -982,7 +991,7 @@ lagg_port_destroy(struct lagg_port *lp, int rundelport)
 
        if (lp->lp_detaching == 0) {
                lagg_setflags(lp, 0);
-               lagg_setcaps(lp, lp->lp_ifcapenable);
+               lagg_setcaps(lp, lp->lp_ifcapenable, lp->lp_ifcapenable2);
                if_setlladdr(ifp, lp->lp_lladdr, ifp->if_addrlen);
        }
 
@@ -1038,6 +1047,7 @@ lagg_port_ioctl(struct ifnet *ifp, u_long cmd, caddr_t 
data)
                break;
 
        case SIOCSIFCAP:
+       case SIOCSIFCAPNV:
                if (lp->lp_ioctl == NULL) {
                        error = EINVAL;
                        break;
@@ -1690,6 +1700,7 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
                break;
 
        case SIOCSIFCAP:
+       case SIOCSIFCAPNV:
                LAGG_XLOCK(sc);
                CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
                        if (lp->lp_ioctl != NULL)
@@ -1701,6 +1712,10 @@ lagg_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
                error = 0;
                break;
 
+       case SIOCGIFCAPNV:
+               error = 0;
+               break;
+
        case SIOCSIFMTU:
                LAGG_XLOCK(sc);
                CK_SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) {
@@ -2013,17 +2028,28 @@ lagg_clrmulti(struct lagg_port *lp)
        return (0);
 }
 
-static int
-lagg_setcaps(struct lagg_port *lp, int cap)
+static void
+lagg_setcaps(struct lagg_port *lp, int cap, int cap2)
 {
        struct ifreq ifr;
+       struct siocsifcapnv_driver_data drv_ioctl_data;
 
-       if (lp->lp_ifp->if_capenable == cap)
-               return (0);
+       if (lp->lp_ifp->if_capenable == cap &&
+           lp->lp_ifp->if_capenable2 == cap2)
+               return;
        if (lp->lp_ioctl == NULL)
-               return (ENXIO);
-       ifr.ifr_reqcap = cap;
-       return ((*lp->lp_ioctl)(lp->lp_ifp, SIOCSIFCAP, (caddr_t)&ifr));
+               return;
+       /* XXX */
+       if ((lp->lp_ifp->if_capabilities & IFCAP_NV) != 0) {
+               drv_ioctl_data.reqcap = cap;
+               drv_ioctl_data.reqcap2 = cap2;
+               drv_ioctl_data.nvcap = NULL;
+               (*lp->lp_ioctl)(lp->lp_ifp, SIOCSIFCAPNV,
+                   (caddr_t)&drv_ioctl_data);
+       } else {
+               ifr.ifr_reqcap = cap;
+               (*lp->lp_ioctl)(lp->lp_ifp, SIOCSIFCAP, (caddr_t)&ifr);
+       }
 }
 
 /* Handle a ref counted flag that should be set on the lagg port as well */
diff --git a/sys/net/if_lagg.h b/sys/net/if_lagg.h
index 94f3487af6f7..9fc6e3862712 100644
--- a/sys/net/if_lagg.h
+++ b/sys/net/if_lagg.h
@@ -273,6 +273,7 @@ struct lagg_port {
        uint32_t                        lp_flags;       /* port flags */
        int                             lp_ifflags;     /* saved ifp flags */
        int                             lp_ifcapenable; /* saved ifp capenable 
*/
+       int                             lp_ifcapenable2;/* saved ifp capenable2 
*/
        void                            *lh_cookie;     /* if state hook */
        void                            *lp_psc;        /* protocol data */
        int                             lp_detaching;   /* ifnet is detaching */

Reply via email to