Lines Matching full:pmc

163 static int sf_setstate(struct ip_mc_list *pmc);
164 static void sf_markstate(struct ip_mc_list *pmc);
166 static void ip_mc_clear_src(struct ip_mc_list *pmc);
178 #define for_each_pmc_rcu(in_dev, pmc) \ argument
179 for (pmc = rcu_dereference(in_dev->mc_list); \
180 pmc != NULL; \
181 pmc = rcu_dereference(pmc->next_rcu))
183 #define for_each_pmc_rtnl(in_dev, pmc) \ argument
184 for (pmc = rtnl_dereference(in_dev->mc_list); \
185 pmc != NULL; \
186 pmc = rtnl_dereference(pmc->next_rcu))
275 static int is_in(struct ip_mc_list *pmc, struct ip_sf_list *psf, int type, in is_in() argument
283 if (!(pmc->gsquery && !psf->sf_gsresp)) { in is_in()
284 if (pmc->sfmode == MCAST_INCLUDE) in is_in()
291 return pmc->sfcount[MCAST_EXCLUDE] == in is_in()
302 if (pmc->sfcount[MCAST_EXCLUDE] == 0 || in is_in()
305 return pmc->sfcount[MCAST_EXCLUDE] == in is_in()
310 return (pmc->sfmode == MCAST_INCLUDE) ^ sdeleted; in is_in()
312 if (pmc->sfmode == MCAST_INCLUDE) in is_in()
320 igmp_scount(struct ip_mc_list *pmc, int type, int gdeleted, int sdeleted) in igmp_scount() argument
325 for (psf = pmc->sources; psf; psf = psf->sf_next) { in igmp_scount()
326 if (!is_in(pmc, psf, type, gdeleted, sdeleted)) in igmp_scount()
433 static int grec_size(struct ip_mc_list *pmc, int type, int gdel, int sdel) in grec_size() argument
435 return sizeof(struct igmpv3_grec) + 4*igmp_scount(pmc, type, gdel, sdel); in grec_size()
438 static struct sk_buff *add_grhead(struct sk_buff *skb, struct ip_mc_list *pmc, in add_grhead() argument
441 struct net_device *dev = pmc->interface->dev; in add_grhead()
454 pgr->grec_mca = pmc->multiaddr; in add_grhead()
463 static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, in add_grec() argument
466 struct net_device *dev = pmc->interface->dev; in add_grec()
474 if (pmc->multiaddr == IGMP_ALL_HOSTS) in add_grec()
476 if (ipv4_is_local_multicast(pmc->multiaddr) && in add_grec()
491 psf_list = sdeleted ? &pmc->tomb : &pmc->sources; in add_grec()
501 AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) { in add_grec()
514 if (!is_in(pmc, psf, type, gdeleted, sdeleted)) { in add_grec()
522 if (((gdeleted && pmc->sfmode == MCAST_EXCLUDE) || in add_grec()
523 (!gdeleted && pmc->crcount)) && in add_grec()
545 skb = add_grhead(skb, pmc, type, &pgr, mtu); in add_grec()
574 if (pmc->crcount || isquery) { in add_grec()
580 skb = add_grhead(skb, pmc, type, &pgr, mtu); in add_grec()
587 pmc->gsquery = 0; /* clear query state on report */ in add_grec()
591 static int igmpv3_send_report(struct in_device *in_dev, struct ip_mc_list *pmc) in igmpv3_send_report() argument
597 if (!pmc) { in igmpv3_send_report()
599 for_each_pmc_rcu(in_dev, pmc) { in igmpv3_send_report()
600 if (pmc->multiaddr == IGMP_ALL_HOSTS) in igmpv3_send_report()
602 if (ipv4_is_local_multicast(pmc->multiaddr) && in igmpv3_send_report()
605 spin_lock_bh(&pmc->lock); in igmpv3_send_report()
606 if (pmc->sfcount[MCAST_EXCLUDE]) in igmpv3_send_report()
610 skb = add_grec(skb, pmc, type, 0, 0); in igmpv3_send_report()
611 spin_unlock_bh(&pmc->lock); in igmpv3_send_report()
615 spin_lock_bh(&pmc->lock); in igmpv3_send_report()
616 if (pmc->sfcount[MCAST_EXCLUDE]) in igmpv3_send_report()
620 skb = add_grec(skb, pmc, type, 0, 0); in igmpv3_send_report()
621 spin_unlock_bh(&pmc->lock); in igmpv3_send_report()
649 static void kfree_pmc(struct ip_mc_list *pmc) in kfree_pmc() argument
651 ip_sf_list_clear_all(pmc->sources); in kfree_pmc()
652 ip_sf_list_clear_all(pmc->tomb); in kfree_pmc()
653 kfree(pmc); in kfree_pmc()
658 struct ip_mc_list *pmc, *pmc_prev, *pmc_next; in igmpv3_send_cr() local
667 for (pmc = in_dev->mc_tomb; pmc; pmc = pmc_next) { in igmpv3_send_cr()
668 pmc_next = pmc->next; in igmpv3_send_cr()
669 if (pmc->sfmode == MCAST_INCLUDE) { in igmpv3_send_cr()
672 skb = add_grec(skb, pmc, type, 1, 0); in igmpv3_send_cr()
673 skb = add_grec(skb, pmc, dtype, 1, 1); in igmpv3_send_cr()
675 if (pmc->crcount) { in igmpv3_send_cr()
676 if (pmc->sfmode == MCAST_EXCLUDE) { in igmpv3_send_cr()
678 skb = add_grec(skb, pmc, type, 1, 0); in igmpv3_send_cr()
680 pmc->crcount--; in igmpv3_send_cr()
681 if (pmc->crcount == 0) { in igmpv3_send_cr()
682 igmpv3_clear_zeros(&pmc->tomb); in igmpv3_send_cr()
683 igmpv3_clear_zeros(&pmc->sources); in igmpv3_send_cr()
686 if (pmc->crcount == 0 && !pmc->tomb && !pmc->sources) { in igmpv3_send_cr()
691 in_dev_put(pmc->interface); in igmpv3_send_cr()
692 kfree_pmc(pmc); in igmpv3_send_cr()
694 pmc_prev = pmc; in igmpv3_send_cr()
699 for_each_pmc_rcu(in_dev, pmc) { in igmpv3_send_cr()
700 spin_lock_bh(&pmc->lock); in igmpv3_send_cr()
701 if (pmc->sfcount[MCAST_EXCLUDE]) { in igmpv3_send_cr()
708 skb = add_grec(skb, pmc, type, 0, 0); in igmpv3_send_cr()
709 skb = add_grec(skb, pmc, dtype, 0, 1); /* deleted sources */ in igmpv3_send_cr()
712 if (pmc->crcount) { in igmpv3_send_cr()
713 if (pmc->sfmode == MCAST_EXCLUDE) in igmpv3_send_cr()
717 skb = add_grec(skb, pmc, type, 0, 0); in igmpv3_send_cr()
718 pmc->crcount--; in igmpv3_send_cr()
720 spin_unlock_bh(&pmc->lock); in igmpv3_send_cr()
729 static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, in igmp_send_report() argument
738 __be32 group = pmc ? pmc->multiaddr : 0; in igmp_send_report()
744 return igmpv3_send_report(in_dev, pmc); in igmp_send_report()
866 static int igmp_xmarksources(struct ip_mc_list *pmc, int nsrcs, __be32 *srcs) in igmp_xmarksources() argument
872 for (psf = pmc->sources; psf; psf = psf->sf_next) { in igmp_xmarksources()
878 pmc->sfcount[MCAST_EXCLUDE] != in igmp_xmarksources()
887 pmc->gsquery = 0; in igmp_xmarksources()
893 static int igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __be32 *srcs) in igmp_marksources() argument
898 if (pmc->sfmode == MCAST_EXCLUDE) in igmp_marksources()
899 return igmp_xmarksources(pmc, nsrcs, srcs); in igmp_marksources()
903 for (psf = pmc->sources; psf; psf = psf->sf_next) { in igmp_marksources()
914 pmc->gsquery = 0; in igmp_marksources()
917 pmc->gsquery = 1; in igmp_marksources()
1181 struct ip_mc_list *pmc; in igmpv3_add_delrec() local
1190 pmc = kzalloc(sizeof(*pmc), gfp); in igmpv3_add_delrec()
1191 if (!pmc) in igmpv3_add_delrec()
1193 spin_lock_init(&pmc->lock); in igmpv3_add_delrec()
1195 pmc->interface = im->interface; in igmpv3_add_delrec()
1197 pmc->multiaddr = im->multiaddr; in igmpv3_add_delrec()
1198 pmc->crcount = in_dev->mr_qrv ?: READ_ONCE(net->ipv4.sysctl_igmp_qrv); in igmpv3_add_delrec()
1199 pmc->sfmode = im->sfmode; in igmpv3_add_delrec()
1200 if (pmc->sfmode == MCAST_INCLUDE) { in igmpv3_add_delrec()
1203 pmc->tomb = im->tomb; in igmpv3_add_delrec()
1204 pmc->sources = im->sources; in igmpv3_add_delrec()
1206 for (psf = pmc->sources; psf; psf = psf->sf_next) in igmpv3_add_delrec()
1207 psf->sf_crcount = pmc->crcount; in igmpv3_add_delrec()
1212 pmc->next = in_dev->mc_tomb; in igmpv3_add_delrec()
1213 in_dev->mc_tomb = pmc; in igmpv3_add_delrec()
1222 struct ip_mc_list *pmc, *pmc_prev; in igmpv3_del_delrec() local
1229 for (pmc = in_dev->mc_tomb; pmc; pmc = pmc->next) { in igmpv3_del_delrec()
1230 if (pmc->multiaddr == multiaddr) in igmpv3_del_delrec()
1232 pmc_prev = pmc; in igmpv3_del_delrec()
1234 if (pmc) { in igmpv3_del_delrec()
1236 pmc_prev->next = pmc->next; in igmpv3_del_delrec()
1238 in_dev->mc_tomb = pmc->next; in igmpv3_del_delrec()
1243 if (pmc) { in igmpv3_del_delrec()
1244 im->interface = pmc->interface; in igmpv3_del_delrec()
1246 swap(im->tomb, pmc->tomb); in igmpv3_del_delrec()
1247 swap(im->sources, pmc->sources); in igmpv3_del_delrec()
1255 in_dev_put(pmc->interface); in igmpv3_del_delrec()
1256 kfree_pmc(pmc); in igmpv3_del_delrec()
1266 struct ip_mc_list *pmc, *nextpmc; in igmpv3_clear_delrec() local
1269 pmc = in_dev->mc_tomb; in igmpv3_clear_delrec()
1273 for (; pmc; pmc = nextpmc) { in igmpv3_clear_delrec()
1274 nextpmc = pmc->next; in igmpv3_clear_delrec()
1275 ip_mc_clear_src(pmc); in igmpv3_clear_delrec()
1276 in_dev_put(pmc->interface); in igmpv3_clear_delrec()
1277 kfree_pmc(pmc); in igmpv3_clear_delrec()
1281 for_each_pmc_rcu(in_dev, pmc) { in igmpv3_clear_delrec()
1284 spin_lock_bh(&pmc->lock); in igmpv3_clear_delrec()
1285 psf = pmc->tomb; in igmpv3_clear_delrec()
1286 pmc->tomb = NULL; in igmpv3_clear_delrec()
1287 spin_unlock_bh(&pmc->lock); in igmpv3_clear_delrec()
1798 struct ip_mc_list *pmc; in ip_mc_unmap() local
1802 for_each_pmc_rtnl(in_dev, pmc) in ip_mc_unmap()
1803 igmp_group_dropped(pmc); in ip_mc_unmap()
1808 struct ip_mc_list *pmc; in ip_mc_remap() local
1812 for_each_pmc_rtnl(in_dev, pmc) { in ip_mc_remap()
1814 igmpv3_del_delrec(in_dev, pmc); in ip_mc_remap()
1816 igmp_group_added(pmc); in ip_mc_remap()
1824 struct ip_mc_list *pmc; in ip_mc_down() local
1828 for_each_pmc_rtnl(in_dev, pmc) in ip_mc_down()
1829 igmp_group_dropped(pmc); in ip_mc_down()
1875 struct ip_mc_list *pmc; in ip_mc_up() local
1882 for_each_pmc_rtnl(in_dev, pmc) { in ip_mc_up()
1884 igmpv3_del_delrec(in_dev, pmc); in ip_mc_up()
1886 igmp_group_added(pmc); in ip_mc_up()
1951 static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode, in ip_mc_del1_src() argument
1958 for (psf = pmc->sources; psf; psf = psf->sf_next) { in ip_mc_del1_src()
1969 ip_rt_multicast_event(pmc->interface); in ip_mc_del1_src()
1973 struct in_device *in_dev = pmc->interface; in ip_mc_del1_src()
1981 pmc->sources = psf->sf_next; in ip_mc_del1_src()
1986 psf->sf_next = pmc->tomb; in ip_mc_del1_src()
1987 pmc->tomb = psf; in ip_mc_del1_src()
2003 struct ip_mc_list *pmc; in ip_mc_del_src() local
2010 for_each_pmc_rcu(in_dev, pmc) { in ip_mc_del_src()
2011 if (*pmca == pmc->multiaddr) in ip_mc_del_src()
2014 if (!pmc) { in ip_mc_del_src()
2019 spin_lock_bh(&pmc->lock); in ip_mc_del_src()
2022 sf_markstate(pmc); in ip_mc_del_src()
2026 if (!pmc->sfcount[sfmode]) in ip_mc_del_src()
2028 pmc->sfcount[sfmode]--; in ip_mc_del_src()
2032 int rv = ip_mc_del1_src(pmc, sfmode, &psfsrc[i]); in ip_mc_del_src()
2038 if (pmc->sfmode == MCAST_EXCLUDE && in ip_mc_del_src()
2039 pmc->sfcount[MCAST_EXCLUDE] == 0 && in ip_mc_del_src()
2040 pmc->sfcount[MCAST_INCLUDE]) { in ip_mc_del_src()
2047 pmc->sfmode = MCAST_INCLUDE; in ip_mc_del_src()
2049 pmc->crcount = in_dev->mr_qrv ?: READ_ONCE(net->ipv4.sysctl_igmp_qrv); in ip_mc_del_src()
2050 WRITE_ONCE(in_dev->mr_ifc_count, pmc->crcount); in ip_mc_del_src()
2051 for (psf = pmc->sources; psf; psf = psf->sf_next) in ip_mc_del_src()
2053 igmp_ifc_event(pmc->interface); in ip_mc_del_src()
2054 } else if (sf_setstate(pmc) || changerec) { in ip_mc_del_src()
2055 igmp_ifc_event(pmc->interface); in ip_mc_del_src()
2059 spin_unlock_bh(&pmc->lock); in ip_mc_del_src()
2066 static int ip_mc_add1_src(struct ip_mc_list *pmc, int sfmode, in ip_mc_add1_src() argument
2072 for (psf = pmc->sources; psf; psf = psf->sf_next) { in ip_mc_add1_src()
2085 pmc->sources = psf; in ip_mc_add1_src()
2089 ip_rt_multicast_event(pmc->interface); in ip_mc_add1_src()
2095 static void sf_markstate(struct ip_mc_list *pmc) in sf_markstate() argument
2098 int mca_xcount = pmc->sfcount[MCAST_EXCLUDE]; in sf_markstate()
2100 for (psf = pmc->sources; psf; psf = psf->sf_next) in sf_markstate()
2101 if (pmc->sfcount[MCAST_EXCLUDE]) { in sf_markstate()
2109 static int sf_setstate(struct ip_mc_list *pmc) in sf_setstate() argument
2112 int mca_xcount = pmc->sfcount[MCAST_EXCLUDE]; in sf_setstate()
2113 int qrv = pmc->interface->mr_qrv; in sf_setstate()
2117 for (psf = pmc->sources; psf; psf = psf->sf_next) { in sf_setstate()
2118 if (pmc->sfcount[MCAST_EXCLUDE]) { in sf_setstate()
2127 for (dpsf = pmc->tomb; dpsf; dpsf = dpsf->sf_next) { in sf_setstate()
2136 pmc->tomb = dpsf->sf_next; in sf_setstate()
2149 for (dpsf = pmc->tomb; dpsf; dpsf = dpsf->sf_next) in sf_setstate()
2157 /* pmc->lock held by callers */ in sf_setstate()
2158 dpsf->sf_next = pmc->tomb; in sf_setstate()
2159 pmc->tomb = dpsf; in sf_setstate()
2175 struct ip_mc_list *pmc; in ip_mc_add_src() local
2182 for_each_pmc_rcu(in_dev, pmc) { in ip_mc_add_src()
2183 if (*pmca == pmc->multiaddr) in ip_mc_add_src()
2186 if (!pmc) { in ip_mc_add_src()
2191 spin_lock_bh(&pmc->lock); in ip_mc_add_src()
2195 sf_markstate(pmc); in ip_mc_add_src()
2197 isexclude = pmc->sfmode == MCAST_EXCLUDE; in ip_mc_add_src()
2199 pmc->sfcount[sfmode]++; in ip_mc_add_src()
2202 err = ip_mc_add1_src(pmc, sfmode, &psfsrc[i]); in ip_mc_add_src()
2210 pmc->sfcount[sfmode]--; in ip_mc_add_src()
2212 (void) ip_mc_del1_src(pmc, sfmode, &psfsrc[j]); in ip_mc_add_src()
2213 } else if (isexclude != (pmc->sfcount[MCAST_EXCLUDE] != 0)) { in ip_mc_add_src()
2216 struct net *net = dev_net(pmc->interface->dev); in ip_mc_add_src()
2217 in_dev = pmc->interface; in ip_mc_add_src()
2221 if (pmc->sfcount[MCAST_EXCLUDE]) in ip_mc_add_src()
2222 pmc->sfmode = MCAST_EXCLUDE; in ip_mc_add_src()
2223 else if (pmc->sfcount[MCAST_INCLUDE]) in ip_mc_add_src()
2224 pmc->sfmode = MCAST_INCLUDE; in ip_mc_add_src()
2228 pmc->crcount = in_dev->mr_qrv ?: READ_ONCE(net->ipv4.sysctl_igmp_qrv); in ip_mc_add_src()
2229 WRITE_ONCE(in_dev->mr_ifc_count, pmc->crcount); in ip_mc_add_src()
2230 for (psf = pmc->sources; psf; psf = psf->sf_next) in ip_mc_add_src()
2233 } else if (sf_setstate(pmc)) { in ip_mc_add_src()
2237 spin_unlock_bh(&pmc->lock); in ip_mc_add_src()
2241 static void ip_mc_clear_src(struct ip_mc_list *pmc) in ip_mc_clear_src() argument
2245 spin_lock_bh(&pmc->lock); in ip_mc_clear_src()
2246 tomb = pmc->tomb; in ip_mc_clear_src()
2247 pmc->tomb = NULL; in ip_mc_clear_src()
2248 sources = pmc->sources; in ip_mc_clear_src()
2249 pmc->sources = NULL; in ip_mc_clear_src()
2250 pmc->sfmode = MCAST_EXCLUDE; in ip_mc_clear_src()
2251 pmc->sfcount[MCAST_INCLUDE] = 0; in ip_mc_clear_src()
2252 pmc->sfcount[MCAST_EXCLUDE] = 1; in ip_mc_clear_src()
2253 spin_unlock_bh(&pmc->lock); in ip_mc_clear_src()
2401 struct ip_mc_socklist *pmc; in ip_mc_source() local
2425 for_each_pmc_rtnl(inet, pmc) { in ip_mc_source()
2426 if ((pmc->multi.imr_multiaddr.s_addr == in ip_mc_source()
2428 (pmc->multi.imr_ifindex == imr.imr_ifindex)) in ip_mc_source()
2431 if (!pmc) { /* must have a prior join */ in ip_mc_source()
2436 if (pmc->sflist) { in ip_mc_source()
2437 if (pmc->sfmode != omode) { in ip_mc_source()
2441 } else if (pmc->sfmode != omode) { in ip_mc_source()
2444 ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, pmc->sfmode, 0, in ip_mc_source()
2446 pmc->sfmode = omode; in ip_mc_source()
2449 psl = rtnl_dereference(pmc->sflist); in ip_mc_source()
2506 rcu_assign_pointer(pmc->sflist, newpsl); in ip_mc_source()
2539 struct ip_mc_socklist *pmc; in ip_mc_msfilter() local
2570 for_each_pmc_rtnl(inet, pmc) { in ip_mc_msfilter()
2571 if (pmc->multi.imr_multiaddr.s_addr == msf->imsf_multiaddr && in ip_mc_msfilter()
2572 pmc->multi.imr_ifindex == imr.imr_ifindex) in ip_mc_msfilter()
2575 if (!pmc) { /* must have a prior join */ in ip_mc_msfilter()
2603 psl = rtnl_dereference(pmc->sflist); in ip_mc_msfilter()
2605 (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode, in ip_mc_msfilter()
2611 (void) ip_mc_del_src(in_dev, &msf->imsf_multiaddr, pmc->sfmode, in ip_mc_msfilter()
2614 rcu_assign_pointer(pmc->sflist, newpsl); in ip_mc_msfilter()
2617 pmc->sfmode = msf->imsf_fmode; in ip_mc_msfilter()
2630 struct ip_mc_socklist *pmc; in ip_mc_msfget() local
2652 for_each_pmc_rtnl(inet, pmc) { in ip_mc_msfget()
2653 if (pmc->multi.imr_multiaddr.s_addr == msf->imsf_multiaddr && in ip_mc_msfget()
2654 pmc->multi.imr_ifindex == imr.imr_ifindex) in ip_mc_msfget()
2657 if (!pmc) /* must have a prior join */ in ip_mc_msfget()
2659 msf->imsf_fmode = pmc->sfmode; in ip_mc_msfget()
2660 psl = rtnl_dereference(pmc->sflist); in ip_mc_msfget()
2690 struct ip_mc_socklist *pmc; in ip_mc_gsfget() local
2703 for_each_pmc_rtnl(inet, pmc) { in ip_mc_gsfget()
2704 if (pmc->multi.imr_multiaddr.s_addr == addr && in ip_mc_gsfget()
2705 pmc->multi.imr_ifindex == gsf->gf_interface) in ip_mc_gsfget()
2708 if (!pmc) /* must have a prior join */ in ip_mc_gsfget()
2710 gsf->gf_fmode = pmc->sfmode; in ip_mc_gsfget()
2711 psl = rtnl_dereference(pmc->sflist); in ip_mc_gsfget()
2737 struct ip_mc_socklist *pmc; in ip_mc_sf_allow() local
2747 for_each_pmc_rcu(inet, pmc) { in ip_mc_sf_allow()
2748 if (pmc->multi.imr_multiaddr.s_addr == loc_addr && in ip_mc_sf_allow()
2749 (pmc->multi.imr_ifindex == dif || in ip_mc_sf_allow()
2750 (sdif && pmc->multi.imr_ifindex == sdif))) in ip_mc_sf_allow()
2754 if (!pmc) in ip_mc_sf_allow()
2756 psl = rcu_dereference(pmc->sflist); in ip_mc_sf_allow()
2757 ret = (pmc->sfmode == MCAST_EXCLUDE); in ip_mc_sf_allow()
2766 if (pmc->sfmode == MCAST_INCLUDE && i >= psl->sl_count) in ip_mc_sf_allow()
2768 if (pmc->sfmode == MCAST_EXCLUDE && i < psl->sl_count) in ip_mc_sf_allow()