summaryrefslogtreecommitdiffstats
path: root/sys/netinet/igmp.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-07-14 22:48:30 +0000
committerrwatson <rwatson@FreeBSD.org>2009-07-14 22:48:30 +0000
commit57ca4583e728cab422fba8f15de10bd0b637b3dd (patch)
tree13848f891fb2f7a396281b31633563d0f764ff65 /sys/netinet/igmp.c
parentef443476d9706035ac219f0280ef0b817dda7a6d (diff)
downloadFreeBSD-src-57ca4583e728cab422fba8f15de10bd0b637b3dd.zip
FreeBSD-src-57ca4583e728cab422fba8f15de10bd0b637b3dd.tar.gz
Build on Jeff Roberson's linker-set based dynamic per-CPU allocator
(DPCPU), as suggested by Peter Wemm, and implement a new per-virtual network stack memory allocator. Modify vnet to use the allocator instead of monolithic global container structures (vinet, ...). This change solves many binary compatibility problems associated with VIMAGE, and restores ELF symbols for virtualized global variables. Each virtualized global variable exists as a "reference copy", and also once per virtual network stack. Virtualized global variables are tagged at compile-time, placing the in a special linker set, which is loaded into a contiguous region of kernel memory. Virtualized global variables in the base kernel are linked as normal, but those in modules are copied and relocated to a reserved portion of the kernel's vnet region with the help of a the kernel linker. Virtualized global variables exist in per-vnet memory set up when the network stack instance is created, and are initialized statically from the reference copy. Run-time access occurs via an accessor macro, which converts from the current vnet and requested symbol to a per-vnet address. When "options VIMAGE" is not compiled into the kernel, normal global ELF symbols will be used instead and indirection is avoided. This change restores static initialization for network stack global variables, restores support for non-global symbols and types, eliminates the need for many subsystem constructors, eliminates large per-subsystem structures that caused many binary compatibility issues both for monitoring applications (netstat) and kernel modules, removes the per-function INIT_VNET_*() macros throughout the stack, eliminates the need for vnet_symmap ksym(2) munging, and eliminates duplicate definitions of virtualized globals under VIMAGE_GLOBALS. Bump __FreeBSD_version and update UPDATING. Portions submitted by: bz Reviewed by: bz, zec Discussed with: gnn, jamie, jeff, jhb, julian, sam Suggested by: peter Approved by: re (kensmith)
Diffstat (limited to 'sys/netinet/igmp.c')
-rw-r--r--sys/netinet/igmp.c146
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);
OpenPOWER on IntegriCloud