summaryrefslogtreecommitdiffstats
path: root/sys/net/if.c
diff options
context:
space:
mode:
authormux <mux@FreeBSD.org>2002-03-11 09:26:07 +0000
committermux <mux@FreeBSD.org>2002-03-11 09:26:07 +0000
commit9a5e4c88a3c8f122fd226c41249210b7d9a95ab7 (patch)
treeead93d76aaa7a11f5c58953041c77a386e18fc64 /sys/net/if.c
parent352806ecf32064d3f84e690dc624e0a0aac0507b (diff)
downloadFreeBSD-src-9a5e4c88a3c8f122fd226c41249210b7d9a95ab7.zip
FreeBSD-src-9a5e4c88a3c8f122fd226c41249210b7d9a95ab7.tar.gz
Simplify the interface cloning framework by handling unit
unit allocation with a bitmap in the generic layer. This allows us to get rid of the duplicated rman code in every clonable interface. Reviewed by: brooks Approved by: phk
Diffstat (limited to 'sys/net/if.c')
-rw-r--r--sys/net/if.c63
1 files changed, 59 insertions, 4 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index fe1f7f7..750b0f7 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -119,6 +119,7 @@ SYSINIT(interface_check, SI_SUB_PROTO_IF, SI_ORDER_FIRST, if_check, NULL)
MALLOC_DEFINE(M_IFADDR, "ifaddr", "interface address");
MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
+MALLOC_DEFINE(M_CLONE, "clone", "interface cloning framework");
#define CDEV_MAJOR 165
@@ -580,7 +581,7 @@ if_clone_create(name, len)
{
struct if_clone *ifc;
char *dp;
- int wildcard;
+ int wildcard, bytoff, bitoff;
int unit;
int err;
@@ -591,12 +592,41 @@ if_clone_create(name, len)
if (ifunit(name) != NULL)
return (EEXIST);
+ bytoff = bitoff = 0;
wildcard = (unit < 0);
+ /*
+ * Find a free unit if none was given.
+ */
+ if (wildcard) {
+ while ((bytoff < ifc->ifc_bmlen)
+ && (ifc->ifc_units[bytoff] == 0xff))
+ bytoff++;
+ if (bytoff >= ifc->ifc_bmlen)
+ return (ENOSPC);
+ while ((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0)
+ bitoff++;
+ unit = (bytoff << 3) + bitoff;
+ }
+
+ if (unit > ifc->ifc_maxunit)
+ return (ENXIO);
- err = (*ifc->ifc_create)(ifc, &unit);
+ err = (*ifc->ifc_create)(ifc, unit);
if (err != 0)
return (err);
+ if (!wildcard) {
+ bytoff = unit >> 3;
+ bitoff = unit - (bytoff << 3);
+ }
+
+ /*
+ * Allocate the unit in the bitmap.
+ */
+ KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) == 0,
+ ("%s: bit is already set", __func__));
+ ifc->ifc_units[bytoff] |= (1 << bitoff);
+
/* In the wildcard case, we need to update the name. */
if (wildcard) {
for (dp = name; *dp != '\0'; dp++);
@@ -624,8 +654,10 @@ if_clone_destroy(name)
{
struct if_clone *ifc;
struct ifnet *ifp;
+ int bytoff, bitoff;
+ int err, unit;
- ifc = if_clone_lookup(name, NULL);
+ ifc = if_clone_lookup(name, &unit);
if (ifc == NULL)
return (EINVAL);
@@ -636,7 +668,19 @@ if_clone_destroy(name)
if (ifc->ifc_destroy == NULL)
return (EOPNOTSUPP);
- return ((*ifc->ifc_destroy)(ifp));
+ err = (*ifc->ifc_destroy)(ifp);
+ if (err != 0)
+ return (err);
+
+ /*
+ * Compute offset in the bitmap and deallocate the unit.
+ */
+ bytoff = unit >> 3;
+ bitoff = unit - (bytoff << 3);
+ KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0,
+ ("%s: bit is already cleared", __func__));
+ ifc->ifc_units[bytoff] &= ~(1 << bitoff);
+ return (0);
}
/*
@@ -689,7 +733,17 @@ void
if_clone_attach(ifc)
struct if_clone *ifc;
{
+ int len, maxclone;
+ /*
+ * Compute bitmap size and allocate it.
+ */
+ maxclone = ifc->ifc_maxunit + 1;
+ len = maxclone >> 3;
+ if ((len << 3) < maxclone)
+ len++;
+ ifc->ifc_units = malloc(len, M_CLONE, M_WAITOK | M_ZERO);
+ ifc->ifc_bmlen = len;
LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
if_cloners_count++;
}
@@ -703,6 +757,7 @@ if_clone_detach(ifc)
{
LIST_REMOVE(ifc, ifc_list);
+ free(ifc->ifc_units, M_CLONE);
if_cloners_count--;
}
OpenPOWER on IntegriCloud