Deleted Added
full compact
vnet.c (195972) vnet.c (196019)
1/*-
1/*-
2 * Copyright (c) 2004-2009 University of Zagreb
3 * Copyright (c) 2006-2009 FreeBSD Foundation
4 * All rights reserved.
5 *
6 * This software was developed by the University of Zagreb and the
7 * FreeBSD Foundation under sponsorship by the Stichting NLnet and the
8 * FreeBSD Foundation.
9 *
2 * Copyright (c) 2009 Jeffrey Roberson <jeff@freebsd.org>
3 * Copyright (c) 2009 Robert N. M. Watson
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
10 * Copyright (c) 2009 Jeffrey Roberson <jeff@freebsd.org>
11 * Copyright (c) 2009 Robert N. M. Watson
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/sys/net/vnet.c 195972 2009-07-30 12:41:19Z rwatson $");
37__FBSDID("$FreeBSD: head/sys/net/vnet.c 196019 2009-08-01 19:26:27Z rwatson $");
30
38
39#include "opt_ddb.h"
40
31#include <sys/param.h>
32#include <sys/kernel.h>
41#include <sys/param.h>
42#include <sys/kernel.h>
43#include <sys/jail.h>
33#include <sys/systm.h>
34#include <sys/sysctl.h>
35#include <sys/linker_set.h>
36#include <sys/lock.h>
37#include <sys/malloc.h>
38#include <sys/proc.h>
44#include <sys/systm.h>
45#include <sys/sysctl.h>
46#include <sys/linker_set.h>
47#include <sys/lock.h>
48#include <sys/malloc.h>
49#include <sys/proc.h>
50#include <sys/socket.h>
39#include <sys/sx.h>
40#include <sys/sysctl.h>
51#include <sys/sx.h>
52#include <sys/sysctl.h>
41#include <sys/vimage.h>
42
53
54#ifdef DDB
55#include <ddb/ddb.h>
56#endif
57
58#include <net/if.h>
59#include <net/if_var.h>
43#include <net/vnet.h>
44
45/*-
46 * This file implements core functions for virtual network stacks:
47 *
60#include <net/vnet.h>
61
62/*-
63 * This file implements core functions for virtual network stacks:
64 *
65 * - Core virtual network stack management functions.
66 *
48 * - Virtual network stack memory allocator, which virtualized global
49 * variables in the network stack
50 *
51 * - Virtualized SYSINIT's/SYSUNINIT's, which allow network stack subsystems
52 * to register startup/shutdown events to be run for each virtual network
53 * stack instance.
67 * - Virtual network stack memory allocator, which virtualized global
68 * variables in the network stack
69 *
70 * - Virtualized SYSINIT's/SYSUNINIT's, which allow network stack subsystems
71 * to register startup/shutdown events to be run for each virtual network
72 * stack instance.
54 *
73 */
74
75MALLOC_DEFINE(M_VNET, "vnet", "network stack control block");
76
77/*
78 * The virtual network stack list has two read-write locks, one sleepable and
79 * the other not, so that the list can be stablized and walked in a variety
80 * of network stack contexts. Both must be acquired exclusively to modify
81 * the list.
82 */
83struct rwlock vnet_rwlock;
84struct sx vnet_sxlock;
85
86#define VNET_LIST_WLOCK() do { \
87 sx_xlock(&vnet_sxlock); \
88 rw_wlock(&vnet_rwlock); \
89} while (0)
90
91#define VNET_LIST_WUNLOCK() do { \
92 rw_wunlock(&vnet_rwlock); \
93 sx_xunlock(&vnet_sxlock); \
94} while (0)
95
96struct vnet_list_head vnet_head;
97struct vnet *vnet0;
98
99/*
55 * The virtual network stack allocator provides storage for virtualized
56 * global variables. These variables are defined/declared using the
57 * VNET_DEFINE()/VNET_DECLARE() macros, which place them in the 'set_vnet'
58 * linker set. The details of the implementation are somewhat subtle, but
59 * allow the majority of most network subsystems to maintain
60 * virtualization-agnostic.
61 *
62 * The virtual network stack allocator handles variables in the base kernel

--- 89 unchanged lines hidden (view full) ---

152};
153
154MALLOC_DEFINE(M_VNET_DATA_FREE, "vnet_data_free", "VNET resource accounting");
155static TAILQ_HEAD(, vnet_data_free) vnet_data_free_head =
156 TAILQ_HEAD_INITIALIZER(vnet_data_free_head);
157static struct sx vnet_data_free_lock;
158
159/*
100 * The virtual network stack allocator provides storage for virtualized
101 * global variables. These variables are defined/declared using the
102 * VNET_DEFINE()/VNET_DECLARE() macros, which place them in the 'set_vnet'
103 * linker set. The details of the implementation are somewhat subtle, but
104 * allow the majority of most network subsystems to maintain
105 * virtualization-agnostic.
106 *
107 * The virtual network stack allocator handles variables in the base kernel

--- 89 unchanged lines hidden (view full) ---

197};
198
199MALLOC_DEFINE(M_VNET_DATA_FREE, "vnet_data_free", "VNET resource accounting");
200static TAILQ_HEAD(, vnet_data_free) vnet_data_free_head =
201 TAILQ_HEAD_INITIALIZER(vnet_data_free_head);
202static struct sx vnet_data_free_lock;
203
204/*
205 * Allocate a virtual network stack.
206 */
207struct vnet *
208vnet_alloc(void)
209{
210 struct vnet *vnet;
211
212 vnet = malloc(sizeof(struct vnet), M_VNET, M_WAITOK | M_ZERO);
213 vnet->vnet_magic_n = VNET_MAGIC_N;
214 vnet_data_init(vnet);
215
216 /* Initialize / attach vnet module instances. */
217 CURVNET_SET_QUIET(vnet);
218
219 sx_xlock(&vnet_sxlock);
220 vnet_sysinit();
221 CURVNET_RESTORE();
222
223 rw_wlock(&vnet_rwlock);
224 LIST_INSERT_HEAD(&vnet_head, vnet, vnet_le);
225 VNET_LIST_WUNLOCK();
226
227 return (vnet);
228}
229
230/*
231 * Destroy a virtual network stack.
232 */
233void
234vnet_destroy(struct vnet *vnet)
235{
236 struct ifnet *ifp, *nifp;
237
238 KASSERT(vnet->vnet_sockcnt == 0,
239 ("%s: vnet still has sockets", __func__));
240
241 VNET_LIST_WLOCK();
242 LIST_REMOVE(vnet, vnet_le);
243 rw_wunlock(&vnet_rwlock);
244
245 CURVNET_SET_QUIET(vnet);
246
247 /* Return all inherited interfaces to their parent vnets. */
248 TAILQ_FOREACH_SAFE(ifp, &V_ifnet, if_link, nifp) {
249 if (ifp->if_home_vnet != ifp->if_vnet)
250 if_vmove(ifp, ifp->if_home_vnet);
251 }
252
253 vnet_sysuninit();
254 sx_xunlock(&vnet_sxlock);
255
256 CURVNET_RESTORE();
257
258 /* Hopefully, we are OK to free the vnet container itself. */
259 vnet_data_destroy(vnet);
260 vnet->vnet_magic_n = 0xdeadbeef;
261 free(vnet, M_VNET);
262}
263
264static void
265vnet_foreach(void (*vnet_foreach_fn)(struct vnet *, void *), void *arg)
266{
267 struct vnet *vnet;
268
269 VNET_LIST_RLOCK();
270 LIST_FOREACH(vnet, &vnet_head, vnet_le)
271 vnet_foreach_fn(vnet, arg);
272 VNET_LIST_RUNLOCK();
273}
274
275/*
276 * Boot time initialization and allocation of virtual network stacks.
277 */
278static void
279vnet_init_prelink(void *arg)
280{
281
282 rw_init(&vnet_rwlock, "vnet_rwlock");
283 sx_init(&vnet_sxlock, "vnet_sxlock");
284 LIST_INIT(&vnet_head);
285}
286SYSINIT(vnet_init_prelink, SI_SUB_VNET_PRELINK, SI_ORDER_FIRST,
287 vnet_init_prelink, NULL);
288
289static void
290vnet0_init(void *arg)
291{
292
293 /*
294 * We MUST clear curvnet in vi_init_done() before going SMP,
295 * otherwise CURVNET_SET() macros would scream about unnecessary
296 * curvnet recursions.
297 */
298 curvnet = prison0.pr_vnet = vnet0 = vnet_alloc();
299}
300SYSINIT(vnet0_init, SI_SUB_VNET, SI_ORDER_FIRST, vnet0_init, NULL);
301
302static void
303vnet_init_done(void *unused)
304{
305
306 curvnet = NULL;
307}
308
309SYSINIT(vnet_init_done, SI_SUB_VNET_DONE, SI_ORDER_FIRST, vnet_init_done,
310 NULL);
311
312/*
160 * Allocate storage for virtualized global variables in a new virtual network
161 * stack instance, and copy in initial values from our 'master' copy.
162 */
163void
164vnet_data_init(struct vnet *vnet)
165{
166
167 vnet->vnet_data_mem = malloc(VNET_SIZE, M_VNET_DATA, M_WAITOK);

--- 317 unchanged lines hidden (view full) ---

485 struct vnet_sysinit *vs;
486
487 sx_assert(&vnet_sxlock, SA_LOCKED);
488 TAILQ_FOREACH_REVERSE(vs, &vnet_destructors, vnet_sysuninit_head,
489 link) {
490 vs->func(vs->arg);
491 }
492}
313 * Allocate storage for virtualized global variables in a new virtual network
314 * stack instance, and copy in initial values from our 'master' copy.
315 */
316void
317vnet_data_init(struct vnet *vnet)
318{
319
320 vnet->vnet_data_mem = malloc(VNET_SIZE, M_VNET_DATA, M_WAITOK);

--- 317 unchanged lines hidden (view full) ---

638 struct vnet_sysinit *vs;
639
640 sx_assert(&vnet_sxlock, SA_LOCKED);
641 TAILQ_FOREACH_REVERSE(vs, &vnet_destructors, vnet_sysuninit_head,
642 link) {
643 vs->func(vs->arg);
644 }
645}
646
647#ifdef DDB
648DB_SHOW_COMMAND(vnets, db_show_vnets)
649{
650 VNET_ITERATOR_DECL(vnet_iter);
651
652#if SIZE_MAX == UINT32_MAX /* 32-bit arch */
653 db_printf(" vnet ifs socks\n");
654#else /* 64-bit arch, most probaly... */
655 db_printf(" vnet ifs socks\n");
656#endif
657 VNET_FOREACH(vnet_iter) {
658 db_printf("%p %3d %5d\n", vnet_iter, vnet_iter->vnet_ifcnt,
659 vnet_iter->vnet_sockcnt);
660 }
661}
662#endif