back to topotato report
topotato coverage report
Current view: top level - pimd - pim_tib.c (source / functions) Hit Total Coverage
Test: test_pim_cbsr.py::PIMCandidateBSRTest Lines: 0 62 0.0 %
Date: 2023-02-16 02:09:14 Functions: 0 3 0.0 %

          Line data    Source code
       1             : /*
       2             :  * TIB (Tree Information Base) - just PIM <> IGMP/MLD glue for now
       3             :  * Copyright (C) 2022  David Lamparter for NetDEF, Inc.
       4             :  *
       5             :  * This program is free software; you can redistribute it and/or modify it
       6             :  * under the terms of the GNU General Public License as published by the Free
       7             :  * Software Foundation; either version 2 of the License, or (at your option)
       8             :  * any later version.
       9             :  *
      10             :  * This program is distributed in the hope that it will be useful, but WITHOUT
      11             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12             :  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      13             :  * more details.
      14             :  *
      15             :  * You should have received a copy of the GNU General Public License along
      16             :  * with this program; see the file COPYING; if not, write to the Free Software
      17             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      18             :  */
      19             : 
      20             : #include <zebra.h>
      21             : 
      22             : #include "pim_tib.h"
      23             : 
      24             : #include "pimd.h"
      25             : #include "pim_instance.h"
      26             : #include "pim_iface.h"
      27             : #include "pim_upstream.h"
      28             : #include "pim_oil.h"
      29             : #include "pim_nht.h"
      30             : 
      31             : static struct channel_oil *
      32           0 : tib_sg_oil_setup(struct pim_instance *pim, pim_sgaddr sg, struct interface *oif)
      33             : {
      34           0 :         struct pim_interface *pim_oif = oif->info;
      35           0 :         int input_iface_vif_index = 0;
      36           0 :         pim_addr vif_source;
      37           0 :         struct prefix grp;
      38           0 :         struct pim_nexthop nexthop;
      39           0 :         struct pim_upstream *up = NULL;
      40             : 
      41           0 :         if (!pim_rp_set_upstream_addr(pim, &vif_source, sg.src, sg.grp)) {
      42             :                 /* no PIM RP - create a dummy channel oil */
      43           0 :                 return pim_channel_oil_add(pim, &sg, __func__);
      44             :         }
      45             : 
      46           0 :         pim_addr_to_prefix(&grp, sg.grp);
      47             : 
      48           0 :         up = pim_upstream_find(pim, &sg);
      49           0 :         if (up) {
      50           0 :                 memcpy(&nexthop, &up->rpf.source_nexthop,
      51             :                        sizeof(struct pim_nexthop));
      52           0 :                 (void)pim_ecmp_nexthop_lookup(pim, &nexthop, vif_source, &grp,
      53             :                                               0);
      54           0 :                 if (nexthop.interface)
      55           0 :                         input_iface_vif_index = pim_if_find_vifindex_by_ifindex(
      56             :                                 pim, nexthop.interface->ifindex);
      57             :         } else
      58           0 :                 input_iface_vif_index =
      59           0 :                         pim_ecmp_fib_lookup_if_vif_index(pim, vif_source, &grp);
      60             : 
      61           0 :         if (PIM_DEBUG_ZEBRA)
      62           0 :                 zlog_debug("%s: NHT %pSG vif_source %pPAs vif_index:%d",
      63             :                            __func__, &sg, &vif_source, input_iface_vif_index);
      64             : 
      65           0 :         if (input_iface_vif_index < 1) {
      66           0 :                 if (PIM_DEBUG_GM_TRACE)
      67           0 :                         zlog_debug(
      68             :                                 "%s %s: could not find input interface for %pSG",
      69             :                                 __FILE__, __func__, &sg);
      70             : 
      71           0 :                 return pim_channel_oil_add(pim, &sg, __func__);
      72             :         }
      73             : 
      74             :         /*
      75             :          * Protect IGMP against adding looped MFC entries created by both
      76             :          * source and receiver attached to the same interface. See TODO T22.
      77             :          * Block only when the intf is non DR DR must create upstream.
      78             :          */
      79           0 :         if ((input_iface_vif_index == pim_oif->mroute_vif_index) &&
      80           0 :             !(PIM_I_am_DR(pim_oif))) {
      81             :                 /* ignore request for looped MFC entry */
      82           0 :                 if (PIM_DEBUG_GM_TRACE)
      83           0 :                         zlog_debug(
      84             :                                 "%s: ignoring request for looped MFC entry (S,G)=%pSG: oif=%s vif_index=%d",
      85             :                                 __func__, &sg, oif->name,
      86             :                                 input_iface_vif_index);
      87             : 
      88           0 :                 return NULL;
      89             :         }
      90             : 
      91           0 :         return pim_channel_oil_add(pim, &sg, __func__);
      92             : }
      93             : 
      94           0 : bool tib_sg_gm_join(struct pim_instance *pim, pim_sgaddr sg,
      95             :                     struct interface *oif, struct channel_oil **oilp)
      96             : {
      97           0 :         struct pim_interface *pim_oif = oif->info;
      98             : 
      99           0 :         if (!pim_oif) {
     100           0 :                 if (PIM_DEBUG_GM_TRACE)
     101           0 :                         zlog_debug("%s: multicast not enabled on oif=%s?",
     102             :                                    __func__, oif->name);
     103           0 :                 return false;
     104             :         }
     105             : 
     106           0 :         if (!*oilp)
     107           0 :                 *oilp = tib_sg_oil_setup(pim, sg, oif);
     108           0 :         if (!*oilp)
     109             :                 return false;
     110             : 
     111           0 :         if (PIM_I_am_DR(pim_oif) || PIM_I_am_DualActive(pim_oif)) {
     112           0 :                 int result;
     113             : 
     114           0 :                 result = pim_channel_add_oif(*oilp, oif, PIM_OIF_FLAG_PROTO_GM,
     115             :                                              __func__);
     116           0 :                 if (result) {
     117           0 :                         if (PIM_DEBUG_MROUTE)
     118           0 :                                 zlog_warn("%s: add_oif() failed with return=%d",
     119             :                                           __func__, result);
     120           0 :                         return false;
     121             :                 }
     122             :         } else {
     123           0 :                 if (PIM_DEBUG_GM_TRACE)
     124           0 :                         zlog_debug(
     125             :                                 "%s: %pSG was received on %s interface but we are not DR for that interface",
     126             :                                 __func__, &sg, oif->name);
     127             : 
     128           0 :                 return false;
     129             :         }
     130             :         /*
     131             :           Feed IGMPv3-gathered local membership information into PIM
     132             :           per-interface (S,G) state.
     133             :          */
     134           0 :         if (!pim_ifchannel_local_membership_add(oif, &sg, false /*is_vxlan*/)) {
     135           0 :                 if (PIM_DEBUG_MROUTE)
     136           0 :                         zlog_warn(
     137             :                                 "%s: Failure to add local membership for %pSG",
     138             :                                 __func__, &sg);
     139             : 
     140           0 :                 pim_channel_del_oif(*oilp, oif, PIM_OIF_FLAG_PROTO_GM,
     141             :                                     __func__);
     142           0 :                 return false;
     143             :         }
     144             : 
     145             :         return true;
     146             : }
     147             : 
     148           0 : void tib_sg_gm_prune(struct pim_instance *pim, pim_sgaddr sg,
     149             :                      struct interface *oif, struct channel_oil **oilp)
     150             : {
     151           0 :         int result;
     152             : 
     153             :         /*
     154             :          It appears that in certain circumstances that
     155             :          igmp_source_forward_stop is called when IGMP forwarding
     156             :          was not enabled in oif_flags for this outgoing interface.
     157             :          Possibly because of multiple calls. When that happens, we
     158             :          enter the below if statement and this function returns early
     159             :          which in turn triggers the calling function to assert.
     160             :          Making the call to pim_channel_del_oif and ignoring the return code
     161             :          fixes the issue without ill effect, similar to
     162             :          pim_forward_stop below.
     163             :         */
     164           0 :         result = pim_channel_del_oif(*oilp, oif, PIM_OIF_FLAG_PROTO_GM,
     165             :                                      __func__);
     166           0 :         if (result) {
     167           0 :                 if (PIM_DEBUG_GM_TRACE)
     168           0 :                         zlog_debug(
     169             :                                 "%s: pim_channel_del_oif() failed with return=%d",
     170             :                                 __func__, result);
     171           0 :                 return;
     172             :         }
     173             : 
     174             :         /*
     175             :           Feed IGMPv3-gathered local membership information into PIM
     176             :           per-interface (S,G) state.
     177             :          */
     178           0 :         pim_ifchannel_local_membership_del(oif, &sg);
     179             : }

Generated by: LCOV version v1.16-topotato