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)
This commit is contained in:
zec 2009-05-23 21:43:44 +00:00
parent 40574d258a
commit 48f748dc29
7 changed files with 118 additions and 30 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -31,7 +31,7 @@
*/
#ifndef _NET_VNET_H_
#define _NET_VNET_H_
#define _NET_VNET_H_
#include <net/if_var.h>
@ -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_ */

View File

@ -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 <sys/types.h>

View File

@ -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