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)
2009-07-14 22:48:30 +00:00
|
|
|
/*-
|
2009-08-01 19:26:27 +00:00
|
|
|
* Copyright (c) 2004-2009 University of Zagreb
|
|
|
|
* Copyright (c) 2006-2009 FreeBSD Foundation
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This software was developed by the University of Zagreb and the
|
|
|
|
* FreeBSD Foundation under sponsorship by the Stichting NLnet and the
|
|
|
|
* FreeBSD Foundation.
|
|
|
|
*
|
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)
2009-07-14 22:48:30 +00:00
|
|
|
* 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$");
|
|
|
|
|
2009-08-01 19:26:27 +00:00
|
|
|
#include "opt_ddb.h"
|
2010-02-04 07:55:42 +00:00
|
|
|
#include "opt_kdb.h"
|
2010-02-09 22:15:59 +00:00
|
|
|
#include "opt_kdtrace.h"
|
2009-08-01 19:26:27 +00:00
|
|
|
|
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)
2009-07-14 22:48:30 +00:00
|
|
|
#include <sys/param.h>
|
2010-02-04 07:55:42 +00:00
|
|
|
#include <sys/kdb.h>
|
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)
2009-07-14 22:48:30 +00:00
|
|
|
#include <sys/kernel.h>
|
2009-08-01 19:26:27 +00:00
|
|
|
#include <sys/jail.h>
|
2010-02-09 22:15:59 +00:00
|
|
|
#include <sys/sdt.h>
|
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)
2009-07-14 22:48:30 +00:00
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/sysctl.h>
|
2010-03-19 19:51:03 +00:00
|
|
|
#include <sys/eventhandler.h>
|
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)
2009-07-14 22:48:30 +00:00
|
|
|
#include <sys/linker_set.h>
|
|
|
|
#include <sys/lock.h>
|
|
|
|
#include <sys/malloc.h>
|
|
|
|
#include <sys/proc.h>
|
2009-08-01 19:26:27 +00:00
|
|
|
#include <sys/socket.h>
|
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)
2009-07-14 22:48:30 +00:00
|
|
|
#include <sys/sx.h>
|
|
|
|
#include <sys/sysctl.h>
|
|
|
|
|
2010-03-19 19:51:03 +00:00
|
|
|
#include <machine/stdarg.h>
|
|
|
|
|
2009-08-01 19:26:27 +00:00
|
|
|
#ifdef DDB
|
|
|
|
#include <ddb/ddb.h>
|
2010-02-09 22:39:34 +00:00
|
|
|
#include <ddb/db_sym.h>
|
2009-08-01 19:26:27 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <net/if.h>
|
|
|
|
#include <net/if_var.h>
|
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)
2009-07-14 22:48:30 +00:00
|
|
|
#include <net/vnet.h>
|
|
|
|
|
|
|
|
/*-
|
2009-07-30 12:41:19 +00:00
|
|
|
* This file implements core functions for virtual network stacks:
|
|
|
|
*
|
2009-08-01 21:58:32 +00:00
|
|
|
* - Virtual network stack management functions.
|
2009-08-01 19:26:27 +00:00
|
|
|
*
|
2009-08-01 21:58:32 +00:00
|
|
|
* - Virtual network stack memory allocator, which virtualizes global
|
2009-07-30 12:41:19 +00:00
|
|
|
* variables in the network stack
|
|
|
|
*
|
|
|
|
* - Virtualized SYSINIT's/SYSUNINIT's, which allow network stack subsystems
|
|
|
|
* to register startup/shutdown events to be run for each virtual network
|
|
|
|
* stack instance.
|
2009-08-01 19:26:27 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
MALLOC_DEFINE(M_VNET, "vnet", "network stack control block");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The virtual network stack list has two read-write locks, one sleepable and
|
|
|
|
* the other not, so that the list can be stablized and walked in a variety
|
|
|
|
* of network stack contexts. Both must be acquired exclusively to modify
|
2009-08-01 21:58:32 +00:00
|
|
|
* the list, but a read lock of either lock is sufficient to walk the list.
|
2009-08-01 19:26:27 +00:00
|
|
|
*/
|
|
|
|
struct rwlock vnet_rwlock;
|
|
|
|
struct sx vnet_sxlock;
|
|
|
|
|
|
|
|
#define VNET_LIST_WLOCK() do { \
|
|
|
|
sx_xlock(&vnet_sxlock); \
|
|
|
|
rw_wlock(&vnet_rwlock); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define VNET_LIST_WUNLOCK() do { \
|
|
|
|
rw_wunlock(&vnet_rwlock); \
|
|
|
|
sx_xunlock(&vnet_sxlock); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
struct vnet_list_head vnet_head;
|
|
|
|
struct vnet *vnet0;
|
|
|
|
|
|
|
|
/*
|
2009-07-30 12:41:19 +00:00
|
|
|
* The virtual network stack allocator 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
|
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)
2009-07-14 22:48:30 +00:00
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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]);
|
|
|
|
|
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT:
- Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will
occur each time a network stack is instantiated and destroyed. In the
!VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT.
For the VIMAGE case, we instead use SYSINIT's to track their order and
properties on registration, using them for each vnet when created/
destroyed, or immediately on module load for already-started vnets.
- Remove vnet_modinfo mechanism that existed to serve this purpose
previously, as well as its dependency scheme: we now just use the
SYSINIT ordering scheme.
- Implement VNET_DOMAIN_SET() to allow protocol domains to declare that
they want init functions to be called for each virtual network stack
rather than just once at boot, compiling down to DOMAIN_SET() in the
non-VIMAGE case.
- Walk all virtualized kernel subsystems and make use of these instead
of modinfo or DOMAIN_SET() for init/uninit events. In some cases,
convert modular components from using modevent to using sysinit (where
appropriate). In some cases, do minor rejuggling of SYSINIT ordering
to make room for or better manage events.
Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup)
Discussed with: jhb, bz, julian, zec
Reviewed by: bz
Approved by: re (VIMAGE blanket)
2009-07-23 20:46:49 +00:00
|
|
|
/*
|
2009-08-01 21:58:32 +00:00
|
|
|
* Global lists of subsystem constructor and destructors for vnets. They are
|
2009-08-28 22:30:55 +00:00
|
|
|
* registered via VNET_SYSINIT() and VNET_SYSUNINIT(). Both lists are
|
|
|
|
* protected by the vnet_sysinit_sxlock global lock.
|
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT:
- Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will
occur each time a network stack is instantiated and destroyed. In the
!VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT.
For the VIMAGE case, we instead use SYSINIT's to track their order and
properties on registration, using them for each vnet when created/
destroyed, or immediately on module load for already-started vnets.
- Remove vnet_modinfo mechanism that existed to serve this purpose
previously, as well as its dependency scheme: we now just use the
SYSINIT ordering scheme.
- Implement VNET_DOMAIN_SET() to allow protocol domains to declare that
they want init functions to be called for each virtual network stack
rather than just once at boot, compiling down to DOMAIN_SET() in the
non-VIMAGE case.
- Walk all virtualized kernel subsystems and make use of these instead
of modinfo or DOMAIN_SET() for init/uninit events. In some cases,
convert modular components from using modevent to using sysinit (where
appropriate). In some cases, do minor rejuggling of SYSINIT ordering
to make room for or better manage events.
Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup)
Discussed with: jhb, bz, julian, zec
Reviewed by: bz
Approved by: re (VIMAGE blanket)
2009-07-23 20:46:49 +00:00
|
|
|
*/
|
|
|
|
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);
|
|
|
|
|
2009-08-28 22:30:55 +00:00
|
|
|
struct sx vnet_sysinit_sxlock;
|
|
|
|
|
|
|
|
#define VNET_SYSINIT_WLOCK() sx_xlock(&vnet_sysinit_sxlock);
|
|
|
|
#define VNET_SYSINIT_WUNLOCK() sx_xunlock(&vnet_sysinit_sxlock);
|
|
|
|
#define VNET_SYSINIT_RLOCK() sx_slock(&vnet_sysinit_sxlock);
|
|
|
|
#define VNET_SYSINIT_RUNLOCK() sx_sunlock(&vnet_sysinit_sxlock);
|
|
|
|
|
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)
2009-07-14 22:48:30 +00:00
|
|
|
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;
|
|
|
|
|
2010-02-09 22:15:59 +00:00
|
|
|
SDT_PROVIDER_DEFINE(vnet);
|
|
|
|
SDT_PROBE_DEFINE1(vnet, functions, vnet_alloc, entry, "int");
|
|
|
|
SDT_PROBE_DEFINE2(vnet, functions, vnet_alloc, alloc, "int", "struct vnet *");
|
|
|
|
SDT_PROBE_DEFINE2(vnet, functions, vnet_alloc, return, "int", "struct vnet *");
|
|
|
|
SDT_PROBE_DEFINE2(vnet, functions, vnet_destroy, entry, "int", "struct vnet *");
|
|
|
|
SDT_PROBE_DEFINE1(vnet, functions, vnet_destroy, return, "int");
|
|
|
|
|
2010-02-09 22:39:34 +00:00
|
|
|
#ifdef DDB
|
|
|
|
static void db_show_vnet_print_vs(struct vnet_sysinit *, int);
|
|
|
|
#endif
|
|
|
|
|
2009-08-01 19:26:27 +00:00
|
|
|
/*
|
|
|
|
* Allocate a virtual network stack.
|
|
|
|
*/
|
|
|
|
struct vnet *
|
|
|
|
vnet_alloc(void)
|
|
|
|
{
|
|
|
|
struct vnet *vnet;
|
|
|
|
|
2010-02-09 22:15:59 +00:00
|
|
|
SDT_PROBE1(vnet, functions, vnet_alloc, entry, __LINE__);
|
2009-08-01 19:26:27 +00:00
|
|
|
vnet = malloc(sizeof(struct vnet), M_VNET, M_WAITOK | M_ZERO);
|
|
|
|
vnet->vnet_magic_n = VNET_MAGIC_N;
|
2010-02-09 22:15:59 +00:00
|
|
|
SDT_PROBE2(vnet, functions, vnet_alloc, alloc, __LINE__, vnet);
|
2009-08-01 21:54:15 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Allocate storage for virtualized global variables and copy in
|
|
|
|
* initial values form our 'master' copy.
|
|
|
|
*/
|
|
|
|
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;
|
2009-08-01 19:26:27 +00:00
|
|
|
|
|
|
|
/* Initialize / attach vnet module instances. */
|
|
|
|
CURVNET_SET_QUIET(vnet);
|
|
|
|
vnet_sysinit();
|
|
|
|
CURVNET_RESTORE();
|
|
|
|
|
2009-08-28 22:30:55 +00:00
|
|
|
VNET_LIST_WLOCK();
|
2009-08-01 19:26:27 +00:00
|
|
|
LIST_INSERT_HEAD(&vnet_head, vnet, vnet_le);
|
|
|
|
VNET_LIST_WUNLOCK();
|
|
|
|
|
2010-02-09 22:15:59 +00:00
|
|
|
SDT_PROBE2(vnet, functions, vnet_alloc, return, __LINE__, vnet);
|
2009-08-01 19:26:27 +00:00
|
|
|
return (vnet);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Destroy a virtual network stack.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
vnet_destroy(struct vnet *vnet)
|
|
|
|
{
|
|
|
|
struct ifnet *ifp, *nifp;
|
|
|
|
|
2010-02-09 22:15:59 +00:00
|
|
|
SDT_PROBE2(vnet, functions, vnet_destroy, entry, __LINE__, vnet);
|
2009-08-01 19:26:27 +00:00
|
|
|
KASSERT(vnet->vnet_sockcnt == 0,
|
|
|
|
("%s: vnet still has sockets", __func__));
|
|
|
|
|
|
|
|
VNET_LIST_WLOCK();
|
|
|
|
LIST_REMOVE(vnet, vnet_le);
|
2009-08-28 22:30:55 +00:00
|
|
|
VNET_LIST_WUNLOCK();
|
2009-08-01 19:26:27 +00:00
|
|
|
|
|
|
|
CURVNET_SET_QUIET(vnet);
|
|
|
|
|
|
|
|
/* Return all inherited interfaces to their parent vnets. */
|
|
|
|
TAILQ_FOREACH_SAFE(ifp, &V_ifnet, if_link, nifp) {
|
|
|
|
if (ifp->if_home_vnet != ifp->if_vnet)
|
|
|
|
if_vmove(ifp, ifp->if_home_vnet);
|
|
|
|
}
|
|
|
|
|
|
|
|
vnet_sysuninit();
|
|
|
|
CURVNET_RESTORE();
|
|
|
|
|
2009-08-01 21:54:15 +00:00
|
|
|
/*
|
|
|
|
* Release storage for the virtual network stack instance.
|
|
|
|
*/
|
|
|
|
free(vnet->vnet_data_mem, M_VNET_DATA);
|
|
|
|
vnet->vnet_data_mem = NULL;
|
|
|
|
vnet->vnet_data_base = 0;
|
2009-08-01 19:26:27 +00:00
|
|
|
vnet->vnet_magic_n = 0xdeadbeef;
|
|
|
|
free(vnet, M_VNET);
|
2010-02-09 22:15:59 +00:00
|
|
|
SDT_PROBE1(vnet, functions, vnet_destroy, return, __LINE__);
|
2009-08-01 19:26:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Boot time initialization and allocation of virtual network stacks.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
vnet_init_prelink(void *arg)
|
|
|
|
{
|
|
|
|
|
|
|
|
rw_init(&vnet_rwlock, "vnet_rwlock");
|
|
|
|
sx_init(&vnet_sxlock, "vnet_sxlock");
|
2009-08-28 22:30:55 +00:00
|
|
|
sx_init(&vnet_sysinit_sxlock, "vnet_sysinit_sxlock");
|
2009-08-01 19:26:27 +00:00
|
|
|
LIST_INIT(&vnet_head);
|
|
|
|
}
|
|
|
|
SYSINIT(vnet_init_prelink, SI_SUB_VNET_PRELINK, SI_ORDER_FIRST,
|
|
|
|
vnet_init_prelink, NULL);
|
|
|
|
|
|
|
|
static void
|
|
|
|
vnet0_init(void *arg)
|
|
|
|
{
|
|
|
|
|
2009-08-01 22:22:45 +00:00
|
|
|
/* Warn people before take off - in case we crash early. */
|
|
|
|
printf("WARNING: VIMAGE (virtualized network stack) is a highly "
|
|
|
|
"experimental feature.\n");
|
|
|
|
|
2009-08-01 19:26:27 +00:00
|
|
|
/*
|
|
|
|
* We MUST clear curvnet in vi_init_done() before going SMP,
|
|
|
|
* otherwise CURVNET_SET() macros would scream about unnecessary
|
|
|
|
* curvnet recursions.
|
|
|
|
*/
|
|
|
|
curvnet = prison0.pr_vnet = vnet0 = vnet_alloc();
|
|
|
|
}
|
|
|
|
SYSINIT(vnet0_init, SI_SUB_VNET, SI_ORDER_FIRST, vnet0_init, NULL);
|
|
|
|
|
|
|
|
static void
|
|
|
|
vnet_init_done(void *unused)
|
|
|
|
{
|
|
|
|
|
|
|
|
curvnet = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
SYSINIT(vnet_init_done, SI_SUB_VNET_DONE, SI_ORDER_FIRST, vnet_init_done,
|
|
|
|
NULL);
|
|
|
|
|
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)
2009-07-14 22:48:30 +00:00
|
|
|
/*
|
|
|
|
* 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);
|
2010-05-14 21:11:58 +00:00
|
|
|
df->vnd_len = VNET_MODMIN;
|
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)
2009-07-14 22:48:30 +00:00
|
|
|
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;
|
|
|
|
/*
|
2009-08-01 21:58:32 +00:00
|
|
|
* If we expand at the end of an entry we may have to merge
|
|
|
|
* it with the one following it as well.
|
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)
2009-07-14 22:48:30 +00:00
|
|
|
*/
|
|
|
|
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;
|
2009-08-01 21:58:32 +00:00
|
|
|
TAILQ_REMOVE(&vnet_data_free_head, dn,
|
|
|
|
vnd_link);
|
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)
2009-07-14 22:48:30 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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)
|
|
|
|
{
|
2009-08-01 20:24:45 +00:00
|
|
|
struct vnet *vnet;
|
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)
2009-07-14 22:48:30 +00:00
|
|
|
|
2009-08-01 20:24:45 +00:00
|
|
|
VNET_LIST_RLOCK();
|
|
|
|
LIST_FOREACH(vnet, &vnet_head, vnet_le)
|
|
|
|
memcpy((void *)((uintptr_t)vnet->vnet_data_base +
|
|
|
|
(uintptr_t)start), start, size);
|
|
|
|
VNET_LIST_RUNLOCK();
|
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)
2009-07-14 22:48:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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));
|
|
|
|
}
|
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT:
- Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will
occur each time a network stack is instantiated and destroyed. In the
!VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT.
For the VIMAGE case, we instead use SYSINIT's to track their order and
properties on registration, using them for each vnet when created/
destroyed, or immediately on module load for already-started vnets.
- Remove vnet_modinfo mechanism that existed to serve this purpose
previously, as well as its dependency scheme: we now just use the
SYSINIT ordering scheme.
- Implement VNET_DOMAIN_SET() to allow protocol domains to declare that
they want init functions to be called for each virtual network stack
rather than just once at boot, compiling down to DOMAIN_SET() in the
non-VIMAGE case.
- Walk all virtualized kernel subsystems and make use of these instead
of modinfo or DOMAIN_SET() for init/uninit events. In some cases,
convert modular components from using modevent to using sysinit (where
appropriate). In some cases, do minor rejuggling of SYSINIT ordering
to make room for or better manage events.
Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup)
Discussed with: jhb, bz, julian, zec
Reviewed by: bz
Approved by: re (VIMAGE blanket)
2009-07-23 20:46:49 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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. */
|
2009-08-28 22:30:55 +00:00
|
|
|
VNET_SYSINIT_WLOCK();
|
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT:
- Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will
occur each time a network stack is instantiated and destroyed. In the
!VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT.
For the VIMAGE case, we instead use SYSINIT's to track their order and
properties on registration, using them for each vnet when created/
destroyed, or immediately on module load for already-started vnets.
- Remove vnet_modinfo mechanism that existed to serve this purpose
previously, as well as its dependency scheme: we now just use the
SYSINIT ordering scheme.
- Implement VNET_DOMAIN_SET() to allow protocol domains to declare that
they want init functions to be called for each virtual network stack
rather than just once at boot, compiling down to DOMAIN_SET() in the
non-VIMAGE case.
- Walk all virtualized kernel subsystems and make use of these instead
of modinfo or DOMAIN_SET() for init/uninit events. In some cases,
convert modular components from using modevent to using sysinit (where
appropriate). In some cases, do minor rejuggling of SYSINIT ordering
to make room for or better manage events.
Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup)
Discussed with: jhb, bz, julian, zec
Reviewed by: bz
Approved by: re (VIMAGE blanket)
2009-07-23 20:46:49 +00:00
|
|
|
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();
|
|
|
|
}
|
2009-08-28 22:30:55 +00:00
|
|
|
VNET_SYSINIT_WUNLOCK();
|
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT:
- Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will
occur each time a network stack is instantiated and destroyed. In the
!VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT.
For the VIMAGE case, we instead use SYSINIT's to track their order and
properties on registration, using them for each vnet when created/
destroyed, or immediately on module load for already-started vnets.
- Remove vnet_modinfo mechanism that existed to serve this purpose
previously, as well as its dependency scheme: we now just use the
SYSINIT ordering scheme.
- Implement VNET_DOMAIN_SET() to allow protocol domains to declare that
they want init functions to be called for each virtual network stack
rather than just once at boot, compiling down to DOMAIN_SET() in the
non-VIMAGE case.
- Walk all virtualized kernel subsystems and make use of these instead
of modinfo or DOMAIN_SET() for init/uninit events. In some cases,
convert modular components from using modevent to using sysinit (where
appropriate). In some cases, do minor rejuggling of SYSINIT ordering
to make room for or better manage events.
Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup)
Discussed with: jhb, bz, julian, zec
Reviewed by: bz
Approved by: re (VIMAGE blanket)
2009-07-23 20:46:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vnet_deregister_sysinit(void *arg)
|
|
|
|
{
|
|
|
|
struct vnet_sysinit *vs;
|
|
|
|
|
|
|
|
vs = arg;
|
|
|
|
|
|
|
|
/* Remove the constructor from the global list of vnet constructors. */
|
2009-08-28 22:30:55 +00:00
|
|
|
VNET_SYSINIT_WLOCK();
|
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT:
- Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will
occur each time a network stack is instantiated and destroyed. In the
!VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT.
For the VIMAGE case, we instead use SYSINIT's to track their order and
properties on registration, using them for each vnet when created/
destroyed, or immediately on module load for already-started vnets.
- Remove vnet_modinfo mechanism that existed to serve this purpose
previously, as well as its dependency scheme: we now just use the
SYSINIT ordering scheme.
- Implement VNET_DOMAIN_SET() to allow protocol domains to declare that
they want init functions to be called for each virtual network stack
rather than just once at boot, compiling down to DOMAIN_SET() in the
non-VIMAGE case.
- Walk all virtualized kernel subsystems and make use of these instead
of modinfo or DOMAIN_SET() for init/uninit events. In some cases,
convert modular components from using modevent to using sysinit (where
appropriate). In some cases, do minor rejuggling of SYSINIT ordering
to make room for or better manage events.
Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup)
Discussed with: jhb, bz, julian, zec
Reviewed by: bz
Approved by: re (VIMAGE blanket)
2009-07-23 20:46:49 +00:00
|
|
|
TAILQ_REMOVE(&vnet_constructors, vs, link);
|
2009-08-28 22:30:55 +00:00
|
|
|
VNET_SYSINIT_WUNLOCK();
|
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT:
- Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will
occur each time a network stack is instantiated and destroyed. In the
!VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT.
For the VIMAGE case, we instead use SYSINIT's to track their order and
properties on registration, using them for each vnet when created/
destroyed, or immediately on module load for already-started vnets.
- Remove vnet_modinfo mechanism that existed to serve this purpose
previously, as well as its dependency scheme: we now just use the
SYSINIT ordering scheme.
- Implement VNET_DOMAIN_SET() to allow protocol domains to declare that
they want init functions to be called for each virtual network stack
rather than just once at boot, compiling down to DOMAIN_SET() in the
non-VIMAGE case.
- Walk all virtualized kernel subsystems and make use of these instead
of modinfo or DOMAIN_SET() for init/uninit events. In some cases,
convert modular components from using modevent to using sysinit (where
appropriate). In some cases, do minor rejuggling of SYSINIT ordering
to make room for or better manage events.
Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup)
Discussed with: jhb, bz, julian, zec
Reviewed by: bz
Approved by: re (VIMAGE blanket)
2009-07-23 20:46:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vnet_register_sysuninit(void *arg)
|
|
|
|
{
|
|
|
|
struct vnet_sysinit *vs, *vs2;
|
|
|
|
|
|
|
|
vs = arg;
|
|
|
|
|
|
|
|
/* Add the destructor to the global list of vnet destructors. */
|
2009-08-28 22:30:55 +00:00
|
|
|
VNET_SYSINIT_WLOCK();
|
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT:
- Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will
occur each time a network stack is instantiated and destroyed. In the
!VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT.
For the VIMAGE case, we instead use SYSINIT's to track their order and
properties on registration, using them for each vnet when created/
destroyed, or immediately on module load for already-started vnets.
- Remove vnet_modinfo mechanism that existed to serve this purpose
previously, as well as its dependency scheme: we now just use the
SYSINIT ordering scheme.
- Implement VNET_DOMAIN_SET() to allow protocol domains to declare that
they want init functions to be called for each virtual network stack
rather than just once at boot, compiling down to DOMAIN_SET() in the
non-VIMAGE case.
- Walk all virtualized kernel subsystems and make use of these instead
of modinfo or DOMAIN_SET() for init/uninit events. In some cases,
convert modular components from using modevent to using sysinit (where
appropriate). In some cases, do minor rejuggling of SYSINIT ordering
to make room for or better manage events.
Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup)
Discussed with: jhb, bz, julian, zec
Reviewed by: bz
Approved by: re (VIMAGE blanket)
2009-07-23 20:46:49 +00:00
|
|
|
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);
|
2009-08-28 22:30:55 +00:00
|
|
|
VNET_SYSINIT_WUNLOCK();
|
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT:
- Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will
occur each time a network stack is instantiated and destroyed. In the
!VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT.
For the VIMAGE case, we instead use SYSINIT's to track their order and
properties on registration, using them for each vnet when created/
destroyed, or immediately on module load for already-started vnets.
- Remove vnet_modinfo mechanism that existed to serve this purpose
previously, as well as its dependency scheme: we now just use the
SYSINIT ordering scheme.
- Implement VNET_DOMAIN_SET() to allow protocol domains to declare that
they want init functions to be called for each virtual network stack
rather than just once at boot, compiling down to DOMAIN_SET() in the
non-VIMAGE case.
- Walk all virtualized kernel subsystems and make use of these instead
of modinfo or DOMAIN_SET() for init/uninit events. In some cases,
convert modular components from using modevent to using sysinit (where
appropriate). In some cases, do minor rejuggling of SYSINIT ordering
to make room for or better manage events.
Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup)
Discussed with: jhb, bz, julian, zec
Reviewed by: bz
Approved by: re (VIMAGE blanket)
2009-07-23 20:46:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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.
|
|
|
|
*/
|
2009-08-28 22:30:55 +00:00
|
|
|
VNET_SYSINIT_WLOCK();
|
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT:
- Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will
occur each time a network stack is instantiated and destroyed. In the
!VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT.
For the VIMAGE case, we instead use SYSINIT's to track their order and
properties on registration, using them for each vnet when created/
destroyed, or immediately on module load for already-started vnets.
- Remove vnet_modinfo mechanism that existed to serve this purpose
previously, as well as its dependency scheme: we now just use the
SYSINIT ordering scheme.
- Implement VNET_DOMAIN_SET() to allow protocol domains to declare that
they want init functions to be called for each virtual network stack
rather than just once at boot, compiling down to DOMAIN_SET() in the
non-VIMAGE case.
- Walk all virtualized kernel subsystems and make use of these instead
of modinfo or DOMAIN_SET() for init/uninit events. In some cases,
convert modular components from using modevent to using sysinit (where
appropriate). In some cases, do minor rejuggling of SYSINIT ordering
to make room for or better manage events.
Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup)
Discussed with: jhb, bz, julian, zec
Reviewed by: bz
Approved by: re (VIMAGE blanket)
2009-07-23 20:46:49 +00:00
|
|
|
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);
|
2009-08-28 22:30:55 +00:00
|
|
|
VNET_SYSINIT_WUNLOCK();
|
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT:
- Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will
occur each time a network stack is instantiated and destroyed. In the
!VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT.
For the VIMAGE case, we instead use SYSINIT's to track their order and
properties on registration, using them for each vnet when created/
destroyed, or immediately on module load for already-started vnets.
- Remove vnet_modinfo mechanism that existed to serve this purpose
previously, as well as its dependency scheme: we now just use the
SYSINIT ordering scheme.
- Implement VNET_DOMAIN_SET() to allow protocol domains to declare that
they want init functions to be called for each virtual network stack
rather than just once at boot, compiling down to DOMAIN_SET() in the
non-VIMAGE case.
- Walk all virtualized kernel subsystems and make use of these instead
of modinfo or DOMAIN_SET() for init/uninit events. In some cases,
convert modular components from using modevent to using sysinit (where
appropriate). In some cases, do minor rejuggling of SYSINIT ordering
to make room for or better manage events.
Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup)
Discussed with: jhb, bz, julian, zec
Reviewed by: bz
Approved by: re (VIMAGE blanket)
2009-07-23 20:46:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2009-08-01 21:58:32 +00:00
|
|
|
* Invoke all registered vnet constructors on the current vnet. Used during
|
|
|
|
* vnet construction. The caller is responsible for ensuring the new vnet is
|
2009-08-28 22:30:55 +00:00
|
|
|
* the current vnet and that the vnet_sysinit_sxlock lock is locked.
|
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT:
- Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will
occur each time a network stack is instantiated and destroyed. In the
!VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT.
For the VIMAGE case, we instead use SYSINIT's to track their order and
properties on registration, using them for each vnet when created/
destroyed, or immediately on module load for already-started vnets.
- Remove vnet_modinfo mechanism that existed to serve this purpose
previously, as well as its dependency scheme: we now just use the
SYSINIT ordering scheme.
- Implement VNET_DOMAIN_SET() to allow protocol domains to declare that
they want init functions to be called for each virtual network stack
rather than just once at boot, compiling down to DOMAIN_SET() in the
non-VIMAGE case.
- Walk all virtualized kernel subsystems and make use of these instead
of modinfo or DOMAIN_SET() for init/uninit events. In some cases,
convert modular components from using modevent to using sysinit (where
appropriate). In some cases, do minor rejuggling of SYSINIT ordering
to make room for or better manage events.
Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup)
Discussed with: jhb, bz, julian, zec
Reviewed by: bz
Approved by: re (VIMAGE blanket)
2009-07-23 20:46:49 +00:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
vnet_sysinit(void)
|
|
|
|
{
|
|
|
|
struct vnet_sysinit *vs;
|
|
|
|
|
2009-08-28 22:30:55 +00:00
|
|
|
VNET_SYSINIT_RLOCK();
|
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT:
- Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will
occur each time a network stack is instantiated and destroyed. In the
!VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT.
For the VIMAGE case, we instead use SYSINIT's to track their order and
properties on registration, using them for each vnet when created/
destroyed, or immediately on module load for already-started vnets.
- Remove vnet_modinfo mechanism that existed to serve this purpose
previously, as well as its dependency scheme: we now just use the
SYSINIT ordering scheme.
- Implement VNET_DOMAIN_SET() to allow protocol domains to declare that
they want init functions to be called for each virtual network stack
rather than just once at boot, compiling down to DOMAIN_SET() in the
non-VIMAGE case.
- Walk all virtualized kernel subsystems and make use of these instead
of modinfo or DOMAIN_SET() for init/uninit events. In some cases,
convert modular components from using modevent to using sysinit (where
appropriate). In some cases, do minor rejuggling of SYSINIT ordering
to make room for or better manage events.
Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup)
Discussed with: jhb, bz, julian, zec
Reviewed by: bz
Approved by: re (VIMAGE blanket)
2009-07-23 20:46:49 +00:00
|
|
|
TAILQ_FOREACH(vs, &vnet_constructors, link) {
|
|
|
|
vs->func(vs->arg);
|
|
|
|
}
|
2009-08-28 22:30:55 +00:00
|
|
|
VNET_SYSINIT_RUNLOCK();
|
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT:
- Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will
occur each time a network stack is instantiated and destroyed. In the
!VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT.
For the VIMAGE case, we instead use SYSINIT's to track their order and
properties on registration, using them for each vnet when created/
destroyed, or immediately on module load for already-started vnets.
- Remove vnet_modinfo mechanism that existed to serve this purpose
previously, as well as its dependency scheme: we now just use the
SYSINIT ordering scheme.
- Implement VNET_DOMAIN_SET() to allow protocol domains to declare that
they want init functions to be called for each virtual network stack
rather than just once at boot, compiling down to DOMAIN_SET() in the
non-VIMAGE case.
- Walk all virtualized kernel subsystems and make use of these instead
of modinfo or DOMAIN_SET() for init/uninit events. In some cases,
convert modular components from using modevent to using sysinit (where
appropriate). In some cases, do minor rejuggling of SYSINIT ordering
to make room for or better manage events.
Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup)
Discussed with: jhb, bz, julian, zec
Reviewed by: bz
Approved by: re (VIMAGE blanket)
2009-07-23 20:46:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2009-08-01 21:58:32 +00:00
|
|
|
* Invoke all registered vnet destructors on the current vnet. Used during
|
|
|
|
* vnet destruction. The caller is responsible for ensuring the dying vnet
|
2009-08-28 22:30:55 +00:00
|
|
|
* the current vnet and that the vnet_sysinit_sxlock lock is locked.
|
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT:
- Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will
occur each time a network stack is instantiated and destroyed. In the
!VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT.
For the VIMAGE case, we instead use SYSINIT's to track their order and
properties on registration, using them for each vnet when created/
destroyed, or immediately on module load for already-started vnets.
- Remove vnet_modinfo mechanism that existed to serve this purpose
previously, as well as its dependency scheme: we now just use the
SYSINIT ordering scheme.
- Implement VNET_DOMAIN_SET() to allow protocol domains to declare that
they want init functions to be called for each virtual network stack
rather than just once at boot, compiling down to DOMAIN_SET() in the
non-VIMAGE case.
- Walk all virtualized kernel subsystems and make use of these instead
of modinfo or DOMAIN_SET() for init/uninit events. In some cases,
convert modular components from using modevent to using sysinit (where
appropriate). In some cases, do minor rejuggling of SYSINIT ordering
to make room for or better manage events.
Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup)
Discussed with: jhb, bz, julian, zec
Reviewed by: bz
Approved by: re (VIMAGE blanket)
2009-07-23 20:46:49 +00:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
vnet_sysuninit(void)
|
|
|
|
{
|
|
|
|
struct vnet_sysinit *vs;
|
|
|
|
|
2009-08-28 22:30:55 +00:00
|
|
|
VNET_SYSINIT_RLOCK();
|
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT:
- Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will
occur each time a network stack is instantiated and destroyed. In the
!VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT.
For the VIMAGE case, we instead use SYSINIT's to track their order and
properties on registration, using them for each vnet when created/
destroyed, or immediately on module load for already-started vnets.
- Remove vnet_modinfo mechanism that existed to serve this purpose
previously, as well as its dependency scheme: we now just use the
SYSINIT ordering scheme.
- Implement VNET_DOMAIN_SET() to allow protocol domains to declare that
they want init functions to be called for each virtual network stack
rather than just once at boot, compiling down to DOMAIN_SET() in the
non-VIMAGE case.
- Walk all virtualized kernel subsystems and make use of these instead
of modinfo or DOMAIN_SET() for init/uninit events. In some cases,
convert modular components from using modevent to using sysinit (where
appropriate). In some cases, do minor rejuggling of SYSINIT ordering
to make room for or better manage events.
Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup)
Discussed with: jhb, bz, julian, zec
Reviewed by: bz
Approved by: re (VIMAGE blanket)
2009-07-23 20:46:49 +00:00
|
|
|
TAILQ_FOREACH_REVERSE(vs, &vnet_destructors, vnet_sysuninit_head,
|
|
|
|
link) {
|
|
|
|
vs->func(vs->arg);
|
|
|
|
}
|
2009-08-28 22:30:55 +00:00
|
|
|
VNET_SYSINIT_RUNLOCK();
|
Introduce and use a sysinit-based initialization scheme for virtual
network stacks, VNET_SYSINIT:
- Add VNET_SYSINIT and VNET_SYSUNINIT macros to declare events that will
occur each time a network stack is instantiated and destroyed. In the
!VIMAGE case, these are simply mapped into regular SYSINIT/SYSUNINIT.
For the VIMAGE case, we instead use SYSINIT's to track their order and
properties on registration, using them for each vnet when created/
destroyed, or immediately on module load for already-started vnets.
- Remove vnet_modinfo mechanism that existed to serve this purpose
previously, as well as its dependency scheme: we now just use the
SYSINIT ordering scheme.
- Implement VNET_DOMAIN_SET() to allow protocol domains to declare that
they want init functions to be called for each virtual network stack
rather than just once at boot, compiling down to DOMAIN_SET() in the
non-VIMAGE case.
- Walk all virtualized kernel subsystems and make use of these instead
of modinfo or DOMAIN_SET() for init/uninit events. In some cases,
convert modular components from using modevent to using sysinit (where
appropriate). In some cases, do minor rejuggling of SYSINIT ordering
to make room for or better manage events.
Portions submitted by: jhb (VNET_SYSINIT), bz (cleanup)
Discussed with: jhb, bz, julian, zec
Reviewed by: bz
Approved by: re (VIMAGE blanket)
2009-07-23 20:46:49 +00:00
|
|
|
}
|
2009-08-01 19:26:27 +00:00
|
|
|
|
2010-03-19 19:51:03 +00:00
|
|
|
/*
|
|
|
|
* EVENTHANDLER(9) extensions.
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* Invoke the eventhandler function originally registered with the possibly
|
|
|
|
* registered argument for all virtual network stack instances.
|
|
|
|
*
|
|
|
|
* This iterator can only be used for eventhandlers that do not take any
|
|
|
|
* additional arguments, as we do ignore the variadic arguments from the
|
|
|
|
* EVENTHANDLER_INVOKE() call.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
vnet_global_eventhandler_iterator_func(void *arg, ...)
|
|
|
|
{
|
|
|
|
VNET_ITERATOR_DECL(vnet_iter);
|
|
|
|
struct eventhandler_entry_vimage *v_ee;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* There is a bug here in that we should actually cast things to
|
|
|
|
* (struct eventhandler_entry_ ## name *) but that's not easily
|
|
|
|
* possible in here so just re-using the variadic version we
|
|
|
|
* defined for the generic vimage case.
|
|
|
|
*/
|
|
|
|
v_ee = arg;
|
|
|
|
VNET_LIST_RLOCK();
|
|
|
|
VNET_FOREACH(vnet_iter) {
|
|
|
|
CURVNET_SET(vnet_iter);
|
|
|
|
((vimage_iterator_func_t)v_ee->func)(v_ee->ee_arg);
|
|
|
|
CURVNET_RESTORE();
|
|
|
|
}
|
|
|
|
VNET_LIST_RUNLOCK();
|
|
|
|
}
|
|
|
|
|
2010-02-04 07:55:42 +00:00
|
|
|
#ifdef VNET_DEBUG
|
|
|
|
struct vnet_recursion {
|
|
|
|
SLIST_ENTRY(vnet_recursion) vnr_le;
|
|
|
|
const char *prev_fn;
|
|
|
|
const char *where_fn;
|
|
|
|
int where_line;
|
|
|
|
struct vnet *old_vnet;
|
|
|
|
struct vnet *new_vnet;
|
|
|
|
};
|
|
|
|
|
|
|
|
static SLIST_HEAD(, vnet_recursion) vnet_recursions =
|
|
|
|
SLIST_HEAD_INITIALIZER(vnet_recursions);
|
|
|
|
|
|
|
|
static void
|
|
|
|
vnet_print_recursion(struct vnet_recursion *vnr, int brief)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!brief)
|
|
|
|
printf("CURVNET_SET() recursion in ");
|
|
|
|
printf("%s() line %d, prev in %s()", vnr->where_fn, vnr->where_line,
|
|
|
|
vnr->prev_fn);
|
|
|
|
if (brief)
|
|
|
|
printf(", ");
|
|
|
|
else
|
|
|
|
printf("\n ");
|
|
|
|
printf("%p -> %p\n", vnr->old_vnet, vnr->new_vnet);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
vnet_log_recursion(struct vnet *old_vnet, const char *old_fn, int line)
|
|
|
|
{
|
|
|
|
struct vnet_recursion *vnr;
|
|
|
|
|
|
|
|
/* Skip already logged recursion events. */
|
|
|
|
SLIST_FOREACH(vnr, &vnet_recursions, vnr_le)
|
|
|
|
if (vnr->prev_fn == old_fn &&
|
|
|
|
vnr->where_fn == curthread->td_vnet_lpush &&
|
|
|
|
vnr->where_line == line &&
|
|
|
|
(vnr->old_vnet == vnr->new_vnet) == (curvnet == old_vnet))
|
|
|
|
return;
|
|
|
|
|
|
|
|
vnr = malloc(sizeof(*vnr), M_VNET, M_NOWAIT | M_ZERO);
|
|
|
|
if (vnr == NULL)
|
|
|
|
panic("%s: malloc failed", __func__);
|
|
|
|
vnr->prev_fn = old_fn;
|
|
|
|
vnr->where_fn = curthread->td_vnet_lpush;
|
|
|
|
vnr->where_line = line;
|
|
|
|
vnr->old_vnet = old_vnet;
|
|
|
|
vnr->new_vnet = curvnet;
|
|
|
|
|
|
|
|
SLIST_INSERT_HEAD(&vnet_recursions, vnr, vnr_le);
|
|
|
|
|
|
|
|
vnet_print_recursion(vnr, 0);
|
|
|
|
#ifdef KDB
|
|
|
|
kdb_backtrace();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif /* VNET_DEBUG */
|
|
|
|
|
2010-03-19 19:51:03 +00:00
|
|
|
/*
|
|
|
|
* DDB(4).
|
|
|
|
*/
|
2009-08-01 19:26:27 +00:00
|
|
|
#ifdef DDB
|
|
|
|
DB_SHOW_COMMAND(vnets, db_show_vnets)
|
|
|
|
{
|
|
|
|
VNET_ITERATOR_DECL(vnet_iter);
|
|
|
|
|
|
|
|
VNET_FOREACH(vnet_iter) {
|
2009-08-12 12:00:21 +00:00
|
|
|
db_printf("vnet = %p\n", vnet_iter);
|
|
|
|
db_printf(" vnet_magic_n = 0x%x (%s, orig 0x%x)\n",
|
|
|
|
vnet_iter->vnet_magic_n,
|
|
|
|
(vnet_iter->vnet_magic_n == VNET_MAGIC_N) ?
|
|
|
|
"ok" : "mismatch", VNET_MAGIC_N);
|
|
|
|
db_printf(" vnet_ifcnt = %u\n", vnet_iter->vnet_ifcnt);
|
|
|
|
db_printf(" vnet_sockcnt = %u\n", vnet_iter->vnet_sockcnt);
|
|
|
|
db_printf(" vnet_data_mem = %p\n", vnet_iter->vnet_data_mem);
|
|
|
|
db_printf(" vnet_data_base = 0x%jx\n",
|
|
|
|
(uintmax_t)vnet_iter->vnet_data_base);
|
|
|
|
db_printf("\n");
|
|
|
|
if (db_pager_quit)
|
|
|
|
break;
|
2009-08-01 19:26:27 +00:00
|
|
|
}
|
|
|
|
}
|
2010-02-04 07:55:42 +00:00
|
|
|
|
2010-02-09 22:39:34 +00:00
|
|
|
static void
|
|
|
|
db_show_vnet_print_vs(struct vnet_sysinit *vs, int ddb)
|
|
|
|
{
|
|
|
|
const char *vsname, *funcname;
|
|
|
|
c_db_sym_t sym;
|
|
|
|
db_expr_t offset;
|
|
|
|
|
|
|
|
#define xprint(...) \
|
|
|
|
if (ddb) \
|
|
|
|
db_printf(__VA_ARGS__); \
|
|
|
|
else \
|
|
|
|
printf(__VA_ARGS__)
|
|
|
|
|
|
|
|
if (vs == NULL) {
|
|
|
|
xprint("%s: no vnet_sysinit * given\n", __func__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
sym = db_search_symbol((vm_offset_t)vs, DB_STGY_ANY, &offset);
|
|
|
|
db_symbol_values(sym, &vsname, NULL);
|
|
|
|
sym = db_search_symbol((vm_offset_t)vs->func, DB_STGY_PROC, &offset);
|
|
|
|
db_symbol_values(sym, &funcname, NULL);
|
|
|
|
xprint("%s(%p)\n", (vsname != NULL) ? vsname : "", vs);
|
|
|
|
xprint(" 0x%08x 0x%08x\n", vs->subsystem, vs->order);
|
|
|
|
xprint(" %p(%s)(%p)\n",
|
|
|
|
vs->func, (funcname != NULL) ? funcname : "", vs->arg);
|
|
|
|
#undef xprint
|
|
|
|
}
|
|
|
|
|
|
|
|
DB_SHOW_COMMAND(vnet_sysinit, db_show_vnet_sysinit)
|
|
|
|
{
|
|
|
|
struct vnet_sysinit *vs;
|
|
|
|
|
|
|
|
db_printf("VNET_SYSINIT vs Name(Ptr)\n");
|
|
|
|
db_printf(" Subsystem Order\n");
|
|
|
|
db_printf(" Function(Name)(Arg)\n");
|
|
|
|
TAILQ_FOREACH(vs, &vnet_constructors, link) {
|
|
|
|
db_show_vnet_print_vs(vs, 1);
|
|
|
|
if (db_pager_quit)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DB_SHOW_COMMAND(vnet_sysuninit, db_show_vnet_sysuninit)
|
|
|
|
{
|
|
|
|
struct vnet_sysinit *vs;
|
|
|
|
|
|
|
|
db_printf("VNET_SYSUNINIT vs Name(Ptr)\n");
|
|
|
|
db_printf(" Subsystem Order\n");
|
|
|
|
db_printf(" Function(Name)(Arg)\n");
|
|
|
|
TAILQ_FOREACH_REVERSE(vs, &vnet_destructors, vnet_sysuninit_head,
|
|
|
|
link) {
|
|
|
|
db_show_vnet_print_vs(vs, 1);
|
|
|
|
if (db_pager_quit)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-04 07:55:42 +00:00
|
|
|
#ifdef VNET_DEBUG
|
|
|
|
DB_SHOW_COMMAND(vnetrcrs, db_show_vnetrcrs)
|
|
|
|
{
|
|
|
|
struct vnet_recursion *vnr;
|
|
|
|
|
|
|
|
SLIST_FOREACH(vnr, &vnet_recursions, vnr_le)
|
|
|
|
vnet_print_recursion(vnr, 1);
|
|
|
|
}
|
2009-08-01 19:26:27 +00:00
|
|
|
#endif
|
2010-02-04 07:55:42 +00:00
|
|
|
#endif /* DDB */
|