diff options
author | Gleb Smirnoff <glebius@FreeBSD.org> | 2019-01-09 01:11:19 +0000 |
---|---|---|
committer | Gleb Smirnoff <glebius@FreeBSD.org> | 2019-01-09 01:11:19 +0000 |
commit | a68cc388790587b330a01380a0c1864fb9ff3f1e (patch) | |
tree | f5bb270ef868e474632d85d470c6f571f63fbe1a /sys/netinet/igmp.c | |
parent | 086566c1c1b306c7eda0485e11c870bfaed6c721 (diff) | |
download | src-a68cc388790587b330a01380a0c1864fb9ff3f1e.tar.gz src-a68cc388790587b330a01380a0c1864fb9ff3f1e.zip |
Mechanical cleanup of epoch(9) usage in network stack.
- Remove macros that covertly create epoch_tracker on thread stack. Such
macros a quite unsafe, e.g. will produce a buggy code if same macro is
used in embedded scopes. Explicitly declare epoch_tracker always.
- Unmask interface list IFNET_RLOCK_NOSLEEP(), interface address list
IF_ADDR_RLOCK() and interface AF specific data IF_AFDATA_RLOCK() read
locking macros to what they actually are - the net_epoch.
Keeping them as is is very misleading. They all are named FOO_RLOCK(),
while they no longer have lock semantics. Now they allow recursion and
what's more important they now no longer guarantee protection against
their companion WLOCK macros.
Note: INP_HASH_RLOCK() has same problems, but not touched by this commit.
This is non functional mechanical change. The only functionally changed
functions are ni6_addrs() and ni6_store_addrs(), where we no longer enter
epoch recursively.
Discussed with: jtl, gallatin
Notes
Notes:
svn path=/head/; revision=342872
Diffstat (limited to 'sys/netinet/igmp.c')
-rw-r--r-- | sys/netinet/igmp.c | 42 |
1 files changed, 25 insertions, 17 deletions
diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c index 27c478382ef3..beb0f98209be 100644 --- a/sys/netinet/igmp.c +++ b/sys/netinet/igmp.c @@ -692,6 +692,7 @@ static int igmp_input_v1_query(struct ifnet *ifp, const struct ip *ip, const struct igmp *igmp) { + struct epoch_tracker et; struct ifmultiaddr *ifma; struct igmp_ifsoftc *igi; struct in_multi *inm; @@ -733,7 +734,7 @@ igmp_input_v1_query(struct ifnet *ifp, const struct ip *ip, * for the interface on which the query arrived, * except those which are already running. */ - IF_ADDR_RLOCK(ifp); + NET_EPOCH_ENTER(et); CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_INET || ifma->ifma_protospec == NULL) @@ -761,7 +762,7 @@ igmp_input_v1_query(struct ifnet *ifp, const struct ip *ip, break; } } - IF_ADDR_RUNLOCK(ifp); + NET_EPOCH_EXIT(et); out_locked: IGMP_UNLOCK(); @@ -777,6 +778,7 @@ static int igmp_input_v2_query(struct ifnet *ifp, const struct ip *ip, const struct igmp *igmp) { + struct epoch_tracker et; struct ifmultiaddr *ifma; struct igmp_ifsoftc *igi; struct in_multi *inm; @@ -834,7 +836,7 @@ igmp_input_v2_query(struct ifnet *ifp, const struct ip *ip, */ CTR2(KTR_IGMPV3, "process v2 general query on ifp %p(%s)", ifp, ifp->if_xname); - IF_ADDR_RLOCK(ifp); + NET_EPOCH_ENTER(et); CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_INET || ifma->ifma_protospec == NULL) @@ -842,7 +844,7 @@ igmp_input_v2_query(struct ifnet *ifp, const struct ip *ip, inm = (struct in_multi *)ifma->ifma_protospec; igmp_v2_update_group(inm, timer); } - IF_ADDR_RUNLOCK(ifp); + NET_EPOCH_EXIT(et); } else { /* * Group-specific IGMPv2 query, we need only @@ -1218,11 +1220,13 @@ igmp_input_v1_report(struct ifnet *ifp, /*const*/ struct ip *ip, * Replace 0.0.0.0 with the subnet address if told to do so. */ if (V_igmp_recvifkludge && in_nullhost(ip->ip_src)) { - NET_EPOCH_ENTER(); + struct epoch_tracker et; + + NET_EPOCH_ENTER(et); IFP_TO_IA(ifp, ia, &in_ifa_tracker); if (ia != NULL) ip->ip_src.s_addr = htonl(ia->ia_subnet); - NET_EPOCH_EXIT(); + NET_EPOCH_EXIT(et); } CTR3(KTR_IGMPV3, "process v1 report 0x%08x on ifp %p(%s)", @@ -1307,6 +1311,7 @@ igmp_input_v2_report(struct ifnet *ifp, /*const*/ struct ip *ip, /*const*/ struct igmp *igmp) { struct rm_priotracker in_ifa_tracker; + struct epoch_tracker et; struct in_ifaddr *ia; struct in_multi *inm; @@ -1315,23 +1320,23 @@ igmp_input_v2_report(struct ifnet *ifp, /*const*/ struct ip *ip, * leave requires knowing that we are the only member of a * group. */ - NET_EPOCH_ENTER(); + NET_EPOCH_ENTER(et); IFP_TO_IA(ifp, ia, &in_ifa_tracker); if (ia != NULL && in_hosteq(ip->ip_src, IA_SIN(ia)->sin_addr)) { - NET_EPOCH_EXIT(); + NET_EPOCH_EXIT(et); return (0); } IGMPSTAT_INC(igps_rcv_reports); if (ifp->if_flags & IFF_LOOPBACK) { - NET_EPOCH_EXIT(); + NET_EPOCH_EXIT(et); return (0); } if (!IN_MULTICAST(ntohl(igmp->igmp_group.s_addr)) || !in_hosteq(igmp->igmp_group, ip->ip_dst)) { - NET_EPOCH_EXIT(); + NET_EPOCH_EXIT(et); IGMPSTAT_INC(igps_rcv_badreports); return (EINVAL); } @@ -1347,7 +1352,7 @@ igmp_input_v2_report(struct ifnet *ifp, /*const*/ struct ip *ip, if (ia != NULL) ip->ip_src.s_addr = htonl(ia->ia_subnet); } - NET_EPOCH_EXIT(); + NET_EPOCH_EXIT(et); CTR3(KTR_IGMPV3, "process v2 report 0x%08x on ifp %p(%s)", ntohl(igmp->igmp_group.s_addr), ifp, ifp->if_xname); @@ -1989,6 +1994,7 @@ igmp_v3_cancel_link_timers(struct igmp_ifsoftc *igi) struct ifnet *ifp; struct in_multi *inm; struct in_multi_head inm_free_tmp; + struct epoch_tracker et; CTR3(KTR_IGMPV3, "%s: cancel v3 timers on ifp %p(%s)", __func__, igi->igi_ifp, igi->igi_ifp->if_xname); @@ -2009,7 +2015,7 @@ igmp_v3_cancel_link_timers(struct igmp_ifsoftc *igi) * for all memberships scoped to this link. */ ifp = igi->igi_ifp; - IF_ADDR_RLOCK(ifp); + NET_EPOCH_ENTER(et); CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_INET || ifma->ifma_protospec == NULL) @@ -2054,7 +2060,7 @@ igmp_v3_cancel_link_timers(struct igmp_ifsoftc *igi) inm->inm_timer = 0; mbufq_drain(&inm->inm_scq); } - IF_ADDR_RUNLOCK(ifp); + NET_EPOCH_EXIT(et); inm_release_list_deferred(&inm_free_tmp); } @@ -3297,6 +3303,7 @@ igmp_v3_merge_state_changes(struct in_multi *inm, struct mbufq *scq) static void igmp_v3_dispatch_general_query(struct igmp_ifsoftc *igi) { + struct epoch_tracker et; struct ifmultiaddr *ifma; struct ifnet *ifp; struct in_multi *inm; @@ -3319,7 +3326,7 @@ igmp_v3_dispatch_general_query(struct igmp_ifsoftc *igi) ifp = igi->igi_ifp; - IF_ADDR_RLOCK(ifp); + NET_EPOCH_ENTER(et); CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_INET || ifma->ifma_protospec == NULL) @@ -3350,7 +3357,7 @@ igmp_v3_dispatch_general_query(struct igmp_ifsoftc *igi) break; } } - IF_ADDR_RUNLOCK(ifp); + NET_EPOCH_EXIT(et); send: loop = (igi->igi_flags & IGIF_LOOPBACK) ? 1 : 0; @@ -3522,13 +3529,14 @@ igmp_v3_encap_report(struct ifnet *ifp, struct mbuf *m) ip->ip_src.s_addr = INADDR_ANY; if (m->m_flags & M_IGMP_LOOP) { + struct epoch_tracker et; struct in_ifaddr *ia; - NET_EPOCH_ENTER(); + NET_EPOCH_ENTER(et); IFP_TO_IA(ifp, ia, &in_ifa_tracker); if (ia != NULL) ip->ip_src = ia->ia_addr.sin_addr; - NET_EPOCH_EXIT(); + NET_EPOCH_EXIT(et); } ip->ip_dst.s_addr = htonl(INADDR_ALLRPTS_GROUP); |