igmp.c (80dbff4e99ba37534b40803a1ddff842f5ebdd58) igmp.c (137f91e80f3802084bd96586d09961a846b91665)
1/*-
2 * Copyright (c) 2007-2009 Bruce Simpson.
3 * Copyright (c) 1988 Stephen Deering.
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Stephen Deering of Stanford University.

--- 604 unchanged lines hidden (view full) ---

613
614 CTR3(KTR_IGMPV3, "%s: called for ifp %p(%s)", __func__, ifp,
615 ifp->if_xname);
616
617 IGMP_LOCK();
618
619 igi = ((struct in_ifinfo *)ifp->if_afdata[AF_INET])->ii_igmp;
620 if (igi->igi_version == IGMP_VERSION_3) {
1/*-
2 * Copyright (c) 2007-2009 Bruce Simpson.
3 * Copyright (c) 1988 Stephen Deering.
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Stephen Deering of Stanford University.

--- 604 unchanged lines hidden (view full) ---

613
614 CTR3(KTR_IGMPV3, "%s: called for ifp %p(%s)", __func__, ifp,
615 ifp->if_xname);
616
617 IGMP_LOCK();
618
619 igi = ((struct in_ifinfo *)ifp->if_afdata[AF_INET])->ii_igmp;
620 if (igi->igi_version == IGMP_VERSION_3) {
621 IF_ADDR_LOCK(ifp);
621 IF_ADDR_RLOCK(ifp);
622 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
623 if (ifma->ifma_addr->sa_family != AF_INET ||
624 ifma->ifma_protospec == NULL)
625 continue;
626#if 0
627 KASSERT(ifma->ifma_protospec != NULL,
628 ("%s: ifma_protospec is NULL", __func__));
629#endif
630 inm = (struct in_multi *)ifma->ifma_protospec;
631 if (inm->inm_state == IGMP_LEAVING_MEMBER) {
632 SLIST_INSERT_HEAD(&igi->igi_relinmhead,
633 inm, inm_nrele);
634 }
635 inm_clear_recorded(inm);
636 }
622 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
623 if (ifma->ifma_addr->sa_family != AF_INET ||
624 ifma->ifma_protospec == NULL)
625 continue;
626#if 0
627 KASSERT(ifma->ifma_protospec != NULL,
628 ("%s: ifma_protospec is NULL", __func__));
629#endif
630 inm = (struct in_multi *)ifma->ifma_protospec;
631 if (inm->inm_state == IGMP_LEAVING_MEMBER) {
632 SLIST_INSERT_HEAD(&igi->igi_relinmhead,
633 inm, inm_nrele);
634 }
635 inm_clear_recorded(inm);
636 }
637 IF_ADDR_UNLOCK(ifp);
637 IF_ADDR_RUNLOCK(ifp);
638 /*
639 * Free the in_multi reference(s) for this IGMP lifecycle.
640 */
641 SLIST_FOREACH_SAFE(inm, &igi->igi_relinmhead, inm_nrele,
642 tinm) {
643 SLIST_REMOVE_HEAD(&igi->igi_relinmhead, inm_nrele);
644 inm_release_locked(inm);
645 }

--- 100 unchanged lines hidden (view full) ---

746
747 CTR2(KTR_IGMPV3, "process v1 query on ifp %p(%s)", ifp, ifp->if_xname);
748
749 /*
750 * Start the timers in all of our group records
751 * for the interface on which the query arrived,
752 * except those which are already running.
753 */
638 /*
639 * Free the in_multi reference(s) for this IGMP lifecycle.
640 */
641 SLIST_FOREACH_SAFE(inm, &igi->igi_relinmhead, inm_nrele,
642 tinm) {
643 SLIST_REMOVE_HEAD(&igi->igi_relinmhead, inm_nrele);
644 inm_release_locked(inm);
645 }

--- 100 unchanged lines hidden (view full) ---

746
747 CTR2(KTR_IGMPV3, "process v1 query on ifp %p(%s)", ifp, ifp->if_xname);
748
749 /*
750 * Start the timers in all of our group records
751 * for the interface on which the query arrived,
752 * except those which are already running.
753 */
754 IF_ADDR_LOCK(ifp);
754 IF_ADDR_RLOCK(ifp);
755 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
756 if (ifma->ifma_addr->sa_family != AF_INET ||
757 ifma->ifma_protospec == NULL)
758 continue;
759 inm = (struct in_multi *)ifma->ifma_protospec;
760 if (inm->inm_timer != 0)
761 continue;
762 switch (inm->inm_state) {

--- 11 unchanged lines hidden (view full) ---

774 inm->inm_timer = IGMP_RANDOM_DELAY(
775 IGMP_V1V2_MAX_RI * PR_FASTHZ);
776 V_current_state_timers_running = 1;
777 break;
778 case IGMP_LEAVING_MEMBER:
779 break;
780 }
781 }
755 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
756 if (ifma->ifma_addr->sa_family != AF_INET ||
757 ifma->ifma_protospec == NULL)
758 continue;
759 inm = (struct in_multi *)ifma->ifma_protospec;
760 if (inm->inm_timer != 0)
761 continue;
762 switch (inm->inm_state) {

--- 11 unchanged lines hidden (view full) ---

774 inm->inm_timer = IGMP_RANDOM_DELAY(
775 IGMP_V1V2_MAX_RI * PR_FASTHZ);
776 V_current_state_timers_running = 1;
777 break;
778 case IGMP_LEAVING_MEMBER:
779 break;
780 }
781 }
782 IF_ADDR_UNLOCK(ifp);
782 IF_ADDR_RUNLOCK(ifp);
783
784out_locked:
785 IGMP_UNLOCK();
786 IN_MULTI_UNLOCK();
787
788 return (0);
789}
790

--- 56 unchanged lines hidden (view full) ---

847
848 if (is_general_query) {
849 /*
850 * For each reporting group joined on this
851 * interface, kick the report timer.
852 */
853 CTR2(KTR_IGMPV3, "process v2 general query on ifp %p(%s)",
854 ifp, ifp->if_xname);
783
784out_locked:
785 IGMP_UNLOCK();
786 IN_MULTI_UNLOCK();
787
788 return (0);
789}
790

--- 56 unchanged lines hidden (view full) ---

847
848 if (is_general_query) {
849 /*
850 * For each reporting group joined on this
851 * interface, kick the report timer.
852 */
853 CTR2(KTR_IGMPV3, "process v2 general query on ifp %p(%s)",
854 ifp, ifp->if_xname);
855 IF_ADDR_LOCK(ifp);
855 IF_ADDR_RLOCK(ifp);
856 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
857 if (ifma->ifma_addr->sa_family != AF_INET ||
858 ifma->ifma_protospec == NULL)
859 continue;
860 inm = (struct in_multi *)ifma->ifma_protospec;
861 igmp_v2_update_group(inm, timer);
862 }
856 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
857 if (ifma->ifma_addr->sa_family != AF_INET ||
858 ifma->ifma_protospec == NULL)
859 continue;
860 inm = (struct in_multi *)ifma->ifma_protospec;
861 igmp_v2_update_group(inm, timer);
862 }
863 IF_ADDR_UNLOCK(ifp);
863 IF_ADDR_RUNLOCK(ifp);
864 } else {
865 /*
866 * Group-specific IGMPv2 query, we need only
867 * look up the single group to process it.
868 */
869 inm = inm_lookup(ifp, igmp->igmp_group);
870 if (inm != NULL) {
871 CTR3(KTR_IGMPV3, "process v2 query %s on ifp %p(%s)",

--- 831 unchanged lines hidden (view full) ---

1703
1704 memset(&qrq, 0, sizeof(struct ifqueue));
1705 IFQ_SET_MAXLEN(&qrq, IGMP_MAX_G_GS_PACKETS);
1706
1707 memset(&scq, 0, sizeof(struct ifqueue));
1708 IFQ_SET_MAXLEN(&scq, IGMP_MAX_STATE_CHANGE_PACKETS);
1709 }
1710
864 } else {
865 /*
866 * Group-specific IGMPv2 query, we need only
867 * look up the single group to process it.
868 */
869 inm = inm_lookup(ifp, igmp->igmp_group);
870 if (inm != NULL) {
871 CTR3(KTR_IGMPV3, "process v2 query %s on ifp %p(%s)",

--- 831 unchanged lines hidden (view full) ---

1703
1704 memset(&qrq, 0, sizeof(struct ifqueue));
1705 IFQ_SET_MAXLEN(&qrq, IGMP_MAX_G_GS_PACKETS);
1706
1707 memset(&scq, 0, sizeof(struct ifqueue));
1708 IFQ_SET_MAXLEN(&scq, IGMP_MAX_STATE_CHANGE_PACKETS);
1709 }
1710
1711 IF_ADDR_LOCK(ifp);
1711 IF_ADDR_RLOCK(ifp);
1712 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1713 if (ifma->ifma_addr->sa_family != AF_INET ||
1714 ifma->ifma_protospec == NULL)
1715 continue;
1716 inm = (struct in_multi *)ifma->ifma_protospec;
1717 switch (igi->igi_version) {
1718 case IGMP_VERSION_1:
1719 case IGMP_VERSION_2:
1720 igmp_v1v2_process_group_timer(inm,
1721 igi->igi_version);
1722 break;
1723 case IGMP_VERSION_3:
1724 igmp_v3_process_group_timers(igi, &qrq,
1725 &scq, inm, uri_fasthz);
1726 break;
1727 }
1728 }
1712 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1713 if (ifma->ifma_addr->sa_family != AF_INET ||
1714 ifma->ifma_protospec == NULL)
1715 continue;
1716 inm = (struct in_multi *)ifma->ifma_protospec;
1717 switch (igi->igi_version) {
1718 case IGMP_VERSION_1:
1719 case IGMP_VERSION_2:
1720 igmp_v1v2_process_group_timer(inm,
1721 igi->igi_version);
1722 break;
1723 case IGMP_VERSION_3:
1724 igmp_v3_process_group_timers(igi, &qrq,
1725 &scq, inm, uri_fasthz);
1726 break;
1727 }
1728 }
1729 IF_ADDR_UNLOCK(ifp);
1729 IF_ADDR_RUNLOCK(ifp);
1730
1731 if (igi->igi_version == IGMP_VERSION_3) {
1732 struct in_multi *tinm;
1733
1734 igmp_dispatch_queue(&qrq, 0, loop);
1735 igmp_dispatch_queue(&scq, 0, loop);
1736
1737 /*

--- 280 unchanged lines hidden (view full) ---

2018 */
2019 igi->igi_v3_timer = 0;
2020
2021 /*
2022 * Now clear the current-state and state-change report timers
2023 * for all memberships scoped to this link.
2024 */
2025 ifp = igi->igi_ifp;
1730
1731 if (igi->igi_version == IGMP_VERSION_3) {
1732 struct in_multi *tinm;
1733
1734 igmp_dispatch_queue(&qrq, 0, loop);
1735 igmp_dispatch_queue(&scq, 0, loop);
1736
1737 /*

--- 280 unchanged lines hidden (view full) ---

2018 */
2019 igi->igi_v3_timer = 0;
2020
2021 /*
2022 * Now clear the current-state and state-change report timers
2023 * for all memberships scoped to this link.
2024 */
2025 ifp = igi->igi_ifp;
2026 IF_ADDR_LOCK(ifp);
2026 IF_ADDR_RLOCK(ifp);
2027 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
2028 if (ifma->ifma_addr->sa_family != AF_INET ||
2029 ifma->ifma_protospec == NULL)
2030 continue;
2031 inm = (struct in_multi *)ifma->ifma_protospec;
2032 switch (inm->inm_state) {
2033 case IGMP_NOT_MEMBER:
2034 case IGMP_SILENT_MEMBER:

--- 28 unchanged lines hidden (view full) ---

2063 /*
2064 * Always clear state-change and group report timers.
2065 * Free any pending IGMPv3 state-change records.
2066 */
2067 inm->inm_sctimer = 0;
2068 inm->inm_timer = 0;
2069 _IF_DRAIN(&inm->inm_scq);
2070 }
2027 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
2028 if (ifma->ifma_addr->sa_family != AF_INET ||
2029 ifma->ifma_protospec == NULL)
2030 continue;
2031 inm = (struct in_multi *)ifma->ifma_protospec;
2032 switch (inm->inm_state) {
2033 case IGMP_NOT_MEMBER:
2034 case IGMP_SILENT_MEMBER:

--- 28 unchanged lines hidden (view full) ---

2063 /*
2064 * Always clear state-change and group report timers.
2065 * Free any pending IGMPv3 state-change records.
2066 */
2067 inm->inm_sctimer = 0;
2068 inm->inm_timer = 0;
2069 _IF_DRAIN(&inm->inm_scq);
2070 }
2071 IF_ADDR_UNLOCK(ifp);
2071 IF_ADDR_RUNLOCK(ifp);
2072 SLIST_FOREACH_SAFE(inm, &igi->igi_relinmhead, inm_nrele, tinm) {
2073 SLIST_REMOVE_HEAD(&igi->igi_relinmhead, inm_nrele);
2074 inm_release_locked(inm);
2075 }
2076}
2077
2078/*
2079 * Update the Older Version Querier Present timers for a link.

--- 1246 unchanged lines hidden (view full) ---

3326 IN_MULTI_LOCK_ASSERT();
3327 IGMP_LOCK_ASSERT();
3328
3329 KASSERT(igi->igi_version == IGMP_VERSION_3,
3330 ("%s: called when version %d", __func__, igi->igi_version));
3331
3332 ifp = igi->igi_ifp;
3333
2072 SLIST_FOREACH_SAFE(inm, &igi->igi_relinmhead, inm_nrele, tinm) {
2073 SLIST_REMOVE_HEAD(&igi->igi_relinmhead, inm_nrele);
2074 inm_release_locked(inm);
2075 }
2076}
2077
2078/*
2079 * Update the Older Version Querier Present timers for a link.

--- 1246 unchanged lines hidden (view full) ---

3326 IN_MULTI_LOCK_ASSERT();
3327 IGMP_LOCK_ASSERT();
3328
3329 KASSERT(igi->igi_version == IGMP_VERSION_3,
3330 ("%s: called when version %d", __func__, igi->igi_version));
3331
3332 ifp = igi->igi_ifp;
3333
3334 IF_ADDR_LOCK(ifp);
3334 IF_ADDR_RLOCK(ifp);
3335 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
3336 if (ifma->ifma_addr->sa_family != AF_INET ||
3337 ifma->ifma_protospec == NULL)
3338 continue;
3339
3340 inm = (struct in_multi *)ifma->ifma_protospec;
3341 KASSERT(ifp == inm->inm_ifp,
3342 ("%s: inconsistent ifp", __func__));

--- 14 unchanged lines hidden (view full) ---

3357 __func__, retval);
3358 break;
3359 case IGMP_G_QUERY_PENDING_MEMBER:
3360 case IGMP_SG_QUERY_PENDING_MEMBER:
3361 case IGMP_LEAVING_MEMBER:
3362 break;
3363 }
3364 }
3335 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
3336 if (ifma->ifma_addr->sa_family != AF_INET ||
3337 ifma->ifma_protospec == NULL)
3338 continue;
3339
3340 inm = (struct in_multi *)ifma->ifma_protospec;
3341 KASSERT(ifp == inm->inm_ifp,
3342 ("%s: inconsistent ifp", __func__));

--- 14 unchanged lines hidden (view full) ---

3357 __func__, retval);
3358 break;
3359 case IGMP_G_QUERY_PENDING_MEMBER:
3360 case IGMP_SG_QUERY_PENDING_MEMBER:
3361 case IGMP_LEAVING_MEMBER:
3362 break;
3363 }
3364 }
3365 IF_ADDR_UNLOCK(ifp);
3365 IF_ADDR_RUNLOCK(ifp);
3366
3367 loop = (igi->igi_flags & IGIF_LOOPBACK) ? 1 : 0;
3368 igmp_dispatch_queue(&igi->igi_gq, IGMP_MAX_RESPONSE_BURST, loop);
3369
3370 /*
3371 * Slew transmission of bursts over 500ms intervals.
3372 */
3373 if (igi->igi_gq.ifq_head != NULL) {

--- 278 unchanged lines hidden ---
3366
3367 loop = (igi->igi_flags & IGIF_LOOPBACK) ? 1 : 0;
3368 igmp_dispatch_queue(&igi->igi_gq, IGMP_MAX_RESPONSE_BURST, loop);
3369
3370 /*
3371 * Slew transmission of bursts over 500ms intervals.
3372 */
3373 if (igi->igi_gq.ifq_head != NULL) {

--- 278 unchanged lines hidden ---