From 48f748dc297cbf46f02ec8b61d47436d66d0d8b9 Mon Sep 17 00:00:00 2001 From: zec Date: Sat, 23 May 2009 21:43:44 +0000 Subject: [PATCH] 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) --- UPDATING | 5 +++ sys/kern/kern_vimage.c | 5 +++ sys/net/if_clone.c | 84 +++++++++++++++++++++++++++++++++++------- sys/net/if_loop.c | 13 +++++++ sys/net/vnet.h | 37 +++++++++++-------- sys/sys/param.h | 2 +- sys/sys/vimage.h | 2 + 7 files changed, 118 insertions(+), 30 deletions(-) diff --git a/UPDATING b/UPDATING index 8ef1991cbccf..85a005af6cd4 100644 --- a/UPDATING +++ b/UPDATING @@ -22,6 +22,11 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.x IS SLOW: to maximize performance. (To disable malloc debugging, run ln -s aj /etc/malloc.conf.) +20090523: + The layout of struct vnet_net has changed, therefore modules + need to be rebuilt. + Bump __FreeBSD_version to 800090. + 20090523: The newly imported zic(8) produces a new format in the output. Please run tzsetup(8) to install the newly created diff --git a/sys/kern/kern_vimage.c b/sys/kern/kern_vimage.c index d4c48b5401f1..7cb6d8461f89 100644 --- a/sys/kern/kern_vimage.c +++ b/sys/kern/kern_vimage.c @@ -66,6 +66,10 @@ struct vprocg vprocg_0; #endif #endif +#ifdef VIMAGE +struct vnet *vnet0; +#endif + void vnet_mod_register(const struct vnet_modinfo *vmi) { @@ -331,6 +335,7 @@ vi_init(void *unused) LIST_INSERT_HEAD(&vnet_head, vnet, vnet_le); vnet->vnet_magic_n = VNET_MAGIC_N; vip->v_net = vnet; + vnet0 = vnet; /* We MUST clear curvnet in vi_init_done before going SMP. */ curvnet = LIST_FIRST(&vnet_head); diff --git a/sys/net/if_clone.c b/sys/net/if_clone.c index a0140fca6e59..eaa7397e0423 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); diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c index 3319ed89379f..cc9251b1a114 100644 --- a/sys/net/if_loop.c +++ b/sys/net/if_loop.c @@ -111,9 +111,14 @@ static int vnet_loif_iattach(const void *); struct ifnet *loif; /* Used externally */ #endif +#ifdef VIMAGE +MALLOC_DEFINE(M_LO_CLONER, "lo_cloner", "lo_cloner"); +#endif + #ifndef VIMAGE_GLOBALS static const vnet_modinfo_t vnet_loif_modinfo = { .vmi_id = VNET_MOD_LOIF, + .vmi_dependson = VNET_MOD_IF_CLONE, .vmi_name = "loif", .vmi_iattach = vnet_loif_iattach }; @@ -167,7 +172,15 @@ static int vnet_loif_iattach(const void *unused __unused) INIT_VNET_NET(curvnet); V_loif = NULL; + +#ifdef VIMAGE + V_lo_cloner = malloc(sizeof(*V_lo_cloner), M_LO_CLONER, + M_WAITOK | M_ZERO); + bcopy(&lo_cloner, V_lo_cloner, sizeof(*V_lo_cloner)); + if_clone_attach(V_lo_cloner); +#else if_clone_attach(&lo_cloner); +#endif return (0); } diff --git a/sys/net/vnet.h b/sys/net/vnet.h index 662586a0d4cc..bdc466b55a48 100644 --- a/sys/net/vnet.h +++ b/sys/net/vnet.h @@ -31,7 +31,7 @@ */ #ifndef _NET_VNET_H_ -#define _NET_VNET_H_ +#define _NET_VNET_H_ #include @@ -50,10 +50,13 @@ struct vnet_net { uma_zone_t _rtzone; struct ifnet * _loif; - LIST_HEAD(, lo_softc) _lo_list; + struct if_clone * _lo_cloner; LIST_HEAD(, rawcb) _rawcb_list; + LIST_HEAD(, if_clone) _if_cloners; + int _if_cloners_count; + int _ether_ipfw; }; @@ -74,19 +77,21 @@ extern struct vnet_net vnet_net_0; #define VNET_NET(sym) VSYM(vnet_net, sym) -#define V_ether_ipfw VNET_NET(ether_ipfw) -#define V_if_index VNET_NET(if_index) -#define V_if_indexlim VNET_NET(if_indexlim) -#define V_ifg_head VNET_NET(ifg_head) -#define V_ifindex_table VNET_NET(ifindex_table) -#define V_ifklist VNET_NET(ifklist) -#define V_ifnet VNET_NET(ifnet) -#define V_lo_list VNET_NET(lo_list) -#define V_loif VNET_NET(loif) -#define V_rawcb_list VNET_NET(rawcb_list) -#define V_rt_tables VNET_NET(rt_tables) -#define V_rtstat VNET_NET(rtstat) -#define V_rttrash VNET_NET(rttrash) -#define V_rtzone VNET_NET(rtzone) +#define V_ether_ipfw VNET_NET(ether_ipfw) +#define V_if_index VNET_NET(if_index) +#define V_if_indexlim VNET_NET(if_indexlim) +#define V_if_cloners VNET_NET(if_cloners) +#define V_if_cloners_count VNET_NET(if_cloners_count) +#define V_ifg_head VNET_NET(ifg_head) +#define V_ifindex_table VNET_NET(ifindex_table) +#define V_ifklist VNET_NET(ifklist) +#define V_ifnet VNET_NET(ifnet) +#define V_lo_cloner VNET_NET(lo_cloner) +#define V_loif VNET_NET(loif) +#define V_rawcb_list VNET_NET(rawcb_list) +#define V_rt_tables VNET_NET(rt_tables) +#define V_rtstat VNET_NET(rtstat) +#define V_rttrash VNET_NET(rttrash) +#define V_rtzone VNET_NET(rtzone) #endif /* !_NET_VNET_H_ */ diff --git a/sys/sys/param.h b/sys/sys/param.h index 19dc83eedcda..eb8c57f3c3a9 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -57,7 +57,7 @@ * is created, otherwise 1. */ #undef __FreeBSD_version -#define __FreeBSD_version 800089 /* Master, propagated to newvers */ +#define __FreeBSD_version 800090 /* Master, propagated to newvers */ #ifndef LOCORE #include diff --git a/sys/sys/vimage.h b/sys/sys/vimage.h index b2c0bc129005..888e1142a0bc 100644 --- a/sys/sys/vimage.h +++ b/sys/sys/vimage.h @@ -95,6 +95,7 @@ struct vnet_modlink { #define VNET_MOD_MLD 13 /* Stateless modules. */ +#define VNET_MOD_IF_CLONE 19 #define VNET_MOD_NG_ETHER 20 #define VNET_MOD_NG_IFACE 21 #define VNET_MOD_NG_EIFACE 22 @@ -271,6 +272,7 @@ extern struct vprocg vprocg_0; #ifdef VIMAGE LIST_HEAD(vnet_list_head, vnet); extern struct vnet_list_head vnet_head; +extern struct vnet *vnet0; #define VNET_ITERATOR_DECL(arg) struct vnet *arg; #define VNET_FOREACH(arg) LIST_FOREACH(arg, &vnet_head, vnet_le) #else