back to topotato report
topotato coverage report
Current view: top level - pimd - pim_static.c (source / functions) Hit Total Coverage
Test: test_pim_basic2.py::PIMTopo2Test Lines: 0 120 0.0 %
Date: 2023-02-24 18:39:36 Functions: 0 5 0.0 %

          Line data    Source code
       1             : /*
       2             :  * PIM for Quagga: add the ability to configure multicast static routes
       3             :  * Copyright (C) 2014  Nathan Bahr, ATCorp
       4             :  *
       5             :  * This program is free software; you can redistribute it and/or modify
       6             :  * it under the terms of the GNU General Public License as published by
       7             :  * the Free Software Foundation; either version 2 of the License, or
       8             :  * (at your option) any later version.
       9             :  *
      10             :  * This program is distributed in the hope that it will be useful, but
      11             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :  * General Public License for 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 "vty.h"
      23             : #include "if.h"
      24             : #include "log.h"
      25             : #include "memory.h"
      26             : #include "linklist.h"
      27             : 
      28             : #include "pimd.h"
      29             : #include "pim_instance.h"
      30             : #include "pim_oil.h"
      31             : #include "pim_static.h"
      32             : #include "pim_time.h"
      33             : #include "pim_str.h"
      34             : #include "pim_iface.h"
      35             : 
      36           0 : void pim_static_route_free(struct static_route *s_route)
      37             : {
      38           0 :         XFREE(MTYPE_PIM_STATIC_ROUTE, s_route);
      39           0 : }
      40             : 
      41           0 : static struct static_route *static_route_alloc(void)
      42             : {
      43           0 :         return XCALLOC(MTYPE_PIM_STATIC_ROUTE, sizeof(struct static_route));
      44             : }
      45             : 
      46           0 : static struct static_route *static_route_new(ifindex_t iif, ifindex_t oif,
      47             :                                              pim_addr group,
      48             :                                              pim_addr source)
      49             : {
      50           0 :         struct static_route *s_route;
      51           0 :         s_route = static_route_alloc();
      52             : 
      53           0 :         s_route->group = group;
      54           0 :         s_route->source = source;
      55           0 :         s_route->iif = iif;
      56           0 :         s_route->oif_ttls[oif] = 1;
      57           0 :         s_route->c_oil.oil_ref_count = 1;
      58           0 :         *oil_origin(&s_route->c_oil) = source;
      59           0 :         *oil_mcastgrp(&s_route->c_oil) = group;
      60           0 :         *oil_parent(&s_route->c_oil) = iif;
      61           0 :         oil_if_set(&s_route->c_oil, oif, 1);
      62           0 :         s_route->c_oil.oif_creation[oif] = pim_time_monotonic_sec();
      63             : 
      64           0 :         return s_route;
      65             : }
      66             : 
      67             : 
      68           0 : int pim_static_add(struct pim_instance *pim, struct interface *iif,
      69             :                    struct interface *oif, pim_addr group, pim_addr source)
      70             : {
      71           0 :         struct listnode *node = NULL;
      72           0 :         struct static_route *s_route = NULL;
      73           0 :         struct static_route *original_s_route = NULL;
      74           0 :         struct pim_interface *pim_iif = iif ? iif->info : NULL;
      75           0 :         struct pim_interface *pim_oif = oif ? oif->info : NULL;
      76           0 :         ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0;
      77           0 :         ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0;
      78             : 
      79           0 :         if (!iif_index || !oif_index || iif_index == -1 || oif_index == -1) {
      80           0 :                 zlog_warn(
      81             :                         "%s %s: Unable to add static route: Invalid interface index(iif=%d,oif=%d)",
      82             :                         __FILE__, __func__, iif_index, oif_index);
      83           0 :                 return -2;
      84             :         }
      85             : 
      86             : #ifdef PIM_ENFORCE_LOOPFREE_MFC
      87           0 :         if (iif_index == oif_index) {
      88             :                 /* looped MFC entry */
      89           0 :                 zlog_warn(
      90             :                         "%s %s: Unable to add static route: Looped MFC entry(iif=%d,oif=%d)",
      91             :                         __FILE__, __func__, iif_index, oif_index);
      92           0 :                 return -4;
      93             :         }
      94             : #endif
      95           0 :         if (iif->vrf->vrf_id != oif->vrf->vrf_id) {
      96             :                 return -3;
      97             :         }
      98             : 
      99           0 :         for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
     100           0 :                 if (!pim_addr_cmp(s_route->group, group) &&
     101           0 :                     !pim_addr_cmp(s_route->source, source) &&
     102           0 :                     (s_route->iif == iif_index)) {
     103             : 
     104           0 :                         if (s_route->oif_ttls[oif_index]) {
     105           0 :                                 zlog_warn(
     106             :                                         "%s %s: Unable to add static route: Route already exists (iif=%d,oif=%d,group=%pPAs,source=%pPAs)",
     107             :                                         __FILE__, __func__, iif_index,
     108             :                                         oif_index, &group, &source);
     109           0 :                                 return -3;
     110             :                         }
     111             : 
     112             :                         /* Ok, from here on out we will be making changes to the
     113             :                          * s_route structure, but if
     114             :                          * for some reason we fail to commit these changes to
     115             :                          * the kernel, we want to be able
     116             :                          * restore the state of the list. So copy the node data
     117             :                          * and if need be, we can copy
     118             :                          * back if it fails.
     119             :                          */
     120           0 :                         original_s_route = static_route_alloc();
     121           0 :                         memcpy(original_s_route, s_route,
     122             :                                sizeof(struct static_route));
     123             : 
     124             :                         /* Route exists and has the same input interface, but
     125             :                          * adding a new output interface */
     126           0 :                         s_route->oif_ttls[oif_index] = 1;
     127           0 :                         oil_if_set(&s_route->c_oil, oif_index, 1);
     128           0 :                         s_route->c_oil.oif_creation[oif_index] =
     129           0 :                                 pim_time_monotonic_sec();
     130           0 :                         ++s_route->c_oil.oil_ref_count;
     131           0 :                         break;
     132             :                 }
     133             :         }
     134             : 
     135             :         /* If node is null then we reached the end of the list without finding a
     136             :          * match */
     137           0 :         if (!node) {
     138           0 :                 s_route = static_route_new(iif_index, oif_index, group, source);
     139           0 :                 listnode_add(pim->static_routes, s_route);
     140             :         }
     141             : 
     142           0 :         s_route->c_oil.pim = pim;
     143             : 
     144           0 :         if (pim_static_mroute_add(&s_route->c_oil, __func__)) {
     145           0 :                 zlog_warn(
     146             :                         "%s %s: Unable to add static route(iif=%d,oif=%d,group=%pPAs,source=%pPAs)",
     147             :                         __FILE__, __func__, iif_index, oif_index, &group,
     148             :                         &source);
     149             : 
     150             :                 /* Need to put s_route back to the way it was */
     151           0 :                 if (original_s_route) {
     152           0 :                         memcpy(s_route, original_s_route,
     153             :                                sizeof(struct static_route));
     154             :                 } else {
     155             :                         /* we never stored off a copy, so it must have been a
     156             :                          * fresh new route */
     157           0 :                         listnode_delete(pim->static_routes, s_route);
     158           0 :                         pim_static_route_free(s_route);
     159             :                 }
     160             : 
     161           0 :                 if (original_s_route) {
     162           0 :                         pim_static_route_free(original_s_route);
     163             :                 }
     164             : 
     165           0 :                 return -1;
     166             :         }
     167             : 
     168             :         /* Make sure we free the memory for the route copy if used */
     169           0 :         if (original_s_route) {
     170           0 :                 pim_static_route_free(original_s_route);
     171             :         }
     172             : 
     173           0 :         if (PIM_DEBUG_STATIC) {
     174           0 :                 zlog_debug(
     175             :                         "%s: Static route added(iif=%d,oif=%d,group=%pPAs,source=%pPAs)",
     176             :                         __func__, iif_index, oif_index, &group,
     177             :                         &source);
     178             :         }
     179             : 
     180             :         return 0;
     181             : }
     182             : 
     183           0 : int pim_static_del(struct pim_instance *pim, struct interface *iif,
     184             :                    struct interface *oif, pim_addr group, pim_addr source)
     185             : {
     186           0 :         struct listnode *node = NULL;
     187           0 :         struct listnode *nextnode = NULL;
     188           0 :         struct static_route *s_route = NULL;
     189           0 :         struct pim_interface *pim_iif = iif ? iif->info : 0;
     190           0 :         struct pim_interface *pim_oif = oif ? oif->info : 0;
     191           0 :         ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0;
     192           0 :         ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0;
     193             : 
     194           0 :         if (!iif_index || !oif_index) {
     195           0 :                 zlog_warn(
     196             :                         "%s %s: Unable to remove static route: Invalid interface index(iif=%d,oif=%d)",
     197             :                         __FILE__, __func__, iif_index, oif_index);
     198           0 :                 return -2;
     199             :         }
     200             : 
     201           0 :         for (ALL_LIST_ELEMENTS(pim->static_routes, node, nextnode, s_route)) {
     202           0 :                 if (s_route->iif == iif_index
     203           0 :                     && !pim_addr_cmp(s_route->group, group)
     204           0 :                     && !pim_addr_cmp(s_route->source, source)
     205           0 :                     && s_route->oif_ttls[oif_index]) {
     206           0 :                         s_route->oif_ttls[oif_index] = 0;
     207           0 :                         oil_if_set(&s_route->c_oil, oif_index, 0);
     208           0 :                         --s_route->c_oil.oil_ref_count;
     209             : 
     210             :                         /* If there are no more outputs then delete the whole
     211             :                          * route, otherwise set the route with the new outputs
     212             :                          */
     213           0 :                         if (s_route->c_oil.oil_ref_count <= 0
     214           0 :                                     ? pim_mroute_del(&s_route->c_oil, __func__)
     215           0 :                                     : pim_static_mroute_add(&s_route->c_oil,
     216             :                                                             __func__)) {
     217           0 :                                 zlog_warn(
     218             :                                         "%s %s: Unable to remove static route(iif=%d,oif=%d,group=%pPAs,source=%pPAs)",
     219             :                                         __FILE__, __func__, iif_index,
     220             :                                         oif_index, &group, &source);
     221             : 
     222           0 :                                 s_route->oif_ttls[oif_index] = 1;
     223           0 :                                 oil_if_set(&s_route->c_oil, oif_index, 1);
     224           0 :                                 ++s_route->c_oil.oil_ref_count;
     225             : 
     226           0 :                                 return -1;
     227             :                         }
     228             : 
     229           0 :                         s_route->c_oil.oif_creation[oif_index] = 0;
     230             : 
     231           0 :                         if (s_route->c_oil.oil_ref_count <= 0) {
     232           0 :                                 listnode_delete(pim->static_routes, s_route);
     233           0 :                                 pim_static_route_free(s_route);
     234             :                         }
     235             : 
     236           0 :                         if (PIM_DEBUG_STATIC) {
     237           0 :                                 zlog_debug(
     238             :                                         "%s: Static route removed(iif=%d,oif=%d,group=%pPAs,source=%pPAs)",
     239             :                                         __func__, iif_index, oif_index,
     240             :                                         &group, &source);
     241             :                         }
     242             : 
     243             :                         break;
     244             :                 }
     245             :         }
     246             : 
     247           0 :         if (!node) {
     248           0 :                 zlog_warn(
     249             :                         "%s %s: Unable to remove static route: Route does not exist(iif=%d,oif=%d,group=%pPAs,source=%pPAs)",
     250             :                         __FILE__, __func__, iif_index, oif_index, &group,
     251             :                         &source);
     252           0 :                 return -3;
     253             :         }
     254             : 
     255             :         return 0;
     256             : }
     257             : 
     258           0 : int pim_static_write_mroute(struct pim_instance *pim, struct vty *vty,
     259             :                             struct interface *ifp)
     260             : {
     261           0 :         struct pim_interface *pim_ifp = ifp->info;
     262           0 :         struct listnode *node;
     263           0 :         struct static_route *sroute;
     264           0 :         int count = 0;
     265             : 
     266           0 :         if (!pim_ifp)
     267             :                 return 0;
     268             : 
     269           0 :         for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sroute)) {
     270           0 :                 if (sroute->iif == pim_ifp->mroute_vif_index) {
     271             :                         int i;
     272           0 :                         for (i = 0; i < MAXVIFS; i++)
     273           0 :                                 if (sroute->oif_ttls[i]) {
     274           0 :                                         struct interface *oifp =
     275           0 :                                                 pim_if_find_by_vif_index(pim,
     276             :                                                                          i);
     277           0 :                                         if (pim_addr_is_any(sroute->source))
     278           0 :                                                 vty_out(vty,
     279             :                                                         " " PIM_AF_NAME " mroute %s %pPA\n",
     280           0 :                                                         oifp->name, &sroute->group);
     281             :                                         else
     282           0 :                                                 vty_out(vty,
     283             :                                                         " " PIM_AF_NAME " mroute %s %pPA %pPA\n",
     284           0 :                                                         oifp->name, &sroute->group,
     285             :                                                         &sroute->source);
     286           0 :                                         count++;
     287             :                                 }
     288             :                 }
     289             :         }
     290             : 
     291             :         return count;
     292             : }

Generated by: LCOV version v1.16-topotato