Lines Matching +full:atomic +full:- +full:threshold +full:- +full:us
1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 2007-2009 Bruce Simpson.
157 * System-wide globals.
160 * queue. The IGMP subsystem lock ends up being system-wide for the moment,
173 * per-link state iterators.
187 * to a vnet in ifp->if_vnet.
201 * VIMAGE-wide globals.
203 * The IGMPv3 timers themselves need to run per-image, however, for
211 * IGMP for IPv4 does not force link-local addresses to be used for each
213 * Obviously the IGMPv3 per-interface state has per-vimage granularity
221 VNET_DEFINE_STATIC(int, state_change_timers_running); /* IGMPv3 state-change
290 "Rate limit for IGMPv3 Group-and-Source queries in seconds");
293 * Non-virtualized sysctls.
297 "Per-interface IGMPv3 state");
304 m->m_pkthdr.PH_loc.ptr = ifp->if_vnet; in igmp_save_context()
306 m->m_pkthdr.rcvif = ifp; in igmp_save_context()
307 m->m_pkthdr.flowid = ifp->if_index; in igmp_save_context()
314 m->m_pkthdr.PH_loc.ptr = NULL; in igmp_scrub_context()
315 m->m_pkthdr.flowid = 0; in igmp_scrub_context()
331 KASSERT(curvnet == (m->m_pkthdr.PH_loc.ptr), in igmp_restore_context()
335 return (m->m_pkthdr.flowid); in igmp_restore_context()
352 if (req->oldptr != NULL) { in sysctl_igmp_stat()
353 if (req->oldlen < sizeof(struct igmpstat)) in sysctl_igmp_stat()
368 req->validlen = sizeof(struct igmpstat); in sysctl_igmp_stat()
371 if (req->newptr != NULL) { in sysctl_igmp_stat()
372 if (req->newlen < sizeof(struct igmpstat)) in sysctl_igmp_stat()
417 if (error || !req->newptr) in sysctl_igmp_default_version()
434 if (igi->igi_version > V_igmp_default_version){ in sysctl_igmp_default_version()
447 * Retrieve or set threshold between group-source queries in seconds.
467 if (error || !req->newptr) in sysctl_igmp_gsr()
470 if (i < -1 || i >= 60) { in sysctl_igmp_gsr()
505 if (req->newptr != NULL) in sysctl_igmp_ifinfo()
527 if (ifp == igi->igi_ifp) { in sysctl_igmp_ifinfo()
530 info.igi_version = igi->igi_version; in sysctl_igmp_ifinfo()
531 info.igi_v1_timer = igi->igi_v1_timer; in sysctl_igmp_ifinfo()
532 info.igi_v2_timer = igi->igi_v2_timer; in sysctl_igmp_ifinfo()
533 info.igi_v3_timer = igi->igi_v3_timer; in sysctl_igmp_ifinfo()
534 info.igi_flags = igi->igi_flags; in sysctl_igmp_ifinfo()
535 info.igi_rv = igi->igi_rv; in sysctl_igmp_ifinfo()
536 info.igi_qi = igi->igi_qi; in sysctl_igmp_ifinfo()
537 info.igi_qri = igi->igi_qri; in sysctl_igmp_ifinfo()
538 info.igi_uri = igi->igi_uri; in sysctl_igmp_ifinfo()
565 m->m_flags |= M_IGMP_LOOP; in igmp_dispatch_queue()
567 if (--limit == 0) in igmp_dispatch_queue()
576 * Reports are ALWAYS suppressed for ALL-HOSTS (224.0.0.1).
578 * disabled for all groups in the 224.0.0.0/24 link-local scope. However,
583 * should be suppressed, or non-zero if reports should be issued.
607 p->ipopt_dst.s_addr = INADDR_ANY; in igmp_ra_alloc()
608 p->ipopt_list[0] = (char)IPOPT_RA; /* Router Alert Option */ in igmp_ra_alloc()
609 p->ipopt_list[1] = 0x04; /* 4 bytes long */ in igmp_ra_alloc()
610 p->ipopt_list[2] = IPOPT_EOL; /* End of IP option list */ in igmp_ra_alloc()
611 p->ipopt_list[3] = 0x00; /* pad byte */ in igmp_ra_alloc()
612 m->m_len = sizeof(p->ipopt_dst) + p->ipopt_list[1]; in igmp_ra_alloc()
626 __func__, ifp, ifp->if_xname); in igmp_domifattach()
631 if (!(ifp->if_flags & IFF_MULTICAST)) in igmp_domifattach()
632 igi->igi_flags |= IGIF_SILENT; in igmp_domifattach()
653 igi->igi_ifp = ifp; in igi_alloc_locked()
654 igi->igi_version = V_igmp_default_version; in igi_alloc_locked()
655 igi->igi_flags = 0; in igi_alloc_locked()
656 igi->igi_rv = IGMP_RV_INIT; in igi_alloc_locked()
657 igi->igi_qi = IGMP_QI_INIT; in igi_alloc_locked()
658 igi->igi_qri = IGMP_QRI_INIT; in igi_alloc_locked()
659 igi->igi_uri = IGMP_URI_INIT; in igi_alloc_locked()
660 mbufq_init(&igi->igi_gq, IGMP_MAX_RESPONSE_PACKETS); in igi_alloc_locked()
665 ifp, ifp->if_xname); in igi_alloc_locked()
689 ifp->if_xname); in igmp_ifdetach()
694 igi = ((struct in_ifinfo *)ifp->if_afdata[AF_INET])->ii_igmp; in igmp_ifdetach()
695 if (igi->igi_version == IGMP_VERSION_3) { in igmp_ifdetach()
698 CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { in igmp_ifdetach()
702 if (inm->inm_state == IGMP_LEAVING_MEMBER) in igmp_ifdetach()
722 __func__, ifp, ifp->if_xname); in igmp_domifdetach()
735 __func__, ifp, ifp->if_xname); in igi_delete_locked()
740 if (igi->igi_ifp == ifp) { in igi_delete_locked()
744 mbufq_drain(&igi->igi_gq); in igi_delete_locked()
755 * Return non-zero if the message should be dropped.
774 * XXX SMPng: unlocked increments in igmpstat assumed atomic. in igmp_input_v1_query()
776 if (!in_allhosts(ip->ip_dst) || !in_nullhost(igmp->igmp_group)) { in igmp_input_v1_query()
785 igi = ((struct in_ifinfo *)ifp->if_afdata[AF_INET])->ii_igmp; in igmp_input_v1_query()
788 if (igi->igi_flags & IGIF_LOOPBACK) { in igmp_input_v1_query()
790 ifp, ifp->if_xname); in igmp_input_v1_query()
799 CTR2(KTR_IGMPV3, "process v1 query on ifp %p(%s)", ifp, ifp->if_xname); in igmp_input_v1_query()
806 CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { in igmp_input_v1_query()
810 if (inm->inm_timer != 0) in igmp_input_v1_query()
812 switch (inm->inm_state) { in igmp_input_v1_query()
823 inm->inm_state = IGMP_REPORTING_MEMBER; in igmp_input_v1_query()
824 inm->inm_timer = IGMP_RANDOM_DELAY( in igmp_input_v1_query()
841 * Process a received IGMPv2 general or group-specific query.
859 * XXX SMPng: unlocked increments in igmpstat assumed atomic. in igmp_input_v2_query()
861 if (in_nullhost(igmp->igmp_group)) { in igmp_input_v2_query()
864 * If this was not sent to the all-hosts group, ignore it. in igmp_input_v2_query()
866 if (!in_allhosts(ip->ip_dst)) in igmp_input_v2_query()
871 /* IGMPv2 Group-Specific Query. */ in igmp_input_v2_query()
878 igi = ((struct in_ifinfo *)ifp->if_afdata[AF_INET])->ii_igmp; in igmp_input_v2_query()
881 if (igi->igi_flags & IGIF_LOOPBACK) { in igmp_input_v2_query()
883 ifp, ifp->if_xname); in igmp_input_v2_query()
890 if (igi->igi_version == IGMP_VERSION_1) in igmp_input_v2_query()
895 timer = igmp->igmp_code * IGMP_FASTHZ / IGMP_TIMER_SCALE; in igmp_input_v2_query()
905 ifp, ifp->if_xname); in igmp_input_v2_query()
906 CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { in igmp_input_v2_query()
914 * Group-specific IGMPv2 query, we need only in igmp_input_v2_query()
917 inm = inm_lookup(ifp, igmp->igmp_group); in igmp_input_v2_query()
921 ntohl(igmp->igmp_group.s_addr), ifp, ifp->if_xname); in igmp_input_v2_query()
938 * below the threshold, reset it.
943 * for group and group-source query responses.
953 ntohl(inm->inm_addr.s_addr), inm->inm_ifp->if_xname, timer); in igmp_v2_update_group()
957 switch (inm->inm_state) { in igmp_v2_update_group()
962 if (inm->inm_timer != 0 && in igmp_v2_update_group()
963 inm->inm_timer <= timer) { in igmp_v2_update_group()
974 CTR1(KTR_IGMPV3, "%s: ->REPORTING", __func__); in igmp_v2_update_group()
975 inm->inm_state = IGMP_REPORTING_MEMBER; in igmp_v2_update_group()
976 inm->inm_timer = IGMP_RANDOM_DELAY(timer); in igmp_v2_update_group()
980 CTR1(KTR_IGMPV3, "%s: ->AWAKENING", __func__); in igmp_v2_update_group()
981 inm->inm_state = IGMP_AWAKENING_MEMBER; in igmp_v2_update_group()
989 * Process a received IGMPv3 general, group-specific or
990 * group-and-source-specific query.
1007 CTR2(KTR_IGMPV3, "process v3 query on ifp %p(%s)", ifp, ifp->if_xname); in igmp_input_v3_query()
1009 maxresp = igmpv3->igmp_code; /* in 1/10ths of a second */ in igmp_input_v3_query()
1011 maxresp = IGMP_MANT(igmpv3->igmp_code) << in igmp_input_v3_query()
1012 (IGMP_EXP(igmpv3->igmp_code) + 3); in igmp_input_v3_query()
1016 * Robustness must never be less than 2 for on-wire IGMPv3. in igmp_input_v3_query()
1021 qrv = IGMP_QRV(igmpv3->igmp_misc); in igmp_input_v3_query()
1028 qqi = igmpv3->igmp_qqi; in igmp_input_v3_query()
1030 qqi = IGMP_MANT(igmpv3->igmp_qqi) << in igmp_input_v3_query()
1031 (IGMP_EXP(igmpv3->igmp_qqi) + 3); in igmp_input_v3_query()
1038 nsrc = ntohs(igmpv3->igmp_numsrc); in igmp_input_v3_query()
1045 if (in_nullhost(igmpv3->igmp_group)) { in igmp_input_v3_query()
1054 if (!in_allhosts(ip->ip_dst) || nsrc > 0) { in igmp_input_v3_query()
1060 /* Group or group-source specific query. */ in igmp_input_v3_query()
1070 igi = ((struct in_ifinfo *)ifp->if_afdata[AF_INET])->ii_igmp; in igmp_input_v3_query()
1073 if (igi->igi_flags & IGIF_LOOPBACK) { in igmp_input_v3_query()
1075 ifp, ifp->if_xname); in igmp_input_v3_query()
1085 if (igi->igi_version != IGMP_VERSION_3) { in igmp_input_v3_query()
1087 igi->igi_version, ifp, ifp->if_xname); in igmp_input_v3_query()
1092 igi->igi_rv = qrv; in igmp_input_v3_query()
1093 igi->igi_qi = qqi; in igmp_input_v3_query()
1094 igi->igi_qri = maxresp; in igmp_input_v3_query()
1101 * Schedule a current-state report on this ifp for in igmp_input_v3_query()
1109 ifp, ifp->if_xname); in igmp_input_v3_query()
1110 if (igi->igi_v3_timer == 0 || igi->igi_v3_timer >= timer) { in igmp_input_v3_query()
1111 igi->igi_v3_timer = IGMP_RANDOM_DELAY(timer); in igmp_input_v3_query()
1116 * Group-source-specific queries are throttled on in igmp_input_v3_query()
1117 * a per-group basis to defeat denial-of-service attempts. in igmp_input_v3_query()
1121 inm = inm_lookup(ifp, igmpv3->igmp_group); in igmp_input_v3_query()
1125 if (!ratecheck(&inm->inm_lastgsrtv, in igmp_input_v3_query()
1134 ntohl(igmpv3->igmp_group.s_addr), ifp, ifp->if_xname); in igmp_input_v3_query()
1140 * group-specific or group-and-source query. in igmp_input_v3_query()
1142 if (igi->igi_v3_timer == 0 || igi->igi_v3_timer >= timer) in igmp_input_v3_query()
1154 * Process a received IGMPv3 group-specific or group-and-source-specific
1170 switch (inm->inm_state) { in igmp_input_v3_group_query()
1186 nsrc = ntohs(igmpv3->igmp_numsrc); in igmp_input_v3_group_query()
1189 * Deal with group-specific queries upfront. in igmp_input_v3_group_query()
1191 * source-list state if it exists, and schedule a query response in igmp_input_v3_group_query()
1192 * for this group-specific query. in igmp_input_v3_group_query()
1195 if (inm->inm_state == IGMP_G_QUERY_PENDING_MEMBER || in igmp_input_v3_group_query()
1196 inm->inm_state == IGMP_SG_QUERY_PENDING_MEMBER) { in igmp_input_v3_group_query()
1198 timer = min(inm->inm_timer, timer); in igmp_input_v3_group_query()
1200 inm->inm_state = IGMP_G_QUERY_PENDING_MEMBER; in igmp_input_v3_group_query()
1201 inm->inm_timer = IGMP_RANDOM_DELAY(timer); in igmp_input_v3_group_query()
1207 * Deal with the case where a group-and-source-specific query has in igmp_input_v3_group_query()
1208 * been received but a group-specific query is already pending. in igmp_input_v3_group_query()
1210 if (inm->inm_state == IGMP_G_QUERY_PENDING_MEMBER) { in igmp_input_v3_group_query()
1211 timer = min(inm->inm_timer, timer); in igmp_input_v3_group_query()
1212 inm->inm_timer = IGMP_RANDOM_DELAY(timer); in igmp_input_v3_group_query()
1218 * Finally, deal with the case where a group-and-source-specific in igmp_input_v3_group_query()
1219 * query has been received, where a response to a previous g-s-r in igmp_input_v3_group_query()
1221 * In this case, we need to parse the source-list which the Querier in igmp_input_v3_group_query()
1222 * has provided us with and check if we have any source list filter in igmp_input_v3_group_query()
1225 * If we do, we must record them and schedule a current-state in igmp_input_v3_group_query()
1231 if (inm->inm_nsrc > 0) { in igmp_input_v3_group_query()
1238 retval = inm_record_source(inm, ap->s_addr); in igmp_input_v3_group_query()
1246 inm->inm_state = IGMP_SG_QUERY_PENDING_MEMBER; in igmp_input_v3_group_query()
1247 inm->inm_timer = IGMP_RANDOM_DELAY(timer); in igmp_input_v3_group_query()
1269 if (ifp->if_flags & IFF_LOOPBACK) in igmp_input_v1_report()
1272 if (!IN_MULTICAST(ntohl(igmp->igmp_group.s_addr)) || in igmp_input_v1_report()
1273 !in_hosteq(igmp->igmp_group, ip->ip_dst)) { in igmp_input_v1_report()
1285 if (V_igmp_recvifkludge && in_nullhost(ip->ip_src)) { in igmp_input_v1_report()
1288 ip->ip_src.s_addr = htonl(ia->ia_subnet); in igmp_input_v1_report()
1292 ntohl(igmp->igmp_group.s_addr), ifp, ifp->if_xname); in igmp_input_v1_report()
1300 inm = inm_lookup(ifp, igmp->igmp_group); in igmp_input_v1_report()
1304 igi = inm->inm_igi; in igmp_input_v1_report()
1318 if (igi->igi_version == IGMP_VERSION_3) { in igmp_input_v1_report()
1324 inm->inm_timer = 0; in igmp_input_v1_report()
1326 switch (inm->inm_state) { in igmp_input_v1_report()
1335 ntohl(igmp->igmp_group.s_addr), ifp, in igmp_input_v1_report()
1336 ifp->if_xname); in igmp_input_v1_report()
1338 inm->inm_state = IGMP_SLEEPING_MEMBER; in igmp_input_v1_report()
1343 ntohl(igmp->igmp_group.s_addr), ifp, in igmp_input_v1_report()
1344 ifp->if_xname); in igmp_input_v1_report()
1345 if (igi->igi_version == IGMP_VERSION_1) in igmp_input_v1_report()
1346 inm->inm_state = IGMP_LAZY_MEMBER; in igmp_input_v1_report()
1347 else if (igi->igi_version == IGMP_VERSION_2) in igmp_input_v1_report()
1348 inm->inm_state = IGMP_SLEEPING_MEMBER; in igmp_input_v1_report()
1381 if (ia != NULL && in_hosteq(ip->ip_src, IA_SIN(ia)->sin_addr)) { in igmp_input_v2_report()
1387 if (ifp->if_flags & IFF_LOOPBACK) { in igmp_input_v2_report()
1391 if (!IN_MULTICAST(ntohl(igmp->igmp_group.s_addr)) || in igmp_input_v2_report()
1392 !in_hosteq(igmp->igmp_group, ip->ip_dst)) { in igmp_input_v2_report()
1404 if (V_igmp_recvifkludge && in_nullhost(ip->ip_src)) { in igmp_input_v2_report()
1406 ip->ip_src.s_addr = htonl(ia->ia_subnet); in igmp_input_v2_report()
1410 ntohl(igmp->igmp_group.s_addr), ifp, ifp->if_xname); in igmp_input_v2_report()
1419 inm = inm_lookup(ifp, igmp->igmp_group); in igmp_input_v2_report()
1423 igi = inm->inm_igi; in igmp_input_v2_report()
1433 if (igi->igi_version == IGMP_VERSION_3) { in igmp_input_v2_report()
1439 inm->inm_timer = 0; in igmp_input_v2_report()
1441 switch (inm->inm_state) { in igmp_input_v2_report()
1451 ntohl(igmp->igmp_group.s_addr), ifp, ifp->if_xname); in igmp_input_v2_report()
1453 inm->inm_state = IGMP_LAZY_MEMBER; in igmp_input_v2_report()
1483 ifp = m->m_pkthdr.rcvif; in igmp_input()
1491 igmplen = ntohs(ip->ip_len) - iphlen; in igmp_input()
1511 if ((!M_WRITABLE(m) || m->m_len < minlen) && in igmp_input()
1521 m->m_data += iphlen; in igmp_input()
1522 m->m_len -= iphlen; in igmp_input()
1529 m->m_data -= iphlen; in igmp_input()
1530 m->m_len += iphlen; in igmp_input()
1533 * IGMP control traffic is link-scope, and must have a TTL of 1. in igmp_input()
1537 if (igmp->igmp_type != IGMP_DVMRP && ip->ip_ttl != 1) { in igmp_input()
1543 switch (igmp->igmp_type) { in igmp_input()
1546 if (igmp->igmp_code == 0) in igmp_input()
1589 nsrc = ntohs(igmpv3->igmp_numsrc); in igmp_input()
1591 UINT16_MAX - iphlen - IGMP_V3_QUERY_MINLEN) { in igmp_input()
1603 m->m_len < igmpv3len) && in igmp_input()
1685 * Fast timeout handler (per-vnet).
1692 struct mbufq scq; /* State-change packets */ in igmp_fasttimo_vnet()
1726 if (igi->igi_v3_timer == 0) { in igmp_fasttimo_vnet()
1728 } else if (--igi->igi_v3_timer == 0) { in igmp_fasttimo_vnet()
1746 * IGMPv1/v2/v3 host report and state-change timer processing. in igmp_fasttimo_vnet()
1750 ifp = igi->igi_ifp; in igmp_fasttimo_vnet()
1752 if (igi->igi_version == IGMP_VERSION_3) { in igmp_fasttimo_vnet()
1753 loop = (igi->igi_flags & IGIF_LOOPBACK) ? 1 : 0; in igmp_fasttimo_vnet()
1754 uri_fasthz = IGMP_RANDOM_DELAY(igi->igi_uri * in igmp_fasttimo_vnet()
1761 CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { in igmp_fasttimo_vnet()
1765 switch (igi->igi_version) { in igmp_fasttimo_vnet()
1769 igi->igi_version); in igmp_fasttimo_vnet()
1779 if (igi->igi_version == IGMP_VERSION_3) { in igmp_fasttimo_vnet()
1808 if (inm->inm_timer == 0) { in igmp_v1v2_process_group_timer()
1810 } else if (--inm->inm_timer == 0) { in igmp_v1v2_process_group_timer()
1817 switch (inm->inm_state) { in igmp_v1v2_process_group_timer()
1827 inm->inm_state = IGMP_IDLE_MEMBER; in igmp_v1v2_process_group_timer()
1863 * timer active. This is a no-op in this function; it is easier in igmp_v3_process_group_timers()
1864 * to deal with it here than to complicate the slow-timeout path. in igmp_v3_process_group_timers()
1866 if (inm->inm_timer == 0) { in igmp_v3_process_group_timers()
1868 } else if (--inm->inm_timer == 0) { in igmp_v3_process_group_timers()
1874 if (inm->inm_sctimer == 0) { in igmp_v3_process_group_timers()
1876 } else if (--inm->inm_sctimer == 0) { in igmp_v3_process_group_timers()
1887 switch (inm->inm_state) { in igmp_v3_process_group_timers()
1898 * Respond to a previously pending Group-Specific in igmp_v3_process_group_timers()
1899 * or Group-and-Source-Specific query by enqueueing in igmp_v3_process_group_timers()
1900 * the appropriate Current-State report for in igmp_v3_process_group_timers()
1907 (inm->inm_state == IGMP_SG_QUERY_PENDING_MEMBER)); in igmp_v3_process_group_timers()
1910 inm->inm_state = IGMP_REPORTING_MEMBER; in igmp_v3_process_group_timers()
1919 * State-change retransmission timer fired. in igmp_v3_process_group_timers()
1921 * set the global pending state-change flag, and in igmp_v3_process_group_timers()
1924 if (--inm->inm_scrv > 0) { in igmp_v3_process_group_timers()
1925 inm->inm_sctimer = uri_fasthz; in igmp_v3_process_group_timers()
1929 * Retransmit the previously computed state-change in igmp_v3_process_group_timers()
1933 * a state-change. in igmp_v3_process_group_timers()
1938 CTR3(KTR_IGMPV3, "%s: T1 -> T0 for 0x%08x/%s", __func__, in igmp_v3_process_group_timers()
1939 ntohl(inm->inm_addr.s_addr), in igmp_v3_process_group_timers()
1940 inm->inm_ifp->if_xname); in igmp_v3_process_group_timers()
1949 if (inm->inm_state == IGMP_LEAVING_MEMBER && in igmp_v3_process_group_timers()
1950 inm->inm_scrv == 0) { in igmp_v3_process_group_timers()
1951 inm->inm_state = IGMP_NOT_MEMBER; in igmp_v3_process_group_timers()
1974 KASSERT(inm->inm_igi->igi_version == IGMP_VERSION_3, in igmp_v3_suppress_group_record()
1977 if (inm->inm_state != IGMP_G_QUERY_PENDING_MEMBER || in igmp_v3_suppress_group_record()
1978 inm->inm_state != IGMP_SG_QUERY_PENDING_MEMBER) in igmp_v3_suppress_group_record()
1981 if (inm->inm_state == IGMP_SG_QUERY_PENDING_MEMBER) in igmp_v3_suppress_group_record()
1984 inm->inm_timer = 0; in igmp_v3_suppress_group_record()
1985 inm->inm_state = IGMP_REPORTING_MEMBER; in igmp_v3_suppress_group_record()
2000 version, igi->igi_ifp, igi->igi_ifp->if_xname); in igmp_set_version()
2007 old_version_timer = igi->igi_rv * igi->igi_qi + igi->igi_qri; in igmp_set_version()
2011 igi->igi_v1_timer = old_version_timer; in igmp_set_version()
2012 igi->igi_v2_timer = 0; in igmp_set_version()
2014 igi->igi_v1_timer = 0; in igmp_set_version()
2015 igi->igi_v2_timer = old_version_timer; in igmp_set_version()
2019 if (igi->igi_v1_timer == 0 && igi->igi_v2_timer > 0) { in igmp_set_version()
2020 if (igi->igi_version != IGMP_VERSION_2) { in igmp_set_version()
2021 igi->igi_version = IGMP_VERSION_2; in igmp_set_version()
2024 } else if (igi->igi_v1_timer > 0) { in igmp_set_version()
2025 if (igi->igi_version != IGMP_VERSION_1) { in igmp_set_version()
2026 igi->igi_version = IGMP_VERSION_1; in igmp_set_version()
2034 * joined on it; state-change, general-query, and group-query timers.
2050 igi->igi_ifp, igi->igi_ifp->if_xname); in igmp_v3_cancel_link_timers()
2063 igi->igi_v3_timer = 0; in igmp_v3_cancel_link_timers()
2066 * Now clear the current-state and state-change report timers in igmp_v3_cancel_link_timers()
2069 ifp = igi->igi_ifp; in igmp_v3_cancel_link_timers()
2071 CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { in igmp_v3_cancel_link_timers()
2075 switch (inm->inm_state) { in igmp_v3_cancel_link_timers()
2093 * message is sent upstream to the old querier -- in igmp_v3_cancel_link_timers()
2103 inm->inm_state = IGMP_REPORTING_MEMBER; in igmp_v3_cancel_link_timers()
2107 * Always clear state-change and group report timers. in igmp_v3_cancel_link_timers()
2108 * Free any pending IGMPv3 state-change records. in igmp_v3_cancel_link_timers()
2110 inm->inm_sctimer = 0; in igmp_v3_cancel_link_timers()
2111 inm->inm_timer = 0; in igmp_v3_cancel_link_timers()
2112 mbufq_drain(&inm->inm_scq); in igmp_v3_cancel_link_timers()
2129 if (igi->igi_v1_timer == 0 && igi->igi_v2_timer == 0) { in igmp_v1v2_process_querier_timers()
2136 igi->igi_version != IGMP_VERSION_3) { in igmp_v1v2_process_querier_timers()
2138 "%s: transition from v%d -> v%d on %p(%s)", in igmp_v1v2_process_querier_timers()
2139 __func__, igi->igi_version, IGMP_VERSION_3, in igmp_v1v2_process_querier_timers()
2140 igi->igi_ifp, igi->igi_ifp->if_xname); in igmp_v1v2_process_querier_timers()
2141 igi->igi_version = IGMP_VERSION_3; in igmp_v1v2_process_querier_timers()
2143 } else if (igi->igi_v1_timer == 0 && igi->igi_v2_timer > 0) { in igmp_v1v2_process_querier_timers()
2154 "%s: transition from v%d -> v%d on %p(%s)", in igmp_v1v2_process_querier_timers()
2155 __func__, igi->igi_version, IGMP_VERSION_3, in igmp_v1v2_process_querier_timers()
2156 igi->igi_ifp, igi->igi_ifp->if_xname); in igmp_v1v2_process_querier_timers()
2157 igi->igi_v2_timer = 0; in igmp_v1v2_process_querier_timers()
2158 igi->igi_version = IGMP_VERSION_3; in igmp_v1v2_process_querier_timers()
2160 --igi->igi_v2_timer; in igmp_v1v2_process_querier_timers()
2162 igi->igi_version != IGMP_VERSION_2) { in igmp_v1v2_process_querier_timers()
2164 "%s: transition from v%d -> v%d on %p(%s)", in igmp_v1v2_process_querier_timers()
2165 __func__, igi->igi_version, IGMP_VERSION_2, in igmp_v1v2_process_querier_timers()
2166 igi->igi_ifp, igi->igi_ifp->if_xname); in igmp_v1v2_process_querier_timers()
2167 igi->igi_version = IGMP_VERSION_2; in igmp_v1v2_process_querier_timers()
2171 } else if (igi->igi_v1_timer > 0) { in igmp_v1v2_process_querier_timers()
2183 "%s: transition from v%d -> v%d on %p(%s)", in igmp_v1v2_process_querier_timers()
2184 __func__, igi->igi_version, IGMP_VERSION_3, in igmp_v1v2_process_querier_timers()
2185 igi->igi_ifp, igi->igi_ifp->if_xname); in igmp_v1v2_process_querier_timers()
2186 igi->igi_v1_timer = 0; in igmp_v1v2_process_querier_timers()
2187 igi->igi_version = IGMP_VERSION_3; in igmp_v1v2_process_querier_timers()
2189 --igi->igi_v1_timer; in igmp_v1v2_process_querier_timers()
2191 if (igi->igi_v2_timer > 0) { in igmp_v1v2_process_querier_timers()
2194 __func__, igi->igi_ifp, igi->igi_ifp->if_xname); in igmp_v1v2_process_querier_timers()
2195 igi->igi_v2_timer = 0; in igmp_v1v2_process_querier_timers()
2225 * Per-vnet slowtimo handler.
2257 ifp = inm->inm_ifp; in igmp_v1v2_queue_report()
2264 m->m_pkthdr.len = sizeof(struct ip) + sizeof(struct igmp); in igmp_v1v2_queue_report()
2266 m->m_data += sizeof(struct ip); in igmp_v1v2_queue_report()
2267 m->m_len = sizeof(struct igmp); in igmp_v1v2_queue_report()
2270 igmp->igmp_type = type; in igmp_v1v2_queue_report()
2271 igmp->igmp_code = 0; in igmp_v1v2_queue_report()
2272 igmp->igmp_group = inm->inm_addr; in igmp_v1v2_queue_report()
2273 igmp->igmp_cksum = 0; in igmp_v1v2_queue_report()
2274 igmp->igmp_cksum = in_cksum(m, sizeof(struct igmp)); in igmp_v1v2_queue_report()
2276 m->m_data -= sizeof(struct ip); in igmp_v1v2_queue_report()
2277 m->m_len += sizeof(struct ip); in igmp_v1v2_queue_report()
2280 ip->ip_tos = 0; in igmp_v1v2_queue_report()
2281 ip->ip_len = htons(sizeof(struct ip) + sizeof(struct igmp)); in igmp_v1v2_queue_report()
2282 ip->ip_off = 0; in igmp_v1v2_queue_report()
2283 ip->ip_p = IPPROTO_IGMP; in igmp_v1v2_queue_report()
2284 ip->ip_src.s_addr = INADDR_ANY; in igmp_v1v2_queue_report()
2287 ip->ip_dst.s_addr = htonl(INADDR_ALLRTRS_GROUP); in igmp_v1v2_queue_report()
2289 ip->ip_dst = inm->inm_addr; in igmp_v1v2_queue_report()
2293 m->m_flags |= M_IGMPV2; in igmp_v1v2_queue_report()
2294 if (inm->inm_igi->igi_flags & IGIF_LOOPBACK) in igmp_v1v2_queue_report()
2295 m->m_flags |= M_IGMP_LOOP; in igmp_v1v2_queue_report()
2311 * has been any change between T0 (when the last state-change was issued)
2336 * Try to detect if the upper layer just asked us to change state in igmp_change_state()
2339 KASSERT(inm->inm_ifma != NULL, ("%s: no ifma", __func__)); in igmp_change_state()
2340 ifp = inm->inm_ifma->ifma_ifp; in igmp_change_state()
2347 KASSERT(inm->inm_ifp == ifp, ("%s: bad ifp", __func__)); in igmp_change_state()
2351 igi = ((struct in_ifinfo *)ifp->if_afdata[AF_INET])->ii_igmp; in igmp_change_state()
2359 if (inm->inm_st[1].iss_fmode != inm->inm_st[0].iss_fmode) { in igmp_change_state()
2360 CTR3(KTR_IGMPV3, "%s: inm transition %d -> %d", __func__, in igmp_change_state()
2361 inm->inm_st[0].iss_fmode, inm->inm_st[1].iss_fmode); in igmp_change_state()
2362 if (inm->inm_st[0].iss_fmode == MCAST_UNDEFINED) { in igmp_change_state()
2366 } else if (inm->inm_st[1].iss_fmode == MCAST_UNDEFINED) { in igmp_change_state()
2389 * IGMPv3 will schedule an IGMPv3 state-change report containing the
2400 ntohl(inm->inm_addr.s_addr), inm->inm_ifp, inm->inm_ifp->if_xname); in igmp_initial_join()
2405 ifp = inm->inm_ifp; in igmp_initial_join()
2410 KASSERT(igi && igi->igi_ifp == ifp, ("%s: inconsistent ifp", __func__)); in igmp_initial_join()
2421 if ((ifp->if_flags & IFF_LOOPBACK) || in igmp_initial_join()
2422 (igi->igi_flags & IGIF_SILENT) || in igmp_initial_join()
2423 !igmp_isgroupreported(inm->inm_addr)) { in igmp_initial_join()
2426 inm->inm_state = IGMP_SILENT_MEMBER; in igmp_initial_join()
2427 inm->inm_timer = 0; in igmp_initial_join()
2435 if (igi->igi_version == IGMP_VERSION_3 && in igmp_initial_join()
2436 inm->inm_state == IGMP_LEAVING_MEMBER) { in igmp_initial_join()
2437 MPASS(inm->inm_refcount > 1); in igmp_initial_join()
2440 inm->inm_state = IGMP_REPORTING_MEMBER; in igmp_initial_join()
2442 switch (igi->igi_version) { in igmp_initial_join()
2445 inm->inm_state = IGMP_IDLE_MEMBER; in igmp_initial_join()
2447 (igi->igi_version == IGMP_VERSION_2) ? in igmp_initial_join()
2451 inm->inm_timer = IGMP_RANDOM_DELAY( in igmp_initial_join()
2465 * Immediately enqueue a State-Change Report for in igmp_initial_join()
2470 mq = &inm->inm_scq; in igmp_initial_join()
2477 error = retval * -1; in igmp_initial_join()
2482 * Schedule transmission of pending state-change in igmp_initial_join()
2485 * giving us an opportunity to merge the reports. in igmp_initial_join()
2487 if (igi->igi_flags & IGIF_LOOPBACK) { in igmp_initial_join()
2488 inm->inm_scrv = 1; in igmp_initial_join()
2490 KASSERT(igi->igi_rv > 1, in igmp_initial_join()
2492 igi->igi_rv)); in igmp_initial_join()
2493 inm->inm_scrv = igi->igi_rv; in igmp_initial_join()
2495 inm->inm_sctimer = 1; in igmp_initial_join()
2504 * Only update the T0 state if state change is atomic, in igmp_initial_join()
2510 CTR3(KTR_IGMPV3, "%s: T1 -> T0 for 0x%08x/%s", __func__, in igmp_initial_join()
2511 ntohl(inm->inm_addr.s_addr), inm->inm_ifp->if_xname); in igmp_initial_join()
2518 * Issue an intermediate state change during the IGMP life-cycle.
2527 ntohl(inm->inm_addr.s_addr), inm->inm_ifp, inm->inm_ifp->if_xname); in igmp_handle_state_change()
2529 ifp = inm->inm_ifp; in igmp_handle_state_change()
2534 KASSERT(igi && igi->igi_ifp == ifp, ("%s: inconsistent ifp", __func__)); in igmp_handle_state_change()
2536 if ((ifp->if_flags & IFF_LOOPBACK) || in igmp_handle_state_change()
2537 (igi->igi_flags & IGIF_SILENT) || in igmp_handle_state_change()
2538 !igmp_isgroupreported(inm->inm_addr) || in igmp_handle_state_change()
2539 (igi->igi_version != IGMP_VERSION_3)) { in igmp_handle_state_change()
2540 if (!igmp_isgroupreported(inm->inm_addr)) { in igmp_handle_state_change()
2546 CTR3(KTR_IGMPV3, "%s: T1 -> T0 for 0x%08x/%s", __func__, in igmp_handle_state_change()
2547 ntohl(inm->inm_addr.s_addr), inm->inm_ifp->if_xname); in igmp_handle_state_change()
2551 mbufq_drain(&inm->inm_scq); in igmp_handle_state_change()
2553 retval = igmp_v3_enqueue_group_record(&inm->inm_scq, inm, 1, 0, 0); in igmp_handle_state_change()
2556 return (-retval); in igmp_handle_state_change()
2559 * If record(s) were enqueued, start the state-change in igmp_handle_state_change()
2562 inm->inm_scrv = ((igi->igi_flags & IGIF_LOOPBACK) ? 1 : igi->igi_rv); in igmp_handle_state_change()
2563 inm->inm_sctimer = 1; in igmp_handle_state_change()
2575 * IGMPv3 enqueues a state-change report containing a transition
2586 __func__, ntohl(inm->inm_addr.s_addr), inm->inm_ifp, in igmp_final_leave()
2587 inm->inm_ifp->if_xname); in igmp_final_leave()
2592 switch (inm->inm_state) { in igmp_final_leave()
2604 if (igi->igi_version == IGMP_VERSION_2) { in igmp_final_leave()
2606 if (inm->inm_state == IGMP_G_QUERY_PENDING_MEMBER || in igmp_final_leave()
2607 inm->inm_state == IGMP_SG_QUERY_PENDING_MEMBER) in igmp_final_leave()
2612 inm->inm_state = IGMP_NOT_MEMBER; in igmp_final_leave()
2613 } else if (igi->igi_version == IGMP_VERSION_3) { in igmp_final_leave()
2616 * Immediately enqueue a state-change report in igmp_final_leave()
2618 * giving us an opportunity to merge reports. in igmp_final_leave()
2620 mbufq_drain(&inm->inm_scq); in igmp_final_leave()
2621 inm->inm_timer = 0; in igmp_final_leave()
2622 if (igi->igi_flags & IGIF_LOOPBACK) { in igmp_final_leave()
2623 inm->inm_scrv = 1; in igmp_final_leave()
2625 inm->inm_scrv = igi->igi_rv; in igmp_final_leave()
2629 ntohl(inm->inm_addr.s_addr), in igmp_final_leave()
2630 inm->inm_ifp->if_xname, inm->inm_scrv); in igmp_final_leave()
2631 if (inm->inm_scrv == 0) { in igmp_final_leave()
2632 inm->inm_state = IGMP_NOT_MEMBER; in igmp_final_leave()
2633 inm->inm_sctimer = 0; in igmp_final_leave()
2640 &inm->inm_scq, inm, 1, 0, 0); in igmp_final_leave()
2645 inm->inm_state = IGMP_LEAVING_MEMBER; in igmp_final_leave()
2646 inm->inm_sctimer = 1; in igmp_final_leave()
2662 CTR3(KTR_IGMPV3, "%s: T1 -> T0 for 0x%08x/%s", __func__, in igmp_final_leave()
2663 ntohl(inm->inm_addr.s_addr), inm->inm_ifp->if_xname); in igmp_final_leave()
2664 inm->inm_st[1].iss_fmode = MCAST_UNDEFINED; in igmp_final_leave()
2666 __func__, ntohl(inm->inm_addr.s_addr), in igmp_final_leave()
2667 inm->inm_ifp->if_xname); in igmp_final_leave()
2675 * split out, and the multiple-tree-walks coalesced into a single
2678 * If is_state_change is zero, a current-state record is appended.
2679 * If is_state_change is non-zero, a state-change report is appended.
2681 * If is_group_query is non-zero, an mbuf packet chain is allocated.
2687 * If is_source_query is non-zero, each source is checked to see if
2688 * it was recorded for a Group-Source query, and will be omitted if
2689 * it is not both in-mode and recorded.
2718 ifp = inm->inm_ifp; in igmp_v3_enqueue_group_record()
2729 mode = inm->inm_st[1].iss_fmode; in igmp_v3_enqueue_group_record()
2732 * If we did not transition out of ASM mode during t0->t1, in igmp_v3_enqueue_group_record()
2736 if (inm->inm_st[0].iss_asm > 0 && inm->inm_st[1].iss_asm > 0 && in igmp_v3_enqueue_group_record()
2737 inm->inm_nsrc == 0) in igmp_v3_enqueue_group_record()
2743 * If the mode did not change, and there are non-ASM in igmp_v3_enqueue_group_record()
2751 if (mode != inm->inm_st[0].iss_fmode) { in igmp_v3_enqueue_group_record()
2778 KASSERT(inm->inm_st[1].iss_asm == 0, in igmp_v3_enqueue_group_record()
2780 __func__, inm, inm->inm_st[1].iss_asm)); in igmp_v3_enqueue_group_record()
2792 ntohl(inm->inm_addr.s_addr), inm->inm_ifp->if_xname); in igmp_v3_enqueue_group_record()
2806 igmp_rec_type_to_str(type), ntohl(inm->inm_addr.s_addr), in igmp_v3_enqueue_group_record()
2807 inm->inm_ifp->if_xname); in igmp_v3_enqueue_group_record()
2820 (m0->m_pkthdr.vt_nrecs + 1 <= IGMP_V3_REPORT_MAXRECS) && in igmp_v3_enqueue_group_record()
2821 (m0->m_pkthdr.len + minrec0len) < in igmp_v3_enqueue_group_record()
2822 (ifp->if_mtu - IGMP_LEADINGSPACE)) { in igmp_v3_enqueue_group_record()
2823 m0srcs = (ifp->if_mtu - m0->m_pkthdr.len - in igmp_v3_enqueue_group_record()
2830 return (-ENOMEM); in igmp_v3_enqueue_group_record()
2833 m0srcs = (ifp->if_mtu - IGMP_LEADINGSPACE - in igmp_v3_enqueue_group_record()
2838 m->m_data += IGMP_LEADINGSPACE; in igmp_v3_enqueue_group_record()
2846 return (-ENOMEM); in igmp_v3_enqueue_group_record()
2860 ig.ig_group = inm->inm_addr; in igmp_v3_enqueue_group_record()
2865 return (-ENOMEM); in igmp_v3_enqueue_group_record()
2876 * Only append sources which are in-mode at t1. If we are in igmp_v3_enqueue_group_record()
2880 * to a group-source query. in igmp_v3_enqueue_group_record()
2886 md->m_len - nbytes); in igmp_v3_enqueue_group_record()
2893 RB_FOREACH_SAFE(ims, ip_msource_tree, &inm->inm_srcs, nims) { in igmp_v3_enqueue_group_record()
2895 ims->ims_haddr); in igmp_v3_enqueue_group_record()
2903 if (is_source_query && ims->ims_stp == 0) { in igmp_v3_enqueue_group_record()
2909 naddr = htonl(ims->ims_haddr); in igmp_v3_enqueue_group_record()
2915 return (-ENOMEM); in igmp_v3_enqueue_group_record()
2924 pig->ig_numsrc = htons(msrcs); in igmp_v3_enqueue_group_record()
2940 m->m_pkthdr.vt_nrecs = 1; in igmp_v3_enqueue_group_record()
2943 m->m_pkthdr.vt_nrecs++; in igmp_v3_enqueue_group_record()
2959 return (-ENOMEM); in igmp_v3_enqueue_group_record()
2963 m->m_data += IGMP_LEADINGSPACE; in igmp_v3_enqueue_group_record()
2970 return (-ENOMEM); in igmp_v3_enqueue_group_record()
2980 return (-ENOMEM); in igmp_v3_enqueue_group_record()
2982 m->m_pkthdr.vt_nrecs = 1; in igmp_v3_enqueue_group_record()
2985 m0srcs = (ifp->if_mtu - IGMP_LEADINGSPACE - in igmp_v3_enqueue_group_record()
2991 ims->ims_haddr); in igmp_v3_enqueue_group_record()
2998 if (is_source_query && ims->ims_stp == 0) { in igmp_v3_enqueue_group_record()
3004 naddr = htonl(ims->ims_haddr); in igmp_v3_enqueue_group_record()
3010 return (-ENOMEM); in igmp_v3_enqueue_group_record()
3016 pig->ig_numsrc = htons(msrcs); in igmp_v3_enqueue_group_record()
3041 * Source list filter state is held in an RB-tree. When the filter list
3046 * As we may potentially queue two record types, and the entire R-B tree
3052 * which makes things easier on us, and it may or may not be harder on
3079 if (inm->inm_nsrc == 0 || in igmp_v3_enqueue_filter_change()
3080 (inm->inm_st[0].iss_asm > 0 && inm->inm_st[1].iss_asm > 0)) in igmp_v3_enqueue_filter_change()
3083 ifp = inm->inm_ifp; /* interface */ in igmp_v3_enqueue_filter_change()
3084 mode = inm->inm_st[1].iss_fmode; /* filter mode at t1 */ in igmp_v3_enqueue_filter_change()
3089 nbytes = 0; /* # of bytes appended to group's state-change queue */ in igmp_v3_enqueue_filter_change()
3101 * The first kind of source we encounter tells us which in igmp_v3_enqueue_filter_change()
3110 (m0->m_pkthdr.vt_nrecs + 1 <= in igmp_v3_enqueue_filter_change()
3112 (m0->m_pkthdr.len + MINRECLEN) < in igmp_v3_enqueue_filter_change()
3113 (ifp->if_mtu - IGMP_LEADINGSPACE)) { in igmp_v3_enqueue_filter_change()
3115 m0srcs = (ifp->if_mtu - m0->m_pkthdr.len - in igmp_v3_enqueue_filter_change()
3123 m->m_data += IGMP_LEADINGSPACE; in igmp_v3_enqueue_filter_change()
3132 return (-ENOMEM); in igmp_v3_enqueue_filter_change()
3134 m->m_pkthdr.vt_nrecs = 0; in igmp_v3_enqueue_filter_change()
3136 m0srcs = (ifp->if_mtu - IGMP_LEADINGSPACE - in igmp_v3_enqueue_filter_change()
3151 ig.ig_group = inm->inm_addr; in igmp_v3_enqueue_filter_change()
3157 return (-ENOMEM); in igmp_v3_enqueue_filter_change()
3162 md = m_getptr(m, npbytes - in igmp_v3_enqueue_filter_change()
3170 uint8_t *) + md->m_len - in igmp_v3_enqueue_filter_change()
3177 * Only report deltas in-mode at t1. in igmp_v3_enqueue_filter_change()
3184 nims = RB_MIN(ip_msource_tree, &inm->inm_srcs); in igmp_v3_enqueue_filter_change()
3187 __func__, ims->ims_haddr); in igmp_v3_enqueue_filter_change()
3211 naddr = htonl(ims->ims_haddr); in igmp_v3_enqueue_filter_change()
3218 return (-ENOMEM); in igmp_v3_enqueue_filter_change()
3232 npbytes -= sizeof(struct igmp_grouprec); in igmp_v3_enqueue_filter_change()
3239 "%s: m_adj(m, -ig)", __func__); in igmp_v3_enqueue_filter_change()
3240 m_adj(m, -((int)sizeof( in igmp_v3_enqueue_filter_change()
3247 pig->ig_type = IGMP_ALLOW_NEW_SOURCES; in igmp_v3_enqueue_filter_change()
3249 pig->ig_type = IGMP_BLOCK_OLD_SOURCES; in igmp_v3_enqueue_filter_change()
3250 pig->ig_numsrc = htons(rsrcs); in igmp_v3_enqueue_filter_change()
3255 m->m_pkthdr.vt_nrecs++; in igmp_v3_enqueue_filter_change()
3274 struct mbuf *m; /* pending state-change */ in igmp_v3_merge_state_changes()
3275 struct mbuf *m0; /* copy of pending state-change */ in igmp_v3_merge_state_changes()
3276 struct mbuf *mt; /* last state-change in packet */ in igmp_v3_merge_state_changes()
3289 * copy of each queued state-change message before merging. in igmp_v3_merge_state_changes()
3291 if (inm->inm_scrv > 0) in igmp_v3_merge_state_changes()
3294 gq = &inm->inm_scq; in igmp_v3_merge_state_changes()
3317 if ((mt->m_pkthdr.vt_nrecs + in igmp_v3_merge_state_changes()
3318 m->m_pkthdr.vt_nrecs <= in igmp_v3_merge_state_changes()
3320 (mt->m_pkthdr.len + recslen <= in igmp_v3_merge_state_changes()
3321 (inm->inm_ifp->if_mtu - IGMP_LEADINGSPACE))) in igmp_v3_merge_state_changes()
3329 mt = m->m_nextpkt; in igmp_v3_merge_state_changes()
3339 m = m0->m_nextpkt; in igmp_v3_merge_state_changes()
3345 m0->m_nextpkt = NULL; in igmp_v3_merge_state_changes()
3346 m = m->m_nextpkt; in igmp_v3_merge_state_changes()
3360 m0->m_flags &= ~M_PKTHDR; in igmp_v3_merge_state_changes()
3361 mt->m_pkthdr.len += recslen; in igmp_v3_merge_state_changes()
3362 mt->m_pkthdr.vt_nrecs += in igmp_v3_merge_state_changes()
3363 m0->m_pkthdr.vt_nrecs; in igmp_v3_merge_state_changes()
3365 mtl->m_next = m0; in igmp_v3_merge_state_changes()
3387 KASSERT(igi->igi_version == IGMP_VERSION_3, in igmp_v3_dispatch_general_query()
3388 ("%s: called when version %d", __func__, igi->igi_version)); in igmp_v3_dispatch_general_query()
3396 if (!mbufq_empty(&igi->igi_gq)) in igmp_v3_dispatch_general_query()
3399 ifp = igi->igi_ifp; in igmp_v3_dispatch_general_query()
3401 CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { in igmp_v3_dispatch_general_query()
3405 KASSERT(ifp == inm->inm_ifp, in igmp_v3_dispatch_general_query()
3408 switch (inm->inm_state) { in igmp_v3_dispatch_general_query()
3417 inm->inm_state = IGMP_REPORTING_MEMBER; in igmp_v3_dispatch_general_query()
3418 retval = igmp_v3_enqueue_group_record(&igi->igi_gq, in igmp_v3_dispatch_general_query()
3431 loop = (igi->igi_flags & IGIF_LOOPBACK) ? 1 : 0; in igmp_v3_dispatch_general_query()
3432 igmp_dispatch_queue(&igi->igi_gq, IGMP_MAX_RESPONSE_BURST, loop); in igmp_v3_dispatch_general_query()
3437 if (mbufq_first(&igi->igi_gq) != NULL) { in igmp_v3_dispatch_general_query()
3438 igi->igi_v3_timer = 1 + IGMP_RANDOM_DELAY( in igmp_v3_dispatch_general_query()
3450 * VIMAGE: Needs to store/restore vnet pointer on a per-mbuf-chain basis.
3452 * a link and uses a link-scope multicast address.
3471 CURVNET_SET((struct vnet *)(m->m_pkthdr.PH_loc.ptr)); in igmp_intr()
3491 imo.imo_multicast_vif = -1; in igmp_intr()
3500 if (m->m_flags & M_IGMP_LOOP) in igmp_intr()
3505 if (m->m_flags & M_IGMPV2) { in igmp_intr()
3519 m0->m_pkthdr.rcvif = V_loif; in igmp_intr()
3545 * will however be re-computed.
3557 KASSERT((m->m_flags & M_PKTHDR), in igmp_v3_encap_report()
3563 if (m->m_flags & M_IGMPV3_HDR) { in igmp_v3_encap_report()
3564 igmpreclen -= hdrlen; in igmp_v3_encap_report()
3569 m->m_flags |= M_IGMPV3_HDR; in igmp_v3_encap_report()
3574 m->m_data += sizeof(struct ip); in igmp_v3_encap_report()
3575 m->m_len -= sizeof(struct ip); in igmp_v3_encap_report()
3578 igmp->ir_type = IGMP_v3_HOST_MEMBERSHIP_REPORT; in igmp_v3_encap_report()
3579 igmp->ir_rsv1 = 0; in igmp_v3_encap_report()
3580 igmp->ir_rsv2 = 0; in igmp_v3_encap_report()
3581 igmp->ir_numgrps = htons(m->m_pkthdr.vt_nrecs); in igmp_v3_encap_report()
3582 igmp->ir_cksum = 0; in igmp_v3_encap_report()
3583 igmp->ir_cksum = in_cksum(m, sizeof(struct igmp_report) + igmpreclen); in igmp_v3_encap_report()
3584 m->m_pkthdr.vt_nrecs = 0; in igmp_v3_encap_report()
3586 m->m_data -= sizeof(struct ip); in igmp_v3_encap_report()
3587 m->m_len += sizeof(struct ip); in igmp_v3_encap_report()
3590 ip->ip_tos = IPTOS_PREC_INTERNETCONTROL; in igmp_v3_encap_report()
3591 ip->ip_len = htons(hdrlen + igmpreclen); in igmp_v3_encap_report()
3592 ip->ip_off = htons(IP_DF); in igmp_v3_encap_report()
3593 ip->ip_p = IPPROTO_IGMP; in igmp_v3_encap_report()
3594 ip->ip_sum = 0; in igmp_v3_encap_report()
3596 ip->ip_src.s_addr = INADDR_ANY; in igmp_v3_encap_report()
3598 if (m->m_flags & M_IGMP_LOOP) { in igmp_v3_encap_report()
3603 ip->ip_src = ia->ia_addr.sin_addr; in igmp_v3_encap_report()
3606 ip->ip_dst.s_addr = htonl(INADDR_ALLRPTS_GROUP); in igmp_v3_encap_report()
3679 db_printf(" ifp %p\n", igi->igi_ifp); in DB_SHOW_COMMAND()
3680 db_printf(" version %u\n", igi->igi_version); in DB_SHOW_COMMAND()
3681 db_printf(" v1_timer %u\n", igi->igi_v1_timer); in DB_SHOW_COMMAND()
3682 db_printf(" v2_timer %u\n", igi->igi_v2_timer); in DB_SHOW_COMMAND()
3683 db_printf(" v3_timer %u\n", igi->igi_v3_timer); in DB_SHOW_COMMAND()
3684 db_printf(" flags %#x\n", igi->igi_flags); in DB_SHOW_COMMAND()
3685 db_printf(" rv %u\n", igi->igi_rv); in DB_SHOW_COMMAND()
3686 db_printf(" qi %u\n", igi->igi_qi); in DB_SHOW_COMMAND()
3687 db_printf(" qri %u\n", igi->igi_qri); in DB_SHOW_COMMAND()
3688 db_printf(" uri %u\n", igi->igi_uri); in DB_SHOW_COMMAND()