summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
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