summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-07-23 20:46:49 +0000
committerrwatson <rwatson@FreeBSD.org>2009-07-23 20:46:49 +0000
commitb3be1c6e3bd7d3b5cf946ddb04c1c5811644229b (patch)
tree0191b21173debdadfbf9f7565dfc5a8b9eefe94a /sys/net
parentfc8defe5dd957eaee1f1c841d45804df5bbf20f5 (diff)
downloadFreeBSD-src-b3be1c6e3bd7d3b5cf946ddb04c1c5811644229b.zip
FreeBSD-src-b3be1c6e3bd7d3b5cf946ddb04c1c5811644229b.tar.gz
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT: - Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will occur each time a network stack is instantiated and destroyed. In the !VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT. For the VIMAGE case, we instead use SYSINIT's to track their order and properties on registration, using them for each vnet when created/ destroyed, or immediately on module load for already-started vnets. - Remove vnet_modinfo mechanism that existed to serve this purpose previously, as well as its dependency scheme: we now just use the SYSINIT ordering scheme. - Implement VNET_DOMAIN_SET() to allow protocol domains to declare that they want init functions to be called for each virtual network stack rather than just once at boot, compiling down to DOMAIN_SET() in the non-VIMAGE case. - Walk all virtualized kernel subsystems and make use of these instead of modinfo or DOMAIN_SET() for init/uninit events. In some cases, convert modular components from using modevent to using sysinit (where appropriate). In some cases, do minor rejuggling of SYSINIT ordering to make room for or better manage events. Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup) Discussed with: jhb, bz, julian, zec Reviewed by: bz Approved by: re (VIMAGE blanket)
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/flowtable.c40
-rw-r--r--sys/net/if.c52
-rw-r--r--sys/net/if_clone.c18
-rw-r--r--sys/net/if_clone.h1
-rw-r--r--sys/net/if_gif.c60
-rw-r--r--sys/net/if_loop.c56
-rw-r--r--sys/net/route.c40
-rw-r--r--sys/net/rtsock.c4
-rw-r--r--sys/net/vnet.c142
-rw-r--r--sys/net/vnet.h51
10 files changed, 271 insertions, 193 deletions
diff --git a/sys/net/flowtable.c b/sys/net/flowtable.c
index d16ffa3..1fe2bbe 100644
--- a/sys/net/flowtable.c
+++ b/sys/net/flowtable.c
@@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$");
#include <net/if_var.h>
#include <net/route.h>
#include <net/flowtable.h>
+#include <net/vnet.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
@@ -173,18 +174,6 @@ static VNET_DEFINE(uma_zone_t, flow_ipv6_zone);
#define V_flow_ipv4_zone VNET(flow_ipv4_zone)
#define V_flow_ipv6_zone VNET(flow_ipv6_zone)
-static int flowtable_iattach(const void *);
-#ifdef VIMAGE
-static int flowtable_idetach(const void *);
-
-static const vnet_modinfo_t flowtable_modinfo = {
- .vmi_id = VNET_MOD_FLOWTABLE,
- .vmi_name = "flowtable",
- .vmi_iattach = flowtable_iattach,
- .vmi_idetach = flowtable_idetach
-};
-#endif
-
/*
* TODO:
* - Make flowtable stats per-cpu, aggregated at sysctl call time,
@@ -802,18 +791,7 @@ flowtable_alloc(int nentry, int flags)
}
static void
-flowtable_setup(void *arg)
-{
-
-#ifdef VIMAGE
- vnet_mod_register(&flowtable_modinfo);
-#else
- flowtable_iattach(NULL);
-#endif
-}
-
-static int
-flowtable_iattach(const void *unused __unused)
+flowtable_init(const void *unused __unused)
{
V_flow_ipv4_zone = uma_zcreate("ip4flow", sizeof(struct flentry_v4),
@@ -822,21 +800,23 @@ flowtable_iattach(const void *unused __unused)
NULL, NULL, NULL, NULL, 64, UMA_ZONE_MAXBUCKET);
uma_zone_set_max(V_flow_ipv4_zone, V_flowtable_nmbflows);
uma_zone_set_max(V_flow_ipv6_zone, V_flowtable_nmbflows);
- return (0);
}
+VNET_SYSINIT(flowtable_init, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY,
+ flowtable_init, NULL);
+
#ifdef VIMAGE
-static int
-flowtable_idetach(const void *unused __unused)
+static void
+flowtable_uninit(const void *unused __unused)
{
uma_zdestroy(V_flow_ipv4_zone);
uma_zdestroy(V_flow_ipv6_zone);
- return (0);
}
-#endif
-SYSINIT(flowtable_setup, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY, flowtable_setup, NULL);
+VNET_SYSUNINIT(flowtable_uninit, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY,
+ flowtable_uninit, NULL);
+#endif
/*
* The rest of the code is devoted to garbage collection of expired entries.
diff --git a/sys/net/if.c b/sys/net/if.c
index 608eb08..3916675 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -150,11 +150,6 @@ static void if_detach_internal(struct ifnet *, int);
extern void nd6_setmtu(struct ifnet *);
#endif
-static int vnet_net_iattach(const void *);
-#ifdef VIMAGE
-static int vnet_net_idetach(const void *);
-#endif
-
VNET_DEFINE(struct ifnethead, ifnet); /* depend on static init XXX */
VNET_DEFINE(struct ifgrouphead, ifg_head);
VNET_DEFINE(int, if_index);
@@ -171,19 +166,9 @@ struct rwlock ifnet_lock;
static if_com_alloc_t *if_com_alloc[256];
static if_com_free_t *if_com_free[256];
-#ifdef VIMAGE
-static const vnet_modinfo_t vnet_net_modinfo = {
- .vmi_id = VNET_MOD_NET,
- .vmi_name = "net",
- .vmi_iattach = vnet_net_iattach,
- .vmi_idetach = vnet_net_idetach
-};
-#endif
-
/*
* System initialization
*/
-SYSINIT(interfaces, SI_SUB_INIT_IF, SI_ORDER_FIRST, if_init, NULL);
SYSINIT(interface_check, SI_SUB_PROTO_IF, SI_ORDER_FIRST, if_check, NULL);
MALLOC_DEFINE(M_IFNET, "ifnet", "interface internals");
@@ -255,44 +240,41 @@ ifaddr_byindex(u_short idx)
* parameters.
*/
+static void
+vnet_if_init(const void *unused __unused)
+{
+
+ TAILQ_INIT(&V_ifnet);
+ TAILQ_INIT(&V_ifg_head);
+ if_grow(); /* create initial table */
+ vnet_if_clone_init();
+}
+VNET_SYSINIT(vnet_if_init, SI_SUB_INIT_IF, SI_ORDER_FIRST, vnet_if_init,
+ NULL);
+
/* ARGSUSED*/
static void
if_init(void *dummy __unused)
{
-#ifdef VIMAGE
- vnet_mod_register(&vnet_net_modinfo);
-#else
- vnet_net_iattach(NULL);
-#endif
-
IFNET_LOCK_INIT();
if_clone_init();
}
+SYSINIT(interfaces, SI_SUB_INIT_IF, SI_ORDER_SECOND, if_init, NULL);
-static int
-vnet_net_iattach(const void *unused __unused)
-{
-
- TAILQ_INIT(&V_ifnet);
- TAILQ_INIT(&V_ifg_head);
- if_grow(); /* create initial table */
-
- return (0);
-}
#ifdef VIMAGE
-static int
-vnet_net_idetach(const void *unused __unused)
+static void
+vnet_if_uninit(const void *unused __unused)
{
VNET_ASSERT(TAILQ_EMPTY(&V_ifnet));
VNET_ASSERT(TAILQ_EMPTY(&V_ifg_head));
free((caddr_t)V_ifindex_table, M_IFNET);
-
- return (0);
}
+VNET_SYSUNINIT(vnet_if_uninit, SI_SUB_INIT_IF, SI_ORDER_FIRST,
+ vnet_if_uninit, NULL);
#endif
void
diff --git a/sys/net/if_clone.c b/sys/net/if_clone.c
index 4e3f787..95c07b7 100644
--- a/sys/net/if_clone.c
+++ b/sys/net/if_clone.c
@@ -55,7 +55,6 @@
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;
static VNET_DEFINE(int, if_cloners_count);
@@ -116,19 +115,11 @@ VNET_DEFINE(LIST_HEAD(, if_clone), if_cloners);
static MALLOC_DEFINE(M_CLONE, "clone", "interface cloning framework");
-#ifdef VIMAGE
-static const vnet_modinfo_t vnet_clone_modinfo = {
- .vmi_id = VNET_MOD_IF_CLONE,
- .vmi_name = "if_clone",
- .vmi_iattach = vnet_clone_iattach
-};
-#endif
-
-static int vnet_clone_iattach(const void *unused __unused)
+void
+vnet_if_clone_init(void)
{
LIST_INIT(&V_if_cloners);
- return (0);
}
void
@@ -136,11 +127,6 @@ if_clone_init(void)
{
IF_CLONERS_LOCK_INIT();
-#ifdef VIMAGE
- vnet_mod_register(&vnet_clone_modinfo);
-#else
- vnet_clone_iattach(NULL);
-#endif
}
/*
diff --git a/sys/net/if_clone.h b/sys/net/if_clone.h
index 280a545..f125f8b 100644
--- a/sys/net/if_clone.h
+++ b/sys/net/if_clone.h
@@ -72,6 +72,7 @@ struct if_clone {
void if_clone_init(void);
void if_clone_attach(struct if_clone *);
void if_clone_detach(struct if_clone *);
+void vnet_if_clone_init(void);
int if_clone_create(char *, size_t, caddr_t);
int if_clone_destroy(const char *);
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c
index f663283..3d75dd4 100644
--- a/sys/net/if_gif.c
+++ b/sys/net/if_gif.c
@@ -96,19 +96,15 @@ static struct mtx gif_mtx;
static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
static VNET_DEFINE(LIST_HEAD(, gif_softc), gif_softc_list);
-static VNET_DEFINE(int, max_gif_nesting);
-static VNET_DEFINE(int, parallel_tunnels);
#define V_gif_softc_list VNET(gif_softc_list)
-#define V_max_gif_nesting VNET(max_gif_nesting)
-#define V_parallel_tunnels VNET(parallel_tunnels)
#ifdef INET
-VNET_DEFINE(int, ip_gif_ttl);
+VNET_DEFINE(int, ip_gif_ttl) = GIF_TTL;
#define V_ip_gif_ttl VNET(ip_gif_ttl)
#endif
#ifdef INET6
-VNET_DEFINE(int, ip6_gif_hlim);
+VNET_DEFINE(int, ip6_gif_hlim) = GIF_HLIM;
#define V_ip6_gif_hlim VNET(ip6_gif_hlim)
#endif
@@ -120,16 +116,6 @@ void (*ng_gif_detach_p)(struct ifnet *ifp);
static void gif_start(struct ifnet *);
static int gif_clone_create(struct if_clone *, int, caddr_t);
static void gif_clone_destroy(struct ifnet *);
-static int vnet_gif_iattach(const void *);
-
-#ifdef VIMAGE
-static const vnet_modinfo_t vnet_gif_modinfo = {
- .vmi_id = VNET_MOD_GIF,
- .vmi_name = "gif",
- .vmi_dependson = VNET_MOD_NET,
- .vmi_iattach = vnet_gif_iattach
-};
-#endif
IFC_SIMPLE_DECLARE(gif, 0);
@@ -149,6 +135,10 @@ SYSCTL_NODE(_net_link, IFT_GIF, gif, CTLFLAG_RW, 0,
*/
#define MAX_GIF_NEST 1
#endif
+
+static VNET_DEFINE(int, max_gif_nesting) = MAX_GIF_NEST;
+#define V_max_gif_nesting VNET(max_gif_nesting)
+
SYSCTL_VNET_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW,
&VNET_NAME(max_gif_nesting), 0, "Max nested tunnels");
@@ -163,6 +153,13 @@ SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim, CTLFLAG_RW,
* pair of addresses. Some applications require this functionality so
* we allow control over this check here.
*/
+#ifdef XBONEHACK
+static VNET_DEFINE(int, parallel_tunnels) = 1;
+#else
+static VNET_DEFINE(int, parallel_tunnels) = 0;
+#endif
+#define V_parallel_tunnels VNET(parallel_tunnels)
+
SYSCTL_VNET_INT(_net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW,
&VNET_NAME(parallel_tunnels), 0, "Allow parallel tunnels?");
@@ -259,26 +256,14 @@ gif_clone_destroy(ifp)
free(sc, M_GIF);
}
-static int
-vnet_gif_iattach(const void *unused __unused)
+static void
+vnet_gif_init(const void *unused __unused)
{
LIST_INIT(&V_gif_softc_list);
- V_max_gif_nesting = MAX_GIF_NEST;
-#ifdef XBONEHACK
- V_parallel_tunnels = 1;
-#else
- V_parallel_tunnels = 0;
-#endif
-#ifdef INET
- V_ip_gif_ttl = GIF_TTL;
-#endif
-#ifdef INET6
- V_ip6_gif_hlim = GIF_HLIM;
-#endif
-
- return (0);
}
+VNET_SYSINIT(vnet_gif_init, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, vnet_gif_init,
+ NULL);
static int
gifmodevent(mod, type, data)
@@ -290,20 +275,11 @@ gifmodevent(mod, type, data)
switch (type) {
case MOD_LOAD:
mtx_init(&gif_mtx, "gif_mtx", NULL, MTX_DEF);
-
-#ifdef VIMAGE
- vnet_mod_register(&vnet_gif_modinfo);
-#else
- vnet_gif_iattach(NULL);
-#endif
if_clone_attach(&gif_cloner);
-
break;
+
case MOD_UNLOAD:
if_clone_detach(&gif_cloner);
-#ifdef VIMAGE
- vnet_mod_deregister(&vnet_gif_modinfo);
-#endif
mtx_destroy(&gif_mtx);
break;
default:
diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c
index 7889570..043c808 100644
--- a/sys/net/if_loop.c
+++ b/sys/net/if_loop.c
@@ -103,30 +103,14 @@ int looutput(struct ifnet *ifp, struct mbuf *m,
struct sockaddr *dst, struct route *ro);
static int lo_clone_create(struct if_clone *, int, caddr_t);
static void lo_clone_destroy(struct ifnet *);
-static int vnet_loif_iattach(const void *);
-#ifdef VIMAGE
-static int vnet_loif_idetach(const void *);
-#endif
VNET_DEFINE(struct ifnet *, loif); /* Used externally */
#ifdef VIMAGE
-static VNET_DEFINE(struct ifc_simple_data *, lo_cloner_data);
-static VNET_DEFINE(struct if_clone *, lo_cloner);
+static VNET_DEFINE(struct ifc_simple_data, lo_cloner_data);
+static VNET_DEFINE(struct if_clone, lo_cloner);
#define V_lo_cloner_data VNET(lo_cloner_data)
#define V_lo_cloner VNET(lo_cloner)
-
-MALLOC_DEFINE(M_LO_CLONER, "lo_cloner", "lo_cloner");
-#endif
-
-#ifdef VIMAGE
-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,
- .vmi_idetach = vnet_loif_idetach
-};
#endif
IFC_SIMPLE_DECLARE(lo, 1);
@@ -170,37 +154,32 @@ lo_clone_create(struct if_clone *ifc, int unit, caddr_t params)
return (0);
}
-static int
-vnet_loif_iattach(const void *unused __unused)
+static void
+vnet_loif_init(const void *unused __unused)
{
#ifdef VIMAGE
- V_lo_cloner = malloc(sizeof(*V_lo_cloner), M_LO_CLONER,
- M_WAITOK | M_ZERO);
- V_lo_cloner_data = malloc(sizeof(*V_lo_cloner_data), M_LO_CLONER,
- M_WAITOK | M_ZERO);
- bcopy(&lo_cloner, V_lo_cloner, sizeof(*V_lo_cloner));
- bcopy(lo_cloner.ifc_data, V_lo_cloner_data, sizeof(*V_lo_cloner_data));
- V_lo_cloner->ifc_data = V_lo_cloner_data;
- if_clone_attach(V_lo_cloner);
+ V_lo_cloner = lo_cloner;
+ V_lo_cloner_data = lo_cloner_data;
+ V_lo_cloner.ifc_data = &V_lo_cloner_data;
+ if_clone_attach(&V_lo_cloner);
#else
if_clone_attach(&lo_cloner);
#endif
- return (0);
}
+VNET_SYSINIT(vnet_loif_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ vnet_loif_init, NULL);
#ifdef VIMAGE
-static int
-vnet_loif_idetach(const void *unused __unused)
+static void
+vnet_loif_uninit(const void *unused __unused)
{
- if_clone_detach(V_lo_cloner);
- free(V_lo_cloner, M_LO_CLONER);
- free(V_lo_cloner_data, M_LO_CLONER);
+ if_clone_detach(&V_lo_cloner);
V_loif = NULL;
-
- return (0);
}
+VNET_SYSUNINIT(vnet_loif_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+ vnet_loif_uninit, NULL);
#endif
static int
@@ -209,11 +188,6 @@ loop_modevent(module_t mod, int type, void *data)
switch (type) {
case MOD_LOAD:
-#ifdef VIMAGE
- vnet_mod_register(&vnet_loif_modinfo);
-#else
- vnet_loif_iattach(NULL);
-#endif
break;
case MOD_UNLOAD:
diff --git a/sys/net/route.c b/sys/net/route.c
index de677bc..544c3b6 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -99,17 +99,6 @@ VNET_DEFINE(struct rtstat, rtstat);
static void rt_maskedcopy(struct sockaddr *,
struct sockaddr *, struct sockaddr *);
-static int vnet_route_iattach(const void *);
-#ifdef VIMAGE
-static int vnet_route_idetach(const void *);
-
-static const vnet_modinfo_t vnet_rtable_modinfo = {
- .vmi_id = VNET_MOD_RTABLE,
- .vmi_name = "rtable",
- .vmi_iattach = vnet_route_iattach,
- .vmi_idetach = vnet_route_idetach
-};
-#endif
/* compare two sockaddr structures */
#define sa_equal(a1, a2) (bcmp((a1), (a2), (a1)->sa_len) == 0)
@@ -174,6 +163,10 @@ rt_tables_get_rnh(int table, int fam)
return (*rt_tables_get_rnh_ptr(table, fam));
}
+/*
+ * route initialization must occur before ip6_init2(), which happenas at
+ * SI_ORDER_MIDDLE.
+ */
static void
route_init(void)
{
@@ -184,16 +177,11 @@ route_init(void)
if (rt_numfibs == 0)
rt_numfibs = 1;
rn_init(); /* initialize all zeroes, all ones, mask table */
-
-#ifdef VIMAGE
- vnet_mod_register(&vnet_rtable_modinfo);
-#else
- vnet_route_iattach(NULL);
-#endif
}
+SYSINIT(route_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, route_init, 0);
-static int
-vnet_route_iattach(const void *unused __unused)
+static void
+vnet_route_init(const void *unused __unused)
{
struct domain *dom;
struct radix_node_head **rnh;
@@ -229,13 +217,13 @@ vnet_route_iattach(const void *unused __unused)
}
}
}
-
- return (0);
}
+VNET_SYSINIT(vnet_route_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH,
+ vnet_route_init, 0);
#ifdef VIMAGE
-static int
-vnet_route_idetach(const void *unused __unused)
+static void
+vnet_route_uninit(const void *unused __unused)
{
int table;
int fam;
@@ -259,8 +247,9 @@ vnet_route_idetach(const void *unused __unused)
}
}
}
- return (0);
}
+VNET_SYSUNINIT(vnet_route_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD,
+ vnet_route_uninit, 0);
#endif
#ifndef _SYS_SYSPROTO_H_
@@ -1510,6 +1499,3 @@ rtinit(struct ifaddr *ifa, int cmd, int flags)
fib = -1;
return (rtinit1(ifa, cmd, flags, fib));
}
-
-/* This must be before ip6_init2(), which is now SI_ORDER_MIDDLE */
-SYSINIT(route, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, route_init, 0);
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index bdea325..88c9807 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -35,9 +35,9 @@
#include "opt_inet6.h"
#include <sys/param.h>
-#include <sys/domain.h>
#include <sys/jail.h>
#include <sys/kernel.h>
+#include <sys/domain.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
@@ -1525,4 +1525,4 @@ static struct domain routedomain = {
.dom_protoswNPROTOSW = &routesw[sizeof(routesw)/sizeof(routesw[0])]
};
-DOMAIN_SET(route);
+VNET_DOMAIN_SET(route);
diff --git a/sys/net/vnet.c b/sys/net/vnet.c
index a314886..cd5b2b3 100644
--- a/sys/net/vnet.c
+++ b/sys/net/vnet.c
@@ -126,6 +126,16 @@ MALLOC_DEFINE(M_VNET_DATA, "vnet_data", "VNET data");
*/
static VNET_DEFINE(char, modspace[VNET_MODMIN]);
+/*
+ * Global lists of subsystem constructor and destructors for vnets.
+ * They are registered via VNET_SYSINIT() and VNET_SYSUNINIT(). The
+ * lists are protected by the vnet_sxlock global lock.
+ */
+static TAILQ_HEAD(vnet_sysinit_head, vnet_sysinit) vnet_constructors =
+ TAILQ_HEAD_INITIALIZER(vnet_constructors);
+static TAILQ_HEAD(vnet_sysuninit_head, vnet_sysinit) vnet_destructors =
+ TAILQ_HEAD_INITIALIZER(vnet_destructors);
+
struct vnet_data_free {
uintptr_t vnd_start;
int vnd_len;
@@ -339,3 +349,135 @@ vnet_sysctl_handle_uint(SYSCTL_HANDLER_ARGS)
arg1 = (void *)(curvnet->vnet_data_base + (uintptr_t)arg1);
return (sysctl_handle_int(oidp, arg1, arg2, req));
}
+
+/*
+ * Support for special SYSINIT handlers registered via VNET_SYSINIT()
+ * and VNET_SYSUNINIT().
+ */
+void
+vnet_register_sysinit(void *arg)
+{
+ struct vnet_sysinit *vs, *vs2;
+ struct vnet *vnet;
+
+ vs = arg;
+ KASSERT(vs->subsystem > SI_SUB_VNET, ("vnet sysinit too early"));
+
+ /* Add the constructor to the global list of vnet constructors. */
+ sx_xlock(&vnet_sxlock);
+ TAILQ_FOREACH(vs2, &vnet_constructors, link) {
+ if (vs2->subsystem > vs->subsystem)
+ break;
+ if (vs2->subsystem == vs->subsystem && vs2->order > vs->order)
+ break;
+ }
+ if (vs2 != NULL)
+ TAILQ_INSERT_BEFORE(vs2, vs, link);
+ else
+ TAILQ_INSERT_TAIL(&vnet_constructors, vs, link);
+
+ /*
+ * Invoke the constructor on all the existing vnets when it is
+ * registered.
+ */
+ VNET_FOREACH(vnet) {
+ CURVNET_SET_QUIET(vnet);
+ vs->func(vs->arg);
+ CURVNET_RESTORE();
+ }
+ sx_xunlock(&vnet_sxlock);
+}
+
+void
+vnet_deregister_sysinit(void *arg)
+{
+ struct vnet_sysinit *vs;
+
+ vs = arg;
+
+ /* Remove the constructor from the global list of vnet constructors. */
+ sx_xlock(&vnet_sxlock);
+ TAILQ_REMOVE(&vnet_constructors, vs, link);
+ sx_xunlock(&vnet_sxlock);
+}
+
+void
+vnet_register_sysuninit(void *arg)
+{
+ struct vnet_sysinit *vs, *vs2;
+
+ vs = arg;
+
+ /* Add the destructor to the global list of vnet destructors. */
+ sx_xlock(&vnet_sxlock);
+ TAILQ_FOREACH(vs2, &vnet_destructors, link) {
+ if (vs2->subsystem > vs->subsystem)
+ break;
+ if (vs2->subsystem == vs->subsystem && vs2->order > vs->order)
+ break;
+ }
+ if (vs2 != NULL)
+ TAILQ_INSERT_BEFORE(vs2, vs, link);
+ else
+ TAILQ_INSERT_TAIL(&vnet_destructors, vs, link);
+ sx_xunlock(&vnet_sxlock);
+}
+
+void
+vnet_deregister_sysuninit(void *arg)
+{
+ struct vnet_sysinit *vs;
+ struct vnet *vnet;
+
+ vs = arg;
+
+ /*
+ * Invoke the destructor on all the existing vnets when it is
+ * deregistered.
+ */
+ sx_xlock(&vnet_sxlock);
+ VNET_FOREACH(vnet) {
+ CURVNET_SET_QUIET(vnet);
+ vs->func(vs->arg);
+ CURVNET_RESTORE();
+ }
+
+ /* Remove the destructor from the global list of vnet destructors. */
+ TAILQ_REMOVE(&vnet_destructors, vs, link);
+ sx_xunlock(&vnet_sxlock);
+}
+
+/*
+ * Invoke all registered vnet constructors on the current vnet. Used
+ * during vnet construction. The caller is responsible for ensuring
+ * the new vnet is the current vnet and that the vnet_sxlock lock is
+ * locked.
+ */
+void
+vnet_sysinit(void)
+{
+ struct vnet_sysinit *vs;
+
+ sx_assert(&vnet_sxlock, SA_LOCKED);
+ TAILQ_FOREACH(vs, &vnet_constructors, link) {
+ vs->func(vs->arg);
+ }
+}
+
+/*
+ * Invoke all registered vnet destructors on the current vnet. Used
+ * during vnet destruction. The caller is responsible for ensuring
+ * the dying vnet is the current vnet and that the vnet_sxlock lock is
+ * locked.
+ */
+void
+vnet_sysuninit(void)
+{
+ struct vnet_sysinit *vs;
+
+ sx_assert(&vnet_sxlock, SA_LOCKED);
+ TAILQ_FOREACH_REVERSE(vs, &vnet_destructors, vnet_sysuninit_head,
+ link) {
+ vs->func(vs->arg);
+ }
+}
diff --git a/sys/net/vnet.h b/sys/net/vnet.h
index aec448a..8877bab 100644
--- a/sys/net/vnet.h
+++ b/sys/net/vnet.h
@@ -46,6 +46,43 @@
#ifdef _KERNEL
#ifdef VIMAGE
+#include <sys/kernel.h>
+
+/*
+ * SYSINIT/SYSUNINIT variants that provide per-vnet constructors and
+ * destructors.
+ */
+struct vnet_sysinit {
+ enum sysinit_sub_id subsystem;
+ enum sysinit_elem_order order;
+ sysinit_cfunc_t func;
+ const void *arg;
+ TAILQ_ENTRY(vnet_sysinit) link;
+};
+
+#define VNET_SYSINIT(ident, subsystem, order, func, arg) \
+ static struct vnet_sysinit ident ## _vnet_init = { \
+ subsystem, \
+ order, \
+ (sysinit_cfunc_t)(sysinit_nfunc_t)func, \
+ (arg) \
+ }; \
+ SYSINIT(vnet_init_ ## ident, subsystem, order, \
+ vnet_register_sysinit, &ident ## _vnet_init); \
+ SYSUNINIT(vnet_init_ ## ident, subsystem, order, \
+ vnet_deregister_sysinit, &ident ## _vnet_init)
+
+#define VNET_SYSUNINIT(ident, subsystem, order, func, arg) \
+ static struct vnet_sysinit ident ## _vnet_uninit = { \
+ subsystem, \
+ order, \
+ (sysinit_cfunc_t)(sysinit_nfunc_t)func, \
+ (arg) \
+ }; \
+ SYSINIT(vnet_uninit_ ## ident, subsystem, order, \
+ vnet_register_sysuninit, &ident ## _vnet_uninit); \
+ SYSUNINIT(vnet_uninit_ ## ident, subsystem, order, \
+ vnet_deregister_sysuninit, &ident ## _vnet_uninit)
#if defined(__arm__)
__asm__(".section " VNET_SETNAME ", \"aw\", %progbits");
@@ -121,6 +158,16 @@ void vnet_data_free(void *start_arg, int size);
struct vnet;
void vnet_data_init(struct vnet *vnet);
void vnet_data_destroy(struct vnet *vnet);
+void vnet_sysinit(void);
+void vnet_sysuninit(void);
+
+/*
+ * Interfaces for managing per-vnet constructors and destructors.
+ */
+void vnet_register_sysinit(void *arg);
+void vnet_register_sysuninit(void *arg);
+void vnet_deregister_sysinit(void *arg);
+void vnet_deregister_sysuninit(void *arg);
#else /* !VIMAGE */
@@ -132,6 +179,10 @@ void vnet_data_destroy(struct vnet *vnet);
#define VNET_DECLARE(t, n) extern t n
#define VNET_DEFINE(t, n) t n
#define _VNET_PTR(b, n) &VNET_NAME(n)
+#define VNET_SYSINIT(ident, subsystem, order, func, arg) \
+ SYSINIT(ident, subsystem, order, func, arg)
+#define VNET_SYSUNINIT(ident, subsystem, order, func, arg) \
+ SYSUNINIT(ident, subsystem, order, func, arg)
#ifdef SYSCTL_OID
#define SYSCTL_VNET_INT(parent, nbr, name, access, ptr, val, descr) \
OpenPOWER on IntegriCloud