Module Name: src Committed By: yamaguchi Date: Thu Sep 30 04:29:17 UTC 2021
Modified Files: src/sys/net: if_ethersubr.c src/sys/net/lagg: if_lagg.c if_laggproto.h if_laggvar.h Log Message: lagg: Register lagg_ifdetach to ether_ifdetach hook To generate a diff of this commit: cvs rdiff -u -r1.299 -r1.300 src/sys/net/if_ethersubr.c cvs rdiff -u -r1.9 -r1.10 src/sys/net/lagg/if_lagg.c cvs rdiff -u -r1.5 -r1.6 src/sys/net/lagg/if_laggproto.h cvs rdiff -u -r1.3 -r1.4 src/sys/net/lagg/if_laggvar.h 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/if_ethersubr.c diff -u src/sys/net/if_ethersubr.c:1.299 src/sys/net/if_ethersubr.c:1.300 --- src/sys/net/if_ethersubr.c:1.299 Thu Sep 30 04:13:42 2021 +++ src/sys/net/if_ethersubr.c Thu Sep 30 04:29:16 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: if_ethersubr.c,v 1.299 2021/09/30 04:13:42 yamaguchi Exp $ */ +/* $NetBSD: if_ethersubr.c,v 1.300 2021/09/30 04:29:16 yamaguchi Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.299 2021/09/30 04:13:42 yamaguchi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.300 2021/09/30 04:29:16 yamaguchi Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -78,7 +78,6 @@ __KERNEL_RCSID(0, "$NetBSD: if_ethersubr #include "bridge.h" #include "arp.h" #include "agr.h" -#include "lagg.h" #include <sys/sysctl.h> #include <sys/mbuf.h> @@ -1068,11 +1067,6 @@ ether_ifdetach(struct ifnet *ifp) bpf_detach(ifp); -#if NLAGG > 0 - if (ifp->if_lagg) - lagg_ifdetach(ifp); -#endif - ETHER_LOCK(ec); KASSERT(ec->ec_nvlans == 0); while ((enm = LIST_FIRST(&ec->ec_multiaddrs)) != NULL) { Index: src/sys/net/lagg/if_lagg.c diff -u src/sys/net/lagg/if_lagg.c:1.9 src/sys/net/lagg/if_lagg.c:1.10 --- src/sys/net/lagg/if_lagg.c:1.9 Thu Sep 30 04:23:30 2021 +++ src/sys/net/lagg/if_lagg.c Thu Sep 30 04:29:17 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: if_lagg.c,v 1.9 2021/09/30 04:23:30 yamaguchi Exp $ */ +/* $NetBSD: if_lagg.c,v 1.10 2021/09/30 04:29:17 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.9 2021/09/30 04:23:30 yamaguchi Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.10 2021/09/30 04:29:17 yamaguchi Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -148,6 +148,7 @@ static int lagg_media_change(struct ifne static void lagg_media_status(struct ifnet *, struct ifmediareq *); static int lagg_vlan_cb(struct ethercom *, uint16_t, bool); static void lagg_linkstate_changed(void *); +static void lagg_ifdetach(void *); static struct lagg_softc * lagg_softc_alloc(enum lagg_iftypes); static void lagg_softc_free(struct lagg_softc *); @@ -174,7 +175,7 @@ static int lagg_pr_attach(struct lagg_so static void lagg_pr_detach(struct lagg_softc *); static int lagg_addport(struct lagg_softc *, struct ifnet *); static int lagg_delport(struct lagg_softc *, struct ifnet *); -static void lagg_delport_all(struct lagg_softc *); +static int lagg_delport_all(struct lagg_softc *); static int lagg_port_ioctl(struct ifnet *, u_long, void *); static int lagg_port_output(struct ifnet *, struct mbuf *, const struct sockaddr *, const struct rtentry *); @@ -440,12 +441,15 @@ static int lagg_clone_destroy(struct ifnet *ifp) { struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; + struct lagg_port *lp; lagg_stop(ifp, 1); - IFNET_LOCK(ifp); - lagg_delport_all(sc); - IFNET_UNLOCK(ifp); + LAGG_LOCK(sc); + while ((lp = LAGG_PORTS_FIRST(sc)) != NULL) { + lagg_port_teardown(sc, lp, false); + } + LAGG_UNLOCK(sc); switch (ifp->if_type) { case IFT_ETHER: @@ -552,7 +556,9 @@ lagg_config(struct lagg_softc *sc, struc break; } - lagg_delport_all(sc); + error = lagg_delport_all(sc); + if (error != 0) + break; error = lagg_pr_attach(sc, lrq->lrq_proto); if (error != 0) break; @@ -2020,6 +2026,8 @@ lagg_port_setup(struct lagg_softc *sc, lp->lp_prio = LAGG_PORT_PRIO; lp->lp_linkstate_hook = if_linkstate_change_establish(ifp_port, lagg_linkstate_changed, ifp_port); + lp->lp_ifdetach_hook = ether_ifdetachhook_establish(ifp_port, + lagg_ifdetach, ifp_port); psref_target_init(&lp->lp_psref, lagg_port_psref_class); IFNET_LOCK(ifp_port); @@ -2116,6 +2124,8 @@ restore_ipv6lla: psref_target_destroy(&lp->lp_psref, lagg_port_psref_class); if_linkstate_change_disestablish(ifp_port, lp->lp_linkstate_hook, NULL); + ether_ifdetachhook_disestablish(ifp_port, + lp->lp_ifdetach_hook, &sc->sc_lock); return error; } @@ -2129,12 +2139,17 @@ lagg_port_teardown(struct lagg_softc *sc KASSERT(LAGG_LOCKED(sc)); - if (lp == NULL) - return; - ifp_port = lp->lp_ifp; stopped = false; + ether_ifdetachhook_disestablish(ifp_port, + lp->lp_ifdetach_hook, &sc->sc_lock); + + if (ifp_port->if_lagg == NULL) { + /* already done in lagg_ifdetach() */ + return; + } + SIMPLEQ_REMOVE(&sc->sc_ports, lp, lagg_port, lp_entry); sc->sc_nports--; atomic_store_release(&ifp_port->if_lagg, NULL); @@ -2209,38 +2224,59 @@ lagg_delport(struct lagg_softc *sc, stru { struct lagg_port *lp; uint8_t lladdr[ETHER_ADDR_LEN]; + int error; KASSERT(IFNET_LOCKED(&sc->sc_if)); + error = 0; LAGG_LOCK(sc); lp = ifp_port->if_lagg; if (lp == NULL || lp->lp_softc != sc) { - LAGG_UNLOCK(sc); - return ENOENT; + error = ENOENT; + goto out; + } + + if (lp->lp_ifdetaching) { + error = EBUSY; + goto out; } lagg_lladdr_cpy(lladdr, sc->sc_lladdr); lagg_port_teardown(sc, lp, false); lagg_sadl_update(sc, lladdr); + +out: LAGG_UNLOCK(sc); - return 0; + return error; } -static void +static int lagg_delport_all(struct lagg_softc *sc) { - struct lagg_port *lp, *lp0; + struct lagg_port *lp; uint8_t lladdr[ETHER_ADDR_LEN]; + int error; + + KASSERT(IFNET_LOCKED(&sc->sc_if)); + + error = 0; LAGG_LOCK(sc); lagg_lladdr_cpy(lladdr, sc->sc_lladdr); - LAGG_PORTS_FOREACH_SAFE(sc, lp, lp0) { + while ((lp = LAGG_PORTS_FIRST(sc)) != NULL) { + if (lp->lp_ifdetaching) { + error = EBUSY; + continue; + } + lagg_port_teardown(sc, lp, false); } lagg_sadl_update(sc, lladdr); LAGG_UNLOCK(sc); + + return error; } static int @@ -2406,8 +2442,9 @@ lagg_port_output(struct ifnet *ifp, stru } void -lagg_ifdetach(struct ifnet *ifp_port) +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]; @@ -2429,16 +2466,29 @@ lagg_ifdetach(struct ifnet *ifp_port) } pserialize_read_exit(s); - IFNET_LOCK(&sc->sc_if); LAGG_LOCK(sc); + lp = ifp_port->if_lagg; + if (lp == NULL) { + LAGG_UNLOCK(sc); + return; + } + /* - * reload if_lagg because it may write - * after pserialize_read_exit. + * mark as a detaching to prevent other + * lagg_port_teardown() processings with IFNET_LOCK() held */ + lp->lp_ifdetaching = true; + + LAGG_UNLOCK(sc); + + IFNET_LOCK(&sc->sc_if); + LAGG_LOCK(sc); lp = ifp_port->if_lagg; - lagg_lladdr_cpy(lladdr, sc->sc_lladdr); - lagg_port_teardown(sc, lp, true); - lagg_sadl_update(sc, lladdr); + 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); } Index: src/sys/net/lagg/if_laggproto.h diff -u src/sys/net/lagg/if_laggproto.h:1.5 src/sys/net/lagg/if_laggproto.h:1.6 --- src/sys/net/lagg/if_laggproto.h:1.5 Thu Sep 30 04:23:30 2021 +++ src/sys/net/lagg/if_laggproto.h Thu Sep 30 04:29:17 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: if_laggproto.h,v 1.5 2021/09/30 04:23:30 yamaguchi Exp $ */ +/* $NetBSD: if_laggproto.h,v 1.6 2021/09/30 04:29:17 yamaguchi Exp $ */ /* * Copyright (c) 2021 Internet Initiative Japan Inc. @@ -67,8 +67,9 @@ struct lagg_port { struct ifnet *lp_ifp; /* physical interface */ struct lagg_softc *lp_softc; /* parent lagg */ void *lp_proto_ctx; - bool lp_detaching; + bool lp_ifdetaching; void *lp_linkstate_hook; + void *lp_ifdetach_hook; uint32_t lp_prio; /* port priority */ uint32_t lp_flags; /* port flags */ @@ -205,8 +206,7 @@ struct lagg_softc { #define LAGG_PORTS_FOREACH(_sc, _lp) \ SIMPLEQ_FOREACH((_lp), &(_sc)->sc_ports, lp_entry) -#define LAGG_PORTS_FOREACH_SAFE(_sc, _lp, _lptmp) \ - SIMPLEQ_FOREACH_SAFE((_lp), &(_sc)->sc_ports, lp_entry, (_lptmp)) +#define LAGG_PORTS_FIRST(_sc) SIMPLEQ_FIRST(&(_sc)->sc_ports) #define LAGG_PORTS_EMPTY(_sc) SIMPLEQ_EMPTY(&(_sc)->sc_ports) #define LAGG_PORT_IOCTL(_lp, _cmd, _data) \ (_lp)->lp_ioctl == NULL ? ENOTTY : \ Index: src/sys/net/lagg/if_laggvar.h diff -u src/sys/net/lagg/if_laggvar.h:1.3 src/sys/net/lagg/if_laggvar.h:1.4 --- src/sys/net/lagg/if_laggvar.h:1.3 Thu Sep 30 03:39:39 2021 +++ src/sys/net/lagg/if_laggvar.h Thu Sep 30 04:29:17 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: if_laggvar.h,v 1.3 2021/09/30 03:39:39 yamaguchi Exp $ */ +/* $NetBSD: if_laggvar.h,v 1.4 2021/09/30 04:29:17 yamaguchi Exp $ */ /* * Copyright (c) 2021 Internet Initiative Japan Inc. @@ -29,8 +29,6 @@ #ifndef _NET_LAGG_IF_LAGGVAR_H_ #define _NET_LAGG_IF_LAGGVAR_H_ -void lagg_ifdetach(struct ifnet *); - extern struct mbuf * (*lagg_input_ethernet_p)(struct ifnet *, struct mbuf *);