diff options
author | zec <zec@FreeBSD.org> | 2009-05-23 21:43:44 +0000 |
---|---|---|
committer | zec <zec@FreeBSD.org> | 2009-05-23 21:43:44 +0000 |
commit | 48f748dc297cbf46f02ec8b61d47436d66d0d8b9 (patch) | |
tree | 488633605f2f07bbba417ff74314596b3bb04cf2 /sys/net/if_clone.c | |
parent | 40574d258ab1aec7b8c5ad9d5d9ee09d5e3f5296 (diff) | |
download | FreeBSD-src-48f748dc297cbf46f02ec8b61d47436d66d0d8b9.zip FreeBSD-src-48f748dc297cbf46f02ec8b61d47436d66d0d8b9.tar.gz |
V_irtualize the if_clone framework, thus allowing for clonable ifnets
to optionally have overlapping unit numbers if attached in different
vnets.
At this stage if_loop is the only clonable ifnet class that has been
extended to allow for such overlapping allocation of unit numbers, i.e.
in each vnet it is possible to have a lo0 interface. Other clonable ifnet
classes remain to operate with traditional semantics, i.e. each instance
of a clonable ifnet will be assigned a globally unique unit number,
regardless in which vnet such an ifnet becomes instantiated.
While here, garbage collect unused _lo_list field in struct vnet_net,
as well as improve indentation for #defines in sys/net/vnet.h.
The layout of struct vnet_net has changed, therefore bump
__FreeBSD_version.
This change has no functional impact on nooptions VIMAGE kernel builds.
Reviewed by: bz, brooks
Approved by: julian (mentor)
Diffstat (limited to 'sys/net/if_clone.c')
-rw-r--r-- | sys/net/if_clone.c | 84 |
1 files changed, 71 insertions, 13 deletions
diff --git a/sys/net/if_clone.c b/sys/net/if_clone.c index a0140fc..eaa7397 100644 --- a/sys/net/if_clone.c +++ b/sys/net/if_clone.c @@ -55,10 +55,13 @@ static void if_clone_free(struct if_clone *ifc); static int if_clone_createif(struct if_clone *ifc, char *name, size_t len, caddr_t params); +static int vnet_clone_iattach(const void *); static struct mtx if_cloners_mtx; +#ifdef VIMAGE_GLOBALS static int if_cloners_count; -LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners); +LIST_HEAD(, if_clone) if_cloners; +#endif #define IF_CLONERS_LOCK_INIT() \ mtx_init(&if_cloners_mtx, "if_cloners lock", NULL, MTX_DEF) @@ -112,10 +115,32 @@ LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners); static MALLOC_DEFINE(M_CLONE, "clone", "interface cloning framework"); +#ifndef VIMAGE_GLOBALS +static const vnet_modinfo_t vnet_clone_modinfo = { + .vmi_id = VNET_MOD_IF_CLONE, + .vmi_name = "if_clone", + .vmi_iattach = vnet_clone_iattach +}; +#endif /* !VIMAGE_GLOBALS */ + +static int vnet_clone_iattach(const void *unused __unused) +{ + INIT_VNET_NET(curvnet); + + LIST_INIT(&V_if_cloners); + return (0); +} + void if_clone_init(void) { + IF_CLONERS_LOCK_INIT(); +#ifndef VIMAGE_GLOBALS + vnet_mod_register(&vnet_clone_modinfo); +#else + vnet_clone_iattach(NULL); +#endif } /* @@ -124,15 +149,27 @@ if_clone_init(void) int if_clone_create(char *name, size_t len, caddr_t params) { + INIT_VNET_NET(curvnet); struct if_clone *ifc; /* Try to find an applicable cloner for this request */ IF_CLONERS_LOCK(); - LIST_FOREACH(ifc, &if_cloners, ifc_list) { + LIST_FOREACH(ifc, &V_if_cloners, ifc_list) { if (ifc->ifc_match(ifc, name)) { break; } } +#ifdef VIMAGE + if (ifc == NULL && !IS_DEFAULT_VNET(curvnet)) { + CURVNET_SET_QUIET(vnet0); + INIT_VNET_NET(vnet0); + LIST_FOREACH(ifc, &V_if_cloners, ifc_list) { + if (ifc->ifc_match(ifc, name)) + break; + } + CURVNET_RESTORE(); + } +#endif IF_CLONERS_UNLOCK(); if (ifc == NULL) @@ -176,6 +213,7 @@ if_clone_createif(struct if_clone *ifc, char *name, size_t len, caddr_t params) int if_clone_destroy(const char *name) { + INIT_VNET_NET(curvnet); struct if_clone *ifc; struct ifnet *ifp; @@ -185,11 +223,22 @@ if_clone_destroy(const char *name) /* Find the cloner for this interface */ IF_CLONERS_LOCK(); - LIST_FOREACH(ifc, &if_cloners, ifc_list) { + LIST_FOREACH(ifc, &V_if_cloners, ifc_list) { if (strcmp(ifc->ifc_name, ifp->if_dname) == 0) { break; } } +#ifdef VIMAGE + if (ifc == NULL && !IS_DEFAULT_VNET(curvnet)) { + CURVNET_SET_QUIET(vnet0); + INIT_VNET_NET(vnet0); + LIST_FOREACH(ifc, &V_if_cloners, ifc_list) { + if (ifc->ifc_match(ifc, name)) + break; + } + CURVNET_RESTORE(); + } +#endif IF_CLONERS_UNLOCK(); if (ifc == NULL) return (EINVAL); @@ -208,11 +257,17 @@ if_clone_destroyif(struct if_clone *ifc, struct ifnet *ifp) if (ifc->ifc_destroy == NULL) return(EOPNOTSUPP); + /* + * Given that the cloned ifnet might be attached to a different + * vnet from where its cloner was registered, we have to + * switch to the vnet context of the target vnet. + */ + CURVNET_SET_QUIET(ifp->if_vnet); + IF_CLONE_LOCK(ifc); IFC_IFLIST_REMOVE(ifc, ifp); IF_CLONE_UNLOCK(ifc); - CURVNET_SET_QUIET(ifp->if_vnet); if_delgroup(ifp, ifc->ifc_name); err = (*ifc->ifc_destroy)(ifc, ifp); @@ -234,6 +289,7 @@ if_clone_destroyif(struct if_clone *ifc, struct ifnet *ifp) void if_clone_attach(struct if_clone *ifc) { + INIT_VNET_NET(curvnet); int len, maxclone; /* @@ -249,8 +305,8 @@ if_clone_attach(struct if_clone *ifc) IF_CLONE_ADDREF(ifc); IF_CLONERS_LOCK(); - LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list); - if_cloners_count++; + LIST_INSERT_HEAD(&V_if_cloners, ifc, ifc_list); + V_if_cloners_count++; IF_CLONERS_UNLOCK(); LIST_INIT(&ifc->ifc_iflist); @@ -266,11 +322,12 @@ if_clone_attach(struct if_clone *ifc) void if_clone_detach(struct if_clone *ifc) { + INIT_VNET_NET(curvnet); struct ifc_simple_data *ifcs = ifc->ifc_data; IF_CLONERS_LOCK(); LIST_REMOVE(ifc, ifc_list); - if_cloners_count--; + V_if_cloners_count--; IF_CLONERS_UNLOCK(); /* Allow all simples to be destroyed */ @@ -305,6 +362,7 @@ if_clone_free(struct if_clone *ifc) int if_clone_list(struct if_clonereq *ifcr) { + INIT_VNET_NET(curvnet); char *buf, *dst, *outbuf = NULL; struct if_clone *ifc; int buf_count, count, err = 0; @@ -321,23 +379,23 @@ if_clone_list(struct if_clonereq *ifcr) * could be because that would let arbitrary users cause us to * allocate abritrary amounts of kernel memory. */ - buf_count = (if_cloners_count < ifcr->ifcr_count) ? - if_cloners_count : ifcr->ifcr_count; + buf_count = (V_if_cloners_count < ifcr->ifcr_count) ? + V_if_cloners_count : ifcr->ifcr_count; IF_CLONERS_UNLOCK(); outbuf = malloc(IFNAMSIZ*buf_count, M_CLONE, M_WAITOK | M_ZERO); IF_CLONERS_LOCK(); - ifcr->ifcr_total = if_cloners_count; + ifcr->ifcr_total = V_if_cloners_count; if ((dst = ifcr->ifcr_buffer) == NULL) { /* Just asking how many there are. */ goto done; } - count = (if_cloners_count < buf_count) ? - if_cloners_count : buf_count; + count = (V_if_cloners_count < buf_count) ? + V_if_cloners_count : buf_count; - for (ifc = LIST_FIRST(&if_cloners), buf = outbuf; + for (ifc = LIST_FIRST(&V_if_cloners), buf = outbuf; ifc != NULL && count != 0; ifc = LIST_NEXT(ifc, ifc_list), count--, buf += IFNAMSIZ) { strlcpy(buf, ifc->ifc_name, IFNAMSIZ); |