diff options
author | rwatson <rwatson@FreeBSD.org> | 2009-07-14 22:48:30 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2009-07-14 22:48:30 +0000 |
commit | 57ca4583e728cab422fba8f15de10bd0b637b3dd (patch) | |
tree | 13848f891fb2f7a396281b31633563d0f764ff65 /sys/netinet/igmp.c | |
parent | ef443476d9706035ac219f0280ef0b817dda7a6d (diff) | |
download | FreeBSD-src-57ca4583e728cab422fba8f15de10bd0b637b3dd.zip FreeBSD-src-57ca4583e728cab422fba8f15de10bd0b637b3dd.tar.gz |
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual
network stack memory allocator. Modify vnet to use the allocator
instead of monolithic global container structures (vinet, ...). This
change solves many binary compatibility problems associated with
VIMAGE, and restores ELF symbols for virtualized global variables.
Each virtualized global variable exists as a "reference copy", and also
once per virtual network stack. Virtualized global variables are
tagged at compile-time, placing the in a special linker set, which is
loaded into a contiguous region of kernel memory. Virtualized global
variables in the base kernel are linked as normal, but those in modules
are copied and relocated to a reserved portion of the kernel's vnet
region with the help of a the kernel linker.
Virtualized global variables exist in per-vnet memory set up when the
network stack instance is created, and are initialized statically from
the reference copy. Run-time access occurs via an accessor macro, which
converts from the current vnet and requested symbol to a per-vnet
address. When "options VIMAGE" is not compiled into the kernel, normal
global ELF symbols will be used instead and indirection is avoided.
This change restores static initialization for network stack global
variables, restores support for non-global symbols and types, eliminates
the need for many subsystem constructors, eliminates large per-subsystem
structures that caused many binary compatibility issues both for
monitoring applications (netstat) and kernel modules, removes the
per-function INIT_VNET_*() macros throughout the stack, eliminates the
need for vnet_symmap ksym(2) munging, and eliminates duplicate
definitions of virtualized globals under VIMAGE_GLOBALS.
Bump __FreeBSD_version and update UPDATING.
Portions submitted by: bz
Reviewed by: bz, zec
Discussed with: gnn, jamie, jeff, jhb, julian, sam
Suggested by: peter
Approved by: re (kensmith)
Diffstat (limited to 'sys/netinet/igmp.c')
-rw-r--r-- | sys/netinet/igmp.c | 146 |
1 files changed, 58 insertions, 88 deletions
diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c index be102d4..c8bd09a 100644 --- a/sys/netinet/igmp.c +++ b/sys/netinet/igmp.c @@ -75,7 +75,6 @@ __FBSDID("$FreeBSD$"); #include <netinet/ip_options.h> #include <netinet/igmp.h> #include <netinet/igmp_var.h> -#include <netinet/vinet.h> #include <machine/in_cksum.h> @@ -212,55 +211,72 @@ MALLOC_DEFINE(M_IGMP, "igmp", "igmp state"); * FUTURE: Stop using IFP_TO_IA/INADDR_ANY, and use source address selection * policy to control the address used by IGMP on the link. */ -#ifdef VIMAGE_GLOBALS -int interface_timers_running; /* IGMPv3 general query response */ -int state_change_timers_running; /* IGMPv3 state-change retransmit */ -int current_state_timers_running; /* IGMPv1/v2 host report; - * IGMPv3 g/sg query response */ - -LIST_HEAD(, igmp_ifinfo) igi_head; -struct igmpstat igmpstat; -struct timeval igmp_gsrdelay; - -int igmp_recvifkludge; -int igmp_sendra; -int igmp_sendlocal; -int igmp_v1enable; -int igmp_v2enable; -int igmp_legacysupp; -int igmp_default_version; -#endif /* VIMAGE_GLOBALS */ +static VNET_DEFINE(int, interface_timers_running); /* IGMPv3 general + * query response */ +static VNET_DEFINE(int, state_change_timers_running); /* IGMPv3 state-change + * retransmit */ +static VNET_DEFINE(int, current_state_timers_running); /* IGMPv1/v2 host + * report; IGMPv3 g/sg + * query response */ + +#define V_interface_timers_running VNET_GET(interface_timers_running) +#define V_state_change_timers_running VNET_GET(state_change_timers_running) +#define V_current_state_timers_running VNET_GET(current_state_timers_running) + +static VNET_DEFINE(LIST_HEAD(, igmp_ifinfo), igi_head); +static VNET_DEFINE(struct igmpstat, igmpstat); +static VNET_DEFINE(struct timeval, igmp_gsrdelay) = {10, 0}; + +#define V_igi_head VNET_GET(igi_head) +#define V_igmpstat VNET_GET(igmpstat) +#define V_igmp_gsrdelay VNET_GET(igmp_gsrdelay) + +static VNET_DEFINE(int, igmp_recvifkludge) = 1; +static VNET_DEFINE(int, igmp_sendra) = 1; +static VNET_DEFINE(int, igmp_sendlocal) = 1; +static VNET_DEFINE(int, igmp_v1enable) = 1; +static VNET_DEFINE(int, igmp_v2enable) = 1; +static VNET_DEFINE(int, igmp_legacysupp); +static VNET_DEFINE(int, igmp_default_version) = IGMP_VERSION_3; + +#define V_igmp_recvifkludge VNET_GET(igmp_recvifkludge) +#define V_igmp_sendra VNET_GET(igmp_sendra) +#define V_igmp_sendlocal VNET_GET(igmp_sendlocal) +#define V_igmp_v1enable VNET_GET(igmp_v1enable) +#define V_igmp_v2enable VNET_GET(igmp_v2enable) +#define V_igmp_legacysupp VNET_GET(igmp_legacysupp) +#define V_igmp_default_version VNET_GET(igmp_default_version) /* * Virtualized sysctls. */ -SYSCTL_V_STRUCT(V_NET, vnet_inet, _net_inet_igmp, IGMPCTL_STATS, stats, - CTLFLAG_RW, igmpstat, igmpstat, ""); -SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_igmp, OID_AUTO, recvifkludge, - CTLFLAG_RW, igmp_recvifkludge, 0, +SYSCTL_VNET_STRUCT(_net_inet_igmp, IGMPCTL_STATS, stats, CTLFLAG_RW, + &VNET_NAME(igmpstat), igmpstat, ""); +SYSCTL_VNET_INT(_net_inet_igmp, OID_AUTO, recvifkludge, CTLFLAG_RW, + &VNET_NAME(igmp_recvifkludge), 0, "Rewrite IGMPv1/v2 reports from 0.0.0.0 to contain subnet address"); -SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_igmp, OID_AUTO, sendra, - CTLFLAG_RW, igmp_sendra, 0, +SYSCTL_VNET_INT(_net_inet_igmp, OID_AUTO, sendra, CTLFLAG_RW, + &VNET_NAME(igmp_sendra), 0, "Send IP Router Alert option in IGMPv2/v3 messages"); -SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_igmp, OID_AUTO, sendlocal, - CTLFLAG_RW, igmp_sendlocal, 0, +SYSCTL_VNET_INT(_net_inet_igmp, OID_AUTO, sendlocal, CTLFLAG_RW, + &VNET_NAME(igmp_sendlocal), 0, "Send IGMP membership reports for 224.0.0.0/24 groups"); -SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_igmp, OID_AUTO, v1enable, - CTLFLAG_RW, igmp_v1enable, 0, +SYSCTL_VNET_INT(_net_inet_igmp, OID_AUTO, v1enable, CTLFLAG_RW, + &VNET_NAME(igmp_v1enable), 0, "Enable backwards compatibility with IGMPv1"); -SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_igmp, OID_AUTO, v2enable, - CTLFLAG_RW, igmp_v2enable, 0, +SYSCTL_VNET_INT(_net_inet_igmp, OID_AUTO, v2enable, CTLFLAG_RW, + &VNET_NAME(igmp_v2enable), 0, "Enable backwards compatibility with IGMPv2"); -SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_igmp, OID_AUTO, legacysupp, - CTLFLAG_RW, igmp_legacysupp, 0, +SYSCTL_VNET_INT(_net_inet_igmp, OID_AUTO, legacysupp, CTLFLAG_RW, + &VNET_NAME(igmp_legacysupp), 0, "Allow v1/v2 reports to suppress v3 group responses"); -SYSCTL_V_PROC(V_NET, vnet_inet, _net_inet_igmp, OID_AUTO, default_version, - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, igmp_default_version, 0, - sysctl_igmp_default_version, "I", +SYSCTL_VNET_PROC(_net_inet_igmp, OID_AUTO, default_version, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, + &VNET_NAME(igmp_default_version), 0, sysctl_igmp_default_version, "I", "Default version of IGMP to run on each interface"); -SYSCTL_V_PROC(V_NET, vnet_inet, _net_inet_igmp, OID_AUTO, gsrdelay, - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, igmp_gsrdelay.tv_sec, 0, - sysctl_igmp_gsr, "I", +SYSCTL_VNET_PROC(_net_inet_igmp, OID_AUTO, gsrdelay, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, + &VNET_NAME(igmp_gsrdelay.tv_sec), 0, sysctl_igmp_gsr, "I", "Rate limit for IGMPv3 Group-and-Source queries in seconds"); /* @@ -327,7 +343,6 @@ igmp_restore_context(struct mbuf *m) static int sysctl_igmp_default_version(SYSCTL_HANDLER_ARGS) { - INIT_VNET_INET(curvnet); int error; int new; @@ -367,7 +382,6 @@ out_locked: static int sysctl_igmp_gsr(SYSCTL_HANDLER_ARGS) { - INIT_VNET_INET(curvnet); int error; int i; @@ -408,8 +422,6 @@ out_locked: static int sysctl_igmp_ifinfo(SYSCTL_HANDLER_ARGS) { - INIT_VNET_NET(curvnet); - INIT_VNET_INET(curvnet); int *name; int error; u_int namelen; @@ -495,7 +507,6 @@ igmp_dispatch_queue(struct ifqueue *ifq, int limit, const int loop) static __inline int igmp_isgroupreported(const struct in_addr addr) { - INIT_VNET_INET(curvnet); if (in_allhosts(addr) || ((!V_igmp_sendlocal && IN_LOCAL_GROUP(ntohl(addr.s_addr))))) @@ -553,7 +564,6 @@ igmp_domifattach(struct ifnet *ifp) static struct igmp_ifinfo * igi_alloc_locked(/*const*/ struct ifnet *ifp) { - INIT_VNET_INET(ifp->if_vnet); struct igmp_ifinfo *igi; IGMP_LOCK_ASSERT(); @@ -661,7 +671,6 @@ igmp_domifdetach(struct ifnet *ifp) static void igi_delete_locked(const struct ifnet *ifp) { - INIT_VNET_INET(ifp->if_vnet); struct igmp_ifinfo *igi, *tigi; CTR3(KTR_IGMPV3, "%s: freeing igmp_ifinfo for ifp %p(%s)", @@ -702,7 +711,6 @@ static int igmp_input_v1_query(struct ifnet *ifp, const struct ip *ip, const struct igmp *igmp) { - INIT_VNET_INET(ifp->if_vnet); struct ifmultiaddr *ifma; struct igmp_ifinfo *igi; struct in_multi *inm; @@ -788,7 +796,6 @@ static int igmp_input_v2_query(struct ifnet *ifp, const struct ip *ip, const struct igmp *igmp) { - INIT_VNET_INET(ifp->if_vnet); struct ifmultiaddr *ifma; struct igmp_ifinfo *igi; struct in_multi *inm; @@ -893,7 +900,6 @@ out_locked: static void igmp_v2_update_group(struct in_multi *inm, const int timer) { - INIT_VNET_INET(curvnet); CTR4(KTR_IGMPV3, "%s: %s/%s timer=%d", __func__, inet_ntoa(inm->inm_addr), inm->inm_ifp->if_xname, timer); @@ -941,7 +947,6 @@ static int igmp_input_v3_query(struct ifnet *ifp, const struct ip *ip, /*const*/ struct igmpv3 *igmpv3) { - INIT_VNET_INET(ifp->if_vnet); struct igmp_ifinfo *igi; struct in_multi *inm; int is_general_query; @@ -1106,7 +1111,6 @@ static int igmp_input_v3_group_query(struct in_multi *inm, struct igmp_ifinfo *igi, int timer, /*const*/ struct igmpv3 *igmpv3) { - INIT_VNET_INET(curvnet); int retval; uint16_t nsrc; @@ -1209,7 +1213,6 @@ static int igmp_input_v1_report(struct ifnet *ifp, /*const*/ struct ip *ip, /*const*/ struct igmp *igmp) { - INIT_VNET_INET(ifp->if_vnet); struct in_ifaddr *ia; struct in_multi *inm; @@ -1318,7 +1321,6 @@ static int igmp_input_v2_report(struct ifnet *ifp, /*const*/ struct ip *ip, /*const*/ struct igmp *igmp) { - INIT_VNET_INET(ifp->if_vnet); struct in_ifaddr *ia; struct in_multi *inm; @@ -1436,7 +1438,6 @@ igmp_input(struct mbuf *m, int off) CTR3(KTR_IGMPV3, "%s: called w/mbuf (%p,%d)", __func__, m, off); ifp = m->m_pkthdr.rcvif; - INIT_VNET_INET(ifp->if_vnet); IGMPSTAT_INC(igps_rcv_total); @@ -1633,7 +1634,6 @@ igmp_fasttimo(void) static void igmp_fasttimo_vnet(void) { - INIT_VNET_INET(curvnet); struct ifqueue scq; /* State-change packets */ struct ifqueue qrq; /* Query response packets */ struct ifnet *ifp; @@ -1756,7 +1756,6 @@ out_locked: static void igmp_v1v2_process_group_timer(struct in_multi *inm, const int version) { - INIT_VNET_INET(curvnet); int report_timer_expired; IN_MULTI_LOCK_ASSERT(); @@ -1805,7 +1804,6 @@ igmp_v3_process_group_timers(struct igmp_ifinfo *igi, struct ifqueue *qrq, struct ifqueue *scq, struct in_multi *inm, const int uri_fasthz) { - INIT_VNET_INET(curvnet); int query_response_timer_expired; int state_change_retransmit_timer_expired; @@ -2083,7 +2081,6 @@ igmp_v3_cancel_link_timers(struct igmp_ifinfo *igi) static void igmp_v1v2_process_querier_timers(struct igmp_ifinfo *igi) { - INIT_VNET_INET(curvnet); IGMP_LOCK_ASSERT(); @@ -2177,7 +2174,6 @@ igmp_slowtimo(void) static void igmp_slowtimo_vnet(void) { - INIT_VNET_INET(curvnet); struct igmp_ifinfo *igi; IGMP_LOCK(); @@ -2342,7 +2338,6 @@ out_locked: static int igmp_initial_join(struct in_multi *inm, struct igmp_ifinfo *igi) { - INIT_VNET_INET(curvnet); struct ifnet *ifp; struct ifqueue *ifq; int error, retval, syncstates; @@ -2471,7 +2466,6 @@ igmp_initial_join(struct in_multi *inm, struct igmp_ifinfo *igi) static int igmp_handle_state_change(struct in_multi *inm, struct igmp_ifinfo *igi) { - INIT_VNET_INET(curvnet); struct ifnet *ifp; int retval; @@ -2531,7 +2525,6 @@ igmp_handle_state_change(struct in_multi *inm, struct igmp_ifinfo *igi) static void igmp_final_leave(struct in_multi *inm, struct igmp_ifinfo *igi) { - INIT_VNET_INET(curvnet); int syncstates; syncstates = 1; @@ -3324,7 +3317,6 @@ igmp_v3_merge_state_changes(struct in_multi *inm, struct ifqueue *ifscq) static void igmp_v3_dispatch_general_query(struct igmp_ifinfo *igi) { - INIT_VNET_INET(curvnet); struct ifmultiaddr *ifma, *tifma; struct ifnet *ifp; struct in_multi *inm; @@ -3412,8 +3404,6 @@ igmp_intr(struct mbuf *m) * unique to each VIMAGE and must be retrieved. */ CURVNET_SET((struct vnet *)(m->m_pkthdr.header)); - INIT_VNET_NET(curvnet); - INIT_VNET_INET(curvnet); ifindex = igmp_restore_context(m); /* @@ -3495,7 +3485,6 @@ out: static struct mbuf * igmp_v3_encap_report(struct ifnet *ifp, struct mbuf *m) { - INIT_VNET_INET(curvnet); struct igmp_report *igmp; struct ip *ip; int hdrlen, igmpreclen; @@ -3621,30 +3610,14 @@ igmp_sysuninit(void) static int vnet_igmp_iattach(const void *unused __unused) { - INIT_VNET_INET(curvnet); CTR1(KTR_IGMPV3, "%s: initializing", __func__); LIST_INIT(&V_igi_head); - V_current_state_timers_running = 0; - V_state_change_timers_running = 0; - V_interface_timers_running = 0; - /* * Initialize sysctls to default values. */ - V_igmp_recvifkludge = 1; - V_igmp_sendra = 1; - V_igmp_sendlocal = 1; - V_igmp_v1enable = 1; - V_igmp_v2enable = 1; - V_igmp_legacysupp = 0; - V_igmp_default_version = IGMP_VERSION_3; - V_igmp_gsrdelay.tv_sec = 10; - V_igmp_gsrdelay.tv_usec = 0; - - memset(&V_igmpstat, 0, sizeof(struct igmpstat)); V_igmpstat.igps_version = IGPS_VERSION_3; V_igmpstat.igps_len = sizeof(struct igmpstat); @@ -3654,9 +3627,6 @@ vnet_igmp_iattach(const void *unused __unused) static int vnet_igmp_idetach(const void *unused __unused) { -#ifdef INVARIANTS - INIT_VNET_INET(curvnet); -#endif CTR1(KTR_IGMPV3, "%s: tearing down", __func__); @@ -3666,7 +3636,7 @@ vnet_igmp_idetach(const void *unused __unused) return (0); } -#ifndef VIMAGE_GLOBALS +#ifdef VIMAGE static vnet_modinfo_t vnet_igmp_modinfo = { .vmi_id = VNET_MOD_IGMP, .vmi_name = "igmp", @@ -3683,14 +3653,14 @@ igmp_modevent(module_t mod, int type, void *unused __unused) switch (type) { case MOD_LOAD: igmp_sysinit(); -#ifndef VIMAGE_GLOBALS +#ifdef VIMAGE vnet_mod_register(&vnet_igmp_modinfo); #else vnet_igmp_iattach(NULL); #endif break; case MOD_UNLOAD: -#ifndef VIMAGE_GLOBALS +#ifdef VIMAGE vnet_mod_deregister(&vnet_igmp_modinfo); #else vnet_igmp_idetach(NULL); |