Skip site navigation (1)Skip section navigation (2)
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>