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 |
|