mld6.c (19b0c9b24697aeef40bbbc1ca767c54dbdad9950) mld6.c (137f91e80f3802084bd96586d09961a846b91665)
1/*-
2 * Copyright (c) 2009 Bruce Simpson.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.

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

538 CTR3(KTR_MLD, "%s: called for ifp %p(%s)", __func__, ifp,
539 ifp->if_xname);
540
541 IN6_MULTI_LOCK_ASSERT();
542 MLD_LOCK();
543
544 mli = MLD_IFINFO(ifp);
545 if (mli->mli_version == MLD_VERSION_2) {
1/*-
2 * Copyright (c) 2009 Bruce Simpson.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.

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

538 CTR3(KTR_MLD, "%s: called for ifp %p(%s)", __func__, ifp,
539 ifp->if_xname);
540
541 IN6_MULTI_LOCK_ASSERT();
542 MLD_LOCK();
543
544 mli = MLD_IFINFO(ifp);
545 if (mli->mli_version == MLD_VERSION_2) {
546 IF_ADDR_LOCK(ifp);
546 IF_ADDR_RLOCK(ifp);
547 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
548 if (ifma->ifma_addr->sa_family != AF_INET6 ||
549 ifma->ifma_protospec == NULL)
550 continue;
551 inm = (struct in6_multi *)ifma->ifma_protospec;
552 if (inm->in6m_state == MLD_LEAVING_MEMBER) {
553 SLIST_INSERT_HEAD(&mli->mli_relinmhead,
554 inm, in6m_nrele);
555 }
556 in6m_clear_recorded(inm);
557 }
547 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
548 if (ifma->ifma_addr->sa_family != AF_INET6 ||
549 ifma->ifma_protospec == NULL)
550 continue;
551 inm = (struct in6_multi *)ifma->ifma_protospec;
552 if (inm->in6m_state == MLD_LEAVING_MEMBER) {
553 SLIST_INSERT_HEAD(&mli->mli_relinmhead,
554 inm, in6m_nrele);
555 }
556 in6m_clear_recorded(inm);
557 }
558 IF_ADDR_UNLOCK(ifp);
558 IF_ADDR_RUNLOCK(ifp);
559 SLIST_FOREACH_SAFE(inm, &mli->mli_relinmhead, in6m_nrele,
560 tinm) {
561 SLIST_REMOVE_HEAD(&mli->mli_relinmhead, in6m_nrele);
562 in6m_release_locked(inm);
563 }
564 }
565
566 MLD_UNLOCK();

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

689 mli = MLD_IFINFO(ifp);
690 KASSERT(mli != NULL, ("%s: no mld_ifinfo for ifp %p", __func__, ifp));
691 mld_set_version(mli, MLD_VERSION_1);
692
693 timer = (ntohs(mld->mld_maxdelay) * PR_FASTHZ) / MLD_TIMER_SCALE;
694 if (timer == 0)
695 timer = 1;
696
559 SLIST_FOREACH_SAFE(inm, &mli->mli_relinmhead, in6m_nrele,
560 tinm) {
561 SLIST_REMOVE_HEAD(&mli->mli_relinmhead, in6m_nrele);
562 in6m_release_locked(inm);
563 }
564 }
565
566 MLD_UNLOCK();

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

689 mli = MLD_IFINFO(ifp);
690 KASSERT(mli != NULL, ("%s: no mld_ifinfo for ifp %p", __func__, ifp));
691 mld_set_version(mli, MLD_VERSION_1);
692
693 timer = (ntohs(mld->mld_maxdelay) * PR_FASTHZ) / MLD_TIMER_SCALE;
694 if (timer == 0)
695 timer = 1;
696
697 IF_ADDR_LOCK(ifp);
697 IF_ADDR_RLOCK(ifp);
698 if (is_general_query) {
699 /*
700 * For each reporting group joined on this
701 * interface, kick the report timer.
702 */
703 CTR2(KTR_MLD, "process v1 general query on ifp %p(%s)",
704 ifp, ifp->if_xname);
705 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {

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

721 ip6_sprintf(ip6tbuf, &mld->mld_addr),
722 ifp, ifp->if_xname);
723 mld_v1_update_group(inm, timer);
724 }
725 /* XXX Clear embedded scope ID as userland won't expect it. */
726 in6_clearscope(&mld->mld_addr);
727 }
728
698 if (is_general_query) {
699 /*
700 * For each reporting group joined on this
701 * interface, kick the report timer.
702 */
703 CTR2(KTR_MLD, "process v1 general query on ifp %p(%s)",
704 ifp, ifp->if_xname);
705 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {

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

721 ip6_sprintf(ip6tbuf, &mld->mld_addr),
722 ifp, ifp->if_xname);
723 mld_v1_update_group(inm, timer);
724 }
725 /* XXX Clear embedded scope ID as userland won't expect it. */
726 in6_clearscope(&mld->mld_addr);
727 }
728
729 IF_ADDR_UNLOCK(ifp);
729 IF_ADDR_RUNLOCK(ifp);
730 MLD_UNLOCK();
731 IN6_MULTI_UNLOCK();
732
733 return (0);
734}
735
736/*
737 * Update the report timer on a group in response to an MLDv1 query.

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

932 /*
933 * MLDv2 Group-specific or Group-and-source-specific Query.
934 *
935 * Group-source-specific queries are throttled on
936 * a per-group basis to defeat denial-of-service attempts.
937 * Queries for groups we are not a member of on this
938 * link are simply ignored.
939 */
730 MLD_UNLOCK();
731 IN6_MULTI_UNLOCK();
732
733 return (0);
734}
735
736/*
737 * Update the report timer on a group in response to an MLDv1 query.

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

932 /*
933 * MLDv2 Group-specific or Group-and-source-specific Query.
934 *
935 * Group-source-specific queries are throttled on
936 * a per-group basis to defeat denial-of-service attempts.
937 * Queries for groups we are not a member of on this
938 * link are simply ignored.
939 */
940 IF_ADDR_LOCK(ifp);
940 IF_ADDR_RLOCK(ifp);
941 inm = in6m_lookup_locked(ifp, &mld->mld_addr);
942 if (inm == NULL) {
941 inm = in6m_lookup_locked(ifp, &mld->mld_addr);
942 if (inm == NULL) {
943 IF_ADDR_UNLOCK(ifp);
943 IF_ADDR_RUNLOCK(ifp);
944 goto out_locked;
945 }
946 if (nsrc > 0) {
947 if (!ratecheck(&inm->in6m_lastgsrtv,
948 &V_mld_gsrdelay)) {
949 CTR1(KTR_MLD, "%s: GS query throttled.",
950 __func__);
944 goto out_locked;
945 }
946 if (nsrc > 0) {
947 if (!ratecheck(&inm->in6m_lastgsrtv,
948 &V_mld_gsrdelay)) {
949 CTR1(KTR_MLD, "%s: GS query throttled.",
950 __func__);
951 IF_ADDR_UNLOCK(ifp);
951 IF_ADDR_RUNLOCK(ifp);
952 goto out_locked;
953 }
954 }
955 CTR2(KTR_MLD, "process v2 group query on ifp %p(%s)",
956 ifp, ifp->if_xname);
957 /*
958 * If there is a pending General Query response
959 * scheduled sooner than the selected delay, no
960 * further report need be scheduled.
961 * Otherwise, prepare to respond to the
962 * group-specific or group-and-source query.
963 */
964 if (mli->mli_v2_timer == 0 || mli->mli_v2_timer >= timer)
965 mld_v2_process_group_query(inm, mli, timer, m, off);
966
967 /* XXX Clear embedded scope ID as userland won't expect it. */
968 in6_clearscope(&mld->mld_addr);
952 goto out_locked;
953 }
954 }
955 CTR2(KTR_MLD, "process v2 group query on ifp %p(%s)",
956 ifp, ifp->if_xname);
957 /*
958 * If there is a pending General Query response
959 * scheduled sooner than the selected delay, no
960 * further report need be scheduled.
961 * Otherwise, prepare to respond to the
962 * group-specific or group-and-source query.
963 */
964 if (mli->mli_v2_timer == 0 || mli->mli_v2_timer >= timer)
965 mld_v2_process_group_query(inm, mli, timer, m, off);
966
967 /* XXX Clear embedded scope ID as userland won't expect it. */
968 in6_clearscope(&mld->mld_addr);
969 IF_ADDR_UNLOCK(ifp);
969 IF_ADDR_RUNLOCK(ifp);
970 }
971
972out_locked:
973 MLD_UNLOCK();
974 IN6_MULTI_UNLOCK();
975
976 return (0);
977}

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

1171 * Embed scope ID of receiving interface in MLD query for lookup
1172 * whilst we don't hold other locks (due to KAME locking lameness).
1173 */
1174 if (!IN6_IS_ADDR_UNSPECIFIED(&mld->mld_addr))
1175 in6_setscope(&mld->mld_addr, ifp, NULL);
1176
1177 IN6_MULTI_LOCK();
1178 MLD_LOCK();
970 }
971
972out_locked:
973 MLD_UNLOCK();
974 IN6_MULTI_UNLOCK();
975
976 return (0);
977}

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

1171 * Embed scope ID of receiving interface in MLD query for lookup
1172 * whilst we don't hold other locks (due to KAME locking lameness).
1173 */
1174 if (!IN6_IS_ADDR_UNSPECIFIED(&mld->mld_addr))
1175 in6_setscope(&mld->mld_addr, ifp, NULL);
1176
1177 IN6_MULTI_LOCK();
1178 MLD_LOCK();
1179 IF_ADDR_LOCK(ifp);
1179 IF_ADDR_RLOCK(ifp);
1180
1181 /*
1182 * MLDv1 report suppression.
1183 * If we are a member of this group, and our membership should be
1184 * reported, and our group timer is pending or about to be reset,
1185 * stop our group timer by transitioning to the 'lazy' state.
1186 */
1187 inm = in6m_lookup_locked(ifp, &mld->mld_addr);

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

1219 case MLD_G_QUERY_PENDING_MEMBER:
1220 case MLD_SG_QUERY_PENDING_MEMBER:
1221 case MLD_LEAVING_MEMBER:
1222 break;
1223 }
1224 }
1225
1226out_locked:
1180
1181 /*
1182 * MLDv1 report suppression.
1183 * If we are a member of this group, and our membership should be
1184 * reported, and our group timer is pending or about to be reset,
1185 * stop our group timer by transitioning to the 'lazy' state.
1186 */
1187 inm = in6m_lookup_locked(ifp, &mld->mld_addr);

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

1219 case MLD_G_QUERY_PENDING_MEMBER:
1220 case MLD_SG_QUERY_PENDING_MEMBER:
1221 case MLD_LEAVING_MEMBER:
1222 break;
1223 }
1224 }
1225
1226out_locked:
1227 IF_ADDR_RUNLOCK(ifp);
1227 MLD_UNLOCK();
1228 MLD_UNLOCK();
1228 IF_ADDR_UNLOCK(ifp);
1229 IN6_MULTI_UNLOCK();
1230
1231 /* XXX Clear embedded scope ID as userland won't expect it. */
1232 in6_clearscope(&mld->mld_addr);
1233
1234 return (0);
1235}
1236

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

1396
1397 memset(&qrq, 0, sizeof(struct ifqueue));
1398 IFQ_SET_MAXLEN(&qrq, MLD_MAX_G_GS_PACKETS);
1399
1400 memset(&scq, 0, sizeof(struct ifqueue));
1401 IFQ_SET_MAXLEN(&scq, MLD_MAX_STATE_CHANGE_PACKETS);
1402 }
1403
1229 IN6_MULTI_UNLOCK();
1230
1231 /* XXX Clear embedded scope ID as userland won't expect it. */
1232 in6_clearscope(&mld->mld_addr);
1233
1234 return (0);
1235}
1236

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

1396
1397 memset(&qrq, 0, sizeof(struct ifqueue));
1398 IFQ_SET_MAXLEN(&qrq, MLD_MAX_G_GS_PACKETS);
1399
1400 memset(&scq, 0, sizeof(struct ifqueue));
1401 IFQ_SET_MAXLEN(&scq, MLD_MAX_STATE_CHANGE_PACKETS);
1402 }
1403
1404 IF_ADDR_LOCK(ifp);
1404 IF_ADDR_RLOCK(ifp);
1405 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1406 if (ifma->ifma_addr->sa_family != AF_INET6 ||
1407 ifma->ifma_protospec == NULL)
1408 continue;
1409 inm = (struct in6_multi *)ifma->ifma_protospec;
1410 switch (mli->mli_version) {
1411 case MLD_VERSION_1:
1412 mld_v1_process_group_timer(mli, inm);
1413 break;
1414 case MLD_VERSION_2:
1415 mld_v2_process_group_timers(mli, &qrq,
1416 &scq, inm, uri_fasthz);
1417 break;
1418 }
1419 }
1405 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1406 if (ifma->ifma_addr->sa_family != AF_INET6 ||
1407 ifma->ifma_protospec == NULL)
1408 continue;
1409 inm = (struct in6_multi *)ifma->ifma_protospec;
1410 switch (mli->mli_version) {
1411 case MLD_VERSION_1:
1412 mld_v1_process_group_timer(mli, inm);
1413 break;
1414 case MLD_VERSION_2:
1415 mld_v2_process_group_timers(mli, &qrq,
1416 &scq, inm, uri_fasthz);
1417 break;
1418 }
1419 }
1420 IF_ADDR_UNLOCK(ifp);
1420 IF_ADDR_RUNLOCK(ifp);
1421
1422 switch (mli->mli_version) {
1423 case MLD_VERSION_1:
1424 /*
1425 * Transmit reports for this lifecycle. This
1426 * is done while not holding IF_ADDR_LOCK
1427 * since this can call
1428 * in6ifa_ifpforlinklocal() which locks

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

1680 !V_state_change_timers_running6 &&
1681 !V_current_state_timers_running6)
1682 return;
1683
1684 mli->mli_v2_timer = 0;
1685
1686 ifp = mli->mli_ifp;
1687
1421
1422 switch (mli->mli_version) {
1423 case MLD_VERSION_1:
1424 /*
1425 * Transmit reports for this lifecycle. This
1426 * is done while not holding IF_ADDR_LOCK
1427 * since this can call
1428 * in6ifa_ifpforlinklocal() which locks

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

1680 !V_state_change_timers_running6 &&
1681 !V_current_state_timers_running6)
1682 return;
1683
1684 mli->mli_v2_timer = 0;
1685
1686 ifp = mli->mli_ifp;
1687
1688 IF_ADDR_LOCK(ifp);
1688 IF_ADDR_RLOCK(ifp);
1689 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1690 if (ifma->ifma_addr->sa_family != AF_INET6)
1691 continue;
1692 inm = (struct in6_multi *)ifma->ifma_protospec;
1693 switch (inm->in6m_state) {
1694 case MLD_NOT_MEMBER:
1695 case MLD_SILENT_MEMBER:
1696 case MLD_IDLE_MEMBER:

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

1717 inm->in6m_state = MLD_REPORTING_MEMBER;
1718 /*
1719 * Free any pending MLDv2 state-change records.
1720 */
1721 _IF_DRAIN(&inm->in6m_scq);
1722 break;
1723 }
1724 }
1689 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1690 if (ifma->ifma_addr->sa_family != AF_INET6)
1691 continue;
1692 inm = (struct in6_multi *)ifma->ifma_protospec;
1693 switch (inm->in6m_state) {
1694 case MLD_NOT_MEMBER:
1695 case MLD_SILENT_MEMBER:
1696 case MLD_IDLE_MEMBER:

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

1717 inm->in6m_state = MLD_REPORTING_MEMBER;
1718 /*
1719 * Free any pending MLDv2 state-change records.
1720 */
1721 _IF_DRAIN(&inm->in6m_scq);
1722 break;
1723 }
1724 }
1725 IF_ADDR_UNLOCK(ifp);
1725 IF_ADDR_RUNLOCK(ifp);
1726 SLIST_FOREACH_SAFE(inm, &mli->mli_relinmhead, in6m_nrele, tinm) {
1727 SLIST_REMOVE_HEAD(&mli->mli_relinmhead, in6m_nrele);
1728 in6m_release_locked(inm);
1729 }
1730}
1731
1732/*
1733 * Global slowtimo handler.

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

2991 IN6_MULTI_LOCK_ASSERT();
2992 MLD_LOCK_ASSERT();
2993
2994 KASSERT(mli->mli_version == MLD_VERSION_2,
2995 ("%s: called when version %d", __func__, mli->mli_version));
2996
2997 ifp = mli->mli_ifp;
2998
1726 SLIST_FOREACH_SAFE(inm, &mli->mli_relinmhead, in6m_nrele, tinm) {
1727 SLIST_REMOVE_HEAD(&mli->mli_relinmhead, in6m_nrele);
1728 in6m_release_locked(inm);
1729 }
1730}
1731
1732/*
1733 * Global slowtimo handler.

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

2991 IN6_MULTI_LOCK_ASSERT();
2992 MLD_LOCK_ASSERT();
2993
2994 KASSERT(mli->mli_version == MLD_VERSION_2,
2995 ("%s: called when version %d", __func__, mli->mli_version));
2996
2997 ifp = mli->mli_ifp;
2998
2999 IF_ADDR_LOCK(ifp);
2999 IF_ADDR_RLOCK(ifp);
3000 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
3001 if (ifma->ifma_addr->sa_family != AF_INET6 ||
3002 ifma->ifma_protospec == NULL)
3003 continue;
3004
3005 inm = (struct in6_multi *)ifma->ifma_protospec;
3006 KASSERT(ifp == inm->in6m_ifp,
3007 ("%s: inconsistent ifp", __func__));

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

3022 __func__, retval);
3023 break;
3024 case MLD_G_QUERY_PENDING_MEMBER:
3025 case MLD_SG_QUERY_PENDING_MEMBER:
3026 case MLD_LEAVING_MEMBER:
3027 break;
3028 }
3029 }
3000 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
3001 if (ifma->ifma_addr->sa_family != AF_INET6 ||
3002 ifma->ifma_protospec == NULL)
3003 continue;
3004
3005 inm = (struct in6_multi *)ifma->ifma_protospec;
3006 KASSERT(ifp == inm->in6m_ifp,
3007 ("%s: inconsistent ifp", __func__));

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

3022 __func__, retval);
3023 break;
3024 case MLD_G_QUERY_PENDING_MEMBER:
3025 case MLD_SG_QUERY_PENDING_MEMBER:
3026 case MLD_LEAVING_MEMBER:
3027 break;
3028 }
3029 }
3030 IF_ADDR_UNLOCK(ifp);
3030 IF_ADDR_RUNLOCK(ifp);
3031
3032 mld_dispatch_queue(&mli->mli_gq, MLD_MAX_RESPONSE_BURST);
3033
3034 /*
3035 * Slew transmission of bursts over 500ms intervals.
3036 */
3037 if (mli->mli_gq.ifq_head != NULL) {
3038 mli->mli_v2_timer = 1 + MLD_RANDOM_DELAY(

--- 281 unchanged lines hidden ---
3031
3032 mld_dispatch_queue(&mli->mli_gq, MLD_MAX_RESPONSE_BURST);
3033
3034 /*
3035 * Slew transmission of bursts over 500ms intervals.
3036 */
3037 if (mli->mli_gq.ifq_head != NULL) {
3038 mli->mli_v2_timer = 1 + MLD_RANDOM_DELAY(

--- 281 unchanged lines hidden ---