Date: Tue, 12 May 2009 18:48:20 GMT From: Marko Zec <zec@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 161987 for review Message-ID: <200905121848.n4CImKQt036691@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=161987 Change 161987 by zec@zec_tpx32 on 2009/05/12 18:47:49 Back out O(n**2) ad-hoc hack for searching for available ifunits in cloning ifnets, and restore the standard O(n) bitmapped searching / ifunit allocation method for both default and options VIMAGE builds. HOWEVER, hereby we also introduce per-vnet if_clone driver registration and ifunit allocation. As a (necessary) example, if_loop is modified to attach itself as an independent cloner instance to each vnet. This approach has a neat byproduct: if_clone drivers that do not explicitly declare themselves as multi-vnet, by exporting an iattach() method and registering to the vnet framework, continue to work with unmodified semantics in the default vnet. However, they will NOT be available in other vnets. This brings us a step closer to being able to selectively attach subsystems to particular vnets, instead of having all subsystems unconditionally available to all vnets by default. Affected files ... .. //depot/projects/vimage-commit2/src/sys/net/if_clone.c#7 edit .. //depot/projects/vimage-commit2/src/sys/net/if_clone.h#3 edit .. //depot/projects/vimage-commit2/src/sys/net/if_loop.c#29 edit .. //depot/projects/vimage-commit2/src/sys/net/vnet.h#17 edit .. //depot/projects/vimage-commit2/src/sys/netinet/in.c#27 edit .. //depot/projects/vimage-commit2/src/sys/sys/vimage.h#59 edit Differences ... ==== //depot/projects/vimage-commit2/src/sys/net/if_clone.c#7 (text+ko) ==== @@ -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 @@ 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_loif_iattach(NULL); +#endif } /* @@ -124,11 +149,12 @@ 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; } @@ -176,6 +202,7 @@ int if_clone_destroy(const char *name) { + INIT_VNET_NET(curvnet); struct if_clone *ifc; struct ifnet *ifp; @@ -185,7 +212,7 @@ /* 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; } @@ -212,7 +239,6 @@ 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); @@ -224,7 +250,6 @@ IFC_IFLIST_INSERT(ifc, ifp); IF_CLONE_UNLOCK(ifc); } - CURVNET_RESTORE(); return (err); } @@ -234,6 +259,7 @@ void if_clone_attach(struct if_clone *ifc) { + INIT_VNET_NET(curvnet); int len, maxclone; /* @@ -249,8 +275,8 @@ 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 +292,12 @@ 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 */ @@ -287,6 +314,7 @@ static void if_clone_free(struct if_clone *ifc) { + for (int bytoff = 0; bytoff < ifc->ifc_bmlen; bytoff++) { KASSERT(ifc->ifc_units[bytoff] == 0x00, ("ifc_units[%d] is not empty", bytoff)); @@ -294,7 +322,6 @@ KASSERT(LIST_EMPTY(&ifc->ifc_iflist), ("%s: ifc_iflist not empty", __func__)); - IF_CLONE_LOCK_DESTROY(ifc); free(ifc->ifc_units, M_CLONE); } @@ -305,6 +332,7 @@ 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 +349,23 @@ * 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); @@ -401,25 +429,6 @@ * Find a free unit if none was given. */ if (wildcard) { -#ifdef VIMAGE - /* XXX revisit - O(n**2) loop below! */ - INIT_VNET_NET(curvnet); - char name[IFNAMSIZ]; - struct ifnet *ifp; - int i = 0; - - IFNET_RLOCK(); -again: - TAILQ_FOREACH(ifp, &V_ifnet, if_link) { - sprintf(name, "%s%d", ifc->ifc_name, i); - if (strcmp(name, ifp->if_xname) == 0) { - i++; - goto again; - } - } - IFNET_RUNLOCK(); - *unit = i; -#else while ((bytoff < ifc->ifc_bmlen) && (ifc->ifc_units[bytoff] == 0xff)) bytoff++; @@ -430,7 +439,6 @@ while ((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0) bitoff++; *unit = (bytoff << 3) + bitoff; -#endif } if (*unit > ifc->ifc_maxunit) { @@ -438,7 +446,6 @@ goto done; } -#ifndef VIMAGE if (!wildcard) { bytoff = *unit >> 3; bitoff = *unit - (bytoff << 3); @@ -454,7 +461,6 @@ KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) == 0, ("%s: bit is already set", __func__)); ifc->ifc_units[bytoff] |= (1 << bitoff); -#endif IF_CLONE_ADDREF_LOCKED(ifc); done: @@ -465,7 +471,6 @@ void ifc_free_unit(struct if_clone *ifc, int unit) { -#ifndef VIMAGE int bytoff, bitoff; /* @@ -473,14 +478,11 @@ */ bytoff = unit >> 3; bitoff = unit - (bytoff << 3); -#endif IF_CLONE_LOCK(ifc); -#ifndef VIMAGE KASSERT((ifc->ifc_units[bytoff] & (1 << bitoff)) != 0, ("%s: bit is already cleared", __func__)); ifc->ifc_units[bytoff] &= ~(1 << bitoff); -#endif IF_CLONE_REMREF_LOCKED(ifc); /* releases lock */ } ==== //depot/projects/vimage-commit2/src/sys/net/if_clone.h#3 (text+ko) ==== ==== //depot/projects/vimage-commit2/src/sys/net/if_loop.c#29 (text+ko) ==== @@ -111,16 +111,21 @@ struct ifnet *loif; /* Used externally */ #endif +IFC_SIMPLE_DECLARE(lo, 1); + +#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 }; #endif /* !VIMAGE_GLOBALS */ -IFC_SIMPLE_DECLARE(lo, 1); - static void lo_clone_destroy(struct ifnet *ifp) { @@ -168,10 +173,15 @@ V_loif = NULL; LIST_INIT(&V_lo_list); - if (IS_DEFAULT_VNET(curvnet)) - if_clone_attach(&lo_cloner); - else - lo_cloner.ifc_attach(&lo_cloner); + +#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); } ==== //depot/projects/vimage-commit2/src/sys/net/vnet.h#17 (text+ko) ==== @@ -31,26 +31,31 @@ */ #ifndef _NET_VNET_H_ -#define _NET_VNET_H_ +#define _NET_VNET_H_ #include <net/if_var.h> struct vnet_net { - int _if_index; - struct ifindex_entry * _ifindex_table; struct ifnethead _ifnet; struct ifgrouphead _ifg_head; - int _if_indexlim; - struct knlist _ifklist; + struct ifnet * _loif; + LIST_HEAD(, lo_softc) _lo_list; + struct radix_node_head *_rt_tables[RT_MAXFIBS][AF_MAX+1]; struct rtstat _rtstat; - struct radix_node_head *_rt_tables[RT_MAXFIBS][AF_MAX+1]; int _rttrash; uma_zone_t _rtzone; - struct ifnet * _loif; - LIST_HEAD(, lo_softc) _lo_list; + struct ifindex_entry * _ifindex_table; + int _if_index; + int _if_indexlim; + struct knlist _ifklist; + + struct if_clone * _lo_cloner; + + LIST_HEAD(, if_clone) _if_cloners; + int _if_cloners_count; LIST_HEAD(, rawcb) _rawcb_list; @@ -74,19 +79,22 @@ #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_cloners VNET_NET(if_cloners) +#define V_if_cloners_count VNET_NET(if_cloners_count) +#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_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_ */ ==== //depot/projects/vimage-commit2/src/sys/netinet/in.c#27 (text+ko) ==== @@ -814,6 +814,7 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin, int scrub) { + INIT_VNET_NET(ifp->if_vnet); INIT_VNET_INET(ifp->if_vnet); register u_long i = ntohl(sin->sin_addr.s_addr); struct sockaddr_in oldaddr; @@ -1004,6 +1005,7 @@ static int in_scrubprefix(struct in_ifaddr *target) { + INIT_VNET_NET(curvnet); INIT_VNET_INET(curvnet); struct in_ifaddr *ia; struct in_addr prefix, mask, p; ==== //depot/projects/vimage-commit2/src/sys/sys/vimage.h#59 (text+ko) ==== @@ -123,6 +123,7 @@ #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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905121848.n4CImKQt036691>