back to topotato report
topotato coverage report
Current view: top level - staticd - static_routes.c (source / functions) Hit Total Coverage
Test: test_pim_crp.py::PIMCandidateBSRTest Lines: 171 417 41.0 %
Date: 2023-02-16 02:09:37 Functions: 22 34 64.7 %

          Line data    Source code
       1             : /*
       2             :  * STATICd - route code
       3             :  * Copyright (C) 2018 Cumulus Networks, Inc.
       4             :  *               Donald Sharp
       5             :  *
       6             :  * This program is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the Free
       8             :  * Software Foundation; either version 2 of the License, or (at your option)
       9             :  * any later version.
      10             :  *
      11             :  * This program is distributed in the hope that it will be useful, but WITHOUT
      12             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13             :  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      14             :  * more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : #include <zebra.h>
      21             : 
      22             : #include <lib/nexthop.h>
      23             : #include <lib/memory.h>
      24             : #include <lib/srcdest_table.h>
      25             : #include <lib/if.h>
      26             : #include <lib/vty.h>
      27             : #include <lib/vrf.h>
      28             : #include <lib/memory.h>
      29             : 
      30             : #include "printfrr.h"
      31             : 
      32             : #include "static_vrf.h"
      33             : #include "static_routes.h"
      34             : #include "static_zebra.h"
      35             : #include "static_debug.h"
      36             : 
      37           9 : DEFINE_MGROUP(STATIC, "staticd");
      38             : 
      39           9 : DEFINE_MTYPE_STATIC(STATIC, STATIC_ROUTE,   "Static Route Info");
      40           9 : DEFINE_MTYPE_STATIC(STATIC, STATIC_PATH,    "Static Path");
      41           9 : DEFINE_MTYPE_STATIC(STATIC, STATIC_NEXTHOP, "Static Nexthop");
      42             : 
      43           9 : void zebra_stable_node_cleanup(struct route_table *table,
      44             :                                struct route_node *node)
      45             : {
      46           9 :         struct static_nexthop *nh;
      47           9 :         struct static_path *pn;
      48           9 :         struct static_route_info *si;
      49           9 :         struct route_table *src_table;
      50           9 :         struct route_node *src_node;
      51           9 :         struct static_path *src_pn;
      52           9 :         struct static_route_info *src_si;
      53             : 
      54           9 :         si = node->info;
      55             : 
      56           9 :         if (si) {
      57          18 :                 frr_each_safe(static_path_list, &si->path_list, pn) {
      58          18 :                         frr_each_safe(static_nexthop_list, &pn->nexthop_list,
      59             :                                        nh) {
      60           6 :                                 static_nexthop_list_del(&pn->nexthop_list, nh);
      61           6 :                                 XFREE(MTYPE_STATIC_NEXTHOP, nh);
      62             :                         }
      63           6 :                         static_path_list_del(&si->path_list, pn);
      64           6 :                         XFREE(MTYPE_STATIC_PATH, pn);
      65             :                 }
      66             : 
      67             :                 /* clean up for dst table */
      68           6 :                 src_table = srcdest_srcnode_table(node);
      69           6 :                 if (src_table) {
      70             :                         /* This means the route_node is part of the top
      71             :                          * hierarchy and refers to a destination prefix.
      72             :                          */
      73           0 :                         for (src_node = route_top(src_table); src_node;
      74           0 :                              src_node = route_next(src_node)) {
      75           0 :                                 src_si = src_node->info;
      76             : 
      77           0 :                                 frr_each_safe(static_path_list,
      78             :                                               &src_si->path_list, src_pn) {
      79           0 :                                         frr_each_safe(static_nexthop_list,
      80             :                                                       &src_pn->nexthop_list,
      81             :                                                       nh) {
      82           0 :                                                 static_nexthop_list_del(
      83             :                                                         &src_pn->nexthop_list,
      84             :                                                         nh);
      85           0 :                                                 XFREE(MTYPE_STATIC_NEXTHOP, nh);
      86             :                                         }
      87           0 :                                         static_path_list_del(&src_si->path_list,
      88             :                                                              src_pn);
      89           0 :                                         XFREE(MTYPE_STATIC_PATH, src_pn);
      90             :                                 }
      91             : 
      92           0 :                                 XFREE(MTYPE_STATIC_ROUTE, src_node->info);
      93             :                         }
      94             :                 }
      95             : 
      96           6 :                 XFREE(MTYPE_STATIC_ROUTE, node->info);
      97             :         }
      98           9 : }
      99             : 
     100             : /* Install static path into rib. */
     101           0 : void static_install_path(struct static_path *pn)
     102             : {
     103           0 :         struct static_nexthop *nh;
     104             : 
     105           0 :         frr_each(static_nexthop_list, &pn->nexthop_list, nh)
     106           0 :                 static_zebra_nht_register(nh, true);
     107             : 
     108           0 :         if (static_nexthop_list_count(&pn->nexthop_list))
     109           0 :                 static_zebra_route_add(pn, true);
     110           0 : }
     111             : 
     112             : /* Uninstall static path from RIB. */
     113           0 : static void static_uninstall_path(struct static_path *pn)
     114             : {
     115           0 :         if (static_nexthop_list_count(&pn->nexthop_list))
     116           0 :                 static_zebra_route_add(pn, true);
     117             :         else
     118           0 :                 static_zebra_route_add(pn, false);
     119           0 : }
     120             : 
     121           6 : struct route_node *static_add_route(afi_t afi, safi_t safi, struct prefix *p,
     122             :                                     struct prefix_ipv6 *src_p,
     123             :                                     struct static_vrf *svrf)
     124             : {
     125           6 :         struct route_node *rn;
     126           6 :         struct static_route_info *si;
     127           6 :         struct route_table *stable = svrf->stable[afi][safi];
     128             : 
     129           6 :         assert(stable);
     130             : 
     131             :         /* Lookup static route prefix. */
     132           6 :         rn = srcdest_rnode_get(stable, p, src_p);
     133             : 
     134           6 :         si = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(struct static_route_info));
     135             : 
     136           6 :         si->svrf = svrf;
     137           6 :         si->safi = safi;
     138           6 :         static_path_list_init(&(si->path_list));
     139             : 
     140           6 :         rn->info = si;
     141             : 
     142           6 :         return rn;
     143             : }
     144             : 
     145             : /* To delete the srcnodes */
     146           0 : static void static_del_src_route(struct route_node *rn)
     147             : {
     148           0 :         struct static_path *pn;
     149           0 :         struct static_route_info *si;
     150             : 
     151           0 :         si = rn->info;
     152             : 
     153           0 :         frr_each_safe(static_path_list, &si->path_list, pn) {
     154           0 :                 static_del_path(pn);
     155             :         }
     156             : 
     157           0 :         XFREE(MTYPE_STATIC_ROUTE, rn->info);
     158           0 :         route_unlock_node(rn);
     159           0 : }
     160             : 
     161           0 : void static_del_route(struct route_node *rn)
     162             : {
     163           0 :         struct static_path *pn;
     164           0 :         struct static_route_info *si;
     165           0 :         struct route_table *src_table;
     166           0 :         struct route_node *src_node;
     167             : 
     168           0 :         si = rn->info;
     169             : 
     170           0 :         frr_each_safe(static_path_list, &si->path_list, pn) {
     171           0 :                 static_del_path(pn);
     172             :         }
     173             : 
     174             :         /* clean up for dst table */
     175           0 :         src_table = srcdest_srcnode_table(rn);
     176           0 :         if (src_table) {
     177             :                 /* This means the route_node is part of the top hierarchy
     178             :                  * and refers to a destination prefix.
     179             :                  */
     180           0 :                 for (src_node = route_top(src_table); src_node;
     181           0 :                      src_node = route_next(src_node)) {
     182           0 :                         static_del_src_route(src_node);
     183             :                 }
     184             :         }
     185           0 :         XFREE(MTYPE_STATIC_ROUTE, rn->info);
     186           0 :         route_unlock_node(rn);
     187           0 : }
     188             : 
     189           6 : bool static_add_nexthop_validate(const char *nh_vrf_name,
     190             :                                  enum static_nh_type type,
     191             :                                  struct ipaddr *ipaddr)
     192             : {
     193           6 :         struct vrf *vrf;
     194             : 
     195           6 :         vrf = vrf_lookup_by_name(nh_vrf_name);
     196           6 :         if (!vrf)
     197             :                 return true;
     198             : 
     199           6 :         switch (type) {
     200           6 :         case STATIC_IPV4_GATEWAY:
     201             :         case STATIC_IPV4_GATEWAY_IFNAME:
     202           6 :                 if (if_address_is_local(&ipaddr->ipaddr_v4, AF_INET,
     203             :                                         vrf->vrf_id))
     204             :                         return false;
     205             :                 break;
     206           0 :         case STATIC_IPV6_GATEWAY:
     207             :         case STATIC_IPV6_GATEWAY_IFNAME:
     208           0 :                 if (if_address_is_local(&ipaddr->ipaddr_v6, AF_INET6,
     209             :                                         vrf->vrf_id))
     210             :                         return false;
     211             :                 break;
     212             :         case STATIC_IFNAME:
     213             :         case STATIC_BLACKHOLE:
     214             :                 break;
     215             :         }
     216             : 
     217             :         return true;
     218             : }
     219             : 
     220           6 : struct static_path *static_add_path(struct route_node *rn, uint32_t table_id,
     221             :                                     uint8_t distance)
     222             : {
     223           6 :         struct static_path *pn;
     224           6 :         struct static_route_info *si;
     225             : 
     226           6 :         route_lock_node(rn);
     227             : 
     228             :         /* Make new static route structure. */
     229           6 :         pn = XCALLOC(MTYPE_STATIC_PATH, sizeof(struct static_path));
     230             : 
     231           6 :         pn->rn = rn;
     232           6 :         pn->distance = distance;
     233           6 :         pn->table_id = table_id;
     234           6 :         static_nexthop_list_init(&(pn->nexthop_list));
     235             : 
     236           6 :         si = rn->info;
     237           6 :         static_path_list_add_head(&(si->path_list), pn);
     238             : 
     239           6 :         return pn;
     240             : }
     241             : 
     242           0 : void static_del_path(struct static_path *pn)
     243             : {
     244           0 :         struct route_node *rn = pn->rn;
     245           0 :         struct static_route_info *si;
     246           0 :         struct static_nexthop *nh;
     247             : 
     248           0 :         si = rn->info;
     249             : 
     250           0 :         static_path_list_del(&si->path_list, pn);
     251             : 
     252           0 :         frr_each_safe(static_nexthop_list, &pn->nexthop_list, nh) {
     253           0 :                 static_delete_nexthop(nh);
     254             :         }
     255             : 
     256           0 :         route_unlock_node(rn);
     257             : 
     258           0 :         XFREE(MTYPE_STATIC_PATH, pn);
     259           0 : }
     260             : 
     261           6 : struct static_nexthop *static_add_nexthop(struct static_path *pn,
     262             :                                           enum static_nh_type type,
     263             :                                           struct ipaddr *ipaddr,
     264             :                                           const char *ifname,
     265             :                                           const char *nh_vrf, uint32_t color)
     266             : {
     267           6 :         struct route_node *rn = pn->rn;
     268           6 :         struct static_nexthop *nh;
     269           6 :         struct static_vrf *nh_svrf;
     270           6 :         struct interface *ifp;
     271           6 :         struct static_nexthop *cp;
     272             : 
     273           6 :         route_lock_node(rn);
     274             : 
     275           6 :         nh_svrf = static_vrf_lookup_by_name(nh_vrf);
     276             : 
     277             :         /* Make new static route structure. */
     278           6 :         nh = XCALLOC(MTYPE_STATIC_NEXTHOP, sizeof(struct static_nexthop));
     279             : 
     280             :         /* Copy back pointers. */
     281           6 :         nh->rn = rn;
     282           6 :         nh->pn = pn;
     283             : 
     284           6 :         nh->type = type;
     285           6 :         nh->color = color;
     286             : 
     287           6 :         if (nh->type == STATIC_BLACKHOLE)
     288           0 :                 nh->bh_type = STATIC_BLACKHOLE_NULL;
     289             : 
     290           6 :         nh->nh_vrf_id = nh_svrf ? nh_svrf->vrf->vrf_id : VRF_UNKNOWN;
     291           6 :         strlcpy(nh->nh_vrfname, nh_vrf, sizeof(nh->nh_vrfname));
     292             : 
     293           6 :         if (ifname)
     294           6 :                 strlcpy(nh->ifname, ifname, sizeof(nh->ifname));
     295           6 :         nh->ifindex = IFINDEX_INTERNAL;
     296             : 
     297           6 :         switch (type) {
     298           6 :         case STATIC_IPV4_GATEWAY:
     299             :         case STATIC_IPV4_GATEWAY_IFNAME:
     300           6 :                 nh->addr.ipv4 = ipaddr->ipaddr_v4;
     301           6 :                 break;
     302           0 :         case STATIC_IPV6_GATEWAY:
     303             :         case STATIC_IPV6_GATEWAY_IFNAME:
     304           0 :                 nh->addr.ipv6 = ipaddr->ipaddr_v6;
     305           0 :                 break;
     306             :         case STATIC_IFNAME:
     307             :         case STATIC_BLACKHOLE:
     308             :                 break;
     309             :         }
     310             :         /*
     311             :          * Add new static route information to the tree with sort by
     312             :          * gateway address.
     313             :          */
     314          12 :         frr_each(static_nexthop_list, &pn->nexthop_list, cp) {
     315           0 :                 if (nh->type == STATIC_IPV4_GATEWAY
     316           0 :                     && cp->type == STATIC_IPV4_GATEWAY) {
     317           0 :                         if (ntohl(nh->addr.ipv4.s_addr)
     318           0 :                             < ntohl(cp->addr.ipv4.s_addr))
     319             :                                 break;
     320             :                         if (ntohl(nh->addr.ipv4.s_addr)
     321             :                             > ntohl(cp->addr.ipv4.s_addr))
     322             :                                 continue;
     323             :                 }
     324             :         }
     325           6 :         static_nexthop_list_add_after(&(pn->nexthop_list), cp, nh);
     326             : 
     327           6 :         if (nh->nh_vrf_id == VRF_UNKNOWN) {
     328           0 :                 zlog_warn(
     329             :                         "Static Route to %pFX not installed currently because dependent config not fully available",
     330             :                         &rn->p);
     331           0 :                 return nh;
     332             :         }
     333             : 
     334             :         /* check whether interface exists in system & install if it does */
     335           6 :         switch (nh->type) {
     336             :         case STATIC_IPV4_GATEWAY:
     337             :         case STATIC_IPV6_GATEWAY:
     338             :         case STATIC_BLACKHOLE:
     339             :                 break;
     340           0 :         case STATIC_IPV4_GATEWAY_IFNAME:
     341             :         case STATIC_IPV6_GATEWAY_IFNAME:
     342             :         case STATIC_IFNAME:
     343           0 :                 ifp = if_lookup_by_name(ifname, nh->nh_vrf_id);
     344           0 :                 if (ifp && ifp->ifindex != IFINDEX_INTERNAL)
     345           0 :                         nh->ifindex = ifp->ifindex;
     346             :                 else
     347           0 :                         zlog_warn(
     348             :                                 "Static Route using %s interface not installed because the interface does not exist in specified vrf",
     349             :                                 ifname);
     350             :                 break;
     351             :         }
     352             : 
     353             :         return nh;
     354             : }
     355             : 
     356           6 : void static_install_nexthop(struct static_nexthop *nh)
     357             : {
     358           6 :         struct static_path *pn = nh->pn;
     359           6 :         struct route_node *rn = pn->rn;
     360           6 :         struct interface *ifp;
     361             : 
     362           6 :         if (nh->nh_vrf_id == VRF_UNKNOWN) {
     363           0 :                 char nexthop_str[NEXTHOP_STR];
     364             : 
     365           0 :                 static_get_nh_str(nh, nexthop_str, sizeof(nexthop_str));
     366           0 :                 DEBUGD(&static_dbg_route,
     367             :                        "Static Route %pFX not installed for %s vrf %s is unknown",
     368             :                        &rn->p, nexthop_str, nh->nh_vrfname);
     369           0 :                 return;
     370             :         }
     371             : 
     372             :         /* check whether interface exists in system & install if it does */
     373           6 :         switch (nh->type) {
     374           6 :         case STATIC_IPV4_GATEWAY:
     375             :         case STATIC_IPV6_GATEWAY:
     376           6 :                 static_zebra_nht_register(nh, true);
     377           6 :                 break;
     378           0 :         case STATIC_IPV4_GATEWAY_IFNAME:
     379             :         case STATIC_IPV6_GATEWAY_IFNAME:
     380           0 :                 static_zebra_nht_register(nh, true);
     381           0 :                 break;
     382           0 :         case STATIC_BLACKHOLE:
     383           0 :                 static_install_path(pn);
     384           0 :                 break;
     385           0 :         case STATIC_IFNAME:
     386           0 :                 ifp = if_lookup_by_name(nh->ifname, nh->nh_vrf_id);
     387           0 :                 if (ifp && ifp->ifindex != IFINDEX_INTERNAL)
     388           0 :                         static_install_path(pn);
     389             : 
     390             :                 break;
     391             :         }
     392             : }
     393             : 
     394           0 : void static_delete_nexthop(struct static_nexthop *nh)
     395             : {
     396           0 :         struct static_path *pn = nh->pn;
     397           0 :         struct route_node *rn = pn->rn;
     398             : 
     399           0 :         static_nexthop_list_del(&(pn->nexthop_list), nh);
     400             :         /* Remove BFD session/configuration if any. */
     401           0 :         bfd_sess_free(&nh->bsp);
     402             : 
     403           0 :         if (nh->nh_vrf_id == VRF_UNKNOWN)
     404           0 :                 goto EXIT;
     405             : 
     406           0 :         static_zebra_nht_register(nh, false);
     407             :         /*
     408             :          * If we have other si nodes then route replace
     409             :          * else delete the route
     410             :          */
     411           0 :         static_uninstall_path(pn);
     412             : 
     413           0 : EXIT:
     414           0 :         route_unlock_node(rn);
     415             :         /* Free static route configuration. */
     416           0 :         XFREE(MTYPE_STATIC_NEXTHOP, nh);
     417           0 : }
     418             : 
     419          58 : static void static_ifindex_update_nh(struct interface *ifp, bool up,
     420             :                                      struct route_node *rn,
     421             :                                      struct static_path *pn,
     422             :                                      struct static_nexthop *nh,
     423             :                                      struct static_vrf *svrf, safi_t safi)
     424             : {
     425          58 :         if (!nh->ifname[0])
     426             :                 return;
     427          58 :         if (up) {
     428          42 :                 if (strcmp(nh->ifname, ifp->name))
     429             :                         return;
     430           0 :                 if (nh->nh_vrf_id != ifp->vrf->vrf_id)
     431             :                         return;
     432           0 :                 nh->ifindex = ifp->ifindex;
     433             :         } else {
     434          16 :                 if (nh->ifindex != ifp->ifindex)
     435             :                         return;
     436           0 :                 if (nh->nh_vrf_id != ifp->vrf->vrf_id)
     437             :                         return;
     438           0 :                 nh->ifindex = IFINDEX_INTERNAL;
     439             :         }
     440             : 
     441             :         /* Remove previously configured route if any. */
     442           0 :         static_uninstall_path(pn);
     443           0 :         static_install_path(pn);
     444             : }
     445             : 
     446         116 : static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi,
     447             :                                      safi_t safi)
     448             : {
     449         116 :         struct route_table *stable;
     450         116 :         struct route_node *rn;
     451         116 :         struct static_nexthop *nh;
     452         116 :         struct static_path *pn;
     453         116 :         struct vrf *vrf;
     454         116 :         struct static_route_info *si;
     455             : 
     456         348 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
     457         116 :                 struct static_vrf *svrf;
     458             : 
     459         116 :                 svrf = vrf->info;
     460             : 
     461         116 :                 stable = static_vrf_static_table(afi, safi, svrf);
     462         116 :                 if (!stable)
     463           0 :                         continue;
     464         203 :                 for (rn = route_top(stable); rn; rn = srcdest_route_next(rn)) {
     465          87 :                         si = static_route_info_from_rnode(rn);
     466          87 :                         if (!si)
     467          29 :                                 continue;
     468         232 :                         frr_each(static_path_list, &si->path_list, pn) {
     469         232 :                                 frr_each(static_nexthop_list,
     470             :                                           &pn->nexthop_list, nh) {
     471          58 :                                         static_ifindex_update_nh(ifp, up, rn,
     472             :                                                                  pn, nh, svrf,
     473             :                                                                  safi);
     474             :                                 }
     475             :                         }
     476             :                 }
     477             :         }
     478         116 : }
     479             : 
     480             : /*
     481             :  * This function looks at a svrf's stable and notices if any of the
     482             :  * nexthops we are using are part of the vrf coming up.
     483             :  * If we are using them then cleanup the nexthop vrf id
     484             :  * to be the new value and then re-installs them
     485             :  *
     486             :  *
     487             :  * stable -> The table we are looking at.
     488             :  * svrf -> The newly changed vrf.
     489             :  * afi -> The afi to look at
     490             :  * safi -> the safi to look at
     491             :  */
     492          24 : static void static_fixup_vrf(struct static_vrf *svrf,
     493             :                              struct route_table *stable, afi_t afi, safi_t safi)
     494             : {
     495          24 :         struct route_node *rn;
     496          24 :         struct static_nexthop *nh;
     497          24 :         struct interface *ifp;
     498          24 :         struct static_path *pn;
     499          24 :         struct static_route_info *si;
     500             : 
     501          24 :         for (rn = route_top(stable); rn; rn = route_next(rn)) {
     502           0 :                 si = static_route_info_from_rnode(rn);
     503           0 :                 if (!si)
     504           0 :                         continue;
     505           0 :                 frr_each(static_path_list, &si->path_list, pn) {
     506           0 :                         frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
     507           0 :                                 if (strcmp(svrf->vrf->name, nh->nh_vrfname)
     508             :                                     != 0)
     509           0 :                                         continue;
     510             : 
     511           0 :                                 nh->nh_vrf_id = svrf->vrf->vrf_id;
     512           0 :                                 nh->nh_registered = false;
     513           0 :                                 if (nh->ifindex) {
     514           0 :                                         ifp = if_lookup_by_name(nh->ifname,
     515             :                                                                 nh->nh_vrf_id);
     516           0 :                                         if (ifp)
     517           0 :                                                 nh->ifindex = ifp->ifindex;
     518             :                                         else
     519           0 :                                                 continue;
     520             :                                 }
     521             : 
     522           0 :                                 static_install_path(pn);
     523             :                         }
     524             :                 }
     525             :         }
     526          24 : }
     527             : 
     528             : /*
     529             :  * This function enables static routes in a svrf as it
     530             :  * is coming up.  It sets the new vrf_id as appropriate.
     531             :  *
     532             :  * svrf -> The svrf that is being brought up and enabled by the kernel
     533             :  * stable -> The stable we are looking at.
     534             :  * afi -> the afi in question
     535             :  * safi -> the safi in question
     536             :  */
     537          24 : static void static_enable_vrf(struct static_vrf *svrf,
     538             :                               struct route_table *stable, afi_t afi,
     539             :                               safi_t safi)
     540             : {
     541          24 :         struct route_node *rn;
     542          24 :         struct static_nexthop *nh;
     543          24 :         struct interface *ifp;
     544          24 :         struct static_path *pn;
     545          24 :         struct static_route_info *si;
     546             : 
     547          24 :         for (rn = route_top(stable); rn; rn = route_next(rn)) {
     548           0 :                 si = static_route_info_from_rnode(rn);
     549           0 :                 if (!si)
     550           0 :                         continue;
     551           0 :                 frr_each(static_path_list, &si->path_list, pn) {
     552           0 :                         frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
     553           0 :                                 if (nh->ifindex) {
     554           0 :                                         ifp = if_lookup_by_name(nh->ifname,
     555             :                                                                 nh->nh_vrf_id);
     556           0 :                                         if (ifp)
     557           0 :                                                 nh->ifindex = ifp->ifindex;
     558             :                                         else
     559           0 :                                                 continue;
     560             :                                 }
     561           0 :                                 if (nh->nh_vrf_id == VRF_UNKNOWN)
     562           0 :                                         continue;
     563           0 :                                 static_install_path(pn);
     564             :                         }
     565             :                 }
     566             :         }
     567          24 : }
     568             : 
     569             : /*
     570             :  * When a vrf is being enabled by the kernel, go through all the
     571             :  * static routes in the system that use this vrf (both nexthops vrfs
     572             :  * and the routes vrf )
     573             :  *
     574             :  * enable_svrf -> the vrf being enabled
     575             :  */
     576           6 : void static_fixup_vrf_ids(struct static_vrf *enable_svrf)
     577             : {
     578           6 :         struct route_table *stable;
     579           6 :         struct vrf *vrf;
     580           6 :         afi_t afi;
     581           6 :         safi_t safi;
     582             : 
     583          18 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
     584           6 :                 struct static_vrf *svrf;
     585             : 
     586           6 :                 svrf = vrf->info;
     587             :                 /* Install any static routes configured for this VRF. */
     588         150 :                 FOREACH_AFI_SAFI (afi, safi) {
     589         126 :                         stable = svrf->stable[afi][safi];
     590         126 :                         if (!stable)
     591         102 :                                 continue;
     592             : 
     593          24 :                         static_fixup_vrf(enable_svrf, stable, afi, safi);
     594             : 
     595          24 :                         if (enable_svrf == svrf)
     596          24 :                                 static_enable_vrf(svrf, stable, afi, safi);
     597             :                 }
     598             :         }
     599           6 : }
     600             : 
     601             : /*
     602             :  * Look at the specified stable and if any of the routes in
     603             :  * this table are using the svrf as the nexthop, uninstall
     604             :  * those routes.
     605             :  *
     606             :  * svrf -> the vrf being disabled
     607             :  * stable -> the table we need to look at.
     608             :  * afi -> the afi in question
     609             :  * safi -> the safi in question
     610             :  */
     611           0 : static void static_cleanup_vrf(struct static_vrf *svrf,
     612             :                                struct route_table *stable,
     613             :                                afi_t afi, safi_t safi)
     614             : {
     615           0 :         struct route_node *rn;
     616           0 :         struct static_nexthop *nh;
     617           0 :         struct static_path *pn;
     618           0 :         struct static_route_info *si;
     619             : 
     620           0 :         for (rn = route_top(stable); rn; rn = route_next(rn)) {
     621           0 :                 si = static_route_info_from_rnode(rn);
     622           0 :                 if (!si)
     623           0 :                         continue;
     624           0 :                 frr_each(static_path_list, &si->path_list, pn) {
     625           0 :                         frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
     626           0 :                                 if (strcmp(svrf->vrf->name, nh->nh_vrfname)
     627             :                                     != 0)
     628           0 :                                         continue;
     629             : 
     630           0 :                                 static_uninstall_path(pn);
     631             :                         }
     632             :                 }
     633             :         }
     634           0 : }
     635             : 
     636             : /*
     637             :  * Look at all static routes in this table and uninstall
     638             :  * them.
     639             :  *
     640             :  * stable -> The table to uninstall from
     641             :  * afi -> The afi in question
     642             :  * safi -> the safi in question
     643             :  */
     644           0 : static void static_disable_vrf(struct route_table *stable,
     645             :                                afi_t afi, safi_t safi)
     646             : {
     647           0 :         struct route_node *rn;
     648           0 :         struct static_nexthop *nh;
     649           0 :         struct static_path *pn;
     650           0 :         struct static_route_info *si;
     651             : 
     652           0 :         for (rn = route_top(stable); rn; rn = route_next(rn)) {
     653           0 :                 si = static_route_info_from_rnode(rn);
     654           0 :                 if (!si)
     655           0 :                         continue;
     656           0 :                 frr_each(static_path_list, &si->path_list, pn) {
     657           0 :                         frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
     658           0 :                                 static_uninstall_path(pn);
     659             :                         }
     660             :                 }
     661             :         }
     662           0 : }
     663             : 
     664             : /*
     665             :  * When the disable_svrf is shutdown by the kernel, we call
     666             :  * this function and it cleans up all static routes using
     667             :  * this vrf as a nexthop as well as all static routes
     668             :  * in it's stables.
     669             :  *
     670             :  * disable_svrf - The vrf being disabled
     671             :  */
     672           0 : void static_cleanup_vrf_ids(struct static_vrf *disable_svrf)
     673             : {
     674           0 :         struct vrf *vrf;
     675           0 :         afi_t afi;
     676           0 :         safi_t safi;
     677             : 
     678           0 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
     679           0 :                 struct static_vrf *svrf;
     680             : 
     681           0 :                 svrf = vrf->info;
     682             : 
     683             :                 /* Uninstall any static routes configured for this VRF. */
     684           0 :                 FOREACH_AFI_SAFI (afi, safi) {
     685           0 :                         struct route_table *stable;
     686             : 
     687           0 :                         stable = svrf->stable[afi][safi];
     688           0 :                         if (!stable)
     689           0 :                                 continue;
     690             : 
     691           0 :                         static_cleanup_vrf(disable_svrf, stable, afi, safi);
     692             : 
     693           0 :                         if (disable_svrf == svrf)
     694           0 :                                 static_disable_vrf(stable, afi, safi);
     695             :                 }
     696             :         }
     697           0 : }
     698             : 
     699             : /*
     700             :  * This function enables static routes when an interface it relies
     701             :  * on in a different vrf is coming up.
     702             :  *
     703             :  * stable -> The stable we are looking at.
     704             :  * ifp -> interface coming up
     705             :  * afi -> the afi in question
     706             :  * safi -> the safi in question
     707             :  */
     708           0 : static void static_fixup_intf_nh(struct route_table *stable,
     709             :                                  struct interface *ifp,
     710             :                                  afi_t afi, safi_t safi)
     711             : {
     712           0 :         struct route_node *rn;
     713           0 :         struct static_nexthop *nh;
     714           0 :         struct static_path *pn;
     715           0 :         struct static_route_info *si;
     716             : 
     717           0 :         for (rn = route_top(stable); rn; rn = route_next(rn)) {
     718           0 :                 si = static_route_info_from_rnode(rn);
     719           0 :                 if (!si)
     720           0 :                         continue;
     721           0 :                 frr_each(static_path_list, &si->path_list, pn) {
     722           0 :                         frr_each(static_nexthop_list, &pn->nexthop_list, nh) {
     723           0 :                                 if (nh->nh_vrf_id != ifp->vrf->vrf_id)
     724           0 :                                         continue;
     725             : 
     726           0 :                                 if (nh->ifindex != ifp->ifindex)
     727           0 :                                         continue;
     728             : 
     729           0 :                                 static_install_path(pn);
     730             :                         }
     731             :                 }
     732             :         }
     733           0 : }
     734             : 
     735             : /*
     736             :  * This function enables static routes that rely on an interface in
     737             :  * a different vrf when that interface comes up.
     738             :  */
     739           6 : void static_install_intf_nh(struct interface *ifp)
     740             : {
     741           6 :         struct route_table *stable;
     742           6 :         struct vrf *vrf;
     743           6 :         afi_t afi;
     744           6 :         safi_t safi;
     745             : 
     746          18 :         RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
     747           6 :                 struct static_vrf *svrf = vrf->info;
     748             : 
     749             :                 /* Not needed if same vrf since happens naturally */
     750           6 :                 if (vrf->vrf_id == ifp->vrf->vrf_id)
     751           6 :                         continue;
     752             : 
     753             :                 /* Install any static routes configured for this interface. */
     754           0 :                 FOREACH_AFI_SAFI (afi, safi) {
     755           0 :                         stable = svrf->stable[afi][safi];
     756           0 :                         if (!stable)
     757           0 :                                 continue;
     758             : 
     759           0 :                         static_fixup_intf_nh(stable, ifp, afi, safi);
     760             :                 }
     761             :         }
     762           6 : }
     763             : 
     764             : /* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
     765          29 : void static_ifindex_update(struct interface *ifp, bool up)
     766             : {
     767          29 :         static_ifindex_update_af(ifp, up, AFI_IP, SAFI_UNICAST);
     768          29 :         static_ifindex_update_af(ifp, up, AFI_IP, SAFI_MULTICAST);
     769          29 :         static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_UNICAST);
     770          29 :         static_ifindex_update_af(ifp, up, AFI_IP6, SAFI_MULTICAST);
     771          29 : }
     772             : 
     773           6 : void static_get_nh_type(enum static_nh_type stype, char *type, size_t size)
     774             : {
     775           6 :         switch (stype) {
     776           0 :         case STATIC_IFNAME:
     777           0 :                 strlcpy(type, "ifindex", size);
     778           0 :                 break;
     779           6 :         case STATIC_IPV4_GATEWAY:
     780           6 :                 strlcpy(type, "ip4", size);
     781           6 :                 break;
     782           0 :         case STATIC_IPV4_GATEWAY_IFNAME:
     783           0 :                 strlcpy(type, "ip4-ifindex", size);
     784           0 :                 break;
     785           0 :         case STATIC_BLACKHOLE:
     786           0 :                 strlcpy(type, "blackhole", size);
     787           0 :                 break;
     788           0 :         case STATIC_IPV6_GATEWAY:
     789           0 :                 strlcpy(type, "ip6", size);
     790           0 :                 break;
     791           0 :         case STATIC_IPV6_GATEWAY_IFNAME:
     792           0 :                 strlcpy(type, "ip6-ifindex", size);
     793           0 :                 break;
     794           6 :         };
     795           6 : }
     796             : 
     797           0 : struct stable_info *static_get_stable_info(struct route_node *rn)
     798             : {
     799           0 :         struct route_table *table;
     800             : 
     801           0 :         table = srcdest_rnode_table(rn);
     802           0 :         return table->info;
     803             : }
     804             : 
     805           0 : void static_get_nh_str(struct static_nexthop *nh, char *nexthop, size_t size)
     806             : {
     807           0 :         switch (nh->type) {
     808           0 :         case STATIC_IFNAME:
     809           0 :                 snprintfrr(nexthop, size, "ifindex : %s", nh->ifname);
     810           0 :                 break;
     811           0 :         case STATIC_IPV4_GATEWAY:
     812           0 :                 snprintfrr(nexthop, size, "ip4 : %pI4", &nh->addr.ipv4);
     813           0 :                 break;
     814           0 :         case STATIC_IPV4_GATEWAY_IFNAME:
     815           0 :                 snprintfrr(nexthop, size, "ip4-ifindex : %pI4 : %s",
     816           0 :                            &nh->addr.ipv4, nh->ifname);
     817           0 :                 break;
     818           0 :         case STATIC_BLACKHOLE:
     819           0 :                 snprintfrr(nexthop, size, "blackhole : %d", nh->bh_type);
     820           0 :                 break;
     821           0 :         case STATIC_IPV6_GATEWAY:
     822           0 :                 snprintfrr(nexthop, size, "ip6 : %pI6", &nh->addr.ipv6);
     823           0 :                 break;
     824           0 :         case STATIC_IPV6_GATEWAY_IFNAME:
     825           0 :                 snprintfrr(nexthop, size, "ip6-ifindex : %pI6 : %s",
     826           0 :                            &nh->addr.ipv6, nh->ifname);
     827           0 :                 break;
     828           0 :         };
     829           0 : }

Generated by: LCOV version v1.16-topotato