--- //depot/projects/netperf_socket/sys/netinet/igmp.c 2004/04/08 02:39:15 +++ //depot/user/rwatson/netperf/sys/netinet/igmp.c 2004/04/08 03:11:34 @@ -80,10 +80,28 @@ SYSCTL_STRUCT(_net_inet_igmp, IGMPCTL_STATS, stats, CTLFLAG_RW, &igmpstat, igmpstat, ""); +/* + * igmp_mtx protects all mutable global variables in igmp.c, as well as + * the data fields in struct router_info. In general, a router_info + * structure will be valid as long as the referencing struct in_multi is + * valid, so no reference counting is used. We allow unlocked reads of + * router_info data when accessed via an in_multi read-only. + */ +static struct mtx igmp_mtx; static SLIST_HEAD(, router_info) router_info_head; static int igmp_timers_are_running; + +/* + * XXXRW: can we define these such that these can be made const? In any + * case, these shouldn't be changed after igmp_init() and therefore don't + * need locking. + */ static u_long igmp_all_hosts_group; static u_long igmp_all_rtrs_group; + +/* + * XXXRW: These variables make me vaguely nervous. + */ static struct mbuf *router_alert; static struct route igmprt; @@ -108,6 +126,7 @@ /* * Construct a Router Alert option to use in outgoing packets + * XXXRW: This might actually need a MAC label. */ MGET(router_alert, M_DONTWAIT, MT_DATA); ra = mtod(router_alert, struct ipoption *); @@ -118,6 +137,7 @@ ra->ipopt_list[3] = 0x00; router_alert->m_len = sizeof(ra->ipopt_dst) + ra->ipopt_list[1]; + mtx_init(&igmp_mtx, "igmp_mtx", NULL, MTX_DEF); SLIST_INIT(&router_info_head); } @@ -126,6 +146,7 @@ { struct router_info *rti; + mtx_assert(&igmp_mtx, MA_OWNED); IGMP_PRINTF("[igmp.c, _find_rti] --> entering \n"); SLIST_FOREACH(rti, &router_info_head, rti_list) { if (rti->rti_ifp == ifp) { @@ -134,6 +155,9 @@ return rti; } } + /* + * XXXRW: return value of malloc not checked, despite M_NOWAIT. + */ MALLOC(rti, struct router_info *, sizeof *rti, M_IGMP, M_NOWAIT); rti->rti_ifp = ifp; rti->rti_type = IGMP_V2_ROUTER; @@ -197,7 +221,6 @@ timer = igmp->igmp_code * PR_FASTHZ / IGMP_TIMER_SCALE; if (timer == 0) timer = 1; - rti = find_rti(ifp); /* * In the IGMPv2 specification, there are 3 states and a flag. @@ -224,8 +247,11 @@ * value in RFC 1112. */ + mtx_lock(&igmp_mtx); + rti = find_rti(ifp); rti->rti_type = IGMP_V1_ROUTER; rti->rti_time = 0; + mtx_unlock(&igmp_mtx); timer = IGMP_MAX_HOST_REPORT_DELAY * PR_FASTHZ; @@ -344,7 +370,9 @@ inm->inm_timer = 0; inm->inm_state = IGMP_OTHERMEMBER; } else { + mtx_lock(&igmp_mtx); inm->inm_rti = find_rti(inm->inm_ifp); + mtx_unlock(&igmp_mtx); igmp_sendpkt(inm, inm->inm_rti->rti_type, 0); inm->inm_timer = IGMP_RANDOM_DELAY( IGMP_MAX_HOST_REPORT_DELAY*PR_FASTHZ); @@ -404,6 +432,7 @@ struct router_info *rti; IGMP_PRINTF("[igmp.c,_slowtimo] -- > entering \n"); + mtx_lock(&igmp_mtx); SLIST_FOREACH(rti, &router_info_head, rti_list) { if (rti->rti_type == IGMP_V1_ROUTER) { rti->rti_time++; @@ -411,6 +440,7 @@ rti->rti_type = IGMP_V2_ROUTER; } } + mtx_unlock(&igmp_mtx); IGMP_PRINTF("[igmp.c,_slowtimo] -- > exiting \n"); splx(s); }