Module Name: src Committed By: yamaguchi Date: Fri Apr 1 07:26:51 UTC 2022
Modified Files: src/sys/net/lagg: if_lagg.c if_lagg_lacp.c Log Message: lagg(4): reimplement add and delete port The IFNET_LOCK for the adding or deleting port became to be held the whole time while the ifnet of the port is changed. To generate a diff of this commit: cvs rdiff -u -r1.44 -r1.45 src/sys/net/lagg/if_lagg.c cvs rdiff -u -r1.21 -r1.22 src/sys/net/lagg/if_lagg_lacp.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/lagg/if_lagg.c diff -u src/sys/net/lagg/if_lagg.c:1.44 src/sys/net/lagg/if_lagg.c:1.45 --- src/sys/net/lagg/if_lagg.c:1.44 Thu Mar 31 07:59:05 2022 +++ src/sys/net/lagg/if_lagg.c Fri Apr 1 07:26:51 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: if_lagg.c,v 1.44 2022/03/31 07:59:05 yamaguchi Exp $ */ +/* $NetBSD: if_lagg.c,v 1.45 2022/04/01 07:26:51 yamaguchi Exp $ */ /* * Copyright (c) 2005, 2006 Reyk Floeter <r...@openbsd.org> @@ -20,7 +20,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.44 2022/03/31 07:59:05 yamaguchi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.45 2022/04/01 07:26:51 yamaguchi Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -133,7 +133,7 @@ static const struct lagg_proto lagg_prot }, }; -static int lagg_chg_sadl(struct ifnet *, uint8_t *, size_t); +static int lagg_chg_sadl(struct ifnet *, const uint8_t *, size_t); static struct mbuf * lagg_input_ethernet(struct ifnet *, struct mbuf *); static int lagg_clone_create(struct if_clone *, int); @@ -195,10 +195,10 @@ static void lagg_port_teardown(struct la bool); 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 void lagg_sync_ifcaps(struct lagg_softc *); static void lagg_sync_ethcaps(struct lagg_softc *); +static void lagg_sync_sadl(struct lagg_softc *); static struct if_clone lagg_cloner = IF_CLONE_INITIALIZER("lagg", lagg_clone_create, lagg_clone_destroy); @@ -212,11 +212,13 @@ static enum lagg_iftypes lagg_iftype = LAGG_IF_TYPE_ETHERNET; #ifdef LAGG_DEBUG +#define __LAGGDEBUGUSED #define LAGG_DPRINTF(_sc, _fmt, _args...) do { \ printf("%s: " _fmt, (_sc) != NULL ? \ (_sc)->sc_if.if_xname : "lagg", ##_args); \ } while (0) #else +#define __LAGGDEBUGUSED __unused #define LAGG_DPRINTF(_sc, _fmt, _args...) __nothing #endif @@ -413,7 +415,7 @@ lagg_clone_create(struct if_clone *ifc, sc->sc_lladdr_rand[0] |= 0x02; /* set G/L bit */ lagg_lladdr_cpy(sc->sc_lladdr, sc->sc_lladdr_rand); ether_set_vlan_cb((struct ethercom *)ifp, lagg_vlan_cb); - ether_ifattach(ifp, sc->sc_lladdr); + ether_ifattach(ifp, sc->sc_lladdr_rand); break; default: panic("unknown if type"); @@ -500,7 +502,7 @@ lagg_init_locked(struct lagg_softc *sc) if (ISSET(ifp->if_flags, IFF_RUNNING)) lagg_stop_locked(sc); - lagg_lladdr_update(sc); + lagg_sync_sadl(sc); SET(ifp->if_flags, IFF_RUNNING); @@ -2009,85 +2011,42 @@ lagg_capabilities_update(struct lagg_sof } static int -lagg_setup_mtu(struct lagg_softc *sc, struct lagg_port *lp) +lagg_setmtu(struct ifnet *ifp, uint64_t mtu) { - struct ifnet *ifp, *ifp_port; + struct lagg_softc *sc __LAGGDEBUGUSED; + struct lagg_port *lp; struct ifreq ifr; int error; - ifp = &sc->sc_if; - ifp_port = lp->lp_ifp; - - KASSERT(IFNET_LOCKED(ifp_port)); + KASSERT(IFNET_LOCKED(ifp)); - error = 0; memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_mtu = mtu; + lp = ifp->if_lagg; - if (SIMPLEQ_EMPTY(&sc->sc_ports)) { - ifr.ifr_mtu = lp->lp_mtu; - - if (ifp->if_mtu != (uint64_t)ifr.ifr_mtu) { - KASSERT(IFNET_LOCKED(ifp)); - error = ether_ioctl(ifp, SIOCSIFMTU, &ifr); - } + if (lp != NULL) { + /* ioctl for port interface */ + error = lp->lp_ioctl(ifp, SIOCSIFMTU, &ifr); + sc = lp->lp_softc; } else { - ifr.ifr_mtu = sc->sc_if.if_mtu; - - if (lp->lp_mtu != (uint64_t)ifr.ifr_mtu) { - if (lp->lp_ioctl == NULL) { - LAGG_DPRINTF(sc, - "cannot change MTU for %s\n", - ifp_port->if_xname); - return EINVAL; - } + /* ioctl for lagg interface */ + error = ether_ioctl(ifp, SIOCSIFMTU, &ifr); + sc = ifp->if_softc; + } - strlcpy(ifr.ifr_name, ifp_port->if_xname, - sizeof(ifr.ifr_name)); - error = lp->lp_ioctl(ifp_port, - SIOCSIFMTU, (void *)&ifr); - if (error != 0) { - LAGG_DPRINTF(sc, - "invalid MTU %d for %s\n", - ifr.ifr_mtu, ifp_port->if_xname); - } - } + if (error != 0) { + LAGG_DPRINTF(sc, + "couldn't change MTU for %s\n", + ifp->if_xname); } return error; } static void -lagg_teardown_mtu(struct lagg_softc *sc, struct lagg_port *lp) -{ - struct ifnet *ifp_port; - struct ifreq ifr; - int error; - - if (lp->lp_ioctl == NULL) - return; - - ifp_port = lp->lp_ifp; - KASSERT(IFNET_LOCKED(ifp_port)); - - if (ifp_port->if_mtu != lp->lp_mtu) { - memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, ifp_port->if_xname, sizeof(ifr.ifr_name)); - ifr.ifr_mtu = lp->lp_mtu; - error = lp->lp_ioctl(ifp_port, SIOCSIFMTU, (void *)&ifr); - if (error != 0) { - LAGG_LOG(sc, LOG_WARNING, - "failed to reset MTU %d to %s\n", - ifr.ifr_mtu, ifp_port->if_xname); - } - } -} - -static void -lagg_port_setsadl(struct lagg_port *lp, uint8_t *lladdr, - bool iftype_changed) +lagg_port_setsadl(struct lagg_port *lp, const uint8_t *lladdr) { struct ifnet *ifp_port; - bool lladdr_changed; int error; ifp_port = lp->lp_ifp; @@ -2097,58 +2056,16 @@ lagg_port_setsadl(struct lagg_port *lp, switch (lp->lp_iftype) { case IFT_ETHER: - lladdr_changed = lagg_lladdr_equal(lladdr, - CLLADDR(ifp_port->if_sadl)) ? false : true; - - if (lladdr_changed == false && - iftype_changed == false) { - break; - } - - lagg_chg_sadl(ifp_port, - lladdr, ETHER_ADDR_LEN); - - if (ifp_port->if_init != NULL) { - error = 0; - if (ISSET(ifp_port->if_flags, IFF_RUNNING)) - error = if_init(ifp_port); - - if (error != 0) { - LAGG_LOG(lp->lp_softc, LOG_WARNING, - "%s failed to if_init() on %d\n", - ifp_port->if_xname, error); - } + if (lladdr == NULL) { + lladdr = lp->lp_lladdr; } else { - if (lp->lp_promisc == false) { - ifpromisc_locked(ifp_port, 1); - lp->lp_promisc = true; - } + if (lagg_lladdr_equal(lladdr, + CLLADDR(ifp_port->if_sadl))) + break; } - break; - default: - if_alloc_sadl(ifp_port); - break; - } -} - -static void -lagg_port_unsetsadl(struct lagg_port *lp) -{ - struct ifnet *ifp_port; - int error; - - ifp_port = lp->lp_ifp; - - KASSERT(LAGG_LOCKED(lp->lp_softc)); - KASSERT(IFNET_LOCKED(ifp_port)); - - switch (lp->lp_iftype) { - case IFT_ETHER: - /* reset if_type before changing ifp->if_sadl */ - ifp_port->if_type = lp->lp_iftype; lagg_chg_sadl(ifp_port, - lp->lp_lladdr, ETHER_ADDR_LEN); + lladdr, ETHER_ADDR_LEN); if (ifp_port->if_init != NULL) { error = 0; @@ -2160,129 +2077,74 @@ lagg_port_unsetsadl(struct lagg_port *lp "%s failed to if_init() on %d\n", ifp_port->if_xname, error); } - } else { - if (lp->lp_promisc == true) { - ifpromisc_locked(ifp_port, 0); - lp->lp_promisc = false; - } } break; - default: - /* reset if_type before if_alloc_sadl */ - ifp_port->if_type = lp->lp_iftype; if_alloc_sadl(ifp_port); break; } } static void -lagg_setup_lladdr(struct lagg_softc *sc, struct lagg_port *lp) -{ - - KASSERT(LAGG_LOCKED(sc)); - - if (lagg_lladdr_equal(sc->sc_lladdr, sc->sc_lladdr_rand)) - lagg_lladdr_cpy(sc->sc_lladdr, lp->lp_lladdr); -} - -static void -lagg_teardown_lladdr(struct lagg_softc *sc, struct lagg_port *lp) -{ - struct lagg_port *lp0; - uint8_t *lladdr_next; - - KASSERT(LAGG_LOCKED(sc)); - - if (lagg_lladdr_equal(sc->sc_lladdr, - lp->lp_lladdr) == false) { - return; - } - - lladdr_next = sc->sc_lladdr_rand; - - LAGG_PORTS_FOREACH(sc, lp0) { - if (lp0->lp_iftype == IFT_ETHER) { - lladdr_next = lp0->lp_lladdr; - break; - } - } - - lagg_lladdr_cpy(sc->sc_lladdr, lladdr_next); -} - -static void -lagg_lladdr_update(struct lagg_softc *sc) +lagg_if_setsadl(struct lagg_softc *sc, uint8_t *lladdr) { struct ifnet *ifp; - struct lagg_port *lp; - const uint8_t *lladdr; - - ifp = &sc->sc_if; KASSERT(LAGG_LOCKED(sc)); - KASSERT(IFNET_LOCKED(ifp)); - KASSERT(!ISSET(ifp->if_flags, IFF_RUNNING)); - lladdr = CLLADDR(ifp->if_sadl); + ifp = &sc->sc_if; - if (lagg_lladdr_equal(sc->sc_lladdr, lladdr)) + if (lagg_lladdr_equal(CLLADDR(ifp->if_sadl), lladdr)) return; - lagg_lladdr_cpy(sc->sc_lladdr, lladdr); + lagg_chg_sadl(ifp, lladdr, ETHER_ADDR_LEN); - LAGG_PORTS_FOREACH(sc, lp) { - IFNET_LOCK(lp->lp_ifp); - lagg_port_setsadl(lp, sc->sc_lladdr, false); - IFNET_UNLOCK(lp->lp_ifp); - } + LAGG_UNLOCK(sc); + lagg_in6_ifdetach(ifp); + lagg_in6_ifattach(ifp); + LAGG_LOCK(sc); + + lagg_sync_sadl(sc); } static void -lagg_sadl_update(struct lagg_softc *sc, uint8_t *lladdr_prev) +lagg_sync_sadl(struct lagg_softc *sc) { struct ifnet *ifp; struct lagg_port *lp; - const uint8_t *lladdr; + const uint8_t *lla; ifp = &sc->sc_if; - - KASSERT(LAGG_LOCKED(sc)); KASSERT(IFNET_LOCKED(ifp)); - lladdr = CLLADDR(ifp->if_sadl); - - if (lagg_lladdr_equal(sc->sc_lladdr, lladdr)) - return; - - if (lagg_lladdr_equal(lladdr_prev, lladdr) == false) + lla = CLLADDR(ifp->if_sadl); + if (lagg_lladdr_equal(lla, sc->sc_lladdr)) return; - lagg_chg_sadl(ifp, sc->sc_lladdr, ETHER_ADDR_LEN); + lagg_lladdr_cpy(sc->sc_lladdr, lla); LAGG_PORTS_FOREACH(sc, lp) { IFNET_LOCK(lp->lp_ifp); - lagg_port_setsadl(lp, sc->sc_lladdr, false); + lagg_port_setsadl(lp, lla); IFNET_UNLOCK(lp->lp_ifp); } - - LAGG_UNLOCK(sc); - lagg_in6_ifdetach(ifp); - lagg_in6_ifattach(ifp); - LAGG_LOCK(sc); } static int lagg_port_setup(struct lagg_softc *sc, struct lagg_port *lp, struct ifnet *ifp_port) { + struct ifnet *ifp; u_char if_type; int error; - bool stopped, iftype_changed; + bool stopped, is_1st_port; KASSERT(LAGG_LOCKED(sc)); IFNET_ASSERT_UNLOCKED(ifp_port); + ifp = &sc->sc_if; + is_1st_port = SIMPLEQ_EMPTY(&sc->sc_ports); + if (&sc->sc_if == ifp_port) { LAGG_DPRINTF(sc, "cannot add a lagg to itself as a port\n"); return EINVAL; @@ -2318,6 +2180,17 @@ lagg_port_setup(struct lagg_softc *sc, psref_target_init(&lp->lp_psref, lagg_port_psref_class); IFNET_LOCK(ifp_port); + /* stop packet processing */ + if (ISSET(ifp_port->if_flags, IFF_RUNNING) && + ifp_port->if_init != NULL) { + if_stop(ifp_port, 0); + stopped = true; + } + + /* to delete ipv6 link local address */ + lagg_in6_ifdetach(ifp_port); + + /* backup members */ lp->lp_iftype = ifp_port->if_type; lp->lp_ioctl = ifp_port->if_ioctl; lp->lp_output = ifp_port->if_output; @@ -2331,81 +2204,85 @@ lagg_port_setup(struct lagg_softc *sc, lp->lp_eccapenable = ec->ec_capenable; } + /* change callbacks and others */ + atomic_store_release(&ifp_port->if_lagg, (void *)lp); ifp_port->if_type = if_type; ifp_port->if_ioctl = lagg_port_ioctl; - - iftype_changed = (lp->lp_iftype != ifp_port->if_type); - - if (ISSET(ifp_port->if_flags, IFF_RUNNING) && - ifp_port->if_init != NULL) { - if_stop(ifp_port, 0); - stopped = true; + ifp_port->if_output = lagg_port_output; + if (is_1st_port) { + if (lp->lp_iftype != ifp_port->if_type) + lagg_port_setsadl(lp, NULL); + } else { + lagg_port_setsadl(lp, CLLADDR(ifp->if_sadl)); + error = lagg_setmtu(ifp_port, ifp->if_mtu); + if (error != 0) + goto restore_sadl; } - /* to delete ipv6 link local address */ - lagg_in6_ifdetach(ifp_port); - - lagg_capabilities_update(sc); - - error = lagg_setup_mtu(sc, lp); + error = lagg_proto_allocport(sc, lp); if (error != 0) - goto restore_ipv6lla; - - if (lp->lp_iftype == IFT_ETHER) - lagg_setup_lladdr(sc, lp); + goto restore_mtu; - lagg_port_setsadl(lp, sc->sc_lladdr, iftype_changed); + /* restart packet processing */ + if (stopped) { + error = if_init(ifp_port); + if (error != 0) + goto free_port; + } + /* setup of ifp_port is complete */ IFNET_UNLOCK(ifp_port); - error = lagg_proto_allocport(sc, lp); - if (error != 0) - goto teardown_lladdr; + if (is_1st_port) { + error = lagg_setmtu(ifp, lp->lp_mtu); + if (error != 0) + goto restore_ifp_port; + if (lp->lp_iftype == IFT_ETHER && + lagg_lladdr_equal(sc->sc_lladdr_rand, + CLLADDR(ifp->if_sadl))) { + lagg_if_setsadl(sc, lp->lp_lladdr); + } + } - atomic_store_release(&ifp_port->if_lagg, (void *)lp); SIMPLEQ_INSERT_TAIL(&sc->sc_ports, lp, lp_entry); sc->sc_nports++; + lagg_capabilities_update(sc); lagg_port_syncmulti(sc, lp); lagg_port_syncvlan(sc, lp); - - IFNET_LOCK(ifp_port); - ifp_port->if_output = lagg_port_output; - if (stopped) { - if (!ISSET(ifp_port->if_flags, IFF_RUNNING)) { - error = if_init(ifp_port); - if (error != 0) - goto remove_port; - } - } - IFNET_UNLOCK(ifp_port); - lagg_config_promisc(sc, lp); + lagg_proto_startport(sc, lp); return 0; -remove_port: - SIMPLEQ_REMOVE(&sc->sc_ports, lp, lagg_port, lp_entry); - sc->sc_nports--; +restore_ifp_port: IFNET_LOCK(ifp_port); - ifp_port->if_output = lp->lp_output; - IFNET_UNLOCK(ifp_port); - atomic_store_release(&ifp_port->if_lagg, NULL); - pserialize_perform(sc->sc_psz); - lagg_port_purgemulti(sc, lp); - lagg_port_purgevlan(sc, lp); + if (stopped) { + if_stop(ifp_port, 0); + } +free_port: + KASSERT(IFNET_LOCKED(ifp_port)); lagg_proto_freeport(sc, lp); - -teardown_lladdr: - IFNET_LOCK(ifp_port); - lagg_teardown_mtu(sc, lp); - lagg_port_unsetsadl(lp); - if (lp->lp_iftype == IFT_ETHER) - lagg_teardown_lladdr(sc, lp); -restore_ipv6lla: +restore_mtu: KASSERT(IFNET_LOCKED(ifp_port)); - lagg_in6_ifdetach(ifp_port); + if (ifp_port->if_mtu != lp->lp_mtu) + lagg_setmtu(ifp_port, lp->lp_mtu); +restore_sadl: + KASSERT(IFNET_LOCKED(ifp_port)); + + /* restore if_type before changing sadl */ + if_type = ifp_port->if_type; + ifp_port->if_type = lp->lp_iftype; + + if (!SIMPLEQ_EMPTY(&sc->sc_ports)) { + lagg_port_setsadl(lp, lp->lp_lladdr); + } else { + if (ifp_port->if_type != if_type) + lagg_port_setsadl(lp, NULL); + } + + lagg_in6_ifattach(ifp_port); if (stopped) { if (if_init(ifp_port) != 0) { LAGG_LOG(sc, LOG_WARNING, @@ -2413,10 +2290,10 @@ restore_ipv6lla: ifp_port->if_xname); } } - ifp_port->if_type = lp->lp_iftype; - if (ifp_port->if_ioctl == lagg_port_ioctl) - ifp_port->if_ioctl = lp->lp_ioctl; + ifp_port->if_ioctl = lp->lp_ioctl; + ifp_port->if_output = lp->lp_output; + atomic_store_release(&ifp_port->if_lagg, NULL); IFNET_UNLOCK(ifp_port); psref_target_destroy(&lp->lp_psref, lagg_port_psref_class); @@ -2432,13 +2309,16 @@ static void lagg_port_teardown(struct lagg_softc *sc, struct lagg_port *lp, bool is_ifdetach) { - struct ifnet *ifp_port; - bool stopped; + struct ifnet *ifp, *ifp_port; + bool stopped, is_1st_port, iftype_changed; KASSERT(LAGG_LOCKED(sc)); + ifp = &sc->sc_if; ifp_port = lp->lp_ifp; stopped = false; + is_1st_port = + SIMPLEQ_FIRST(&sc->sc_ports) == lp ? true : false; ether_ifdetachhook_disestablish(ifp_port, lp->lp_ifdetach_hook, &sc->sc_lock); @@ -2448,56 +2328,92 @@ lagg_port_teardown(struct lagg_softc *sc return; } + if_linkstate_change_disestablish(ifp_port, + lp->lp_linkstate_hook, NULL); + lagg_proto_stopport(sc, lp); + lagg_port_purgemulti(sc, lp); + lagg_port_purgevlan(sc, lp); + if (is_ifdetach == false) { + lagg_unconfig_promisc(sc, lp); + lagg_setifcaps(lp, lp->lp_ifcapenable); + if (lp->lp_iftype == IFT_ETHER) + lagg_setethcaps(lp, lp->lp_eccapenable); + } + + SIMPLEQ_REMOVE(&sc->sc_ports, lp, lagg_port, lp_entry); + sc->sc_nports--; + + if (is_1st_port) { + if (lp->lp_iftype == IFT_ETHER && + lagg_lladdr_equal(lp->lp_lladdr, + CLLADDR(ifp->if_sadl))) { + struct lagg_port *lp0; + uint8_t *lla; + + lp0 = SIMPLEQ_FIRST(&sc->sc_ports); + if (lp0 != NULL && + lp0->lp_iftype == IFT_ETHER) { + lla = lp0->lp_lladdr; + } else { + lla = sc->sc_lladdr_rand; + } + + lagg_if_setsadl(sc, lla); + } + } + IFNET_LOCK(ifp_port); + /* stop packet processing */ if (ISSET(ifp_port->if_flags, IFF_RUNNING) && ifp_port->if_init != NULL) { if_stop(ifp_port, 0); stopped = true; } - ifp_port->if_output = lp->lp_output; - IFNET_UNLOCK(ifp_port); - - SIMPLEQ_REMOVE(&sc->sc_ports, lp, lagg_port, lp_entry); - sc->sc_nports--; - atomic_store_release(&ifp_port->if_lagg, NULL); - pserialize_perform(sc->sc_psz); - if_linkstate_change_disestablish(ifp_port, - lp->lp_linkstate_hook, NULL); + lagg_proto_freeport(sc, lp); - psref_target_destroy(&lp->lp_psref, lagg_port_psref_class); + /* change if_type before set sadl */ + iftype_changed = ifp_port->if_type != lp->lp_iftype ? + true : false; + ifp_port->if_type = lp->lp_iftype; - lagg_port_purgemulti(sc, lp); - lagg_port_purgevlan(sc, lp); - lagg_teardown_lladdr(sc, lp); + if (is_ifdetach == false) { + if (iftype_changed && + lagg_lladdr_equal(CLLADDR(ifp_port->if_sadl), + lp->lp_lladdr)) { + lagg_port_setsadl(lp, NULL); + } + lagg_port_setsadl(lp, lp->lp_lladdr); + lagg_in6_ifattach(ifp_port); + (void)lagg_setmtu(ifp_port, lp->lp_mtu); + } - IFNET_LOCK(ifp_port); - ifp_port->if_type = lp->lp_iftype; + ifp_port->if_output = lp->lp_output; if (ifp_port->if_ioctl == lagg_port_ioctl) ifp_port->if_ioctl = lp->lp_ioctl; - lagg_teardown_mtu(sc, lp); - - if (stopped) - if_init(ifp_port); - IFNET_UNLOCK(ifp_port); + atomic_store_release(&ifp_port->if_lagg, NULL); + pserialize_perform(sc->sc_psz); + /* to assign ipv6 link local address */ if (is_ifdetach == false) { - lagg_unconfig_promisc(sc, lp); - lagg_setifcaps(lp, lp->lp_ifcapenable); - if (lp->lp_iftype == IFT_ETHER) - lagg_setethcaps(lp, lp->lp_eccapenable); - - IFNET_LOCK(ifp_port); - lagg_port_unsetsadl(lp); lagg_in6_ifattach(ifp_port); - IFNET_UNLOCK(ifp_port); } - lagg_capabilities_update(sc); + /* restart packet processing */ + if (stopped) { + int error; + error = if_init(ifp_port); + if (error != 0) { + LAGG_LOG(sc, LOG_WARNING, + "%s failed to if_init() on %d\n", + ifp_port->if_xname, error); + } + } + IFNET_UNLOCK(ifp_port); - lagg_proto_freeport(sc, lp); + psref_target_destroy(&lp->lp_psref, lagg_port_psref_class); kmem_free(lp, sizeof(*lp)); } @@ -2505,17 +2421,13 @@ static int lagg_addport(struct lagg_softc *sc, struct ifnet *ifp_port) { struct lagg_port *lp; - uint8_t lladdr[ETHER_ADDR_LEN]; int error; lp = kmem_zalloc(sizeof(*lp), KM_SLEEP); lp->lp_ifp = ifp_port; LAGG_LOCK(sc); - lagg_lladdr_cpy(lladdr, sc->sc_lladdr); error = lagg_port_setup(sc, lp, ifp_port); - if (error == 0) - lagg_sadl_update(sc, lladdr); LAGG_UNLOCK(sc); if (error != 0) @@ -2528,7 +2440,6 @@ static int lagg_delport(struct lagg_softc *sc, struct ifnet *ifp_port) { struct lagg_port *lp; - uint8_t lladdr[ETHER_ADDR_LEN]; int error; KASSERT(IFNET_LOCKED(&sc->sc_if)); @@ -2546,9 +2457,7 @@ lagg_delport(struct lagg_softc *sc, stru goto out; } - lagg_lladdr_cpy(lladdr, sc->sc_lladdr); lagg_port_teardown(sc, lp, false); - lagg_sadl_update(sc, lladdr); out: LAGG_UNLOCK(sc); @@ -2560,7 +2469,6 @@ static int lagg_delport_all(struct lagg_softc *sc) { struct lagg_port *lp; - uint8_t lladdr[ETHER_ADDR_LEN]; int error; KASSERT(IFNET_LOCKED(&sc->sc_if)); @@ -2568,7 +2476,6 @@ lagg_delport_all(struct lagg_softc *sc) error = 0; LAGG_LOCK(sc); - lagg_lladdr_cpy(lladdr, sc->sc_lladdr); while ((lp = LAGG_PORTS_FIRST(sc)) != NULL) { if (lp->lp_ifdetaching) { error = EBUSY; @@ -2578,7 +2485,6 @@ lagg_delport_all(struct lagg_softc *sc) lagg_port_teardown(sc, lp, false); } - lagg_sadl_update(sc, lladdr); LAGG_UNLOCK(sc); return error; @@ -2772,7 +2678,6 @@ lagg_ifdetach(void *xifp_port) struct ifnet *ifp_port = xifp_port; struct lagg_port *lp; struct lagg_softc *sc; - uint8_t lladdr[ETHER_ADDR_LEN]; int s; IFNET_ASSERT_UNLOCKED(ifp_port); @@ -2810,9 +2715,7 @@ lagg_ifdetach(void *xifp_port) LAGG_LOCK(sc); lp = ifp_port->if_lagg; if (lp != NULL) { - lagg_lladdr_cpy(lladdr, sc->sc_lladdr); lagg_port_teardown(sc, lp, true); - lagg_sadl_update(sc, lladdr); } LAGG_UNLOCK(sc); IFNET_UNLOCK(&sc->sc_if); @@ -2915,7 +2818,7 @@ lagg_workq_wait(struct workqueue *wq, st } static int -lagg_chg_sadl(struct ifnet *ifp, uint8_t *lla, size_t lla_len) +lagg_chg_sadl(struct ifnet *ifp, const uint8_t *lla, size_t lla_len) { struct psref psref_cur, psref_next; struct ifaddr *ifa_cur, *ifa_next, *ifa_lla; Index: src/sys/net/lagg/if_lagg_lacp.c diff -u src/sys/net/lagg/if_lagg_lacp.c:1.21 src/sys/net/lagg/if_lagg_lacp.c:1.22 --- src/sys/net/lagg/if_lagg_lacp.c:1.21 Thu Mar 31 07:59:05 2022 +++ src/sys/net/lagg/if_lagg_lacp.c Fri Apr 1 07:26:51 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: if_lagg_lacp.c,v 1.21 2022/03/31 07:59:05 yamaguchi Exp $ */ +/* $NetBSD: if_lagg_lacp.c,v 1.22 2022/04/01 07:26:51 yamaguchi Exp $ */ /*- * SPDX-License-Identifier: BSD-2-Clause-NetBSD @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_lagg_lacp.c,v 1.21 2022/03/31 07:59:05 yamaguchi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_lagg_lacp.c,v 1.22 2022/04/01 07:26:51 yamaguchi Exp $"); #ifdef _KERNEL_OPT #include "opt_lagg.h" @@ -667,11 +667,10 @@ lacp_allocport(struct lagg_proto_softc * sc = lsc->lsc_softc; KASSERT(LAGG_LOCKED(sc)); + KASSERT(IFNET_LOCKED(lp->lp_ifp)); - IFNET_LOCK(lp->lp_ifp); lacp_mcastaddr(&ifr, lp->lp_ifp->if_xname); error = lp->lp_ioctl(lp->lp_ifp, SIOCADDMULTI, (void *)&ifr); - IFNET_UNLOCK(lp->lp_ifp); switch (error) { case 0: @@ -700,7 +699,6 @@ lacp_allocport(struct lagg_proto_softc * lp->lp_proto_ctx = (void *)lacpp; lp->lp_prio = ntohs(lacpp->lp_actor.lpi_portprio); - lacp_linkstate(xlsc, lp); return 0; } @@ -751,6 +749,7 @@ lacp_freeport(struct lagg_proto_softc *x lacpp = lp->lp_proto_ctx; KASSERT(LAGG_LOCKED(lsc->lsc_softc)); + KASSERT(IFNET_LOCKED(lp->lp_ifp)); lagg_workq_wait(lsc->lsc_workq, &lacpp->lp_work_smtx); lagg_workq_wait(lsc->lsc_workq, &lacpp->lp_work_marker); @@ -758,9 +757,7 @@ lacp_freeport(struct lagg_proto_softc *x if (lacpp->lp_added_multi) { lacp_mcastaddr(&ifr, LACP_PORT_XNAME(lacpp)); - IFNET_LOCK(lp->lp_ifp); (void)lp->lp_ioctl(lp->lp_ifp, SIOCDELMULTI, (void *)&ifr); - IFNET_UNLOCK(lp->lp_ifp); } lp->lp_proto_ctx = NULL;