Index: sys/netinet/igmp.c =================================================================== --- sys/netinet/igmp.c +++ sys/netinet/igmp.c @@ -60,7 +60,6 @@ #include #include #include -#include #include #include #include @@ -93,6 +92,9 @@ #define KTR_IGMPV3 KTR_INET #endif +#define PR_SLOWHZ 2 /* 2 slow timeouts per second */ +#define PR_FASTHZ 5 /* 5 fast timeouts per second */ + static struct igmp_ifsoftc * igi_alloc_locked(struct ifnet *); static void igi_delete_locked(const struct ifnet *); @@ -203,6 +205,7 @@ * * The IGMPv3 timers themselves need to run per-image, however, * protosw timers run globally (see tcp). + * XXXGL: ^^ not true, timers are local and this can be improved ^^ * An ifnet can only be in one vimage at a time, and the loopback * ifnet, loif, is itself virtualized. * It would otherwise be possible to seriously hose IGMP state, @@ -1655,11 +1658,14 @@ * Fast timeout handler (global). * VIMAGE: Timeout handlers are expected to service all vimages. */ -void -igmp_fasttimo(void) +static struct callout igmpfast_callout; +static void +igmp_fasttimo(void *arg __unused) { + struct epoch_tracker et; VNET_ITERATOR_DECL(vnet_iter); + NET_EPOCH_ENTER(et); VNET_LIST_RLOCK_NOSLEEP(); VNET_FOREACH(vnet_iter) { CURVNET_SET(vnet_iter); @@ -1667,6 +1673,9 @@ CURVNET_RESTORE(); } VNET_LIST_RUNLOCK_NOSLEEP(); + NET_EPOCH_EXIT(et); + + callout_reset(&igmpfast_callout, hz / PR_FASTHZ, igmp_fasttimo, NULL); } /* @@ -2193,11 +2202,14 @@ * Global slowtimo handler. * VIMAGE: Timeout handlers are expected to service all vimages. */ -void -igmp_slowtimo(void) +static struct callout igmpslow_callout; +static void +igmp_slowtimo(void *arg __unused) { + struct epoch_tracker et; VNET_ITERATOR_DECL(vnet_iter); + NET_EPOCH_ENTER(et); VNET_LIST_RLOCK_NOSLEEP(); VNET_FOREACH(vnet_iter) { CURVNET_SET(vnet_iter); @@ -2205,6 +2217,9 @@ CURVNET_RESTORE(); } VNET_LIST_RUNLOCK_NOSLEEP(); + NET_EPOCH_EXIT(et); + + callout_reset(&igmpslow_callout, hz / PR_SLOWHZ, igmp_slowtimo, NULL); } /* @@ -3688,6 +3703,12 @@ IGMP_LOCK_INIT(); m_raopt = igmp_ra_alloc(); netisr_register(&igmp_nh); + callout_init(&igmpslow_callout, 1); + callout_reset(&igmpslow_callout, hz / PR_SLOWHZ, igmp_slowtimo, + NULL); + callout_init(&igmpfast_callout, 1); + callout_reset(&igmpfast_callout, hz / PR_FASTHZ, igmp_fasttimo, + NULL); break; case MOD_UNLOAD: CTR1(KTR_IGMPV3, "%s: tearing down", __func__); Index: sys/netinet/igmp_var.h =================================================================== --- sys/netinet/igmp_var.h +++ sys/netinet/igmp_var.h @@ -223,13 +223,11 @@ }; int igmp_change_state(struct in_multi *); -void igmp_fasttimo(void); struct igmp_ifsoftc * igmp_domifattach(struct ifnet *); void igmp_domifdetach(struct ifnet *); void igmp_ifdetach(struct ifnet *); int igmp_input(struct mbuf **, int *, int); -void igmp_slowtimo(void); SYSCTL_DECL(_net_inet_igmp); Index: sys/netinet/in_proto.c =================================================================== --- sys/netinet/in_proto.c +++ sys/netinet/in_proto.c @@ -173,8 +173,6 @@ .pr_protocol = IPPROTO_IGMP, .pr_flags = PR_ATOMIC|PR_ADDR, .pr_ctloutput = rip_ctloutput, - .pr_fasttimo = igmp_fasttimo, - .pr_slowtimo = igmp_slowtimo, .pr_usrreqs = &rip_usrreqs }, {