Print this page
5045 use atomic_{inc,dec}_* instead of atomic_add_*


 491          * In Delaying Member state, our timer is running (ilm->ilm_timer
 492          * < INFINITY).  In Idle Member state, our timer is not running
 493          * (ilm->ilm_timer == INFINITY).
 494          *
 495          * The flag is ilm->ilm_state, it is set to IGMP_OTHERMEMBER if
 496          * we have heard a report from another member, or IGMP_IREPORTEDLAST
 497          * if I sent the last report.
 498          */
 499         if ((igmpa->igmpa_code == 0) ||
 500             (ipst->ips_igmp_max_version == IGMP_V1_ROUTER)) {
 501                 /*
 502                  * Query from an old router.
 503                  * Remember that the querier on this interface is old,
 504                  * and set the timer to the value in RFC 1112.
 505                  */
 506                 ill->ill_mcast_v1_time = 0;
 507                 ill->ill_mcast_v1_tset = 1;
 508                 if (ill->ill_mcast_type != IGMP_V1_ROUTER) {
 509                         ip1dbg(("Received IGMPv1 Query on %s, switching mode "
 510                             "to IGMP_V1_ROUTER\n", ill->ill_name));
 511                         atomic_add_16(&ill->ill_ifptr->illif_mcast_v1, 1);
 512                         ill->ill_mcast_type = IGMP_V1_ROUTER;
 513                 }
 514 
 515                 timer = SEC_TO_MSEC(IGMP_MAX_HOST_REPORT_DELAY);
 516 
 517                 if (ipha->ipha_dst != htonl(INADDR_ALLHOSTS_GROUP) ||
 518                     igmpa->igmpa_group != 0) {
 519                         ++ipst->ips_igmpstat.igps_rcv_badqueries;
 520                         rw_exit(&ill->ill_mcast_lock);
 521                         ill_mcast_timer_start(ill->ill_ipst);
 522                         return (0);
 523                 }
 524 
 525         } else {
 526                 in_addr_t group;
 527 
 528                 /*
 529                  * Query from a new router
 530                  * Simply do a validity check
 531                  */
 532                 group = igmpa->igmpa_group;
 533                 if (group != 0 && (!CLASSD(group))) {
 534                         ++ipst->ips_igmpstat.igps_rcv_badqueries;
 535                         rw_exit(&ill->ill_mcast_lock);
 536                         ill_mcast_timer_start(ill->ill_ipst);
 537                         return (0);
 538                 }
 539 
 540                 /*
 541                  * Switch interface state to v2 on receipt of a v2 query
 542                  * ONLY IF current state is v3.  Let things be if current
 543                  * state if v1 but do reset the v2-querier-present timer.
 544                  */
 545                 if (ill->ill_mcast_type == IGMP_V3_ROUTER) {
 546                         ip1dbg(("Received IGMPv2 Query on %s, switching mode "
 547                             "to IGMP_V2_ROUTER", ill->ill_name));
 548                         atomic_add_16(&ill->ill_ifptr->illif_mcast_v2, 1);
 549                         ill->ill_mcast_type = IGMP_V2_ROUTER;
 550                 }
 551                 ill->ill_mcast_v2_time = 0;
 552                 ill->ill_mcast_v2_tset = 1;
 553 
 554                 timer = DSEC_TO_MSEC((int)igmpa->igmpa_code);
 555         }
 556 
 557         if (ip_debug > 1) {
 558                 (void) mi_strlog(ill->ill_rq, 1, SL_TRACE,
 559                     "igmp_input: TIMER = igmp_code %d igmp_type 0x%x",
 560                     (int)ntohs(igmpa->igmpa_code),
 561                     (int)ntohs(igmpa->igmpa_type));
 562         }
 563 
 564         /*
 565          * -Start the timers in all of our membership records
 566          *  for the physical interface on which the query
 567          *  arrived, excluding those that belong to the "all
 568          *  hosts" group (224.0.0.1).


1699                             (ill->ill_mcast_v1_time >= OVQP(ill))) {
1700                                 if ((ill->ill_mcast_v2_tset > 0) ||
1701                                     (ipst->ips_igmp_max_version ==
1702                                     IGMP_V2_ROUTER)) {
1703                                         ip1dbg(("V1 query timer "
1704                                             "expired on %s; switching "
1705                                             "mode to IGMP_V2\n",
1706                                             ill->ill_name));
1707                                         ill->ill_mcast_type =
1708                                             IGMP_V2_ROUTER;
1709                                 } else {
1710                                         ip1dbg(("V1 query timer "
1711                                             "expired on %s; switching "
1712                                             "mode to IGMP_V3\n",
1713                                             ill->ill_name));
1714                                         ill->ill_mcast_type =
1715                                             IGMP_V3_ROUTER;
1716                                 }
1717                                 ill->ill_mcast_v1_time = 0;
1718                                 ill->ill_mcast_v1_tset = 0;
1719                                 atomic_add_16(&ifp->illif_mcast_v1, -1);
1720                         }
1721                         if ((ill->ill_mcast_type == IGMP_V2_ROUTER) &&
1722                             (ipst->ips_igmp_max_version >= IGMP_V3_ROUTER) &&
1723                             (ill->ill_mcast_v2_time >= OVQP(ill))) {
1724                                 ip1dbg(("V2 query timer expired on "
1725                                     "%s; switching mode to IGMP_V3\n",
1726                                     ill->ill_name));
1727                                 ill->ill_mcast_type = IGMP_V3_ROUTER;
1728                                 ill->ill_mcast_v2_time = 0;
1729                                 ill->ill_mcast_v2_tset = 0;
1730                                 atomic_add_16(&ifp->illif_mcast_v2, -1);
1731                         }
1732                         rw_exit(&ill->ill_mcast_lock);
1733                         ill_refrele(ill);
1734                         rw_enter(&ipst->ips_ill_g_lock, RW_READER);
1735                 }
1736         }
1737         rw_exit(&ipst->ips_ill_g_lock);
1738         ill_mcast_timer_start(ipst);
1739         mutex_enter(&ipst->ips_igmp_slowtimeout_lock);
1740         ipst->ips_igmp_slowtimeout_id = timeout(igmp_slowtimo, (void *)ipst,
1741             MSEC_TO_TICK(MCAST_SLOWTIMO_INTERVAL));
1742         mutex_exit(&ipst->ips_igmp_slowtimeout_lock);
1743 }
1744 
1745 /*
1746  * mld_slowtimo:
1747  * - Resets to newer version if we didn't hear from the older version router
1748  *   in MLD_AGE_THRESHOLD seconds.
1749  * - Restarts slowtimeout.
1750  * Check for ips_mld_max_version ensures that we don't revert to a higher


1769 
1770                 avl_tree = &ifp->illif_avl_by_ppa;
1771                 for (ill = avl_first(avl_tree); ill != NULL;
1772                     ill = avl_walk(avl_tree, ill, AVL_AFTER)) {
1773                         /* Make sure the ill isn't going away. */
1774                         if (!ill_check_and_refhold(ill))
1775                                 continue;
1776                         rw_exit(&ipst->ips_ill_g_lock);
1777                         rw_enter(&ill->ill_mcast_lock, RW_WRITER);
1778                         if (ill->ill_mcast_v1_tset == 1)
1779                                 ill->ill_mcast_v1_time++;
1780                         if ((ill->ill_mcast_type == MLD_V1_ROUTER) &&
1781                             (ipst->ips_mld_max_version >= MLD_V2_ROUTER) &&
1782                             (ill->ill_mcast_v1_time >= OVQP(ill))) {
1783                                 ip1dbg(("MLD query timer expired on"
1784                                     " %s; switching mode to MLD_V2\n",
1785                                     ill->ill_name));
1786                                 ill->ill_mcast_type = MLD_V2_ROUTER;
1787                                 ill->ill_mcast_v1_time = 0;
1788                                 ill->ill_mcast_v1_tset = 0;
1789                                 atomic_add_16(&ifp->illif_mcast_v1, -1);
1790                         }
1791                         rw_exit(&ill->ill_mcast_lock);
1792                         ill_refrele(ill);
1793                         rw_enter(&ipst->ips_ill_g_lock, RW_READER);
1794                 }
1795         }
1796         rw_exit(&ipst->ips_ill_g_lock);
1797         ill_mcast_timer_start(ipst);
1798         mutex_enter(&ipst->ips_mld_slowtimeout_lock);
1799         ipst->ips_mld_slowtimeout_id = timeout(mld_slowtimo, (void *)ipst,
1800             MSEC_TO_TICK(MCAST_SLOWTIMO_INTERVAL));
1801         mutex_exit(&ipst->ips_mld_slowtimeout_lock);
1802 }
1803 
1804 /*
1805  * igmp_sendpkt:
1806  * This will send to ip_output_simple just like icmp_inbound.
1807  */
1808 static void
1809 igmp_sendpkt(ilm_t *ilm, uchar_t type, ipaddr_t addr)


2199          * INFINITY)
2200          *
2201          * The flag is ilm->ilm_state, it is set to IGMP_OTHERMEMBER if
2202          * we have heard a report from another member, or IGMP_IREPORTEDLAST
2203          * if I sent the last report.
2204          */
2205         v6group = &mldh->mld_addr;
2206         if (!(IN6_IS_ADDR_UNSPECIFIED(v6group)) &&
2207             ((!IN6_IS_ADDR_MULTICAST(v6group)))) {
2208                 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInGroupMembBadQueries);
2209                 return (0);
2210         }
2211 
2212         /* Need to do compatibility mode checking */
2213         rw_enter(&ill->ill_mcast_lock, RW_WRITER);
2214         ill->ill_mcast_v1_time = 0;
2215         ill->ill_mcast_v1_tset = 1;
2216         if (ill->ill_mcast_type == MLD_V2_ROUTER) {
2217                 ip1dbg(("Received MLDv1 Query on %s, switching mode to "
2218                     "MLD_V1_ROUTER\n", ill->ill_name));
2219                 atomic_add_16(&ill->ill_ifptr->illif_mcast_v1, 1);
2220                 ill->ill_mcast_type = MLD_V1_ROUTER;
2221         }
2222 
2223         timer = (int)ntohs(mldh->mld_maxdelay);
2224         if (ip_debug > 1) {
2225                 (void) mi_strlog(ill->ill_rq, 1, SL_TRACE,
2226                     "mld_input: TIMER = mld_maxdelay %d mld_type 0x%x",
2227                     timer, (int)mldh->mld_type);
2228         }
2229 
2230         /*
2231          * -Start the timers in all of our membership records for
2232          * the physical interface on which the query arrived,
2233          * excl:
2234          *      1.  those that belong to the "all hosts" group,
2235          *      2.  those with 0 scope, or 1 node-local scope.
2236          *
2237          * -Restart any timer that is already running but has a value
2238          * longer that the requested timeout.
2239          * -Use the value specified in the query message as the




 491          * In Delaying Member state, our timer is running (ilm->ilm_timer
 492          * < INFINITY).  In Idle Member state, our timer is not running
 493          * (ilm->ilm_timer == INFINITY).
 494          *
 495          * The flag is ilm->ilm_state, it is set to IGMP_OTHERMEMBER if
 496          * we have heard a report from another member, or IGMP_IREPORTEDLAST
 497          * if I sent the last report.
 498          */
 499         if ((igmpa->igmpa_code == 0) ||
 500             (ipst->ips_igmp_max_version == IGMP_V1_ROUTER)) {
 501                 /*
 502                  * Query from an old router.
 503                  * Remember that the querier on this interface is old,
 504                  * and set the timer to the value in RFC 1112.
 505                  */
 506                 ill->ill_mcast_v1_time = 0;
 507                 ill->ill_mcast_v1_tset = 1;
 508                 if (ill->ill_mcast_type != IGMP_V1_ROUTER) {
 509                         ip1dbg(("Received IGMPv1 Query on %s, switching mode "
 510                             "to IGMP_V1_ROUTER\n", ill->ill_name));
 511                         atomic_inc_16(&ill->ill_ifptr->illif_mcast_v1);
 512                         ill->ill_mcast_type = IGMP_V1_ROUTER;
 513                 }
 514 
 515                 timer = SEC_TO_MSEC(IGMP_MAX_HOST_REPORT_DELAY);
 516 
 517                 if (ipha->ipha_dst != htonl(INADDR_ALLHOSTS_GROUP) ||
 518                     igmpa->igmpa_group != 0) {
 519                         ++ipst->ips_igmpstat.igps_rcv_badqueries;
 520                         rw_exit(&ill->ill_mcast_lock);
 521                         ill_mcast_timer_start(ill->ill_ipst);
 522                         return (0);
 523                 }
 524 
 525         } else {
 526                 in_addr_t group;
 527 
 528                 /*
 529                  * Query from a new router
 530                  * Simply do a validity check
 531                  */
 532                 group = igmpa->igmpa_group;
 533                 if (group != 0 && (!CLASSD(group))) {
 534                         ++ipst->ips_igmpstat.igps_rcv_badqueries;
 535                         rw_exit(&ill->ill_mcast_lock);
 536                         ill_mcast_timer_start(ill->ill_ipst);
 537                         return (0);
 538                 }
 539 
 540                 /*
 541                  * Switch interface state to v2 on receipt of a v2 query
 542                  * ONLY IF current state is v3.  Let things be if current
 543                  * state if v1 but do reset the v2-querier-present timer.
 544                  */
 545                 if (ill->ill_mcast_type == IGMP_V3_ROUTER) {
 546                         ip1dbg(("Received IGMPv2 Query on %s, switching mode "
 547                             "to IGMP_V2_ROUTER", ill->ill_name));
 548                         atomic_inc_16(&ill->ill_ifptr->illif_mcast_v2);
 549                         ill->ill_mcast_type = IGMP_V2_ROUTER;
 550                 }
 551                 ill->ill_mcast_v2_time = 0;
 552                 ill->ill_mcast_v2_tset = 1;
 553 
 554                 timer = DSEC_TO_MSEC((int)igmpa->igmpa_code);
 555         }
 556 
 557         if (ip_debug > 1) {
 558                 (void) mi_strlog(ill->ill_rq, 1, SL_TRACE,
 559                     "igmp_input: TIMER = igmp_code %d igmp_type 0x%x",
 560                     (int)ntohs(igmpa->igmpa_code),
 561                     (int)ntohs(igmpa->igmpa_type));
 562         }
 563 
 564         /*
 565          * -Start the timers in all of our membership records
 566          *  for the physical interface on which the query
 567          *  arrived, excluding those that belong to the "all
 568          *  hosts" group (224.0.0.1).


1699                             (ill->ill_mcast_v1_time >= OVQP(ill))) {
1700                                 if ((ill->ill_mcast_v2_tset > 0) ||
1701                                     (ipst->ips_igmp_max_version ==
1702                                     IGMP_V2_ROUTER)) {
1703                                         ip1dbg(("V1 query timer "
1704                                             "expired on %s; switching "
1705                                             "mode to IGMP_V2\n",
1706                                             ill->ill_name));
1707                                         ill->ill_mcast_type =
1708                                             IGMP_V2_ROUTER;
1709                                 } else {
1710                                         ip1dbg(("V1 query timer "
1711                                             "expired on %s; switching "
1712                                             "mode to IGMP_V3\n",
1713                                             ill->ill_name));
1714                                         ill->ill_mcast_type =
1715                                             IGMP_V3_ROUTER;
1716                                 }
1717                                 ill->ill_mcast_v1_time = 0;
1718                                 ill->ill_mcast_v1_tset = 0;
1719                                 atomic_dec_16(&ifp->illif_mcast_v1);
1720                         }
1721                         if ((ill->ill_mcast_type == IGMP_V2_ROUTER) &&
1722                             (ipst->ips_igmp_max_version >= IGMP_V3_ROUTER) &&
1723                             (ill->ill_mcast_v2_time >= OVQP(ill))) {
1724                                 ip1dbg(("V2 query timer expired on "
1725                                     "%s; switching mode to IGMP_V3\n",
1726                                     ill->ill_name));
1727                                 ill->ill_mcast_type = IGMP_V3_ROUTER;
1728                                 ill->ill_mcast_v2_time = 0;
1729                                 ill->ill_mcast_v2_tset = 0;
1730                                 atomic_dec_16(&ifp->illif_mcast_v2);
1731                         }
1732                         rw_exit(&ill->ill_mcast_lock);
1733                         ill_refrele(ill);
1734                         rw_enter(&ipst->ips_ill_g_lock, RW_READER);
1735                 }
1736         }
1737         rw_exit(&ipst->ips_ill_g_lock);
1738         ill_mcast_timer_start(ipst);
1739         mutex_enter(&ipst->ips_igmp_slowtimeout_lock);
1740         ipst->ips_igmp_slowtimeout_id = timeout(igmp_slowtimo, (void *)ipst,
1741             MSEC_TO_TICK(MCAST_SLOWTIMO_INTERVAL));
1742         mutex_exit(&ipst->ips_igmp_slowtimeout_lock);
1743 }
1744 
1745 /*
1746  * mld_slowtimo:
1747  * - Resets to newer version if we didn't hear from the older version router
1748  *   in MLD_AGE_THRESHOLD seconds.
1749  * - Restarts slowtimeout.
1750  * Check for ips_mld_max_version ensures that we don't revert to a higher


1769 
1770                 avl_tree = &ifp->illif_avl_by_ppa;
1771                 for (ill = avl_first(avl_tree); ill != NULL;
1772                     ill = avl_walk(avl_tree, ill, AVL_AFTER)) {
1773                         /* Make sure the ill isn't going away. */
1774                         if (!ill_check_and_refhold(ill))
1775                                 continue;
1776                         rw_exit(&ipst->ips_ill_g_lock);
1777                         rw_enter(&ill->ill_mcast_lock, RW_WRITER);
1778                         if (ill->ill_mcast_v1_tset == 1)
1779                                 ill->ill_mcast_v1_time++;
1780                         if ((ill->ill_mcast_type == MLD_V1_ROUTER) &&
1781                             (ipst->ips_mld_max_version >= MLD_V2_ROUTER) &&
1782                             (ill->ill_mcast_v1_time >= OVQP(ill))) {
1783                                 ip1dbg(("MLD query timer expired on"
1784                                     " %s; switching mode to MLD_V2\n",
1785                                     ill->ill_name));
1786                                 ill->ill_mcast_type = MLD_V2_ROUTER;
1787                                 ill->ill_mcast_v1_time = 0;
1788                                 ill->ill_mcast_v1_tset = 0;
1789                                 atomic_dec_16(&ifp->illif_mcast_v1);
1790                         }
1791                         rw_exit(&ill->ill_mcast_lock);
1792                         ill_refrele(ill);
1793                         rw_enter(&ipst->ips_ill_g_lock, RW_READER);
1794                 }
1795         }
1796         rw_exit(&ipst->ips_ill_g_lock);
1797         ill_mcast_timer_start(ipst);
1798         mutex_enter(&ipst->ips_mld_slowtimeout_lock);
1799         ipst->ips_mld_slowtimeout_id = timeout(mld_slowtimo, (void *)ipst,
1800             MSEC_TO_TICK(MCAST_SLOWTIMO_INTERVAL));
1801         mutex_exit(&ipst->ips_mld_slowtimeout_lock);
1802 }
1803 
1804 /*
1805  * igmp_sendpkt:
1806  * This will send to ip_output_simple just like icmp_inbound.
1807  */
1808 static void
1809 igmp_sendpkt(ilm_t *ilm, uchar_t type, ipaddr_t addr)


2199          * INFINITY)
2200          *
2201          * The flag is ilm->ilm_state, it is set to IGMP_OTHERMEMBER if
2202          * we have heard a report from another member, or IGMP_IREPORTEDLAST
2203          * if I sent the last report.
2204          */
2205         v6group = &mldh->mld_addr;
2206         if (!(IN6_IS_ADDR_UNSPECIFIED(v6group)) &&
2207             ((!IN6_IS_ADDR_MULTICAST(v6group)))) {
2208                 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInGroupMembBadQueries);
2209                 return (0);
2210         }
2211 
2212         /* Need to do compatibility mode checking */
2213         rw_enter(&ill->ill_mcast_lock, RW_WRITER);
2214         ill->ill_mcast_v1_time = 0;
2215         ill->ill_mcast_v1_tset = 1;
2216         if (ill->ill_mcast_type == MLD_V2_ROUTER) {
2217                 ip1dbg(("Received MLDv1 Query on %s, switching mode to "
2218                     "MLD_V1_ROUTER\n", ill->ill_name));
2219                 atomic_inc_16(&ill->ill_ifptr->illif_mcast_v1);
2220                 ill->ill_mcast_type = MLD_V1_ROUTER;
2221         }
2222 
2223         timer = (int)ntohs(mldh->mld_maxdelay);
2224         if (ip_debug > 1) {
2225                 (void) mi_strlog(ill->ill_rq, 1, SL_TRACE,
2226                     "mld_input: TIMER = mld_maxdelay %d mld_type 0x%x",
2227                     timer, (int)mldh->mld_type);
2228         }
2229 
2230         /*
2231          * -Start the timers in all of our membership records for
2232          * the physical interface on which the query arrived,
2233          * excl:
2234          *      1.  those that belong to the "all hosts" group,
2235          *      2.  those with 0 scope, or 1 node-local scope.
2236          *
2237          * -Restart any timer that is already running but has a value
2238          * longer that the requested timeout.
2239          * -Use the value specified in the query message as the