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
This commit is contained in:
Andrew Thompson 2005-11-08 20:08:34 +00:00
parent 2a522eb9d3
commit 4e7e0183e1
15 changed files with 63 additions and 134 deletions

View File

@ -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:

View File

@ -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:

View File

@ -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);

View File

@ -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;

View File

@ -49,7 +49,9 @@
#include <net/radix.h>
#include <net/route.h>
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));

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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:

View File

@ -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:

View File

@ -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);

View File

@ -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 *);

View File

@ -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:

View File

@ -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;