PERFORCE change 161987 for review
Marko Zec
zec at FreeBSD.org
Tue May 12 18:48:24 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=161987
Change 161987 by zec at 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
More information about the p4-projects
mailing list