Lines Matching full:pmc

82 static int sf_setstate(struct ifmcaddr6 *pmc);
83 static void sf_markstate(struct ifmcaddr6 *pmc);
84 static void ip6_mc_clear_src(struct ifmcaddr6 *pmc);
120 #define for_each_pmc_socklock(np, sk, pmc) \ argument
121 for (pmc = sock_dereference((np)->ipv6_mc_list, sk); \
122 pmc; \
123 pmc = sock_dereference(pmc->next, sk))
125 #define for_each_pmc_rcu(np, pmc) \ argument
126 for (pmc = rcu_dereference((np)->ipv6_mc_list); \
127 pmc; \
128 pmc = rcu_dereference(pmc->next))
368 struct ipv6_mc_socklist *pmc; in ip6_mc_source() local
390 for_each_pmc_socklock(inet6, sk, pmc) { in ip6_mc_source()
391 if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface) in ip6_mc_source()
393 if (ipv6_addr_equal(&pmc->addr, group)) in ip6_mc_source()
396 if (!pmc) { /* must have a prior join */ in ip6_mc_source()
401 if (rcu_access_pointer(pmc->sflist)) { in ip6_mc_source()
402 if (pmc->sfmode != omode) { in ip6_mc_source()
406 } else if (pmc->sfmode != omode) { in ip6_mc_source()
409 ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0); in ip6_mc_source()
410 pmc->sfmode = omode; in ip6_mc_source()
413 psl = sock_dereference(pmc->sflist, sk); in ip6_mc_source()
467 rcu_assign_pointer(pmc->sflist, newpsl); in ip6_mc_source()
495 struct ipv6_mc_socklist *pmc; in ip6_mc_msfilter() local
522 for_each_pmc_socklock(inet6, sk, pmc) { in ip6_mc_msfilter()
523 if (pmc->ifindex != gsf->gf_interface) in ip6_mc_msfilter()
525 if (ipv6_addr_equal(&pmc->addr, group)) in ip6_mc_msfilter()
528 if (!pmc) { /* must have a prior join */ in ip6_mc_msfilter()
565 psl = sock_dereference(pmc->sflist, sk); in ip6_mc_msfilter()
567 ip6_mc_del_src(idev, group, pmc->sfmode, in ip6_mc_msfilter()
572 ip6_mc_del_src(idev, group, pmc->sfmode, 0, NULL, 0); in ip6_mc_msfilter()
574 rcu_assign_pointer(pmc->sflist, newpsl); in ip6_mc_msfilter()
577 pmc->sfmode = gsf->gf_fmode; in ip6_mc_msfilter()
590 struct ipv6_mc_socklist *pmc; in ip6_mc_msfget() local
604 for_each_pmc_socklock(inet6, sk, pmc) { in ip6_mc_msfget()
605 if (pmc->ifindex != gsf->gf_interface) in ip6_mc_msfget()
607 if (ipv6_addr_equal(group, &pmc->addr)) in ip6_mc_msfget()
610 if (!pmc) /* must have a prior join */ in ip6_mc_msfget()
613 gsf->gf_fmode = pmc->sfmode; in ip6_mc_msfget()
614 psl = sock_dereference(pmc->sflist, sk); in ip6_mc_msfget()
738 struct ifmcaddr6 *pmc; in mld_add_delrec() local
746 pmc = kzalloc(sizeof(*pmc), GFP_KERNEL); in mld_add_delrec()
747 if (!pmc) in mld_add_delrec()
750 pmc->idev = im->idev; in mld_add_delrec()
752 pmc->mca_addr = im->mca_addr; in mld_add_delrec()
753 pmc->mca_crcount = idev->mc_qrv; in mld_add_delrec()
754 pmc->mca_sfmode = im->mca_sfmode; in mld_add_delrec()
755 if (pmc->mca_sfmode == MCAST_INCLUDE) { in mld_add_delrec()
758 rcu_assign_pointer(pmc->mca_tomb, in mld_add_delrec()
760 rcu_assign_pointer(pmc->mca_sources, in mld_add_delrec()
765 for_each_psf_mclock(pmc, psf) in mld_add_delrec()
766 psf->sf_crcount = pmc->mca_crcount; in mld_add_delrec()
769 rcu_assign_pointer(pmc->next, idev->mc_tomb); in mld_add_delrec()
770 rcu_assign_pointer(idev->mc_tomb, pmc); in mld_add_delrec()
778 struct ifmcaddr6 *pmc, *pmc_prev; in mld_del_delrec() local
781 for_each_mc_tomb(idev, pmc) { in mld_del_delrec()
782 if (ipv6_addr_equal(&pmc->mca_addr, pmca)) in mld_del_delrec()
784 pmc_prev = pmc; in mld_del_delrec()
786 if (pmc) { in mld_del_delrec()
788 rcu_assign_pointer(pmc_prev->next, pmc->next); in mld_del_delrec()
790 rcu_assign_pointer(idev->mc_tomb, pmc->next); in mld_del_delrec()
793 if (pmc) { in mld_del_delrec()
794 im->idev = pmc->idev; in mld_del_delrec()
797 mc_dereference(pmc->mca_tomb, pmc->idev), in mld_del_delrec()
799 rcu_assign_pointer(pmc->mca_tomb, tomb); in mld_del_delrec()
802 mc_dereference(pmc->mca_sources, pmc->idev), in mld_del_delrec()
804 rcu_assign_pointer(pmc->mca_sources, sources); in mld_del_delrec()
810 in6_dev_put(pmc->idev); in mld_del_delrec()
811 ip6_mc_clear_src(pmc); in mld_del_delrec()
812 kfree_rcu(pmc, rcu); in mld_del_delrec()
819 struct ifmcaddr6 *pmc, *nextpmc; in mld_clear_delrec() local
821 pmc = mc_dereference(idev->mc_tomb, idev); in mld_clear_delrec()
824 for (; pmc; pmc = nextpmc) { in mld_clear_delrec()
825 nextpmc = mc_dereference(pmc->next, idev); in mld_clear_delrec()
826 ip6_mc_clear_src(pmc); in mld_clear_delrec()
827 in6_dev_put(pmc->idev); in mld_clear_delrec()
828 kfree_rcu(pmc, rcu); in mld_clear_delrec()
832 for_each_mc_mclock(idev, pmc) { in mld_clear_delrec()
835 psf = mc_dereference(pmc->mca_tomb, idev); in mld_clear_delrec()
836 RCU_INIT_POINTER(pmc->mca_tomb, NULL); in mld_clear_delrec()
1187 static bool mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs, in mld_xmarksources() argument
1194 for_each_psf_mclock(pmc, psf) { in mld_xmarksources()
1200 pmc->mca_sfcount[MCAST_EXCLUDE] != in mld_xmarksources()
1209 pmc->mca_flags &= ~MAF_GSQUERY; in mld_xmarksources()
1216 static bool mld_marksources(struct ifmcaddr6 *pmc, int nsrcs, in mld_marksources() argument
1222 if (pmc->mca_sfmode == MCAST_EXCLUDE) in mld_marksources()
1223 return mld_xmarksources(pmc, nsrcs, srcs); in mld_marksources()
1228 for_each_psf_mclock(pmc, psf) { in mld_marksources()
1240 pmc->mca_flags &= ~MAF_GSQUERY; in mld_marksources()
1243 pmc->mca_flags |= MAF_GSQUERY; in mld_marksources()
1688 static bool is_in(struct ifmcaddr6 *pmc, struct ip6_sf_list *psf, int type, in is_in() argument
1696 if (!((pmc->mca_flags & MAF_GSQUERY) && !psf->sf_gsresp)) { in is_in()
1697 if (pmc->mca_sfmode == MCAST_INCLUDE) in is_in()
1704 return pmc->mca_sfcount[MCAST_EXCLUDE] == in is_in()
1715 if (pmc->mca_sfcount[MCAST_EXCLUDE] == 0 || in is_in()
1718 return pmc->mca_sfcount[MCAST_EXCLUDE] == in is_in()
1723 return (pmc->mca_sfmode == MCAST_INCLUDE) ^ sdeleted; in is_in()
1725 if (pmc->mca_sfmode == MCAST_INCLUDE) in is_in()
1733 mld_scount(struct ifmcaddr6 *pmc, int type, int gdeleted, int sdeleted) in mld_scount() argument
1738 for_each_psf_mclock(pmc, psf) { in mld_scount()
1739 if (!is_in(pmc, psf, type, gdeleted, sdeleted)) in mld_scount()
1887 static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel) in grec_size() argument
1889 return sizeof(struct mld2_grec) + 16 * mld_scount(pmc,type,gdel,sdel); in grec_size()
1892 static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, in add_grhead() argument
1899 skb = mld_newpack(pmc->idev, mtu); in add_grhead()
1907 pgr->grec_mca = pmc->mca_addr; /* structure copy */ in add_grhead()
1917 static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, in add_grec() argument
1924 struct inet6_dev *idev = pmc->idev; in add_grec()
1930 if (pmc->mca_flags & MAF_NOREPORT) in add_grec()
1944 psf_list = sdeleted ? &pmc->mca_tomb : &pmc->mca_sources; in add_grec()
1954 AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) { in add_grec()
1969 if (!is_in(pmc, psf, type, gdeleted, sdeleted) && !crsend) { in add_grec()
1977 if (((gdeleted && pmc->mca_sfmode == MCAST_EXCLUDE) || in add_grec()
1978 (!gdeleted && pmc->mca_crcount)) && in add_grec()
2000 skb = add_grhead(skb, pmc, type, &pgr, mtu); in add_grec()
2031 if (pmc->mca_crcount || isquery || crsend) { in add_grec()
2037 skb = add_grhead(skb, pmc, type, &pgr, mtu); in add_grec()
2044 pmc->mca_flags &= ~MAF_GSQUERY; /* clear query state */ in add_grec()
2049 static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc) in mld_send_report() argument
2054 if (!pmc) { in mld_send_report()
2055 for_each_mc_mclock(idev, pmc) { in mld_send_report()
2056 if (pmc->mca_flags & MAF_NOREPORT) in mld_send_report()
2058 if (pmc->mca_sfcount[MCAST_EXCLUDE]) in mld_send_report()
2062 skb = add_grec(skb, pmc, type, 0, 0, 0); in mld_send_report()
2065 if (pmc->mca_sfcount[MCAST_EXCLUDE]) in mld_send_report()
2069 skb = add_grec(skb, pmc, type, 0, 0, 0); in mld_send_report()
2105 struct ifmcaddr6 *pmc, *pmc_prev, *pmc_next; in mld_send_cr() local
2111 for (pmc = mc_dereference(idev->mc_tomb, idev); in mld_send_cr()
2112 pmc; in mld_send_cr()
2113 pmc = pmc_next) { in mld_send_cr()
2114 pmc_next = mc_dereference(pmc->next, idev); in mld_send_cr()
2115 if (pmc->mca_sfmode == MCAST_INCLUDE) { in mld_send_cr()
2118 skb = add_grec(skb, pmc, type, 1, 0, 0); in mld_send_cr()
2119 skb = add_grec(skb, pmc, dtype, 1, 1, 0); in mld_send_cr()
2121 if (pmc->mca_crcount) { in mld_send_cr()
2122 if (pmc->mca_sfmode == MCAST_EXCLUDE) { in mld_send_cr()
2124 skb = add_grec(skb, pmc, type, 1, 0, 0); in mld_send_cr()
2126 pmc->mca_crcount--; in mld_send_cr()
2127 if (pmc->mca_crcount == 0) { in mld_send_cr()
2128 mld_clear_zeros(&pmc->mca_tomb, idev); in mld_send_cr()
2129 mld_clear_zeros(&pmc->mca_sources, idev); in mld_send_cr()
2132 if (pmc->mca_crcount == 0 && in mld_send_cr()
2133 !rcu_access_pointer(pmc->mca_tomb) && in mld_send_cr()
2134 !rcu_access_pointer(pmc->mca_sources)) { in mld_send_cr()
2139 in6_dev_put(pmc->idev); in mld_send_cr()
2140 kfree_rcu(pmc, rcu); in mld_send_cr()
2142 pmc_prev = pmc; in mld_send_cr()
2146 for_each_mc_mclock(idev, pmc) { in mld_send_cr()
2147 if (pmc->mca_sfcount[MCAST_EXCLUDE]) { in mld_send_cr()
2154 skb = add_grec(skb, pmc, type, 0, 0, 0); in mld_send_cr()
2155 skb = add_grec(skb, pmc, dtype, 0, 1, 0); /* deleted sources */ in mld_send_cr()
2158 if (pmc->mca_crcount) { in mld_send_cr()
2159 if (pmc->mca_sfmode == MCAST_EXCLUDE) in mld_send_cr()
2163 skb = add_grec(skb, pmc, type, 0, 0, 0); in mld_send_cr()
2164 pmc->mca_crcount--; in mld_send_cr()
2270 struct ifmcaddr6 *pmc; in mld_send_initial_cr() local
2277 for_each_mc_mclock(idev, pmc) { in mld_send_initial_cr()
2278 if (pmc->mca_sfcount[MCAST_EXCLUDE]) in mld_send_initial_cr()
2282 skb = add_grec(skb, pmc, type, 0, 0, 1); in mld_send_initial_cr()
2320 static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, in ip6_mc_del1_src() argument
2327 for_each_psf_mclock(pmc, psf) { in ip6_mc_del1_src()
2338 struct inet6_dev *idev = pmc->idev; in ip6_mc_del1_src()
2345 rcu_assign_pointer(pmc->mca_sources, in ip6_mc_del1_src()
2348 if (psf->sf_oldin && !(pmc->mca_flags & MAF_NOREPORT) && in ip6_mc_del1_src()
2352 mc_dereference(pmc->mca_tomb, idev)); in ip6_mc_del1_src()
2353 rcu_assign_pointer(pmc->mca_tomb, psf); in ip6_mc_del1_src()
2367 struct ifmcaddr6 *pmc; in ip6_mc_del_src() local
2374 for_each_mc_mclock(idev, pmc) { in ip6_mc_del_src()
2375 if (ipv6_addr_equal(pmca, &pmc->mca_addr)) in ip6_mc_del_src()
2378 if (!pmc) in ip6_mc_del_src()
2381 sf_markstate(pmc); in ip6_mc_del_src()
2383 if (!pmc->mca_sfcount[sfmode]) in ip6_mc_del_src()
2386 pmc->mca_sfcount[sfmode]--; in ip6_mc_del_src()
2390 int rv = ip6_mc_del1_src(pmc, sfmode, &psfsrc[i]); in ip6_mc_del_src()
2396 if (pmc->mca_sfmode == MCAST_EXCLUDE && in ip6_mc_del_src()
2397 pmc->mca_sfcount[MCAST_EXCLUDE] == 0 && in ip6_mc_del_src()
2398 pmc->mca_sfcount[MCAST_INCLUDE]) { in ip6_mc_del_src()
2402 pmc->mca_sfmode = MCAST_INCLUDE; in ip6_mc_del_src()
2403 pmc->mca_crcount = idev->mc_qrv; in ip6_mc_del_src()
2404 idev->mc_ifc_count = pmc->mca_crcount; in ip6_mc_del_src()
2405 for_each_psf_mclock(pmc, psf) in ip6_mc_del_src()
2407 mld_ifc_event(pmc->idev); in ip6_mc_del_src()
2408 } else if (sf_setstate(pmc) || changerec) { in ip6_mc_del_src()
2409 mld_ifc_event(pmc->idev); in ip6_mc_del_src()
2419 static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int sfmode, in ip6_mc_add1_src() argument
2425 for_each_psf_mclock(pmc, psf) { in ip6_mc_add1_src()
2439 rcu_assign_pointer(pmc->mca_sources, psf); in ip6_mc_add1_src()
2447 static void sf_markstate(struct ifmcaddr6 *pmc) in sf_markstate() argument
2450 int mca_xcount = pmc->mca_sfcount[MCAST_EXCLUDE]; in sf_markstate()
2452 for_each_psf_mclock(pmc, psf) { in sf_markstate()
2453 if (pmc->mca_sfcount[MCAST_EXCLUDE]) { in sf_markstate()
2464 static int sf_setstate(struct ifmcaddr6 *pmc) in sf_setstate() argument
2467 int mca_xcount = pmc->mca_sfcount[MCAST_EXCLUDE]; in sf_setstate()
2468 int qrv = pmc->idev->mc_qrv; in sf_setstate()
2472 for_each_psf_mclock(pmc, psf) { in sf_setstate()
2473 if (pmc->mca_sfcount[MCAST_EXCLUDE]) { in sf_setstate()
2482 for_each_psf_tomb(pmc, dpsf) { in sf_setstate()
2492 pmc->idev)); in sf_setstate()
2494 rcu_assign_pointer(pmc->mca_tomb, in sf_setstate()
2496 pmc->idev)); in sf_setstate()
2509 for_each_psf_tomb(pmc, dpsf) in sf_setstate()
2519 mc_dereference(pmc->mca_tomb, pmc->idev)); in sf_setstate()
2520 rcu_assign_pointer(pmc->mca_tomb, dpsf); in sf_setstate()
2537 struct ifmcaddr6 *pmc; in ip6_mc_add_src() local
2544 for_each_mc_mclock(idev, pmc) { in ip6_mc_add_src()
2545 if (ipv6_addr_equal(pmca, &pmc->mca_addr)) in ip6_mc_add_src()
2548 if (!pmc) in ip6_mc_add_src()
2551 sf_markstate(pmc); in ip6_mc_add_src()
2552 isexclude = pmc->mca_sfmode == MCAST_EXCLUDE; in ip6_mc_add_src()
2554 WRITE_ONCE(pmc->mca_sfcount[sfmode], in ip6_mc_add_src()
2555 pmc->mca_sfcount[sfmode] + 1); in ip6_mc_add_src()
2558 err = ip6_mc_add1_src(pmc, sfmode, &psfsrc[i]); in ip6_mc_add_src()
2566 WRITE_ONCE(pmc->mca_sfcount[sfmode], in ip6_mc_add_src()
2567 pmc->mca_sfcount[sfmode] - 1); in ip6_mc_add_src()
2569 ip6_mc_del1_src(pmc, sfmode, &psfsrc[j]); in ip6_mc_add_src()
2570 } else if (isexclude != (pmc->mca_sfcount[MCAST_EXCLUDE] != 0)) { in ip6_mc_add_src()
2574 if (pmc->mca_sfcount[MCAST_EXCLUDE]) in ip6_mc_add_src()
2575 pmc->mca_sfmode = MCAST_EXCLUDE; in ip6_mc_add_src()
2576 else if (pmc->mca_sfcount[MCAST_INCLUDE]) in ip6_mc_add_src()
2577 pmc->mca_sfmode = MCAST_INCLUDE; in ip6_mc_add_src()
2580 pmc->mca_crcount = idev->mc_qrv; in ip6_mc_add_src()
2581 idev->mc_ifc_count = pmc->mca_crcount; in ip6_mc_add_src()
2582 for_each_psf_mclock(pmc, psf) in ip6_mc_add_src()
2585 } else if (sf_setstate(pmc)) { in ip6_mc_add_src()
2592 static void ip6_mc_clear_src(struct ifmcaddr6 *pmc) in ip6_mc_clear_src() argument
2596 for (psf = mc_dereference(pmc->mca_tomb, pmc->idev); in ip6_mc_clear_src()
2599 nextpsf = mc_dereference(psf->sf_next, pmc->idev); in ip6_mc_clear_src()
2602 RCU_INIT_POINTER(pmc->mca_tomb, NULL); in ip6_mc_clear_src()
2603 for (psf = mc_dereference(pmc->mca_sources, pmc->idev); in ip6_mc_clear_src()
2606 nextpsf = mc_dereference(psf->sf_next, pmc->idev); in ip6_mc_clear_src()
2609 RCU_INIT_POINTER(pmc->mca_sources, NULL); in ip6_mc_clear_src()
2610 pmc->mca_sfmode = MCAST_EXCLUDE; in ip6_mc_clear_src()
2611 pmc->mca_sfcount[MCAST_INCLUDE] = 0; in ip6_mc_clear_src()
2613 WRITE_ONCE(pmc->mca_sfcount[MCAST_EXCLUDE], 1); in ip6_mc_clear_src()
2869 struct ifmcaddr6 *pmc; in ipv6_mc_rejoin_groups() local
2875 for_each_mc_mclock(idev, pmc) in ipv6_mc_rejoin_groups()
2876 igmp6_join_group(pmc); in ipv6_mc_rejoin_groups()