From 4e7e0183e1884e2ea9beb2720b22610c0a9e83ba Mon Sep 17 00:00:00 2001 From: Andrew Thompson Date: Tue, 8 Nov 2005 20:08:34 +0000 Subject: Move the cloned interface list management in to if_clone. For some drivers the softc lists and associated mutex are now unused so these have been removed. Calling if_clone_detach() will now destroy all the cloned interfaces for the driver and in most cases is all thats needed to unload. Idea by: brooks Reviewed by: brooks --- sys/contrib/pf/net/if_pflog.c | 3 -- sys/contrib/pf/net/if_pfsync.c | 3 -- sys/net/if_bridge.c | 18 ----------- sys/net/if_bridgevar.h | 1 - sys/net/if_clone.c | 70 ++++++++++++++++++++++++++++++++++++------ sys/net/if_clone.h | 1 + sys/net/if_disc.c | 21 ------------- sys/net/if_faith.c | 22 ------------- sys/net/if_gif.c | 9 ------ sys/net/if_gre.c | 9 ------ sys/net/if_ppp.c | 8 ----- sys/net/if_stf.c | 25 --------------- sys/net/if_var.h | 1 + sys/net/if_vlan.c | 3 -- sys/netinet/ip_carp.c | 3 -- 15 files changed, 63 insertions(+), 134 deletions(-) diff --git a/sys/contrib/pf/net/if_pflog.c b/sys/contrib/pf/net/if_pflog.c index 2497a94df72c..1466ec2b3f8a 100644 --- a/sys/contrib/pf/net/if_pflog.c +++ b/sys/contrib/pf/net/if_pflog.c @@ -369,9 +369,6 @@ pflog_modevent(module_t mod, int type, void *data) case MOD_UNLOAD: if_clone_detach(&pflog_cloner); - while (!LIST_EMPTY(&pflog_list)) - ifc_simple_destroy(&pflog_cloner, - SCP2IFP(LIST_FIRST(&pflog_list))); break; default: diff --git a/sys/contrib/pf/net/if_pfsync.c b/sys/contrib/pf/net/if_pfsync.c index 5f0e8a6f5436..e7f80e2db246 100644 --- a/sys/contrib/pf/net/if_pfsync.c +++ b/sys/contrib/pf/net/if_pfsync.c @@ -1851,9 +1851,6 @@ pfsync_modevent(module_t mod, int type, void *data) case MOD_UNLOAD: if_clone_detach(&pfsync_cloner); - while (!LIST_EMPTY(&pfsync_list)) - ifc_simple_destroy(&pfsync_cloner, - SCP2IFP(LIST_FIRST(&pfsync_list))); break; default: diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c index 0b2bd75278db..7090a6bbd8df 100644 --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -170,8 +170,6 @@ __FBSDID("$FreeBSD$"); #define BRIDGE_RTABLE_PRUNE_PERIOD (5 * 60) #endif -static struct mtx bridge_list_mtx; - int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD; uma_zone_t bridge_rtnode_zone; @@ -339,8 +337,6 @@ const int bridge_control_table_size = static const u_char etherbroadcastaddr[ETHER_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; -LIST_HEAD(, bridge_softc) bridge_list; - IFC_SIMPLE_DECLARE(bridge, 0); static int @@ -349,12 +345,10 @@ bridge_modevent(module_t mod, int type, void *data) switch (type) { case MOD_LOAD: - mtx_init(&bridge_list_mtx, "if_bridge list", NULL, MTX_DEF); if_clone_attach(&bridge_cloner); bridge_rtnode_zone = uma_zcreate("bridge_rtnode", sizeof(struct bridge_rtnode), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); - LIST_INIT(&bridge_list); bridge_input_p = bridge_input; bridge_output_p = bridge_output; bridge_dn_p = bridge_dummynet; @@ -363,16 +357,12 @@ bridge_modevent(module_t mod, int type, void *data) break; case MOD_UNLOAD: if_clone_detach(&bridge_cloner); - while (!LIST_EMPTY(&bridge_list)) - ifc_simple_destroy(&bridge_cloner, - LIST_FIRST(&bridge_list)->sc_ifp); uma_zdestroy(bridge_rtnode_zone); bridge_input_p = NULL; bridge_output_p = NULL; bridge_dn_p = NULL; bridge_detach_p = NULL; bstp_linkstate_p = NULL; - mtx_destroy(&bridge_list_mtx); break; default: return EOPNOTSUPP; @@ -482,10 +472,6 @@ bridge_clone_create(struct if_clone *ifc, int unit) ifp->if_baudrate = 0; ifp->if_type = IFT_BRIDGE; - mtx_lock(&bridge_list_mtx); - LIST_INSERT_HEAD(&bridge_list, sc, sc_list); - mtx_unlock(&bridge_list_mtx); - return (0); } @@ -513,10 +499,6 @@ bridge_clone_destroy(struct ifnet *ifp) callout_drain(&sc->sc_brcallout); callout_drain(&sc->sc_bstpcallout); - mtx_lock(&bridge_list_mtx); - LIST_REMOVE(sc, sc_list); - mtx_unlock(&bridge_list_mtx); - ether_ifdetach(ifp); if_free_type(ifp, IFT_ETHER); diff --git a/sys/net/if_bridgevar.h b/sys/net/if_bridgevar.h index 7c6b9c2fbd1c..98dfcda34dbf 100644 --- a/sys/net/if_bridgevar.h +++ b/sys/net/if_bridgevar.h @@ -264,7 +264,6 @@ struct bridge_rtnode { */ struct bridge_softc { struct ifnet *sc_ifp; /* make this an interface */ - LIST_ENTRY(bridge_softc) sc_list; struct mtx sc_mtx; struct cv sc_cv; uint64_t sc_designated_root; diff --git a/sys/net/if_clone.c b/sys/net/if_clone.c index 746f08f57042..859ece283fe4 100644 --- a/sys/net/if_clone.c +++ b/sys/net/if_clone.c @@ -49,7 +49,9 @@ #include #include -static void if_clone_free(struct if_clone *ifc); +static void if_clone_free(struct if_clone *ifc); +static int if_clone_createif(struct if_clone *ifc, char *name, size_t len); +static int if_clone_destroyif(struct if_clone *ifc, struct ifnet *ifp); static struct mtx if_cloners_mtx; static int if_cloners_count; @@ -100,6 +102,11 @@ LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners); } \ } while (0) +#define IFC_IFLIST_INSERT(_ifc, _ifp) \ + LIST_INSERT_HEAD(&_ifc->ifc_iflist, _ifp, if_clones) +#define IFC_IFLIST_REMOVE(_ifc, _ifp) \ + LIST_REMOVE(_ifp, if_clones) + static MALLOC_DEFINE(M_CLONE, "clone", "interface cloning framework"); void @@ -109,17 +116,13 @@ if_clone_init(void) } /* - * Create a clone network interface. + * Lookup and create a clone network interface. */ int if_clone_create(char *name, size_t len) { - int err; struct if_clone *ifc; - if (ifunit(name) != NULL) - return (EEXIST); - /* Try to find an applicable cloner for this request */ IF_CLONERS_LOCK(); LIST_FOREACH(ifc, &if_cloners, ifc_list) { @@ -132,17 +135,42 @@ if_clone_create(char *name, size_t len) if (ifc == NULL) return (EINVAL); + return (if_clone_createif(ifc, name, len)); +} + +/* + * Create a clone network interface. + */ +static int +if_clone_createif(struct if_clone *ifc, char *name, size_t len) +{ + int err; + struct ifnet *ifp; + + if (ifunit(name) != NULL) + return (EEXIST); + err = (*ifc->ifc_create)(ifc, name, len); + + if (!err) { + ifp = ifunit(name); + if (ifp == NULL) + panic("%s: lookup failed for %s", __func__, name); + + IF_CLONE_LOCK(ifc); + IFC_IFLIST_INSERT(ifc, ifp); + IF_CLONE_UNLOCK(ifc); + } + return (err); } /* - * Destroy a clone network interface. + * Lookup and destroy a clone network interface. */ int if_clone_destroy(const char *name) { - int err; struct if_clone *ifc; struct ifnet *ifp; @@ -161,6 +189,21 @@ if_clone_destroy(const char *name) if (ifc == NULL) return (EINVAL); + return (if_clone_destroyif(ifc, ifp)); +} + +/* + * Destroy a clone network interface. + */ +static int +if_clone_destroyif(struct if_clone *ifc, struct ifnet *ifp) +{ + int err; + + IF_CLONE_LOCK(ifc); + IFC_IFLIST_REMOVE(ifc, ifp); + IF_CLONE_UNLOCK(ifc); + if (ifc->ifc_destroy == NULL) { err = EOPNOTSUPP; goto done; @@ -197,6 +240,8 @@ if_clone_attach(struct if_clone *ifc) if_cloners_count++; IF_CLONERS_UNLOCK(); + LIST_INIT(&ifc->ifc_iflist); + if (ifc->ifc_attach != NULL) (*ifc->ifc_attach)(ifc); EVENTHANDLER_INVOKE(if_clone_event, ifc); @@ -219,6 +264,10 @@ if_clone_detach(struct if_clone *ifc) if (ifc->ifc_attach == ifc_simple_attach) ifcs->ifcs_minifs = 0; + /* destroy all interfaces for this cloner */ + while (!LIST_EMPTY(&ifc->ifc_iflist)) + if_clone_destroyif(ifc, LIST_FIRST(&ifc->ifc_iflist)); + IF_CLONE_REMREF(ifc); } @@ -230,6 +279,9 @@ if_clone_free(struct if_clone *ifc) ("ifc_units[%d] is not empty", bytoff)); } + KASSERT(LIST_EMPTY(&ifc->ifc_iflist), + ("%s: ifc_iflist not empty", __func__)); + IF_CLONE_LOCK_DESTROY(ifc); free(ifc->ifc_units, M_CLONE); } @@ -401,7 +453,7 @@ ifc_simple_attach(struct if_clone *ifc) for (unit = 0; unit < ifcs->ifcs_minifs; unit++) { snprintf(name, IFNAMSIZ, "%s%d", ifc->ifc_name, unit); - err = (*ifc->ifc_create)(ifc, name, IFNAMSIZ); + err = if_clone_createif(ifc, name, IFNAMSIZ); KASSERT(err == 0, ("%s: failed to create required interface %s", __func__, name)); diff --git a/sys/net/if_clone.h b/sys/net/if_clone.h index d84b47ef42aa..38a09598a3e1 100644 --- a/sys/net/if_clone.h +++ b/sys/net/if_clone.h @@ -66,6 +66,7 @@ struct if_clone { long ifc_refcnt; /* (i) Refrence count. */ struct mtx ifc_mtx; /* Muted to protect members. */ + LIST_HEAD(, ifnet) ifc_iflist; /* (i) List of cloned interfaces */ }; void if_clone_init(void); diff --git a/sys/net/if_disc.c b/sys/net/if_disc.c index 3b0804e5cb3a..0a138dfb63ae 100644 --- a/sys/net/if_disc.c +++ b/sys/net/if_disc.c @@ -63,7 +63,6 @@ struct disc_softc { struct ifnet *sc_ifp; /* must be first */ - LIST_ENTRY(disc_softc) sc_list; }; static int discoutput(struct ifnet *, struct mbuf *, @@ -73,9 +72,7 @@ static int discioctl(struct ifnet *, u_long, caddr_t); static int disc_clone_create(struct if_clone *, int); static void disc_clone_destroy(struct ifnet *); -static struct mtx disc_mtx; static MALLOC_DEFINE(M_DISC, DISCNAME, "Discard interface"); -static LIST_HEAD(, disc_softc) disc_softc_list; IFC_SIMPLE_DECLARE(disc, 0); @@ -103,9 +100,6 @@ disc_clone_create(struct if_clone *ifc, int unit) ifp->if_snd.ifq_maxlen = 20; if_attach(ifp); bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); - mtx_lock(&disc_mtx); - LIST_INSERT_HEAD(&disc_softc_list, sc, sc_list); - mtx_unlock(&disc_mtx); return (0); } @@ -116,9 +110,6 @@ disc_clone_destroy(struct ifnet *ifp) struct disc_softc *sc; sc = ifp->if_softc; - mtx_lock(&disc_mtx); - LIST_REMOVE(sc, sc_list); - mtx_unlock(&disc_mtx); bpfdetach(ifp); if_detach(ifp); @@ -130,25 +121,13 @@ disc_clone_destroy(struct ifnet *ifp) static int disc_modevent(module_t mod, int type, void *data) { - struct disc_softc *sc; switch (type) { case MOD_LOAD: - mtx_init(&disc_mtx, "disc_mtx", NULL, MTX_DEF); - LIST_INIT(&disc_softc_list); if_clone_attach(&disc_cloner); break; case MOD_UNLOAD: if_clone_detach(&disc_cloner); - - mtx_lock(&disc_mtx); - while ((sc = LIST_FIRST(&disc_softc_list)) != NULL) { - mtx_unlock(&disc_mtx); - ifc_simple_destroy(&disc_cloner, sc->sc_ifp); - mtx_lock(&disc_mtx); - } - mtx_unlock(&disc_mtx); - mtx_destroy(&disc_mtx); break; default: return (EOPNOTSUPP); diff --git a/sys/net/if_faith.c b/sys/net/if_faith.c index 677e1b22e573..71b8c357359c 100644 --- a/sys/net/if_faith.c +++ b/sys/net/if_faith.c @@ -84,7 +84,6 @@ struct faith_softc { struct ifnet *sc_ifp; - LIST_ENTRY(faith_softc) sc_list; }; static int faithioctl(struct ifnet *, u_long, caddr_t); @@ -97,9 +96,7 @@ static int faithprefix(struct in6_addr *); static int faithmodevent(module_t, int, void *); -static struct mtx faith_mtx; static MALLOC_DEFINE(M_FAITH, FAITHNAME, "Firewall Assisted Tunnel Interface"); -static LIST_HEAD(, faith_softc) faith_softc_list; static int faith_clone_create(struct if_clone *, int); static void faith_clone_destroy(struct ifnet *); @@ -114,12 +111,9 @@ faithmodevent(mod, type, data) int type; void *data; { - struct faith_softc *sc; switch (type) { case MOD_LOAD: - mtx_init(&faith_mtx, "faith_mtx", NULL, MTX_DEF); - LIST_INIT(&faith_softc_list); if_clone_attach(&faith_cloner); #ifdef INET6 @@ -133,15 +127,6 @@ faithmodevent(mod, type, data) #endif if_clone_detach(&faith_cloner); - - mtx_lock(&faith_mtx); - while ((sc = LIST_FIRST(&faith_softc_list)) != NULL) { - mtx_unlock(&faith_mtx); - ifc_simple_destroy(&faith_cloner, sc->sc_ifp); - mtx_lock(&faith_mtx); - } - mtx_unlock(&faith_mtx); - mtx_destroy(&faith_mtx); break; default: return EOPNOTSUPP; @@ -186,9 +171,6 @@ faith_clone_create(ifc, unit) ifp->if_snd.ifq_maxlen = ifqmaxlen; if_attach(ifp); bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); - mtx_lock(&faith_mtx); - LIST_INSERT_HEAD(&faith_softc_list, sc, sc_list); - mtx_unlock(&faith_mtx); return (0); } @@ -198,10 +180,6 @@ faith_clone_destroy(ifp) { struct faith_softc *sc = ifp->if_softc; - mtx_lock(&faith_mtx); - LIST_REMOVE(sc, sc_list); - mtx_unlock(&faith_mtx); - bpfdetach(ifp); if_detach(ifp); if_free(ifp); diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c index da611ccc490b..c946a1cb96ab 100644 --- a/sys/net/if_gif.c +++ b/sys/net/if_gif.c @@ -225,7 +225,6 @@ gifmodevent(mod, type, data) int type; void *data; { - struct gif_softc *sc; switch (type) { case MOD_LOAD: @@ -240,14 +239,6 @@ gifmodevent(mod, type, data) break; case MOD_UNLOAD: if_clone_detach(&gif_cloner); - - mtx_lock(&gif_mtx); - while ((sc = LIST_FIRST(&gif_softc_list)) != NULL) { - mtx_unlock(&gif_mtx); - ifc_simple_destroy(&gif_cloner, GIF2IFP(sc)); - mtx_lock(&gif_mtx); - } - mtx_unlock(&gif_mtx); mtx_destroy(&gif_mtx); #ifdef INET6 ip6_gif_hlim = 0; diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c index 53639f6ce2d3..22ceba549e6b 100644 --- a/sys/net/if_gre.c +++ b/sys/net/if_gre.c @@ -774,7 +774,6 @@ gre_in_cksum(u_int16_t *p, u_int len) static int gremodevent(module_t mod, int type, void *data) { - struct gre_softc *sc; switch (type) { case MOD_LOAD: @@ -782,14 +781,6 @@ gremodevent(module_t mod, int type, void *data) break; case MOD_UNLOAD: if_clone_detach(&gre_cloner); - - mtx_lock(&gre_mtx); - while ((sc = LIST_FIRST(&gre_softc_list)) != NULL) { - mtx_unlock(&gre_mtx); - ifc_simple_destroy(&gre_cloner, GRE2IFP(sc)); - mtx_lock(&gre_mtx); - } - mtx_unlock(&gre_mtx); mtx_destroy(&gre_mtx); break; default: diff --git a/sys/net/if_ppp.c b/sys/net/if_ppp.c index 45915c6b8e1a..3d5cd13f723b 100644 --- a/sys/net/if_ppp.c +++ b/sys/net/if_ppp.c @@ -263,7 +263,6 @@ ppp_clone_destroy(struct ifnet *ifp) static int ppp_modevent(module_t mod, int type, void *data) { - struct ppp_softc *sc; switch (type) { case MOD_LOAD: @@ -285,13 +284,6 @@ ppp_modevent(module_t mod, int type, void *data) netisr_unregister(NETISR_PPP); if_clone_detach(&ppp_cloner); - - PPP_LIST_LOCK(); - while ((sc = LIST_FIRST(&ppp_softc_list)) != NULL) { - PPP_LIST_UNLOCK(); - ifc_simple_destroy(&ppp_cloner, PPP2IFP(sc)); - PPP_LIST_LOCK(); - } PPP_LIST_LOCK_DESTROY(); break; default: diff --git a/sys/net/if_stf.c b/sys/net/if_stf.c index e779b17a8068..a08291a8a9cb 100644 --- a/sys/net/if_stf.c +++ b/sys/net/if_stf.c @@ -138,19 +138,14 @@ struct stf_softc { } __sc_ro46; #define sc_ro __sc_ro46.__sc_ro4 const struct encaptab *encap_cookie; - LIST_ENTRY(stf_softc) sc_list; /* all stf's are linked */ }; #define STF2IFP(sc) ((sc)->sc_ifp) /* - * All mutable global variables in if_stf.c are protected by stf_mtx. * XXXRW: Note that mutable fields in the softc are not currently locked: * in particular, sc_ro needs to be protected from concurrent entrance * of stf_output(). */ -static struct mtx stf_mtx; -static LIST_HEAD(, stf_softc) stf_softc_list; - static MALLOC_DEFINE(M_STF, STFNAME, "6to4 Tunnel Interface"); static const int ip_stf_ttl = 40; @@ -246,9 +241,6 @@ stf_clone_create(struct if_clone *ifc, char *name, size_t len) ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; if_attach(ifp); bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); - mtx_lock(&stf_mtx); - LIST_INSERT_HEAD(&stf_softc_list, sc, sc_list); - mtx_unlock(&stf_mtx); return (0); } @@ -258,10 +250,6 @@ stf_clone_destroy(struct if_clone *ifc, struct ifnet *ifp) struct stf_softc *sc = ifp->if_softc; int err; - mtx_lock(&stf_mtx); - LIST_REMOVE(sc, sc_list); - mtx_unlock(&stf_mtx); - err = encap_detach(sc->encap_cookie); KASSERT(err == 0, ("Unexpected error detaching encap_cookie")); bpfdetach(ifp); @@ -280,26 +268,13 @@ stfmodevent(mod, type, data) int type; void *data; { - struct stf_softc *sc; switch (type) { case MOD_LOAD: - mtx_init(&stf_mtx, "stf_mtx", NULL, MTX_DEF); - LIST_INIT(&stf_softc_list); if_clone_attach(&stf_cloner); - break; case MOD_UNLOAD: if_clone_detach(&stf_cloner); - - mtx_lock(&stf_mtx); - while ((sc = LIST_FIRST(&stf_softc_list)) != NULL) { - mtx_unlock(&stf_mtx); - stf_clone_destroy(&stf_cloner, STF2IFP(sc)); - mtx_lock(&stf_mtx); - } - mtx_unlock(&stf_mtx); - mtx_destroy(&stf_mtx); break; default: return (EOPNOTSUPP); diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 783ddd85eb23..b09319f14a2b 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -180,6 +180,7 @@ struct ifnet { struct task if_starttask; /* task for IFF_NEEDSGIANT */ struct task if_linktask; /* task for link change events */ struct mtx if_addr_mtx; /* mutex to protect address lists */ + LIST_ENTRY(ifnet) if_clones; /* interfaces of a cloner */ }; typedef void if_init_f_t(void *); diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index 15a2a7900ecb..b8b0703dcb4c 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -251,9 +251,6 @@ vlan_modevent(module_t mod, int type, void *data) if_clone_detach(&vlan_cloner); vlan_input_p = NULL; vlan_link_state_p = NULL; - while (!LIST_EMPTY(&ifv_list)) - vlan_clone_destroy(&vlan_cloner, - LIST_FIRST(&ifv_list)->ifv_ifp); VLAN_LOCK_DESTROY(); break; default: diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index 5fe4577e6801..44157b4350f6 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -2143,9 +2143,6 @@ carp_modevent(module_t mod, int type, void *data) case MOD_UNLOAD: if_clone_detach(&carp_cloner); - while (!LIST_EMPTY(&carpif_list)) - ifc_simple_destroy(&carp_cloner, - SC2IFP(LIST_FIRST(&carpif_list))); mtx_destroy(&carp_mtx); break; -- cgit v1.2.3