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 --- |