Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/net/lagg lagg: update capabilities of ifnet and ethercom



details:   https://anonhg.NetBSD.org/src/rev/83bae9f637c8
branches:  trunk
changeset: 1024192:83bae9f637c8
user:      yamaguchi <yamaguchi%NetBSD.org@localhost>
date:      Tue Oct 12 08:26:47 2021 +0000

description:
lagg: update capabilities of ifnet and ethercom

Commonly capabilities of all child interface are configured
to a lagg interface.

diffstat:

 sys/net/lagg/files.lagg     |    3 +-
 sys/net/lagg/if_lagg.c      |  209 ++++++++++++++++++++++++++++++++++++++++++-
 sys/net/lagg/if_laggproto.h |    8 +-
 3 files changed, 208 insertions(+), 12 deletions(-)

diffs (truncated from 325 to 300 lines):

diff -r b3a689ac9b1a -r 83bae9f637c8 sys/net/lagg/files.lagg
--- a/sys/net/lagg/files.lagg   Tue Oct 12 08:09:50 2021 +0000
+++ b/sys/net/lagg/files.lagg   Tue Oct 12 08:26:47 2021 +0000
@@ -1,7 +1,8 @@
-#      $NetBSD: files.lagg,v 1.1 2021/05/17 04:07:43 yamaguchi Exp $
+#      $NetBSD: files.lagg,v 1.2 2021/10/12 08:26:47 yamaguchi Exp $
 
 file   net/lagg/if_lagg.c              lagg & ether    needs-flag
 file   net/lagg/if_lagg_lacp.c         lagg & ether
 file   net/lagg/if_laggproto.c         lagg
 
 defflag opt_lagg.h                     LAGG_DEBUG LACP_DEBUG
+defparam opt_lagg.h                    LAGG_SETCAPS_RETRY
diff -r b3a689ac9b1a -r 83bae9f637c8 sys/net/lagg/if_lagg.c
--- a/sys/net/lagg/if_lagg.c    Tue Oct 12 08:09:50 2021 +0000
+++ b/sys/net/lagg/if_lagg.c    Tue Oct 12 08:26:47 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_lagg.c,v 1.11 2021/10/05 04:17:58 yamaguchi Exp $   */
+/*     $NetBSD: if_lagg.c,v 1.12 2021/10/12 08:26:47 yamaguchi Exp $   */
 
 /*
  * Copyright (c) 2005, 2006 Reyk Floeter <reyk%openbsd.org@localhost>
@@ -20,7 +20,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.11 2021/10/05 04:17:58 yamaguchi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.12 2021/10/12 08:26:47 yamaguchi Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -194,6 +194,7 @@
 static void    lagg_port_syncvlan(struct lagg_softc *, struct lagg_port *);
 static void    lagg_port_purgevlan(struct lagg_softc *, struct lagg_port *);
 static void    lagg_lladdr_update(struct lagg_softc *);
+static void    lagg_capabilities_update(struct lagg_softc *);
 
 static struct if_clone  lagg_cloner =
     IF_CLONE_INITIALIZER("lagg", lagg_clone_create, lagg_clone_destroy);
@@ -215,6 +216,10 @@
 #define LAGG_DPRINTF(_sc, _fmt, _args...)      __nothing
 #endif
 
+#ifndef LAGG_SETCAPS_RETRY
+#define LAGG_SETCAPS_RETRY     (LAGG_MAX_PORTS * 2)
+#endif
+
 static size_t
 lagg_sizeof_softc(enum lagg_iftypes ift)
 {
@@ -1806,6 +1811,181 @@
 }
 
 static int
+lagg_setifcaps(struct lagg_port *lp, uint64_t cap)
+{
+       struct ifcapreq ifcr;
+       int error;
+
+       if (lp->lp_ifp->if_capenable == cap)
+               return 0;
+
+       memset(&ifcr, 0, sizeof(ifcr));
+       ifcr.ifcr_capenable = cap;
+
+       IFNET_LOCK(lp->lp_ifp);
+       error = LAGG_PORT_IOCTL(lp, SIOCSIFCAP, &ifcr);
+       IFNET_UNLOCK(lp->lp_ifp);
+
+       return error;
+}
+
+static int
+lagg_setethcaps(struct lagg_port *lp, int cap)
+{
+       struct ethercom *ec;
+       struct eccapreq eccr;
+       int error;
+
+       KASSERT(lp->lp_iftype == IFT_ETHER);
+       ec = (struct ethercom *)lp->lp_ifp;
+
+       if (ec->ec_capenable == cap)
+               return 0;
+
+       memset(&eccr, 0, sizeof(eccr));
+       eccr.eccr_capenable = cap;
+
+       IFNET_LOCK(lp->lp_ifp);
+       error = LAGG_PORT_IOCTL(lp, SIOCSETHERCAP, &eccr);
+       IFNET_UNLOCK(lp->lp_ifp);
+
+       return error;
+}
+
+static void
+lagg_ifcap_update(struct lagg_softc *sc)
+{
+       struct ifnet *ifp;
+       struct lagg_port *lp;
+       uint64_t cap, ena, pena;
+       size_t i;
+
+       KASSERT(LAGG_LOCKED(sc));
+
+       /* Get common capabilities for the lagg ports */
+       ena = ~(uint64_t)0;
+       cap = ~(uint64_t)0;
+       LAGG_PORTS_FOREACH(sc, lp) {
+               ena &= lp->lp_ifp->if_capenable;
+               cap &= lp->lp_ifp->if_capabilities;
+       }
+
+       if (ena == ~(uint64_t)0)
+               ena = 0;
+       if (cap == ~(uint64_t)0)
+               cap = 0;
+
+       /*
+        * Apply common enabled capabilities back to the lagg ports.
+        * May require several iterations if they are dependent.
+        */
+       for (i = 0; i < LAGG_SETCAPS_RETRY; i++) {
+               pena = ena;
+               LAGG_PORTS_FOREACH(sc, lp) {
+                       lagg_setifcaps(lp, ena);
+                       ena &= lp->lp_ifp->if_capenable;
+               }
+
+               if (pena == ena)
+                       break;
+       }
+
+       if (pena != ena) {
+               lagg_log(sc, LOG_DEBUG, "couldn't set "
+                   "capabilities 0x%08"PRIx64, pena);
+       }
+
+       ifp = &sc->sc_if;
+
+       if (ifp->if_capabilities != cap ||
+           ifp->if_capenable != ena) {
+               ifp->if_capabilities = cap;
+               ifp->if_capenable = ena;
+
+               lagg_log(sc, LOG_DEBUG,"capabilities "
+                   "0x%08"PRIx64" enabled 0x%08"PRIx64,
+                   cap, ena);
+       }
+}
+
+static void
+lagg_ethercap_update(struct lagg_softc *sc)
+{
+       struct ethercom *ec;
+       struct lagg_port *lp;
+       int cap, ena, pena;
+       size_t i;
+
+       KASSERT(LAGG_LOCKED(sc));
+
+       if (sc->sc_if.if_type != IFT_ETHER)
+               return;
+
+       /* Get common enabled capabilities for the lagg ports */
+       ena = ~0;
+       cap = ~0;
+       LAGG_PORTS_FOREACH(sc, lp) {
+               if (lp->lp_iftype == IFT_ETHER) {
+                       ec = (struct ethercom *)lp->lp_ifp;
+                       ena &= ec->ec_capenable;
+                       cap &= ec->ec_capabilities;
+               } else {
+                       ena = 0;
+                       cap = 0;
+               }
+       }
+
+       if (ena == ~0)
+               ena = 0;
+       if (cap == ~0)
+               cap = 0;
+
+       /*
+        * Apply common enabled capabilities back to the lagg ports.
+        * May require several iterations if they are dependent.
+        */
+       for (i = 0; i < LAGG_SETCAPS_RETRY; i++) {
+               pena = ena;
+               LAGG_PORTS_FOREACH(sc, lp) {
+                       if (lp->lp_iftype != IFT_ETHER)
+                               continue;
+
+                       ec = (struct ethercom *)lp->lp_ifp;
+                       lagg_setethcaps(lp, ena);
+                       ena &= ec->ec_capenable;
+               }
+
+               if (pena == ena)
+                       break;
+       }
+
+       if (pena != ena) {
+               lagg_log(sc, LOG_DEBUG, "couldn't set "
+                   "ether capabilities 0x%08x", pena);
+       }
+
+       ec = (struct ethercom *)&sc->sc_if;
+
+       if (ec->ec_capabilities != cap ||
+           ec->ec_capenable != ena) {
+               ec->ec_capabilities = cap;
+               ec->ec_capenable = ena;
+
+               lagg_log(sc, LOG_DEBUG,
+                   "ether capabilities 0x%08x"
+                   " enabled 0x%08x", cap, ena);
+       }
+}
+
+static void
+lagg_capabilities_update(struct lagg_softc *sc)
+{
+
+       lagg_ifcap_update(sc);
+       lagg_ethercap_update(sc);
+}
+
+static int
 lagg_setup_mtu(struct lagg_softc *sc, struct lagg_port *lp)
 {
        struct ifnet *ifp_port;
@@ -2056,8 +2236,13 @@
        lp->lp_output = ifp_port->if_output;
        lp->lp_ifcapenable = ifp_port->if_capenable;
        lp->lp_mtu = ifp_port->if_mtu;
-       if (lp->lp_iftype == IFT_ETHER)
+       if (lp->lp_iftype == IFT_ETHER) {
+               struct ethercom *ec;
+               ec = (struct ethercom *)ifp_port;
+
                lagg_lladdr_cpy(lp->lp_lladdr, CLLADDR(ifp_port->if_sadl));
+               lp->lp_eccapenable = ec->ec_capenable;
+       }
 
        ifp_port->if_type = if_type;
        ifp_port->if_ioctl = lagg_port_ioctl;
@@ -2103,6 +2288,7 @@
        }
 
        lagg_proto_startport(sc, lp);
+       lagg_capabilities_update(sc);
 
        return 0;
 
@@ -2196,24 +2382,30 @@
        if (ifp_port->if_ioctl == lagg_port_ioctl)
                ifp_port->if_ioctl = lp->lp_ioctl;
        ifp_port->if_output = lp->lp_output;
-       ifp_port->if_capenable = lp->lp_ifcapenable;
        lagg_teardown_mtu(sc, lp);
-       lagg_port_setsadl(lp, lp->lp_lladdr, iftype_changed);
        IFNET_UNLOCK(ifp_port);
 
-       lagg_proto_freeport(sc, lp);
-       kmem_free(lp, sizeof(*lp));
-
        if (stopped) {
                ifp_port->if_init(ifp_port);
        }
 
        if (is_ifdetach == false) {
+               lagg_setifcaps(lp, lp->lp_ifcapenable);
+               if (lp->lp_iftype == IFT_ETHER)
+                       lagg_setethcaps(lp, lp->lp_eccapenable);
+
                IFNET_LOCK(ifp_port);
+               if (ifp_port->if_type == IFT_ETHER)
+                       lagg_port_setsadl(lp, lp->lp_lladdr, iftype_changed);
+
                lagg_in6_ifattach(ifp_port);
                IFNET_UNLOCK(ifp_port);
        }
 
+       lagg_capabilities_update(sc);
+
+       lagg_proto_freeport(sc, lp);
+       kmem_free(lp, sizeof(*lp));
 }
 
 static int
@@ -2411,6 +2603,7 @@
                break;
        case SIOCSIFCAP:
        case SIOCSIFMTU:
+       case SIOCSETHERCAP:
                /* Do not allow the setting to be cahanged once joined */
                error = EINVAL;
                break;
diff -r b3a689ac9b1a -r 83bae9f637c8 sys/net/lagg/if_laggproto.h



Home | Main Index | Thread Index | Old Index