summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-07-14 22:48:30 +0000
committerrwatson <rwatson@FreeBSD.org>2009-07-14 22:48:30 +0000
commit57ca4583e728cab422fba8f15de10bd0b637b3dd (patch)
tree13848f891fb2f7a396281b31633563d0f764ff65 /sys/net
parentef443476d9706035ac219f0280ef0b817dda7a6d (diff)
downloadFreeBSD-src-57ca4583e728cab422fba8f15de10bd0b637b3dd.zip
FreeBSD-src-57ca4583e728cab422fba8f15de10bd0b637b3dd.tar.gz
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual network stack memory allocator. Modify vnet to use the allocator instead of monolithic global container structures (vinet, ...). This change solves many binary compatibility problems associated with VIMAGE, and restores ELF symbols for virtualized global variables. Each virtualized global variable exists as a "reference copy", and also once per virtual network stack. Virtualized global variables are tagged at compile-time, placing the in a special linker set, which is loaded into a contiguous region of kernel memory. Virtualized global variables in the base kernel are linked as normal, but those in modules are copied and relocated to a reserved portion of the kernel's vnet region with the help of a the kernel linker. Virtualized global variables exist in per-vnet memory set up when the network stack instance is created, and are initialized statically from the reference copy. Run-time access occurs via an accessor macro, which converts from the current vnet and requested symbol to a per-vnet address. When "options VIMAGE" is not compiled into the kernel, normal global ELF symbols will be used instead and indirection is avoided. This change restores static initialization for network stack global variables, restores support for non-global symbols and types, eliminates the need for many subsystem constructors, eliminates large per-subsystem structures that caused many binary compatibility issues both for monitoring applications (netstat) and kernel modules, removes the per-function INIT_VNET_*() macros throughout the stack, eliminates the need for vnet_symmap ksym(2) munging, and eliminates duplicate definitions of virtualized globals under VIMAGE_GLOBALS. Bump __FreeBSD_version and update UPDATING. Portions submitted by: bz Reviewed by: bz, zec Discussed with: gnn, jamie, jeff, jhb, julian, sam Suggested by: peter Approved by: re (kensmith)
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/bridgestp.c1
-rw-r--r--sys/net/flowtable.c143
-rw-r--r--sys/net/flowtable.h5
-rw-r--r--sys/net/if.c86
-rw-r--r--sys/net/if_bridge.c6
-rw-r--r--sys/net/if_clone.c23
-rw-r--r--sys/net/if_ef.c1
-rw-r--r--sys/net/if_enc.c1
-rw-r--r--sys/net/if_ethersubr.c14
-rw-r--r--sys/net/if_faith.c2
-rw-r--r--sys/net/if_gif.c44
-rw-r--r--sys/net/if_gif.h30
-rw-r--r--sys/net/if_gre.c4
-rw-r--r--sys/net/if_loop.c23
-rw-r--r--sys/net/if_mib.c4
-rw-r--r--sys/net/if_spppsubr.c2
-rw-r--r--sys/net/if_stf.c3
-rw-r--r--sys/net/if_var.h16
-rw-r--r--sys/net/if_vlan.c1
-rw-r--r--sys/net/raw_cb.c5
-rw-r--r--sys/net/raw_cb.h6
-rw-r--r--sys/net/raw_usrreq.c2
-rw-r--r--sys/net/route.c70
-rw-r--r--sys/net/rtsock.c3
-rw-r--r--sys/net/vnet.c341
-rw-r--r--sys/net/vnet.h161
26 files changed, 609 insertions, 388 deletions
diff --git a/sys/net/bridgestp.c b/sys/net/bridgestp.c
index a4ec6bc..9349be4 100644
--- a/sys/net/bridgestp.c
+++ b/sys/net/bridgestp.c
@@ -2006,7 +2006,6 @@ bstp_same_bridgeid(uint64_t id1, uint64_t id2)
void
bstp_reinit(struct bstp_state *bs)
{
- INIT_VNET_NET(curvnet);
struct bstp_port *bp;
struct ifnet *ifp, *mif;
u_char *e_addr;
diff --git a/sys/net/flowtable.c b/sys/net/flowtable.c
index fafdc0a..dd1b040 100644
--- a/sys/net/flowtable.c
+++ b/sys/net/flowtable.c
@@ -64,7 +64,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/sctp.h>
-#include <netinet/vinet.h>
#include <libkern/jenkins.h>
@@ -164,29 +163,28 @@ struct flowtable {
};
static struct proc *flowcleanerproc;
-#ifdef VIMAGE_GLOBALS
-static struct flowtable *flow_list_head;
-static uint32_t flow_hashjitter;
-static uma_zone_t flow_ipv4_zone;
-static uma_zone_t flow_ipv6_zone;
-#endif
+static VNET_DEFINE(struct flowtable *, flow_list_head);
+static VNET_DEFINE(uint32_t, flow_hashjitter);
+static VNET_DEFINE(uma_zone_t, flow_ipv4_zone);
+static VNET_DEFINE(uma_zone_t, flow_ipv6_zone);
+
+#define V_flow_list_head VNET_GET(flow_list_head)
+#define V_flow_hashjitter VNET_GET(flow_hashjitter)
+#define V_flow_ipv4_zone VNET_GET(flow_ipv4_zone)
+#define V_flow_ipv6_zone VNET_GET(flow_ipv6_zone)
static int flowtable_iattach(const void *);
#ifdef VIMAGE
static int flowtable_idetach(const void *);
-#endif
-#ifndef VIMAGE_GLOBALS
static const vnet_modinfo_t flowtable_modinfo = {
.vmi_id = VNET_MOD_FLOWTABLE,
.vmi_name = "flowtable",
.vmi_dependson = VNET_MOD_INET,
.vmi_iattach = flowtable_iattach,
-#ifdef VIMAGE
.vmi_idetach = flowtable_idetach
-#endif
};
-#endif /* !VIMAGE_GLOBALS */
+#endif
/*
* TODO:
@@ -205,54 +203,67 @@ static const vnet_modinfo_t flowtable_modinfo = {
* - support explicit connection state (currently only ad-hoc for DSR)
* - idetach() cleanup for options VIMAGE builds.
*/
-#ifdef VIMAGE_GLOBALS
-int flowtable_enable;
-static int flowtable_hits;
-static int flowtable_lookups;
-static int flowtable_misses;
-static int flowtable_frees;
-static int flowtable_free_checks;
-static int flowtable_max_depth;
-static int flowtable_collisions;
-static int flowtable_syn_expire;
-static int flowtable_udp_expire;
-static int flowtable_fin_wait_expire;
-static int flowtable_tcp_expire;
-static int flowtable_nmbflows;
-#endif
+VNET_DEFINE(int, flowtable_enable) = 1;
+static VNET_DEFINE(int, flowtable_hits);
+static VNET_DEFINE(int, flowtable_lookups);
+static VNET_DEFINE(int, flowtable_misses);
+static VNET_DEFINE(int, flowtable_frees);
+static VNET_DEFINE(int, flowtable_free_checks);
+static VNET_DEFINE(int, flowtable_max_depth);
+static VNET_DEFINE(int, flowtable_collisions);
+static VNET_DEFINE(int, flowtable_syn_expire) = SYN_IDLE;
+static VNET_DEFINE(int, flowtable_udp_expire) = UDP_IDLE;
+static VNET_DEFINE(int, flowtable_fin_wait_expire) = FIN_WAIT_IDLE;
+static VNET_DEFINE(int, flowtable_tcp_expire) = TCP_IDLE;
+static VNET_DEFINE(int, flowtable_nmbflows) = 4096;
+
+#define V_flowtable_enable VNET_GET(flowtable_enable)
+#define V_flowtable_hits VNET_GET(flowtable_hits)
+#define V_flowtable_lookups VNET_GET(flowtable_lookups)
+#define V_flowtable_misses VNET_GET(flowtable_misses)
+#define V_flowtable_frees VNET_GET(flowtable_frees)
+#define V_flowtable_free_checks VNET_GET(flowtable_free_checks)
+#define V_flowtable_max_depth VNET_GET(flowtable_max_depth)
+#define V_flowtable_collisions VNET_GET(flowtable_collisions)
+#define V_flowtable_syn_expire VNET_GET(flowtable_syn_expire)
+#define V_flowtable_udp_expire VNET_GET(flowtable_udp_expire)
+#define V_flowtable_fin_wait_expire VNET_GET(flowtable_fin_wait_expire)
+#define V_flowtable_tcp_expire VNET_GET(flowtable_tcp_expire)
+#define V_flowtable_nmbflows VNET_GET(flowtable_nmbflows)
+
SYSCTL_NODE(_net_inet, OID_AUTO, flowtable, CTLFLAG_RD, NULL, "flowtable");
-SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_flowtable, OID_AUTO, enable,
- CTLFLAG_RW, flowtable_enable, 0, "enable flowtable caching.");
-SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_flowtable, OID_AUTO, hits,
- CTLFLAG_RD, flowtable_hits, 0, "# flowtable hits.");
-SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_flowtable, OID_AUTO, lookups,
- CTLFLAG_RD, flowtable_lookups, 0, "# flowtable lookups.");
-SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_flowtable, OID_AUTO, misses,
- CTLFLAG_RD, flowtable_misses, 0, "#flowtable misses.");
-SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_flowtable, OID_AUTO, frees,
- CTLFLAG_RD, flowtable_frees, 0, "#flows freed.");
-SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_flowtable, OID_AUTO, free_checks,
- CTLFLAG_RD, flowtable_free_checks, 0, "#flows free checks.");
-SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_flowtable, OID_AUTO, max_depth,
- CTLFLAG_RD, flowtable_max_depth, 0, "max collision list length.");
-SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_flowtable, OID_AUTO, collisions,
- CTLFLAG_RD, flowtable_collisions, 0, "#flowtable collisions.");
+SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, enable, CTLFLAG_RW,
+ &VNET_NAME(flowtable_enable), 0, "enable flowtable caching.");
+SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, hits, CTLFLAG_RD,
+ &VNET_NAME(flowtable_hits), 0, "# flowtable hits.");
+SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, lookups, CTLFLAG_RD,
+ &VNET_NAME(flowtable_lookups), 0, "# flowtable lookups.");
+SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, misses, CTLFLAG_RD,
+ &VNET_NAME(flowtable_misses), 0, "#flowtable misses.");
+SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, frees, CTLFLAG_RD,
+ &VNET_NAME(flowtable_frees), 0, "#flows freed.");
+SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, free_checks, CTLFLAG_RD,
+ &VNET_NAME(flowtable_free_checks), 0, "#flows free checks.");
+SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, max_depth, CTLFLAG_RD,
+ &VNET_NAME(flowtable_max_depth), 0, "max collision list length.");
+SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, collisions, CTLFLAG_RD,
+ &VNET_NAME(flowtable_collisions), 0, "#flowtable collisions.");
/*
* XXX This does not end up updating timeouts at runtime
* and only reflects the value for the last table added :-/
*/
-SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_flowtable, OID_AUTO, syn_expire,
- CTLFLAG_RW, flowtable_syn_expire, 0,
+SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, syn_expire, CTLFLAG_RW,
+ &VNET_NAME(flowtable_syn_expire), 0,
"seconds after which to remove syn allocated flow.");
-SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_flowtable, OID_AUTO, udp_expire,
- CTLFLAG_RW, flowtable_udp_expire, 0,
+SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, udp_expire, CTLFLAG_RW,
+ &VNET_NAME(flowtable_udp_expire), 0,
"seconds after which to remove flow allocated to UDP.");
-SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_flowtable, OID_AUTO, fin_wait_expire,
- CTLFLAG_RW, flowtable_fin_wait_expire, 0,
+SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, fin_wait_expire, CTLFLAG_RW,
+ &VNET_NAME(flowtable_fin_wait_expire), 0,
"seconds after which to remove a flow in FIN_WAIT.");
-SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_flowtable, OID_AUTO, tcp_expire,
- CTLFLAG_RW, flowtable_tcp_expire, 0,
+SYSCTL_VNET_INT(_net_inet_flowtable, OID_AUTO, tcp_expire, CTLFLAG_RW,
+ &VNET_NAME(flowtable_tcp_expire), 0,
"seconds after which to remove flow allocated to a TCP connection.");
@@ -266,7 +277,6 @@ SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_flowtable, OID_AUTO, tcp_expire,
static int
sysctl_nmbflows(SYSCTL_HANDLER_ARGS)
{
- INIT_VNET_INET(curvnet);
int error, newnmbflows;
newnmbflows = V_flowtable_nmbflows;
@@ -283,8 +293,8 @@ sysctl_nmbflows(SYSCTL_HANDLER_ARGS)
}
return (error);
}
-SYSCTL_V_PROC(V_NET, vnet_inet, _net_inet_flowtable, OID_AUTO, nmbflows,
- CTLTYPE_INT|CTLFLAG_RW, flowtable_nmbflows, 0, sysctl_nmbflows, "IU",
+SYSCTL_VNET_PROC(_net_inet_flowtable, OID_AUTO, nmbflows,
+ CTLTYPE_INT|CTLFLAG_RW, 0, 0, sysctl_nmbflows, "IU",
"Maximum number of flows allowed");
#ifndef RADIX_MPATH
@@ -338,7 +348,6 @@ static uint32_t
ipv4_flow_lookup_hash_internal(struct mbuf *m, struct route *ro,
uint32_t *key, uint16_t *flags, uint8_t *protop)
{
- INIT_VNET_INET(curvnet);
uint16_t sport = 0, dport = 0;
struct ip *ip = NULL;
uint8_t proto = 0;
@@ -505,7 +514,6 @@ static int
flowtable_insert(struct flowtable *ft, uint32_t hash, uint32_t *key,
uint8_t proto, struct route *ro, uint16_t flags)
{
- INIT_VNET_INET(curvnet);
struct flentry *fle, *fletail, *newfle, **flep;
int depth;
uma_zone_t flezone;
@@ -596,7 +604,6 @@ flowtable_key_equal(struct flentry *fle, uint32_t *key)
int
flowtable_lookup(struct flowtable *ft, struct mbuf *m, struct route *ro)
{
- INIT_VNET_INET(curvnet);
uint32_t key[9], hash;
struct flentry *fle;
uint16_t flags;
@@ -718,7 +725,6 @@ uncached:
struct flowtable *
flowtable_alloc(int nentry, int flags)
{
- INIT_VNET_INET(curvnet);
struct flowtable *ft, *fttail;
int i;
@@ -800,7 +806,7 @@ static void
flowtable_setup(void *arg)
{
-#ifndef VIMAGE_GLOBALS
+#ifdef VIMAGE
vnet_mod_register(&flowtable_modinfo);
#else
flowtable_iattach(NULL);
@@ -810,21 +816,6 @@ flowtable_setup(void *arg)
static int
flowtable_iattach(const void *unused __unused)
{
- INIT_VNET_INET(curvnet);
-
- V_flowtable_enable = 1;
- V_flowtable_hits = 0;
- V_flowtable_lookups = 0;
- V_flowtable_misses = 0;
- V_flowtable_frees = 0;
- V_flowtable_free_checks = 0;
- V_flowtable_max_depth = 0;
- V_flowtable_collisions = 0;
- V_flowtable_syn_expire = SYN_IDLE;
- V_flowtable_udp_expire = UDP_IDLE;
- V_flowtable_fin_wait_expire = FIN_WAIT_IDLE;
- V_flowtable_tcp_expire = TCP_IDLE;
- V_flowtable_nmbflows = 4096;
V_flow_ipv4_zone = uma_zcreate("ip4flow", sizeof(struct flentry_v4),
NULL, NULL, NULL, NULL, 64, UMA_ZONE_MAXBUCKET);
@@ -839,7 +830,6 @@ flowtable_iattach(const void *unused __unused)
static int
flowtable_idetach(const void *unused __unused)
{
- INIT_VNET_INET(curvnet);
uma_zdestroy(V_flow_ipv4_zone);
uma_zdestroy(V_flow_ipv6_zone);
@@ -858,7 +848,6 @@ SYSINIT(flowtable_setup, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY, flowtable_setup, NUL
static void
fle_free(struct flentry *fle)
{
- INIT_VNET_INET(curvnet);
struct rtentry *rt;
struct llentry *lle;
@@ -873,7 +862,6 @@ fle_free(struct flentry *fle)
static void
flowtable_free_stale(struct flowtable *ft)
{
- INIT_VNET_INET(curvnet);
int curbit = 0, count;
struct flentry *fle, **flehead, *fleprev;
struct flentry *flefreehead, *flefreetail, *fletmp;
@@ -961,7 +949,6 @@ flowtable_free_stale(struct flowtable *ft)
static void
flowtable_clean_vnet(void)
{
- INIT_VNET_INET(curvnet);
struct flowtable *ft;
int i;
diff --git a/sys/net/flowtable.h b/sys/net/flowtable.h
index 26aa11d..13fdfdb 100644
--- a/sys/net/flowtable.h
+++ b/sys/net/flowtable.h
@@ -38,9 +38,8 @@ $FreeBSD$
#define FL_PCPU (1<<1) /* pcpu cache */
struct flowtable;
-#ifdef VIMAGE_GLOBALS
-extern struct flowtable *ip_ft;
-#endif
+VNET_DECLARE(struct flowtable *, ip_ft);
+#define V_ip_ft VNET_GET(ip_ft)
struct flowtable *flowtable_alloc(int nentry, int flags);
diff --git a/sys/net/if.c b/sys/net/if.c
index 4803477..daab1ac 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -84,7 +84,6 @@
#endif
#ifdef INET
#include <netinet/if_ether.h>
-#include <netinet/vinet.h>
#endif
#if defined(INET) || defined(INET6)
#ifdef DEV_CARP
@@ -94,12 +93,6 @@
#include <security/mac/mac_framework.h>
-#ifndef VIMAGE
-#ifndef VIMAGE_GLOBALS
-struct vnet_net vnet_net_0;
-#endif
-#endif
-
struct ifindex_entry {
struct ifnet *ife_ifnet;
};
@@ -162,37 +155,30 @@ static int vnet_net_iattach(const void *);
static int vnet_net_idetach(const void *);
#endif
-#ifdef VIMAGE_GLOBALS
-struct ifnethead ifnet; /* depend on static init XXX */
-struct ifgrouphead ifg_head;
-int if_index;
-static int if_indexlim;
+VNET_DEFINE(struct ifnethead, ifnet); /* depend on static init XXX */
+VNET_DEFINE(struct ifgrouphead, ifg_head);
+VNET_DEFINE(int, if_index);
+static VNET_DEFINE(int, if_indexlim) = 8;
+
/* Table of ifnet by index. Locked with ifnet_lock. */
-static struct ifindex_entry *ifindex_table;
-#endif
+static VNET_DEFINE(struct ifindex_entry *, ifindex_table);
+
+#define V_if_indexlim VNET_GET(if_indexlim)
+#define V_ifindex_table VNET_GET(ifindex_table)
int ifqmaxlen = IFQ_MAXLEN;
struct rwlock ifnet_lock;
static if_com_alloc_t *if_com_alloc[256];
static if_com_free_t *if_com_free[256];
-#ifndef VIMAGE_GLOBALS
-static struct vnet_symmap vnet_net_symmap[] = {
- VNET_SYMMAP(net, ifnet),
- VNET_SYMMAP_END
-};
-
+#ifdef VIMAGE
static const vnet_modinfo_t vnet_net_modinfo = {
.vmi_id = VNET_MOD_NET,
.vmi_name = "net",
- .vmi_size = sizeof(struct vnet_net),
- .vmi_symmap = vnet_net_symmap,
.vmi_iattach = vnet_net_iattach,
-#ifdef VIMAGE
.vmi_idetach = vnet_net_idetach
-#endif
};
-#endif /* !VIMAGE_GLOBALS */
+#endif
/*
* System initialization
@@ -207,7 +193,6 @@ MALLOC_DEFINE(M_IFMADDR, "ether_multi", "link-level multicast address");
struct ifnet *
ifnet_byindex_locked(u_short idx)
{
- INIT_VNET_NET(curvnet);
if (idx > V_if_index)
return (NULL);
@@ -244,7 +229,6 @@ ifnet_byindex_ref(u_short idx)
static void
ifnet_setbyindex(u_short idx, struct ifnet *ifp)
{
- INIT_VNET_NET(curvnet);
IFNET_WLOCK_ASSERT();
@@ -276,7 +260,7 @@ static void
if_init(void *dummy __unused)
{
-#ifndef VIMAGE_GLOBALS
+#ifdef VIMAGE
vnet_mod_register(&vnet_net_modinfo);
#else
vnet_net_iattach(NULL);
@@ -289,11 +273,6 @@ if_init(void *dummy __unused)
static int
vnet_net_iattach(const void *unused __unused)
{
- INIT_VNET_NET(curvnet);
-
- V_if_index = 0;
- V_ifindex_table = NULL;
- V_if_indexlim = 8;
TAILQ_INIT(&V_ifnet);
TAILQ_INIT(&V_ifg_head);
@@ -306,7 +285,6 @@ vnet_net_iattach(const void *unused __unused)
static int
vnet_net_idetach(const void *unused __unused)
{
- INIT_VNET_NET(curvnet);
VNET_ASSERT(TAILQ_EMPTY(&V_ifnet));
VNET_ASSERT(TAILQ_EMPTY(&V_ifg_head));
@@ -320,7 +298,6 @@ vnet_net_idetach(const void *unused __unused)
void
if_grow(void)
{
- INIT_VNET_NET(curvnet);
u_int n;
struct ifindex_entry *e;
@@ -354,7 +331,6 @@ if_check(void *dummy __unused)
struct ifnet *
if_alloc(u_char type)
{
- INIT_VNET_NET(curvnet);
struct ifnet *ifp;
ifp = malloc(sizeof(struct ifnet), M_IFNET, M_WAITOK|M_ZERO);
@@ -418,7 +394,6 @@ if_alloc(u_char type)
static void
if_free_internal(struct ifnet *ifp)
{
- INIT_VNET_NET(curvnet); /* ifp->if_vnet is already NULL here */
KASSERT((ifp->if_flags & IFF_DYING),
("if_free_internal: interface not dying"));
@@ -544,7 +519,6 @@ if_attach(struct ifnet *ifp)
static void
if_attach_internal(struct ifnet *ifp, int vmove)
{
- INIT_VNET_NET(curvnet);
unsigned socksize, ifasize;
int namelen, masklen;
struct sockaddr_dl *sdl;
@@ -649,7 +623,6 @@ if_attach_internal(struct ifnet *ifp, int vmove)
static void
if_attachdomain(void *dummy)
{
- INIT_VNET_NET(curvnet);
struct ifnet *ifp;
int s;
@@ -769,7 +742,6 @@ if_detach(struct ifnet *ifp)
static void
if_detach_internal(struct ifnet *ifp, int vmove)
{
- INIT_VNET_NET(ifp->if_vnet);
struct ifaddr *ifa;
struct radix_node_head *rnh;
int i, j;
@@ -904,25 +876,17 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
/*
* Unlink the ifnet from ifindex_table[] in current vnet,
* and shrink the if_index for that vnet if possible.
- * do / while construct below is needed to confine the scope
- * of INIT_VNET_NET().
*/
- {
- INIT_VNET_NET(curvnet);
-
- IFNET_WLOCK();
- ifnet_setbyindex(ifp->if_index, NULL);
- while (V_if_index > 0 && \
- ifnet_byindex_locked(V_if_index) == NULL)
- V_if_index--;
- IFNET_WUNLOCK();
- };
+ IFNET_WLOCK();
+ ifnet_setbyindex(ifp->if_index, NULL);
+ while (V_if_index > 0 && ifnet_byindex_locked(V_if_index) == NULL)
+ V_if_index--;
+ IFNET_WUNLOCK();
/*
* Switch to the context of the target vnet.
*/
CURVNET_SET_QUIET(new_vnet);
- INIT_VNET_NET(new_vnet);
/*
* Try to find an empty slot below if_index. If we fail, take
@@ -956,7 +920,6 @@ if_vmove(struct ifnet *ifp, struct vnet *new_vnet)
int
if_addgroup(struct ifnet *ifp, const char *groupname)
{
- INIT_VNET_NET(ifp->if_vnet);
struct ifg_list *ifgl;
struct ifg_group *ifg = NULL;
struct ifg_member *ifgm;
@@ -1026,7 +989,6 @@ if_addgroup(struct ifnet *ifp, const char *groupname)
int
if_delgroup(struct ifnet *ifp, const char *groupname)
{
- INIT_VNET_NET(ifp->if_vnet);
struct ifg_list *ifgl;
struct ifg_member *ifgm;
@@ -1072,7 +1034,6 @@ if_delgroup(struct ifnet *ifp, const char *groupname)
static void
if_delgroups(struct ifnet *ifp)
{
- INIT_VNET_NET(ifp->if_vnet);
struct ifg_list *ifgl;
struct ifg_member *ifgm;
char groupname[IFNAMSIZ];
@@ -1164,7 +1125,6 @@ if_getgroup(struct ifgroupreq *data, struct ifnet *ifp)
static int
if_getgroupmembers(struct ifgroupreq *data)
{
- INIT_VNET_NET(curvnet);
struct ifgroupreq *ifgr = data;
struct ifg_group *ifg;
struct ifg_member *ifgm;
@@ -1336,7 +1296,6 @@ ifa_free(struct ifaddr *ifa)
static struct ifaddr *
ifa_ifwithaddr_internal(struct sockaddr *addr, int getref)
{
- INIT_VNET_NET(curvnet);
struct ifnet *ifp;
struct ifaddr *ifa;
@@ -1392,7 +1351,6 @@ ifa_ifwithaddr_check(struct sockaddr *addr)
struct ifaddr *
ifa_ifwithbroadaddr(struct sockaddr *addr)
{
- INIT_VNET_NET(curvnet);
struct ifnet *ifp;
struct ifaddr *ifa;
@@ -1426,7 +1384,6 @@ done:
struct ifaddr *
ifa_ifwithdstaddr(struct sockaddr *addr)
{
- INIT_VNET_NET(curvnet);
struct ifnet *ifp;
struct ifaddr *ifa;
@@ -1460,7 +1417,6 @@ done:
struct ifaddr *
ifa_ifwithnet(struct sockaddr *addr)
{
- INIT_VNET_NET(curvnet);
struct ifnet *ifp;
struct ifaddr *ifa;
struct ifaddr *ifa_maybe = NULL;
@@ -1841,7 +1797,6 @@ if_slowtimo(void *arg)
VNET_LIST_RLOCK();
VNET_FOREACH(vnet_iter) {
CURVNET_SET(vnet_iter);
- INIT_VNET_NET(vnet_iter);
TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
if (ifp->if_timer == 0 || --ifp->if_timer)
continue;
@@ -1863,7 +1818,6 @@ if_slowtimo(void *arg)
struct ifnet *
ifunit_ref(const char *name)
{
- INIT_VNET_NET(curvnet);
struct ifnet *ifp;
IFNET_RLOCK();
@@ -1881,7 +1835,6 @@ ifunit_ref(const char *name)
struct ifnet *
ifunit(const char *name)
{
- INIT_VNET_NET(curvnet);
struct ifnet *ifp;
IFNET_RLOCK();
@@ -2478,7 +2431,6 @@ ifpromisc(struct ifnet *ifp, int pswitch)
static int
ifconf(u_long cmd, caddr_t data)
{
- INIT_VNET_NET(curvnet);
struct ifconf *ifc = (struct ifconf *)data;
#ifdef __amd64__
struct ifconf32 *ifc32 = (struct ifconf32 *)data;
@@ -2837,7 +2789,6 @@ if_delmulti(struct ifnet *ifp, struct sockaddr *sa)
int lastref;
#ifdef INVARIANTS
struct ifnet *oifp;
- INIT_VNET_NET(ifp->if_vnet);
IFNET_RLOCK();
TAILQ_FOREACH(oifp, &V_ifnet, if_link)
@@ -2878,9 +2829,6 @@ if_delmulti(struct ifnet *ifp, struct sockaddr *sa)
void
if_delmulti_ifma(struct ifmultiaddr *ifma)
{
-#ifdef DIAGNOSTIC
- INIT_VNET_NET(curvnet);
-#endif
struct ifnet *ifp;
int lastref;
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 08310d7..945bc5f 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -116,11 +116,9 @@ __FBSDID("$FreeBSD$");
#include <netinet/in_var.h>
#include <netinet/ip.h>
#include <netinet/ip_var.h>
-#include <netinet/vinet.h>
#ifdef INET6
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
-#include <netinet6/vinet6.h>
#endif
#if defined(INET) || defined(INET6)
#ifdef DEV_CARP
@@ -3042,7 +3040,6 @@ bridge_pfil(struct mbuf **mp, struct ifnet *bifp, struct ifnet *ifp, int dir)
}
if (ip_fw_chk_ptr && pfil_ipfw != 0 && dir == PFIL_OUT && ifp != NULL) {
- INIT_VNET_INET(curvnet);
struct dn_pkt_tag *dn_tag;
error = -1;
@@ -3236,7 +3233,6 @@ bad:
static int
bridge_ip_checkbasic(struct mbuf **mp)
{
- INIT_VNET_INET(curvnet);
struct mbuf *m = *mp;
struct ip *ip;
int len, hlen;
@@ -3332,7 +3328,6 @@ bad:
static int
bridge_ip6_checkbasic(struct mbuf **mp)
{
- INIT_VNET_INET6(curvnet);
struct mbuf *m = *mp;
struct ip6_hdr *ip6;
@@ -3387,7 +3382,6 @@ static int
bridge_fragment(struct ifnet *ifp, struct mbuf *m, struct ether_header *eh,
int snap, struct llc *llc)
{
- INIT_VNET_INET(curvnet);
struct mbuf *m0;
struct ip *ip;
int error = -1;
diff --git a/sys/net/if_clone.c b/sys/net/if_clone.c
index eaa7397..9347d2c 100644
--- a/sys/net/if_clone.c
+++ b/sys/net/if_clone.c
@@ -58,10 +58,11 @@ static int if_clone_createif(struct if_clone *ifc, char *name, size_t len,
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;
-#endif
+static VNET_DEFINE(int, if_cloners_count);
+VNET_DEFINE(LIST_HEAD(, if_clone), if_cloners);
+
+#define V_if_cloners_count VNET_GET(if_cloners_count)
+#define V_if_cloners VNET_GET(if_cloners)
#define IF_CLONERS_LOCK_INIT() \
mtx_init(&if_cloners_mtx, "if_cloners lock", NULL, MTX_DEF)
@@ -115,17 +116,16 @@ LIST_HEAD(, if_clone) if_cloners;
static MALLOC_DEFINE(M_CLONE, "clone", "interface cloning framework");
-#ifndef VIMAGE_GLOBALS
+#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 /* !VIMAGE_GLOBALS */
+#endif
static int vnet_clone_iattach(const void *unused __unused)
{
- INIT_VNET_NET(curvnet);
LIST_INIT(&V_if_cloners);
return (0);
@@ -136,7 +136,7 @@ if_clone_init(void)
{
IF_CLONERS_LOCK_INIT();
-#ifndef VIMAGE_GLOBALS
+#ifdef VIMAGE
vnet_mod_register(&vnet_clone_modinfo);
#else
vnet_clone_iattach(NULL);
@@ -149,7 +149,6 @@ 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 */
@@ -162,7 +161,6 @@ if_clone_create(char *name, size_t len, caddr_t params)
#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;
@@ -213,7 +211,6 @@ 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;
@@ -231,7 +228,6 @@ if_clone_destroy(const char *name)
#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;
@@ -289,7 +285,6 @@ 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;
/*
@@ -322,7 +317,6 @@ 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();
@@ -362,7 +356,6 @@ 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;
diff --git a/sys/net/if_ef.c b/sys/net/if_ef.c
index e5e7dd8..c0b2d67 100644
--- a/sys/net/if_ef.c
+++ b/sys/net/if_ef.c
@@ -493,7 +493,6 @@ ef_load(void)
VNET_LIST_RLOCK();
VNET_FOREACH(vnet_iter) {
CURVNET_SET(vnet_iter);
- INIT_VNET_NET(vnet_iter);
IFNET_RLOCK();
TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
if (ifp->if_type != IFT_ETHER) continue;
diff --git a/sys/net/if_enc.c b/sys/net/if_enc.c
index 38321ff..7b62734 100644
--- a/sys/net/if_enc.c
+++ b/sys/net/if_enc.c
@@ -47,6 +47,7 @@
#include <net/route.h>
#include <net/netisr.h>
#include <net/bpf.h>
+#include <net/vnet.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 5e98e53..f7c9042 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -73,7 +73,7 @@
#include <netinet/if_ether.h>
#include <netinet/ip_fw.h>
#include <netinet/ip_dummynet.h>
-#include <netinet/vinet.h>
+#include <netinet/ip_var.h>
#endif
#ifdef INET6
#include <netinet6/nd6.h>
@@ -148,9 +148,8 @@ MALLOC_DEFINE(M_ARPCOM, "arpcom", "802.* interface internals");
#if defined(INET) || defined(INET6)
int
ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst, int shared);
-#ifdef VIMAGE_GLOBALS
-static int ether_ipfw;
-#endif
+static VNET_DEFINE(int, ether_ipfw);
+#define V_ether_ipfw VNET_GET(ether_ipfw)
#endif
@@ -434,7 +433,6 @@ int
ether_output_frame(struct ifnet *ifp, struct mbuf *m)
{
#if defined(INET) || defined(INET6)
- INIT_VNET_NET(ifp->if_vnet);
if (ip_fw_chk_ptr && V_ether_ipfw != 0) {
if (ether_ipfw_chk(&m, ifp, 0) == 0) {
@@ -463,7 +461,6 @@ ether_output_frame(struct ifnet *ifp, struct mbuf *m)
int
ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst, int shared)
{
- INIT_VNET_INET(dst->if_vnet);
struct ether_header *eh;
struct ether_header save_eh;
struct mbuf *m;
@@ -774,7 +771,6 @@ ether_demux(struct ifnet *ifp, struct mbuf *m)
KASSERT(ifp != NULL, ("%s: NULL interface pointer", __func__));
#if defined(INET) || defined(INET6)
- INIT_VNET_NET(ifp->if_vnet);
/*
* Allow dummynet and/or ipfw to claim the frame.
* Do not do this for PROMISC frames in case we are re-entered.
@@ -994,8 +990,8 @@ ether_ifdetach(struct ifnet *ifp)
SYSCTL_DECL(_net_link);
SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet");
#if defined(INET) || defined(INET6)
-SYSCTL_V_INT(V_NET, vnet_net, _net_link_ether, OID_AUTO, ipfw, CTLFLAG_RW,
- ether_ipfw, 0, "Pass ether pkts through firewall");
+SYSCTL_VNET_INT(_net_link_ether, OID_AUTO, ipfw, CTLFLAG_RW,
+ &VNET_NAME(ether_ipfw), 0, "Pass ether pkts through firewall");
#endif
#if 0
diff --git a/sys/net/if_faith.c b/sys/net/if_faith.c
index 3b60d2c..cbca740 100644
--- a/sys/net/if_faith.c
+++ b/sys/net/if_faith.c
@@ -77,7 +77,6 @@
#include <netinet6/in6_var.h>
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
-#include <netinet6/vinet6.h>
#endif
#define FAITHNAME "faith"
@@ -328,7 +327,6 @@ static int
faithprefix(in6)
struct in6_addr *in6;
{
- INIT_VNET_INET6(curvnet);
struct rtentry *rt;
struct sockaddr_in6 sin6;
int ret;
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c
index 06a849a..e96cb41 100644
--- a/sys/net/if_gif.c
+++ b/sys/net/if_gif.c
@@ -95,22 +95,21 @@
static struct mtx gif_mtx;
static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface");
-#ifndef VIMAGE
-#ifndef VIMAGE_GLOBALS
-struct vnet_gif vnet_gif_0;
-#endif
-#endif
+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_GET(gif_softc_list)
+#define V_max_gif_nesting VNET_GET(max_gif_nesting)
+#define V_parallel_tunnels VNET_GET(parallel_tunnels)
-#ifdef VIMAGE_GLOBALS
-static LIST_HEAD(, gif_softc) gif_softc_list;
-static int max_gif_nesting;
-static int parallel_tunnels;
#ifdef INET
-int ip_gif_ttl;
+VNET_DEFINE(int, ip_gif_ttl);
+#define V_ip_gif_ttl VNET_GET(ip_gif_ttl)
#endif
#ifdef INET6
-int ip6_gif_hlim;
-#endif
+VNET_DEFINE(int, ip6_gif_hlim);
+#define V_ip6_gif_hlim VNET_GET(ip6_gif_hlim)
#endif
void (*ng_gif_input_p)(struct ifnet *ifp, struct mbuf **mp, int af);
@@ -123,11 +122,10 @@ 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 *);
-#ifndef VIMAGE_GLOBALS
+#ifdef VIMAGE
static const vnet_modinfo_t vnet_gif_modinfo = {
.vmi_id = VNET_MOD_GIF,
.vmi_name = "gif",
- .vmi_size = sizeof(struct vnet_gif),
.vmi_dependson = VNET_MOD_NET,
.vmi_iattach = vnet_gif_iattach
};
@@ -151,13 +149,13 @@ SYSCTL_NODE(_net_link, IFT_GIF, gif, CTLFLAG_RW, 0,
*/
#define MAX_GIF_NEST 1
#endif
-SYSCTL_V_INT(V_NET, vnet_gif, _net_link_gif, OID_AUTO, max_nesting,
- CTLFLAG_RW, max_gif_nesting, 0, "Max nested tunnels");
+SYSCTL_VNET_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW,
+ &VNET_NAME(max_gif_nesting), 0, "Max nested tunnels");
#ifdef INET6
SYSCTL_DECL(_net_inet6_ip6);
-SYSCTL_V_INT(V_NET, vnet_gif, _net_inet6_ip6, IPV6CTL_GIF_HLIM,
- gifhlim, CTLFLAG_RW, ip6_gif_hlim, 0, "");
+SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim, CTLFLAG_RW,
+ &VNET_NAME(ip6_gif_hlim), 0, "");
#endif
/*
@@ -165,8 +163,8 @@ SYSCTL_V_INT(V_NET, vnet_gif, _net_inet6_ip6, IPV6CTL_GIF_HLIM,
* pair of addresses. Some applications require this functionality so
* we allow control over this check here.
*/
-SYSCTL_V_INT(V_NET, vnet_gif, _net_link_gif, OID_AUTO, parallel_tunnels,
- CTLFLAG_RW, parallel_tunnels, 0, "Allow parallel tunnels?");
+SYSCTL_VNET_INT(_net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW,
+ &VNET_NAME(parallel_tunnels), 0, "Allow parallel tunnels?");
/* copy from src/sys/net/if_ethersubr.c */
static const u_char etherbroadcastaddr[ETHER_ADDR_LEN] =
@@ -182,7 +180,6 @@ gif_clone_create(ifc, unit, params)
int unit;
caddr_t params;
{
- INIT_VNET_GIF(curvnet);
struct gif_softc *sc;
sc = malloc(sizeof(struct gif_softc), M_GIF, M_WAITOK | M_ZERO);
@@ -265,7 +262,6 @@ gif_clone_destroy(ifp)
static int
vnet_gif_iattach(const void *unused __unused)
{
- INIT_VNET_GIF(curvnet);
LIST_INIT(&V_gif_softc_list);
V_max_gif_nesting = MAX_GIF_NEST;
@@ -295,7 +291,7 @@ gifmodevent(mod, type, data)
case MOD_LOAD:
mtx_init(&gif_mtx, "gif_mtx", NULL, MTX_DEF);
-#ifndef VIMAGE_GLOBALS
+#ifdef VIMAGE
vnet_mod_register(&vnet_gif_modinfo);
#else
vnet_gif_iattach(NULL);
@@ -419,7 +415,6 @@ gif_output(ifp, m, dst, ro)
struct sockaddr *dst;
struct route *ro;
{
- INIT_VNET_GIF(ifp->if_vnet);
struct gif_softc *sc = ifp->if_softc;
struct m_tag *mtag;
int error = 0;
@@ -944,7 +939,6 @@ gif_set_tunnel(ifp, src, dst)
struct sockaddr *src;
struct sockaddr *dst;
{
- INIT_VNET_GIF(ifp->if_vnet);
struct gif_softc *sc = ifp->if_softc;
struct gif_softc *sc2;
struct sockaddr *osrc, *odst, *sa;
diff --git a/sys/net/if_gif.h b/sys/net/if_gif.h
index c8768b5..5257837 100644
--- a/sys/net/if_gif.h
+++ b/sys/net/if_gif.h
@@ -119,34 +119,8 @@ int gif_set_tunnel(struct ifnet *, struct sockaddr *, struct sockaddr *);
void gif_delete_tunnel(struct ifnet *);
int gif_encapcheck(const struct mbuf *, int, int, void *);
-/*
- * Virtualization support
- */
-
-struct vnet_gif {
- LIST_HEAD(, gif_softc) _gif_softc_list;
- int _max_gif_nesting;
- int _parallel_tunnels;
- int _ip_gif_ttl;
- int _ip6_gif_hlim;
-};
-
-#ifndef VIMAGE
-#ifndef VIMAGE_GLOBALS
-extern struct vnet_gif vnet_gif_0;
-#endif
-#endif
-
-#define INIT_VNET_GIF(vnet) \
- INIT_FROM_VNET(vnet, VNET_MOD_GIF, struct vnet_gif, vnet_gif)
-
-#define VNET_GIF(sym) VSYM(vnet_gif, sym)
-
-#define V_gif_softc_list VNET_GIF(gif_softc_list)
-#define V_max_gif_nesting VNET_GIF(max_gif_nesting)
-#define V_parallel_tunnels VNET_GIF(parallel_tunnels)
-#define V_ip_gif_ttl VNET_GIF(ip_gif_ttl)
-#define V_ip6_gif_hlim VNET_GIF(ip6_gif_hlim)
+VNET_DECLARE(int, ip_gif_ttl);
+#define V_ip_gif_ttl VNET_GET(ip_gif_ttl)
#endif /* _KERNEL */
diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c
index e7eb34a..4ed2a9e 100644
--- a/sys/net/if_gre.c
+++ b/sys/net/if_gre.c
@@ -80,7 +80,6 @@
#include <netinet/ip_gre.h>
#include <netinet/ip_var.h>
#include <netinet/ip_encap.h>
-#include <netinet/vinet.h>
#else
#error "Huh? if_gre without inet?"
#endif
@@ -243,9 +242,6 @@ static int
gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
struct route *ro)
{
-#ifdef INET6
- INIT_VNET_INET(ifp->if_vnet);
-#endif
int error = 0;
struct gre_softc *sc = ifp->if_softc;
struct greip *gh;
diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c
index 82c68ff..c2acacd 100644
--- a/sys/net/if_loop.c
+++ b/sys/net/if_loop.c
@@ -108,25 +108,26 @@ static int vnet_loif_iattach(const void *);
static int vnet_loif_idetach(const void *);
#endif
-#ifdef VIMAGE_GLOBALS
-struct ifnet *loif; /* Used externally */
-#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);
+#define V_lo_cloner_data VNET_GET(lo_cloner_data)
+#define V_lo_cloner VNET_GET(lo_cloner)
+
MALLOC_DEFINE(M_LO_CLONER, "lo_cloner", "lo_cloner");
#endif
-#ifndef VIMAGE_GLOBALS
+#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,
-#ifdef VIMAGE
.vmi_idetach = vnet_loif_idetach
-#endif
};
-#endif /* !VIMAGE_GLOBALS */
+#endif
IFC_SIMPLE_DECLARE(lo, 1);
@@ -147,7 +148,6 @@ lo_clone_destroy(struct ifnet *ifp)
static int
lo_clone_create(struct if_clone *ifc, int unit, caddr_t params)
{
- INIT_VNET_NET(curvnet);
struct ifnet *ifp;
ifp = if_alloc(IFT_LOOP);
@@ -173,10 +173,7 @@ lo_clone_create(struct if_clone *ifc, int unit, caddr_t params)
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);
@@ -196,7 +193,6 @@ vnet_loif_iattach(const void *unused __unused)
static int
vnet_loif_idetach(const void *unused __unused)
{
- INIT_VNET_NET(curvnet);
if_clone_detach(V_lo_cloner);
free(V_lo_cloner, M_LO_CLONER);
@@ -213,7 +209,7 @@ loop_modevent(module_t mod, int type, void *data)
switch (type) {
case MOD_LOAD:
-#ifndef VIMAGE_GLOBALS
+#ifdef VIMAGE
vnet_mod_register(&vnet_loif_modinfo);
#else
vnet_loif_iattach(NULL);
@@ -309,7 +305,6 @@ looutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
int
if_simloop(struct ifnet *ifp, struct mbuf *m, int af, int hlen)
{
- INIT_VNET_NET(ifp->if_vnet);
int isr;
M_ASSERTPKTHDR(m);
diff --git a/sys/net/if_mib.c b/sys/net/if_mib.c
index e4c8a98..c0018ef 100644
--- a/sys/net/if_mib.c
+++ b/sys/net/if_mib.c
@@ -67,8 +67,8 @@ SYSCTL_DECL(_net_link_generic);
SYSCTL_NODE(_net_link_generic, IFMIB_SYSTEM, system, CTLFLAG_RW, 0,
"Variables global to all interfaces");
-SYSCTL_V_INT(V_NET, vnet_net, _net_link_generic_system, IFMIB_IFCOUNT,
- ifcount, CTLFLAG_RD, if_index, 0,
+SYSCTL_VNET_INT(_net_link_generic_system, IFMIB_IFCOUNT, ifcount, CTLFLAG_RD,
+ &VNET_NAME(if_index), 0,
"Number of configured interfaces");
static int
diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c
index 0515afc..2c325ee 100644
--- a/sys/net/if_spppsubr.c
+++ b/sys/net/if_spppsubr.c
@@ -56,7 +56,6 @@
#ifdef INET
#include <netinet/ip.h>
#include <netinet/tcp.h>
-#include <netinet/vinet.h>
#endif
#ifdef INET6
@@ -4937,7 +4936,6 @@ sppp_get_ip_addrs(struct sppp *sp, u_long *src, u_long *dst, u_long *srcmask)
static void
sppp_set_ip_addr(struct sppp *sp, u_long src)
{
- INIT_VNET_INET(curvnet);
STDDCL;
struct ifaddr *ifa;
struct sockaddr_in *si;
diff --git a/sys/net/if_stf.c b/sys/net/if_stf.c
index 24e5ca5..ddc5662 100644
--- a/sys/net/if_stf.c
+++ b/sys/net/if_stf.c
@@ -106,7 +106,6 @@
#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/in_var.h>
-#include <netinet/vinet.h>
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
@@ -378,7 +377,6 @@ static struct in6_ifaddr *
stf_getsrcifa6(ifp)
struct ifnet *ifp;
{
- INIT_VNET_INET(ifp->if_vnet);
struct ifaddr *ia;
struct in_ifaddr *ia4;
struct sockaddr_in6 *sin6;
@@ -596,7 +594,6 @@ stf_checkaddr4(sc, in, inifp)
struct in_addr *in;
struct ifnet *inifp; /* incoming interface */
{
- INIT_VNET_INET(curvnet);
struct in_ifaddr *ia4;
/*
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index a995dfd..07914f5 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -80,6 +80,7 @@ struct vnet;
#include <sys/mbuf.h>
#include <sys/eventhandler.h>
#include <sys/buf_ring.h>
+#include <net/vnet.h>
#endif /* _KERNEL */
#include <sys/lock.h> /* XXX */
#include <sys/mutex.h> /* XXX */
@@ -779,11 +780,16 @@ struct ifnet *ifnet_byindex_ref(u_short idx);
*/
struct ifaddr *ifaddr_byindex(u_short idx);
-#ifdef VIMAGE_GLOBALS
-extern struct ifnethead ifnet;
-extern struct ifnet *loif; /* first loopback interface */
-extern int if_index;
-#endif
+VNET_DECLARE(struct ifnethead, ifnet);
+VNET_DECLARE(struct ifgrouphead, ifg_head);
+VNET_DECLARE(int, if_index);
+VNET_DECLARE(struct ifnet *, loif); /* first loopback interface */
+
+#define V_ifnet VNET_GET(ifnet)
+#define V_ifg_head VNET_GET(ifg_head)
+#define V_if_index VNET_GET(if_index)
+#define V_loif VNET_GET(loif)
+
extern int ifqmaxlen;
int if_addgroup(struct ifnet *, const char *);
diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c
index 6278396..ac72870 100644
--- a/sys/net/if_vlan.c
+++ b/sys/net/if_vlan.c
@@ -576,7 +576,6 @@ MODULE_VERSION(if_vlan, 3);
static struct ifnet *
vlan_clone_match_ethertag(struct if_clone *ifc, const char *name, int *tag)
{
- INIT_VNET_NET(curvnet);
const char *cp;
struct ifnet *ifp;
int t = 0;
diff --git a/sys/net/raw_cb.c b/sys/net/raw_cb.c
index 1dedff8..30a526f 100644
--- a/sys/net/raw_cb.c
+++ b/sys/net/raw_cb.c
@@ -58,9 +58,7 @@
*/
struct mtx rawcb_mtx;
-#ifdef VIMAGE_GLOBALS
-struct rawcb_list_head rawcb_list;
-#endif
+VNET_DEFINE(struct rawcb_list_head, rawcb_list);
SYSCTL_NODE(_net, OID_AUTO, raw, CTLFLAG_RW, 0, "Raw socket infrastructure");
@@ -79,7 +77,6 @@ SYSCTL_ULONG(_net_raw, OID_AUTO, recvspace, CTLFLAG_RW, &raw_recvspace, 0,
int
raw_attach(struct socket *so, int proto)
{
- INIT_VNET_NET(so->so_vnet);
struct rawcb *rp = sotorawcb(so);
int error;
diff --git a/sys/net/raw_cb.h b/sys/net/raw_cb.h
index ffdf731..aa84a05 100644
--- a/sys/net/raw_cb.h
+++ b/sys/net/raw_cb.h
@@ -55,9 +55,9 @@ struct rawcb {
#define RAWRCVQ 8192
#ifdef _KERNEL
-#ifdef VIMAGE_GLOBALS
-extern LIST_HEAD(rawcb_list_head, rawcb) rawcb_list;
-#endif
+VNET_DECLARE(LIST_HEAD(rawcb_list_head, rawcb), rawcb_list);
+#define V_rawcb_list VNET_GET(rawcb_list)
+
extern struct mtx rawcb_mtx;
/*
diff --git a/sys/net/raw_usrreq.c b/sys/net/raw_usrreq.c
index 79d3e30..0759e42 100644
--- a/sys/net/raw_usrreq.c
+++ b/sys/net/raw_usrreq.c
@@ -58,7 +58,6 @@ MTX_SYSINIT(rawcb_mtx, &rawcb_mtx, "rawcb", MTX_DEF);
void
raw_init(void)
{
- INIT_VNET_NET(curvnet);
LIST_INIT(&V_rawcb_list);
}
@@ -73,7 +72,6 @@ raw_init(void)
void
raw_input(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src)
{
- INIT_VNET_NET(curvnet);
struct rawcb *rp;
struct mbuf *m = m0;
struct socket *last;
diff --git a/sys/net/route.c b/sys/net/route.c
index 750829a..59a5912 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -63,7 +63,6 @@
#include <netinet/in.h>
#include <netinet/ip_mroute.h>
-#include <netinet/vinet.h>
#include <vm/uma.h>
@@ -88,68 +87,29 @@ SYSCTL_INT(_net, OID_AUTO, add_addr_allfibs, CTLFLAG_RW,
&rt_add_addr_allfibs, 0, "");
TUNABLE_INT("net.add_addr_allfibs", &rt_add_addr_allfibs);
-#ifdef VIMAGE_GLOBALS
-struct radix_node_head *rt_tables;
-static uma_zone_t rtzone; /* Routing table UMA zone. */
-int rttrash; /* routes not in table but not freed */
-struct rtstat rtstat;
-#endif
-
-#ifndef VIMAGE_GLOBALS
-struct vnet_rtable {
- struct radix_node_head *_rt_tables;
- uma_zone_t _rtzone;
- int _rttrash;
- struct rtstat _rtstat;
-};
-
-/* Size guard. See sys/vimage.h. */
-VIMAGE_CTASSERT(SIZEOF_vnet_rtable, sizeof(struct vnet_rtable));
-
-#ifndef VIMAGE
-static struct vnet_rtable vnet_rtable_0;
-#endif
-#endif
-
-/*
- * Symbol translation macros
- */
-#define INIT_VNET_RTABLE(vnet) \
- INIT_FROM_VNET(vnet, VNET_MOD_RTABLE, struct vnet_rtable, vnet_rtable)
+VNET_DEFINE(struct radix_node_head *, rt_tables);
+static VNET_DEFINE(uma_zone_t, rtzone); /* Routing table UMA zone. */
+VNET_DEFINE(int, rttrash); /* routes not in table but not freed */
+VNET_DEFINE(struct rtstat, rtstat);
-#define VNET_RTABLE(sym) VSYM(vnet_rtable, sym)
-
-#define V_rt_tables VNET_RTABLE(rt_tables)
-#define V_rtstat VNET_RTABLE(rtstat)
-#define V_rttrash VNET_RTABLE(rttrash)
-#define V_rtzone VNET_RTABLE(rtzone)
+#define V_rt_tables VNET_GET(rt_tables)
+#define V_rtzone VNET_GET(rtzone)
+#define V_rttrash VNET_GET(rttrash)
+#define V_rtstat VNET_GET(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 *);
-#endif
-
-#ifndef VIMAGE_GLOBALS
-static struct vnet_symmap vnet_rtable_symmap[] = {
- VNET_SYMMAP(rtable, rt_tables),
- VNET_SYMMAP(rtable, rtstat),
- VNET_SYMMAP(rtable, rttrash),
- VNET_SYMMAP_END
-};
static const vnet_modinfo_t vnet_rtable_modinfo = {
.vmi_id = VNET_MOD_RTABLE,
.vmi_name = "rtable",
- .vmi_size = sizeof(struct vnet_rtable),
- .vmi_symmap = vnet_rtable_symmap,
.vmi_iattach = vnet_route_iattach,
-#ifdef VIMAGE
.vmi_idetach = vnet_route_idetach
-#endif
};
-#endif /* !VIMAGE_GLOBALS */
+#endif
/* compare two sockaddr structures */
#define sa_equal(a1, a2) (bcmp((a1), (a2), (a1)->sa_len) == 0)
@@ -192,7 +152,6 @@ SYSCTL_PROC(_net, OID_AUTO, my_fibnum, CTLTYPE_INT|CTLFLAG_RD,
static __inline struct radix_node_head **
rt_tables_get_rnh_ptr(int table, int fam)
{
- INIT_VNET_RTABLE(curvnet);
struct radix_node_head **rnh;
KASSERT(table >= 0 && table < rt_numfibs, ("%s: table out of bounds.",
@@ -226,7 +185,7 @@ route_init(void)
rt_numfibs = 1;
rn_init(); /* initialize all zeroes, all ones, mask table */
-#ifndef VIMAGE_GLOBALS
+#ifdef VIMAGE
vnet_mod_register(&vnet_rtable_modinfo);
#else
vnet_route_iattach(NULL);
@@ -236,7 +195,6 @@ route_init(void)
static int
vnet_route_iattach(const void *unused __unused)
{
- INIT_VNET_RTABLE(curvnet);
struct domain *dom;
struct radix_node_head **rnh;
int table;
@@ -382,7 +340,6 @@ struct rtentry *
rtalloc1_fib(struct sockaddr *dst, int report, u_long ignflags,
u_int fibnum)
{
- INIT_VNET_RTABLE(curvnet);
struct radix_node_head *rnh;
struct rtentry *rt;
struct radix_node *rn;
@@ -452,7 +409,6 @@ done:
void
rtfree(struct rtentry *rt)
{
- INIT_VNET_RTABLE(curvnet);
struct radix_node_head *rnh;
KASSERT(rt != NULL,("%s: NULL rt", __func__));
@@ -551,7 +507,6 @@ rtredirect_fib(struct sockaddr *dst,
struct sockaddr *src,
u_int fibnum)
{
- INIT_VNET_RTABLE(curvnet);
struct rtentry *rt, *rt0 = NULL;
int error = 0;
short *stat = NULL;
@@ -880,7 +835,6 @@ rt_getifa_fib(struct rt_addrinfo *info, u_int fibnum)
int
rtexpunge(struct rtentry *rt)
{
- INIT_VNET_RTABLE(curvnet);
struct radix_node *rn;
struct radix_node_head *rnh;
struct ifaddr *ifa;
@@ -1018,8 +972,6 @@ gwdelete:
RT_LOCK(rt);
RT_ADDREF(rt);
if (req == RTM_DELETE) {
- INIT_VNET_RTABLE(curvnet);
-
rt->rt_flags &= ~RTF_UP;
/*
* One more rtentry floating around that is not
@@ -1027,7 +979,6 @@ gwdelete:
* when RTFREE(rt) is eventually called.
*/
V_rttrash++;
-
}
nondelete:
@@ -1054,7 +1005,6 @@ int
rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt,
u_int fibnum)
{
- INIT_VNET_RTABLE(curvnet);
int error = 0, needlock = 0;
register struct rtentry *rt;
register struct radix_node *rn;
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index 532070d..bdea325 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -1238,7 +1238,6 @@ rt_ifannouncemsg(struct ifnet *ifp, int what)
static void
rt_dispatch(struct mbuf *m, const struct sockaddr *sa)
{
- INIT_VNET_NET(curvnet);
struct m_tag *tag;
/*
@@ -1317,7 +1316,6 @@ sysctl_dumpentry(struct radix_node *rn, void *vw)
static int
sysctl_iflist(int af, struct walkarg *w)
{
- INIT_VNET_NET(curvnet);
struct ifnet *ifp;
struct ifaddr *ifa;
struct rt_addrinfo info;
@@ -1378,7 +1376,6 @@ done:
static int
sysctl_ifmalist(int af, struct walkarg *w)
{
- INIT_VNET_NET(curvnet);
struct ifnet *ifp;
struct ifmultiaddr *ifma;
struct rt_addrinfo info;
diff --git a/sys/net/vnet.c b/sys/net/vnet.c
new file mode 100644
index 0000000..a314886
--- /dev/null
+++ b/sys/net/vnet.c
@@ -0,0 +1,341 @@
+/*-
+ * Copyright (c) 2009 Jeffrey Roberson <jeff@freebsd.org>
+ * Copyright (c) 2009 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <sys/linker_set.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/sx.h>
+#include <sys/sysctl.h>
+#include <sys/vimage.h>
+
+#include <net/vnet.h>
+
+/*-
+ * This is the virtual network stack allocator, which provides storage for
+ * virtualized global variables. These variables are defined/declared using
+ * the VNET_DEFINE()/VNET_DECLARE() macros, which place them in the
+ * 'set_vnet' linker set. The details of the implementation are somewhat
+ * subtle, but allow the majority of most network subsystems to maintain
+ * virtualization-agnostic.
+ *
+ * The virtual network stack allocator handles variables in the base kernel
+ * vs. modules in similar but different ways. In both cases, virtualized
+ * global variables are marked as such by being declared to be part of the
+ * vnet linker set. These "master" copies of global variables serve two
+ * functions:
+ *
+ * (1) They contain static initialization or "default" values for global
+ * variables which will be propagated to each virtual network stack
+ * instance when created. As with normal global variables, they default
+ * to zero-filled.
+ *
+ * (2) They act as unique global names by which the variable can be referred
+ * to, regardless of network stack instance. The single global symbol
+ * will be used to calculate the location of a per-virtual instance
+ * variable at run-time.
+ *
+ * Each virtual network stack instance has a complete copy of each
+ * virtualized global variable, stored in a malloc'd block of memory
+ * referred to by vnet->vnet_data_mem. Critical to the design is that each
+ * per-instance memory block is laid out identically to the master block so
+ * that the offset of each global variable is the same across all blocks. To
+ * optimize run-time access, a precalculated 'base' address,
+ * vnet->vnet_data_base, is stored in each vnet, and is the amount that can
+ * be added to the address of a 'master' instance of a variable to get to the
+ * per-vnet instance.
+ *
+ * Virtualized global variables are handled in a similar manner, but as each
+ * module has its own 'set_vnet' linker set, and we want to keep all
+ * virtualized globals togther, we reserve space in the kernel's linker set
+ * for potential module variables using a per-vnet character array,
+ * 'modspace'. The virtual network stack allocator maintains a free list to
+ * track what space in the array is free (all, initially) and as modules are
+ * linked, allocates portions of the space to specific globals. The kernel
+ * module linker queries the virtual network stack allocator and will
+ * bind references of the global to the location during linking. It also
+ * calls into the virtual network stack allocator, once the memory is
+ * initialized, in order to propagate the new static initializations to all
+ * existing virtual network stack instances so that the soon-to-be executing
+ * module will find every network stack instance with proper default values.
+ */
+
+/*
+ * Location of the kernel's 'set_vnet' linker set.
+ */
+extern uintptr_t *__start_set_vnet;
+extern uintptr_t *__stop_set_vnet;
+
+#define VNET_START (uintptr_t)&__start_set_vnet
+#define VNET_STOP (uintptr_t)&__stop_set_vnet
+
+/*
+ * Number of bytes of data in the 'set_vnet' linker set, and hence the total
+ * size of all kernel virtualized global variables, and the malloc(9) type
+ * that will be used to allocate it.
+ */
+#define VNET_BYTES (VNET_STOP - VNET_START)
+
+MALLOC_DEFINE(M_VNET_DATA, "vnet_data", "VNET data");
+
+/*
+ * VNET_MODMIN is the minimum number of bytes we will reserve for the sum of
+ * global variables across all loaded modules. As this actually sizes an
+ * array declared as a virtualized global variable in the kernel itself, and
+ * we want the virtualized global variable space to be page-sized, we may
+ * have more space than that in practice.
+ */
+#define VNET_MODMIN 8192
+#define VNET_SIZE roundup2(VNET_BYTES, PAGE_SIZE)
+#define VNET_MODSIZE (VNET_SIZE - (VNET_BYTES - VNET_MODMIN))
+
+/*
+ * Space to store virtualized global variables from loadable kernel modules,
+ * and the free list to manage it.
+ */
+static VNET_DEFINE(char, modspace[VNET_MODMIN]);
+
+struct vnet_data_free {
+ uintptr_t vnd_start;
+ int vnd_len;
+ TAILQ_ENTRY(vnet_data_free) vnd_link;
+};
+
+MALLOC_DEFINE(M_VNET_DATA_FREE, "vnet_data_free", "VNET resource accounting");
+static TAILQ_HEAD(, vnet_data_free) vnet_data_free_head =
+ TAILQ_HEAD_INITIALIZER(vnet_data_free_head);
+static struct sx vnet_data_free_lock;
+
+/*
+ * Allocate storage for virtualized global variables in a new virtual network
+ * stack instance, and copy in initial values from our 'master' copy.
+ */
+void
+vnet_data_init(struct vnet *vnet)
+{
+
+ vnet->vnet_data_mem = malloc(VNET_SIZE, M_VNET_DATA, M_WAITOK);
+ memcpy(vnet->vnet_data_mem, (void *)VNET_START, VNET_BYTES);
+
+ /*
+ * All use of vnet-specific data will immediately subtract VNET_START
+ * from the base memory pointer, so pre-calculate that now to avoid
+ * it on each use.
+ */
+ vnet->vnet_data_base = (uintptr_t)vnet->vnet_data_mem - VNET_START;
+}
+
+/*
+ * Release storage for a virtual network stack instance.
+ */
+void
+vnet_data_destroy(struct vnet *vnet)
+{
+
+ free(vnet->vnet_data_mem, M_VNET_DATA);
+ vnet->vnet_data_mem = NULL;
+ vnet->vnet_data_base = 0;
+}
+
+/*
+ * Once on boot, initialize the modspace freelist to entirely cover modspace.
+ */
+static void
+vnet_data_startup(void *dummy __unused)
+{
+ struct vnet_data_free *df;
+
+ df = malloc(sizeof(*df), M_VNET_DATA_FREE, M_WAITOK | M_ZERO);
+ df->vnd_start = (uintptr_t)&VNET_NAME(modspace);
+ df->vnd_len = VNET_MODSIZE;
+ TAILQ_INSERT_HEAD(&vnet_data_free_head, df, vnd_link);
+ sx_init(&vnet_data_free_lock, "vnet_data alloc lock");
+}
+SYSINIT(vnet_data, SI_SUB_KLD, SI_ORDER_FIRST, vnet_data_startup, 0);
+
+/*
+ * When a module is loaded and requires storage for a virtualized global
+ * variable, allocate space from the modspace free list. This interface
+ * should be used only by the kernel linker.
+ */
+void *
+vnet_data_alloc(int size)
+{
+ struct vnet_data_free *df;
+ void *s;
+
+ s = NULL;
+ size = roundup2(size, sizeof(void *));
+ sx_xlock(&vnet_data_free_lock);
+ TAILQ_FOREACH(df, &vnet_data_free_head, vnd_link) {
+ if (df->vnd_len < size)
+ continue;
+ if (df->vnd_len == size) {
+ s = (void *)df->vnd_start;
+ TAILQ_REMOVE(&vnet_data_free_head, df, vnd_link);
+ free(df, M_VNET_DATA_FREE);
+ break;
+ }
+ s = (void *)df->vnd_start;
+ df->vnd_len -= size;
+ df->vnd_start = df->vnd_start + size;
+ break;
+ }
+ sx_xunlock(&vnet_data_free_lock);
+
+ return (s);
+}
+
+/*
+ * Free space for a virtualized global variable on module unload.
+ */
+void
+vnet_data_free(void *start_arg, int size)
+{
+ struct vnet_data_free *df;
+ struct vnet_data_free *dn;
+ uintptr_t start;
+ uintptr_t end;
+
+ size = roundup2(size, sizeof(void *));
+ start = (uintptr_t)start_arg;
+ end = start + size;
+ /*
+ * Free a region of space and merge it with as many neighbors as
+ * possible. Keeping the list sorted simplifies this operation.
+ */
+ sx_xlock(&vnet_data_free_lock);
+ TAILQ_FOREACH(df, &vnet_data_free_head, vnd_link) {
+ if (df->vnd_start > end)
+ break;
+ /*
+ * If we expand at the end of an entry we may have to
+ * merge it with the one following it as well.
+ */
+ if (df->vnd_start + df->vnd_len == start) {
+ df->vnd_len += size;
+ dn = TAILQ_NEXT(df, vnd_link);
+ if (df->vnd_start + df->vnd_len == dn->vnd_start) {
+ df->vnd_len += dn->vnd_len;
+ TAILQ_REMOVE(&vnet_data_free_head, dn, vnd_link);
+ free(dn, M_VNET_DATA_FREE);
+ }
+ sx_xunlock(&vnet_data_free_lock);
+ return;
+ }
+ if (df->vnd_start == end) {
+ df->vnd_start = start;
+ df->vnd_len += size;
+ sx_xunlock(&vnet_data_free_lock);
+ return;
+ }
+ }
+ dn = malloc(sizeof(*df), M_VNET_DATA_FREE, M_WAITOK | M_ZERO);
+ dn->vnd_start = start;
+ dn->vnd_len = size;
+ if (df)
+ TAILQ_INSERT_BEFORE(df, dn, vnd_link);
+ else
+ TAILQ_INSERT_TAIL(&vnet_data_free_head, dn, vnd_link);
+ sx_xunlock(&vnet_data_free_lock);
+}
+
+struct vnet_data_copy_fn_arg {
+ void *start;
+ int size;
+};
+
+static void
+vnet_data_copy_fn(struct vnet *vnet, void *arg)
+{
+ struct vnet_data_copy_fn_arg *varg = arg;
+
+ memcpy((void *)((uintptr_t)vnet->vnet_data_base +
+ (uintptr_t)varg->start), varg->start, varg->size);
+}
+
+/*
+ * When a new virtualized global variable has been allocated, propagate its
+ * initial value to each already-allocated virtual network stack instance.
+ */
+void
+vnet_data_copy(void *start, int size)
+{
+ struct vnet_data_copy_fn_arg varg;
+
+ varg.start = start;
+ varg.size = size;
+ vnet_foreach(vnet_data_copy_fn, &varg);
+}
+
+/*
+ * Variants on sysctl_handle_foo that know how to handle virtualized global
+ * variables: if 'arg1' is a pointer, then we transform it to the local vnet
+ * offset.
+ */
+int
+vnet_sysctl_handle_int(SYSCTL_HANDLER_ARGS)
+{
+
+ if (arg1 != NULL)
+ arg1 = (void *)(curvnet->vnet_data_base + (uintptr_t)arg1);
+ return (sysctl_handle_int(oidp, arg1, arg2, req));
+}
+
+int
+vnet_sysctl_handle_opaque(SYSCTL_HANDLER_ARGS)
+{
+
+ if (arg1 != NULL)
+ arg1 = (void *)(curvnet->vnet_data_base + (uintptr_t)arg1);
+ return (sysctl_handle_opaque(oidp, arg1, arg2, req));
+}
+
+int
+vnet_sysctl_handle_string(SYSCTL_HANDLER_ARGS)
+{
+
+ if (arg1 != NULL)
+ arg1 = (void *)(curvnet->vnet_data_base + (uintptr_t)arg1);
+ return (sysctl_handle_string(oidp, arg1, arg2, req));
+}
+
+int
+vnet_sysctl_handle_uint(SYSCTL_HANDLER_ARGS)
+{
+
+ if (arg1 != NULL)
+ arg1 = (void *)(curvnet->vnet_data_base + (uintptr_t)arg1);
+ return (sysctl_handle_int(oidp, arg1, arg2, req));
+}
diff --git a/sys/net/vnet.h b/sys/net/vnet.h
index b5d2fbd..4b543e6 100644
--- a/sys/net/vnet.h
+++ b/sys/net/vnet.h
@@ -1,10 +1,6 @@
/*-
- * Copyright (c) 2006-2008 University of Zagreb
- * Copyright (c) 2006-2008 FreeBSD Foundation
- *
- * This software was developed by the University of Zagreb and the
- * FreeBSD Foundation under sponsorship by the Stichting NLnet and the
- * FreeBSD Foundation.
+ * Copyright (c) 2009 Jeffrey Roberson <jeff@freebsd.org>
+ * Copyright (c) 2009 Robert N. M. Watson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,62 +26,131 @@
* $FreeBSD$
*/
+/*
+ * This is the virtual network stack memory allocator, which provides support
+ * for virtualized global variables via a special linker set, set_vnet. When
+ * "options VIMAGE" isn't defined, virtualized global variables are compiled
+ * as normal globals.
+ */
+
#ifndef _NET_VNET_H_
#define _NET_VNET_H_
-#include <net/if_var.h>
+#ifdef _KERNEL
+#ifdef VIMAGE
+
+#if defined(__arm__)
+__asm__(".section set_vnet, \"aw\", %progbits");
+#else
+__asm__(".section set_vnet, \"aw\", @progbits");
+#endif
+__asm__(".previous");
+
+#define VNET_NAME(n) vnet_entry_##n
+#define VNET_DECLARE(t, n) extern t VNET_NAME(n)
+#define VNET_DEFINE(t, n) t VNET_NAME(n) __section("set_vnet") __used
+#define _VNET_PTR(b, n) (__typeof(VNET_NAME(n))*) \
+ ((b) + (uintptr_t)&VNET_NAME(n))
+
+#define _VNET_GET(b, n) (*_VNET_PTR(b, n))
+#define _VNET_SET(b, n, v) (*_VNET_PTR(b, n) = v)
-struct ifindex_entry;
+/*
+ * Virtualized global variable accessor macros.
+ */
+#define VNET_VNET_PTR(vnet, n) _VNET_PTR((vnet)->vnet_data_base, n)
+#define VNET_VNET_GET(vnet, n) (*VNET_VNET_PTR((vnet), n))
+#define VNET_VNET_SET(vnet, n, v) ((*VNET_VNET_PTR((vnet), n)) = v)
-struct vnet_net {
- int _if_index;
- struct ifindex_entry * _ifindex_table;
- struct ifnethead _ifnet;
- struct ifgrouphead _ifg_head;
+#define VNET_PTR(n) VNET_VNET_PTR(curvnet, n)
+#define VNET_GET(n) VNET_VNET_GET(curvnet, n)
+#define VNET_SET(n, v) VNET_VNET_SET(curvnet, n, v)
- int _if_indexlim;
+/*
+ * Sysctl variants for vnet-virtualized global variables. Include
+ * <sys/sysctl.h> to expose these definitions.
+ *
+ * Note: SYSCTL_PROC() handler functions will need to resolve pointer
+ * arguments themselves, if required.
+ */
+#ifdef SYSCTL_OID
+int vnet_sysctl_handle_int(SYSCTL_HANDLER_ARGS);
+int vnet_sysctl_handle_opaque(SYSCTL_HANDLER_ARGS);
+int vnet_sysctl_handle_string(SYSCTL_HANDLER_ARGS);
+int vnet_sysctl_handle_uint(SYSCTL_HANDLER_ARGS);
- struct ifnet * _loif;
- struct if_clone * _lo_cloner;
- struct ifc_simple_data *_lo_cloner_data;
+#define SYSCTL_VNET_INT(parent, nbr, name, access, ptr, val, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_INT|CTLFLAG_MPSAFE|(access), \
+ ptr, val, vnet_sysctl_handle_int, "I", descr)
+#define SYSCTL_VNET_PROC(parent, nbr, name, access, ptr, arg, handler, \
+ fmt, descr) \
+ SYSCTL_OID(parent, nbr, name, access, ptr, arg, handler, fmt, \
+ descr)
+#define SYSCTL_VNET_STRING(parent, nbr, name, access, arg, len, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_STRING|(access), arg, \
+ len, vnet_sysctl_handle_string, "A", descr)
+#define SYSCTL_VNET_STRUCT(parent, nbr, name, access, ptr, type, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_OPAQUE|(access), ptr, \
+ sizeof(struct type), vnet_sysctl_handle_opaque, "S," #type, \
+ descr)
+#define SYSCTL_VNET_UINT(parent, nbr, name, access, ptr, val, descr) \
+ SYSCTL_OID(parent, nbr, name, CTLTYPE_UINT|CTLFLAG_MPSAFE|(access), \
+ ptr, val, vnet_sysctl_handle_uint, "IU", descr)
+#endif /* SYSCTL_OID */
- LIST_HEAD(, rawcb) _rawcb_list;
+/*
+ * Interfaces from the kernel linker.
+ */
+void *vnet_data_alloc(int size);
+void vnet_data_copy(void *start, int size);
+void vnet_data_free(void *start_arg, int size);
- LIST_HEAD(, if_clone) _if_cloners;
- int _if_cloners_count;
+/*
+ * Interfaces for vnet setup/teardown.
+ */
+struct vnet;
+void vnet_data_init(struct vnet *vnet);
+void vnet_data_destroy(struct vnet *vnet);
- int _ether_ipfw;
-};
+#else /* !VIMAGE */
-/* Size guard. See sys/vimage.h. */
-VIMAGE_CTASSERT(SIZEOF_vnet_net, sizeof(struct vnet_net));
+/*
+ * Versions of the VNET macros that compile to normal global variables and
+ * standard sysctl definitions.
+ */
+#define VNET_NAME(n) n
+#define VNET_DECLARE(t, n) extern t n
+#define VNET_DEFINE(t, n) t n
+#define _VNET_PTR(b, n) &VNET_NAME(n)
-#ifndef VIMAGE
-#ifndef VIMAGE_GLOBALS
-extern struct vnet_net vnet_net_0;
-#endif
-#endif
+#ifdef SYSCTL_OID
+#define SYSCTL_VNET_INT(parent, nbr, name, access, ptr, val, descr) \
+ SYSCTL_INT(parent, nbr, name, access, ptr, val, descr)
+#define SYSCTL_VNET_PROC(parent, nbr, name, access, ptr, arg, handler, \
+ fmt, descr) \
+ SYSCTL_PROC(parent, nbr, name, access, ptr, arg, handler, fmt, \
+ descr)
+#define SYSCTL_VNET_STRING(parent, nbr, name, access, arg, len, descr) \
+ SYSCTL_STRING(parent, nbr, name, access, arg, len, descr)
+#define SYSCTL_VNET_STRUCT(parent, nbr, name, access, ptr, type, descr) \
+ SYSCTL_STRUCT(parent, nbr, name, access, ptr, type, descr)
+#define SYSCTL_VNET_UINT(parent, nbr, name, access, ptr, val, descr) \
+ SYSCTL_UINT(parent, nbr, name, access, ptr, val, descr)
+#endif /* SYSCTL_OID */
/*
- * Symbol translation macros
+ * Virtualized global variable accessor macros.
*/
-#define INIT_VNET_NET(vnet) \
- INIT_FROM_VNET(vnet, VNET_MOD_NET, struct vnet_net, vnet_net)
-
-#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_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_lo_cloner_data VNET_NET(lo_cloner_data)
-#define V_loif VNET_NET(loif)
-#define V_rawcb_list VNET_NET(rawcb_list)
+#define VNET_VNET_PTR(vnet, n) (&(n))
+#define VNET_VNET_GET(vnet, n) (n)
+#define VNET_VNET_SET(vnet, n, v) ((n) = (v))
+
+#define VNET_PTR(n) (&(n))
+#define VNET_GET(n) (n)
+#define VNET_SET(n, v) ((n) = (v))
+
+#endif /* VIMAGE */
+
+#endif /* _KERNEL */
#endif /* !_NET_VNET_H_ */
OpenPOWER on IntegriCloud