summaryrefslogtreecommitdiffstats
path: root/sys/net/if_clone.c
diff options
context:
space:
mode:
authorthompsa <thompsa@FreeBSD.org>2005-11-08 20:08:34 +0000
committerthompsa <thompsa@FreeBSD.org>2005-11-08 20:08:34 +0000
commit48c0bcb5c218c021c1da0e53702d2e83708a471a (patch)
treeb5694a5381004aaef7ca02a29efbdb85ad370b4d /sys/net/if_clone.c
parent7b0555d4591f77539a864cf4d9ca449610fd188c (diff)
downloadFreeBSD-src-48c0bcb5c218c021c1da0e53702d2e83708a471a.zip
FreeBSD-src-48c0bcb5c218c021c1da0e53702d2e83708a471a.tar.gz
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
Diffstat (limited to 'sys/net/if_clone.c')
-rw-r--r--sys/net/if_clone.c70
1 files changed, 61 insertions, 9 deletions
diff --git a/sys/net/if_clone.c b/sys/net/if_clone.c
index 746f08f..859ece2 100644
--- a/sys/net/if_clone.c
+++ b/sys/net/if_clone.c
@@ -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));
OpenPOWER on IntegriCloud