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:
parent
40574d258a
commit
48f748dc29
5
UPDATING
5
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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user