back to topotato report
topotato coverage report
Current view: top level - lib - vrf.c (source / functions) Hit Total Coverage
Test: test_pim6_bootstrap.py::PIM6Bootstrap Lines: 215 412 52.2 %
Date: 2023-02-16 02:07:22 Functions: 35 55 63.6 %

          Line data    Source code
       1             : /*
       2             :  * VRF functions.
       3             :  * Copyright (C) 2014 6WIND S.A.
       4             :  *
       5             :  * This file is part of GNU Zebra.
       6             :  *
       7             :  * GNU Zebra is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published
       9             :  * by the Free Software Foundation; either version 2, or (at your
      10             :  * option) any later version.
      11             :  *
      12             :  * GNU Zebra is distributed in the hope that it will be useful, but
      13             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License along
      18             :  * with this program; see the file COPYING; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : #include <zebra.h>
      23             : 
      24             : #include "if.h"
      25             : #include "vrf.h"
      26             : #include "vrf_int.h"
      27             : #include "prefix.h"
      28             : #include "table.h"
      29             : #include "log.h"
      30             : #include "memory.h"
      31             : #include "command.h"
      32             : #include "ns.h"
      33             : #include "privs.h"
      34             : #include "nexthop_group.h"
      35             : #include "lib_errors.h"
      36             : #include "northbound.h"
      37             : #include "northbound_cli.h"
      38             : 
      39             : /* default VRF name value used when VRF backend is not NETNS */
      40             : #define VRF_DEFAULT_NAME_INTERNAL "default"
      41             : 
      42          11 : DEFINE_MTYPE_STATIC(LIB, VRF, "VRF");
      43          11 : DEFINE_MTYPE_STATIC(LIB, VRF_BITMAP, "VRF bit-map");
      44             : 
      45             : DEFINE_QOBJ_TYPE(vrf);
      46             : 
      47             : static __inline int vrf_id_compare(const struct vrf *, const struct vrf *);
      48             : static __inline int vrf_name_compare(const struct vrf *, const struct vrf *);
      49             : 
      50         406 : RB_GENERATE(vrf_id_head, vrf, id_entry, vrf_id_compare);
      51          12 : RB_GENERATE(vrf_name_head, vrf, name_entry, vrf_name_compare);
      52             : 
      53             : struct vrf_id_head vrfs_by_id = RB_INITIALIZER(&vrfs_by_id);
      54             : struct vrf_name_head vrfs_by_name = RB_INITIALIZER(&vrfs_by_name);
      55             : 
      56             : static int vrf_backend;
      57             : static int vrf_backend_configured;
      58             : static char vrf_default_name[VRF_NAMSIZ] = VRF_DEFAULT_NAME_INTERNAL;
      59             : 
      60             : /*
      61             :  * Turn on/off debug code
      62             :  * for vrf.
      63             :  */
      64             : static int debug_vrf = 0;
      65             : 
      66             : /* Holding VRF hooks  */
      67             : static struct vrf_master {
      68             :         int (*vrf_new_hook)(struct vrf *);
      69             :         int (*vrf_delete_hook)(struct vrf *);
      70             :         int (*vrf_enable_hook)(struct vrf *);
      71             :         int (*vrf_disable_hook)(struct vrf *);
      72             : } vrf_master = {
      73             :         0,
      74             : };
      75             : 
      76             : static int vrf_is_enabled(struct vrf *vrf);
      77             : 
      78             : /* VRF list existance check by name. */
      79          15 : struct vrf *vrf_lookup_by_name(const char *name)
      80             : {
      81          15 :         struct vrf vrf;
      82          15 :         strlcpy(vrf.name, name, sizeof(vrf.name));
      83          15 :         return (RB_FIND(vrf_name_head, &vrfs_by_name, &vrf));
      84             : }
      85             : 
      86         406 : static __inline int vrf_id_compare(const struct vrf *a, const struct vrf *b)
      87             : {
      88         406 :         return (a->vrf_id - b->vrf_id);
      89             : }
      90             : 
      91          12 : static int vrf_name_compare(const struct vrf *a, const struct vrf *b)
      92             : {
      93          12 :         return strcmp(a->name, b->name);
      94             : }
      95             : 
      96           6 : int vrf_switch_to_netns(vrf_id_t vrf_id)
      97             : {
      98           6 :         char *name;
      99           6 :         struct vrf *vrf = vrf_lookup_by_id(vrf_id);
     100             : 
     101             :         /* VRF is default VRF. silently ignore */
     102           6 :         if (!vrf || vrf->vrf_id == VRF_DEFAULT)
     103             :                 return 1;       /* 1 = default */
     104             :         /* VRF has no NETNS backend. silently ignore */
     105           0 :         if (vrf->data.l.netns_name[0] == '\0')
     106             :                 return 2;       /* 2 = no netns */
     107           0 :         name = ns_netns_pathname(NULL, vrf->data.l.netns_name);
     108           0 :         if (debug_vrf)
     109           0 :                 zlog_debug("VRF_SWITCH: %s(%u)", name, vrf->vrf_id);
     110           0 :         return ns_switch_to_netns(name);
     111             : }
     112             : 
     113           6 : int vrf_switchback_to_initial(void)
     114             : {
     115           6 :         int ret = ns_switchback_to_initial();
     116             : 
     117           6 :         if (ret == 0 && debug_vrf)
     118           0 :                 zlog_debug("VRF_SWITCHBACK");
     119           6 :         return ret;
     120             : }
     121             : 
     122             : /* Get a VRF. If not found, create one.
     123             :  * Arg:
     124             :  *   name   - The name of the vrf.  May be NULL if unknown.
     125             :  *   vrf_id - The vrf_id of the vrf.  May be VRF_UNKNOWN if unknown
     126             :  * Description: Please note that this routine can be called with just the name
     127             :  * and 0 vrf-id
     128             :  */
     129          17 : struct vrf *vrf_get(vrf_id_t vrf_id, const char *name)
     130             : {
     131          17 :         struct vrf *vrf = NULL;
     132          17 :         int new = 0;
     133             : 
     134             :         /* Nothing to see, move along here */
     135          17 :         if (!name && vrf_id == VRF_UNKNOWN)
     136             :                 return NULL;
     137             : 
     138             :         /* attempt to find already available VRF
     139             :          */
     140          17 :         if (name)
     141          13 :                 vrf = vrf_lookup_by_name(name);
     142          17 :         if (vrf && vrf_id != VRF_UNKNOWN
     143          10 :             && vrf->vrf_id != VRF_UNKNOWN
     144          10 :             && vrf->vrf_id != vrf_id) {
     145           0 :                 zlog_debug("VRF_GET: avoid %s creation(%u), same name exists (%u)",
     146             :                            name, vrf_id, vrf->vrf_id);
     147           0 :                 return NULL;
     148             :         }
     149             :         /* Try to find VRF both by ID and name */
     150          17 :         if (!vrf && vrf_id != VRF_UNKNOWN)
     151           7 :                 vrf = vrf_lookup_by_id(vrf_id);
     152             : 
     153          17 :         if (vrf == NULL) {
     154           3 :                 vrf = XCALLOC(MTYPE_VRF, sizeof(struct vrf));
     155           3 :                 vrf->vrf_id = VRF_UNKNOWN;
     156           3 :                 QOBJ_REG(vrf, vrf);
     157           3 :                 new = 1;
     158             : 
     159           3 :                 if (debug_vrf)
     160           0 :                         zlog_debug("VRF(%u) %s is created.", vrf_id,
     161             :                                    (name) ? name : "(NULL)");
     162             :         }
     163             : 
     164             :         /* Set identifier */
     165          17 :         if (vrf_id != VRF_UNKNOWN && vrf->vrf_id == VRF_UNKNOWN) {
     166           3 :                 vrf->vrf_id = vrf_id;
     167           3 :                 RB_INSERT(vrf_id_head, &vrfs_by_id, vrf);
     168             :         }
     169             : 
     170             :         /* Set name */
     171          17 :         if (name && vrf->name[0] != '\0' && strcmp(name, vrf->name)) {
     172             :                 /* update the vrf name */
     173           0 :                 RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf);
     174           0 :                 strlcpy(vrf->data.l.netns_name,
     175             :                         name, NS_NAMSIZ);
     176           0 :                 strlcpy(vrf->name, name, sizeof(vrf->name));
     177           0 :                 RB_INSERT(vrf_name_head, &vrfs_by_name, vrf);
     178          13 :         } else if (name && vrf->name[0] == '\0') {
     179           3 :                 strlcpy(vrf->name, name, sizeof(vrf->name));
     180           3 :                 RB_INSERT(vrf_name_head, &vrfs_by_name, vrf);
     181             :         }
     182          17 :         if (new &&vrf_master.vrf_new_hook)
     183           3 :                 (*vrf_master.vrf_new_hook)(vrf);
     184             : 
     185             :         return vrf;
     186             : }
     187             : 
     188             : /* Update a VRF. If not found, create one.
     189             :  * Arg:
     190             :  *   name   - The name of the vrf.
     191             :  *   vrf_id - The vrf_id of the vrf.
     192             :  * Description: This function first finds the vrf using its name. If the vrf is
     193             :  * found and the vrf-id of the existing vrf does not match the new vrf id, it
     194             :  * will disable the existing vrf and update it with new vrf-id. If the vrf is
     195             :  * not found, it will create the vrf with given name and the new vrf id.
     196             :  */
     197           0 : struct vrf *vrf_update(vrf_id_t new_vrf_id, const char *name)
     198             : {
     199           0 :         struct vrf *vrf = NULL;
     200             : 
     201             :         /*Treat VRF add for existing vrf as update
     202             :          * Update VRF ID and also update in VRF ID table
     203             :          */
     204           0 :         if (name)
     205           0 :                 vrf = vrf_lookup_by_name(name);
     206           0 :         if (vrf && new_vrf_id != VRF_UNKNOWN && vrf->vrf_id != VRF_UNKNOWN
     207           0 :             && vrf->vrf_id != new_vrf_id) {
     208           0 :                 if (debug_vrf) {
     209           0 :                         zlog_debug(
     210             :                                 "Vrf Update event: %s old id: %u, new id: %u",
     211             :                                 name, vrf->vrf_id, new_vrf_id);
     212             :                 }
     213             : 
     214             :                 /*Disable the vrf to simulate implicit delete
     215             :                  * so that all stale routes are deleted
     216             :                  * This vrf will be enabled down the line
     217             :                  */
     218           0 :                 vrf_disable(vrf);
     219             : 
     220             : 
     221           0 :                 RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
     222           0 :                 vrf->vrf_id = new_vrf_id;
     223           0 :                 RB_INSERT(vrf_id_head, &vrfs_by_id, vrf);
     224             : 
     225             :         } else {
     226             : 
     227             :                 /*
     228             :                  * vrf_get is implied creation if it does not exist
     229             :                  */
     230           0 :                 vrf = vrf_get(new_vrf_id, name);
     231             :         }
     232           0 :         return vrf;
     233             : }
     234             : 
     235             : /* Delete a VRF. This is called when the underlying VRF goes away, a
     236             :  * pre-configured VRF is deleted or when shutting down (vrf_terminate()).
     237             :  */
     238           3 : void vrf_delete(struct vrf *vrf)
     239             : {
     240           3 :         if (debug_vrf)
     241           3 :                 zlog_debug("VRF %s(%u) is to be deleted.", vrf->name,
     242             :                            vrf->vrf_id);
     243             : 
     244           3 :         if (vrf_is_enabled(vrf))
     245           0 :                 vrf_disable(vrf);
     246             : 
     247           3 :         if (vrf->vrf_id != VRF_UNKNOWN) {
     248           3 :                 RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
     249           3 :                 vrf->vrf_id = VRF_UNKNOWN;
     250             :         }
     251             : 
     252             :         /* If the VRF is user configured, it'll stick around, just remove
     253             :          * the ID mapping. Interfaces assigned to this VRF should've been
     254             :          * removed already as part of the VRF going down.
     255             :          */
     256           3 :         if (vrf_is_user_cfged(vrf))
     257             :                 return;
     258             : 
     259             :         /* Do not delete the VRF if it has interfaces configured in it. */
     260           3 :         if (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name))
     261             :                 return;
     262             : 
     263           3 :         if (vrf_master.vrf_delete_hook)
     264           3 :                 (*vrf_master.vrf_delete_hook)(vrf);
     265             : 
     266           3 :         QOBJ_UNREG(vrf);
     267             : 
     268           3 :         if (vrf->name[0] != '\0')
     269           3 :                 RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf);
     270             : 
     271           3 :         XFREE(MTYPE_VRF, vrf);
     272             : }
     273             : 
     274             : /* Look up a VRF by identifier. */
     275         409 : struct vrf *vrf_lookup_by_id(vrf_id_t vrf_id)
     276             : {
     277         409 :         struct vrf vrf;
     278         409 :         vrf.vrf_id = vrf_id;
     279         409 :         return (RB_FIND(vrf_id_head, &vrfs_by_id, &vrf));
     280             : }
     281             : 
     282             : /*
     283             :  * Enable a VRF - that is, let the VRF be ready to use.
     284             :  * The VRF_ENABLE_HOOK callback will be called to inform
     285             :  * that they can allocate resources in this VRF.
     286             :  *
     287             :  * RETURN: 1 - enabled successfully; otherwise, 0.
     288             :  */
     289           5 : int vrf_enable(struct vrf *vrf)
     290             : {
     291           5 :         if (vrf_is_enabled(vrf))
     292             :                 return 1;
     293             : 
     294           3 :         if (debug_vrf)
     295           0 :                 zlog_debug("VRF %s(%u) is enabled.", vrf->name, vrf->vrf_id);
     296             : 
     297           3 :         SET_FLAG(vrf->status, VRF_ACTIVE);
     298             : 
     299           3 :         if (vrf_master.vrf_enable_hook)
     300           3 :                 (*vrf_master.vrf_enable_hook)(vrf);
     301             : 
     302             :         /*
     303             :          * If we have any nexthop group entries that
     304             :          * are awaiting vrf initialization then
     305             :          * let's let people know about it
     306             :          */
     307           3 :         nexthop_group_enable_vrf(vrf);
     308             : 
     309           3 :         return 1;
     310             : }
     311             : 
     312             : /*
     313             :  * Disable a VRF - that is, let the VRF be unusable.
     314             :  * The VRF_DELETE_HOOK callback will be called to inform
     315             :  * that they must release the resources in the VRF.
     316             :  */
     317           3 : void vrf_disable(struct vrf *vrf)
     318             : {
     319           3 :         if (!vrf_is_enabled(vrf))
     320             :                 return;
     321             : 
     322           3 :         UNSET_FLAG(vrf->status, VRF_ACTIVE);
     323             : 
     324           3 :         if (debug_vrf)
     325           0 :                 zlog_debug("VRF %s(%u) is to be disabled.", vrf->name,
     326             :                            vrf->vrf_id);
     327             : 
     328             :         /* Till now, nothing to be done for the default VRF. */
     329             :         // Pending: see why this statement.
     330             : 
     331             : 
     332             :         /*
     333             :          * When the vrf is disabled let's
     334             :          * handle all nexthop-groups associated
     335             :          * with this vrf
     336             :          */
     337           3 :         nexthop_group_disable_vrf(vrf);
     338             : 
     339           3 :         if (vrf_master.vrf_disable_hook)
     340           3 :                 (*vrf_master.vrf_disable_hook)(vrf);
     341             : }
     342             : 
     343           0 : const char *vrf_id_to_name(vrf_id_t vrf_id)
     344             : {
     345           0 :         struct vrf *vrf;
     346             : 
     347           0 :         if (vrf_id == VRF_DEFAULT)
     348           0 :                 return VRF_DEFAULT_NAME;
     349             : 
     350           0 :         vrf = vrf_lookup_by_id(vrf_id);
     351           0 :         return VRF_LOGNAME(vrf);
     352             : }
     353             : 
     354             : /* Look up the data pointer of the specified VRF. */
     355         195 : void *vrf_info_lookup(vrf_id_t vrf_id)
     356             : {
     357         195 :         struct vrf *vrf = vrf_lookup_by_id(vrf_id);
     358         195 :         return vrf ? vrf->info : NULL;
     359             : }
     360             : 
     361             : /*
     362             :  * VRF hash for storing set or not.
     363             :  */
     364             : struct vrf_bit_set {
     365             :         vrf_id_t vrf_id;
     366             :         bool set;
     367             : };
     368             : 
     369          10 : static unsigned int vrf_hash_bitmap_key(const void *data)
     370             : {
     371          10 :         const struct vrf_bit_set *bit = data;
     372             : 
     373          10 :         return bit->vrf_id;
     374             : }
     375             : 
     376           2 : static bool vrf_hash_bitmap_cmp(const void *a, const void *b)
     377             : {
     378           2 :         const struct vrf_bit_set *bit1 = a;
     379           2 :         const struct vrf_bit_set *bit2 = b;
     380             : 
     381           2 :         return bit1->vrf_id == bit2->vrf_id;
     382             : }
     383             : 
     384           8 : static void *vrf_hash_bitmap_alloc(void *data)
     385             : {
     386           8 :         struct vrf_bit_set *copy = data;
     387           8 :         struct vrf_bit_set *bit;
     388             : 
     389           8 :         bit = XMALLOC(MTYPE_VRF_BITMAP, sizeof(*bit));
     390           8 :         bit->vrf_id = copy->vrf_id;
     391             : 
     392           8 :         return bit;
     393             : }
     394             : 
     395           5 : static void vrf_hash_bitmap_free(void *data)
     396             : {
     397           5 :         struct vrf_bit_set *bit = data;
     398             : 
     399           5 :         XFREE(MTYPE_VRF_BITMAP, bit);
     400           5 : }
     401             : 
     402         498 : vrf_bitmap_t vrf_bitmap_init(void)
     403             : {
     404         498 :         return hash_create_size(32, vrf_hash_bitmap_key, vrf_hash_bitmap_cmp,
     405             :                                 "VRF BIT HASH");
     406             : }
     407             : 
     408         402 : void vrf_bitmap_free(vrf_bitmap_t bmap)
     409             : {
     410         402 :         struct hash *vrf_hash = bmap;
     411             : 
     412         402 :         if (vrf_hash == NULL)
     413             :                 return;
     414             : 
     415         402 :         hash_clean(vrf_hash, vrf_hash_bitmap_free);
     416         402 :         hash_free(vrf_hash);
     417             : }
     418             : 
     419           8 : void vrf_bitmap_set(vrf_bitmap_t bmap, vrf_id_t vrf_id)
     420             : {
     421           8 :         struct vrf_bit_set lookup = { .vrf_id = vrf_id };
     422           8 :         struct hash *vrf_hash = bmap;
     423           8 :         struct vrf_bit_set *bit;
     424             : 
     425           8 :         if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
     426           0 :                 return;
     427             : 
     428           8 :         bit = hash_get(vrf_hash, &lookup, vrf_hash_bitmap_alloc);
     429           8 :         bit->set = true;
     430             : }
     431             : 
     432           0 : void vrf_bitmap_unset(vrf_bitmap_t bmap, vrf_id_t vrf_id)
     433             : {
     434           0 :         struct vrf_bit_set lookup = { .vrf_id = vrf_id };
     435           0 :         struct hash *vrf_hash = bmap;
     436           0 :         struct vrf_bit_set *bit;
     437             : 
     438           0 :         if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
     439           0 :                 return;
     440             : 
     441           0 :         bit = hash_get(vrf_hash, &lookup, vrf_hash_bitmap_alloc);
     442           0 :         bit->set = false;
     443             : }
     444             : 
     445         200 : int vrf_bitmap_check(vrf_bitmap_t bmap, vrf_id_t vrf_id)
     446             : {
     447         200 :         struct vrf_bit_set lookup = { .vrf_id = vrf_id };
     448         200 :         struct hash *vrf_hash = bmap;
     449         200 :         struct vrf_bit_set *bit;
     450             : 
     451         200 :         if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
     452             :                 return 0;
     453             : 
     454         200 :         bit = hash_lookup(vrf_hash, &lookup);
     455         200 :         if (bit)
     456           2 :                 return bit->set;
     457             : 
     458             :         return 0;
     459             : }
     460             : 
     461           0 : static void vrf_autocomplete(vector comps, struct cmd_token *token)
     462             : {
     463           0 :         struct vrf *vrf = NULL;
     464             : 
     465           0 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
     466           0 :                 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name));
     467           0 : }
     468             : 
     469             : static const struct cmd_variable_handler vrf_var_handlers[] = {
     470             :         {
     471             :                 .varname = "vrf",
     472             :                 .completions = vrf_autocomplete,
     473             :         },
     474             :         {
     475             :                 .varname = "vrf_name",
     476             :                 .completions = vrf_autocomplete,
     477             :         },
     478             :         {
     479             :                 .varname = "nexthop_vrf",
     480             :                 .completions = vrf_autocomplete,
     481             :         },
     482             :         {.completions = NULL},
     483             : };
     484             : 
     485             : /* Initialize VRF module. */
     486           3 : void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *),
     487             :               int (*disable)(struct vrf *), int (*destroy)(struct vrf *))
     488             : {
     489           3 :         struct vrf *default_vrf;
     490             : 
     491             :         /* initialise NS, in case VRF backend if NETNS */
     492           3 :         ns_init();
     493           3 :         if (debug_vrf)
     494           0 :                 zlog_debug("%s: Initializing VRF subsystem", __func__);
     495             : 
     496           3 :         vrf_master.vrf_new_hook = create;
     497           3 :         vrf_master.vrf_enable_hook = enable;
     498           3 :         vrf_master.vrf_disable_hook = disable;
     499           3 :         vrf_master.vrf_delete_hook = destroy;
     500             : 
     501             :         /* The default VRF always exists. */
     502           3 :         default_vrf = vrf_get(VRF_DEFAULT, VRF_DEFAULT_NAME);
     503           3 :         if (!default_vrf) {
     504           0 :                 flog_err(EC_LIB_VRF_START,
     505             :                          "vrf_init: failed to create the default VRF!");
     506           0 :                 exit(1);
     507             :         }
     508           3 :         if (vrf_is_backend_netns()) {
     509           0 :                 struct ns *ns;
     510             : 
     511           0 :                 strlcpy(default_vrf->data.l.netns_name,
     512             :                         VRF_DEFAULT_NAME, NS_NAMSIZ);
     513           0 :                 ns = ns_lookup(NS_DEFAULT);
     514           0 :                 ns->vrf_ctxt = default_vrf;
     515           0 :                 default_vrf->ns_ctxt = ns;
     516             :         }
     517             : 
     518             :         /* Enable the default VRF. */
     519           3 :         if (!vrf_enable(default_vrf)) {
     520           0 :                 flog_err(EC_LIB_VRF_START,
     521             :                          "vrf_init: failed to enable the default VRF!");
     522           0 :                 exit(1);
     523             :         }
     524             : 
     525           3 :         cmd_variable_handler_register(vrf_var_handlers);
     526           3 : }
     527             : 
     528           3 : static void vrf_terminate_single(struct vrf *vrf)
     529             : {
     530             :         /* Clear configured flag and invoke delete. */
     531           3 :         vrf_disable(vrf);
     532           3 :         UNSET_FLAG(vrf->status, VRF_CONFIGURED);
     533           3 :         if_terminate(vrf);
     534           3 :         vrf_delete(vrf);
     535           3 : }
     536             : 
     537             : /* Terminate VRF module. */
     538           3 : void vrf_terminate(void)
     539             : {
     540           3 :         struct vrf *vrf, *tmp;
     541             : 
     542           3 :         if (debug_vrf)
     543           0 :                 zlog_debug("%s: Shutting down vrf subsystem", __func__);
     544             : 
     545           9 :         RB_FOREACH_SAFE (vrf, vrf_id_head, &vrfs_by_id, tmp) {
     546           3 :                 if (vrf->vrf_id == VRF_DEFAULT)
     547           3 :                         continue;
     548             : 
     549           0 :                 vrf_terminate_single(vrf);
     550             :         }
     551             : 
     552           9 :         RB_FOREACH_SAFE (vrf, vrf_name_head, &vrfs_by_name, tmp) {
     553           3 :                 if (vrf->vrf_id == VRF_DEFAULT)
     554           3 :                         continue;
     555             : 
     556           0 :                 vrf_terminate_single(vrf);
     557             :         }
     558             : 
     559             :         /* Finally terminate default VRF */
     560           3 :         vrf = vrf_lookup_by_id(VRF_DEFAULT);
     561           3 :         if (vrf)
     562           3 :                 vrf_terminate_single(vrf);
     563           3 : }
     564             : 
     565           3 : int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
     566             :                const char *interfacename)
     567             : {
     568           3 :         int ret, save_errno, ret2;
     569             : 
     570           3 :         ret = vrf_switch_to_netns(vrf_id);
     571           3 :         if (ret < 0)
     572           0 :                 flog_err_sys(EC_LIB_SOCKET, "%s: Can't switch to VRF %u (%s)",
     573             :                              __func__, vrf_id, safe_strerror(errno));
     574             : 
     575           3 :         ret = socket(domain, type, protocol);
     576           3 :         save_errno = errno;
     577           3 :         ret2 = vrf_switchback_to_initial();
     578           3 :         if (ret2 < 0)
     579           0 :                 flog_err_sys(EC_LIB_SOCKET,
     580             :                              "%s: Can't switchback from VRF %u (%s)", __func__,
     581             :                              vrf_id, safe_strerror(errno));
     582           3 :         errno = save_errno;
     583           3 :         if (ret <= 0)
     584             :                 return ret;
     585           3 :         ret2 = vrf_bind(vrf_id, ret, interfacename);
     586           3 :         if (ret2 < 0) {
     587           0 :                 close(ret);
     588           0 :                 ret = ret2;
     589             :         }
     590             :         return ret;
     591             : }
     592             : 
     593          65 : int vrf_is_backend_netns(void)
     594             : {
     595          65 :         return (vrf_backend == VRF_BACKEND_NETNS);
     596             : }
     597             : 
     598         105 : int vrf_get_backend(void)
     599             : {
     600         105 :         if (!vrf_backend_configured)
     601             :                 return VRF_BACKEND_UNKNOWN;
     602         105 :         return vrf_backend;
     603             : }
     604             : 
     605           3 : int vrf_configure_backend(enum vrf_backend_type backend)
     606             : {
     607             :         /* Work around issue in old gcc */
     608           3 :         switch (backend) {
     609             :         case VRF_BACKEND_UNKNOWN:
     610             :         case VRF_BACKEND_NETNS:
     611             :         case VRF_BACKEND_VRF_LITE:
     612             :                 break;
     613             :         case VRF_BACKEND_MAX:
     614             :                 return -1;
     615             :         }
     616             : 
     617           3 :         vrf_backend = backend;
     618           3 :         vrf_backend_configured = 1;
     619             : 
     620           3 :         return 0;
     621             : }
     622             : 
     623             : /* vrf CLI commands */
     624           0 : DEFUN_NOSH(vrf_exit,
     625             :            vrf_exit_cmd,
     626             :            "exit-vrf",
     627             :            "Exit current mode and down to previous mode\n")
     628             : {
     629           0 :         cmd_exit(vty);
     630           0 :         return CMD_SUCCESS;
     631             : }
     632             : 
     633           0 : DEFUN_YANG_NOSH (vrf,
     634             :        vrf_cmd,
     635             :        "vrf NAME",
     636             :        "Select a VRF to configure\n"
     637             :        "VRF's name\n")
     638             : {
     639           0 :         int idx_name = 1;
     640           0 :         const char *vrfname = argv[idx_name]->arg;
     641           0 :         char xpath_list[XPATH_MAXLEN];
     642           0 :         struct vrf *vrf;
     643           0 :         int ret;
     644             : 
     645           0 :         if (strlen(vrfname) > VRF_NAMSIZ) {
     646           0 :                 vty_out(vty,
     647             :                         "%% VRF name %s invalid: length exceeds %d bytes\n",
     648             :                         vrfname, VRF_NAMSIZ);
     649           0 :                 return CMD_WARNING_CONFIG_FAILED;
     650             :         }
     651             : 
     652           0 :         snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH, vrfname);
     653             : 
     654           0 :         nb_cli_enqueue_change(vty, xpath_list, NB_OP_CREATE, NULL);
     655           0 :         ret = nb_cli_apply_changes_clear_pending(vty, "%s", xpath_list);
     656           0 :         if (ret == CMD_SUCCESS) {
     657           0 :                 VTY_PUSH_XPATH(VRF_NODE, xpath_list);
     658           0 :                 vrf = vrf_lookup_by_name(vrfname);
     659           0 :                 if (vrf)
     660           0 :                         VTY_PUSH_CONTEXT(VRF_NODE, vrf);
     661             :         }
     662             : 
     663             :         return ret;
     664             : }
     665             : 
     666           0 : DEFUN_YANG (no_vrf,
     667             :        no_vrf_cmd,
     668             :        "no vrf NAME",
     669             :        NO_STR
     670             :        "Delete a pseudo VRF's configuration\n"
     671             :        "VRF's name\n")
     672             : {
     673           0 :         const char *vrfname = argv[2]->arg;
     674           0 :         char xpath_list[XPATH_MAXLEN];
     675             : 
     676           0 :         struct vrf *vrfp;
     677             : 
     678           0 :         vrfp = vrf_lookup_by_name(vrfname);
     679             : 
     680           0 :         if (vrfp == NULL)
     681             :                 return CMD_SUCCESS;
     682             : 
     683           0 :         if (CHECK_FLAG(vrfp->status, VRF_ACTIVE)) {
     684           0 :                 vty_out(vty, "%% Only inactive VRFs can be deleted\n");
     685           0 :                 return CMD_WARNING_CONFIG_FAILED;
     686             :         }
     687             : 
     688           0 :         if (vrf_get_backend() == VRF_BACKEND_VRF_LITE) {
     689             :                 /*
     690             :                  * Remove the VRF interface config when removing the VRF.
     691             :                  */
     692           0 :                 snprintf(xpath_list, sizeof(xpath_list),
     693             :                          "/frr-interface:lib/interface[name='%s']", vrfname);
     694           0 :                 nb_cli_enqueue_change(vty, xpath_list, NB_OP_DESTROY, NULL);
     695             :         }
     696             : 
     697           0 :         snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH, vrfname);
     698             : 
     699           0 :         nb_cli_enqueue_change(vty, xpath_list, NB_OP_DESTROY, NULL);
     700           0 :         return nb_cli_apply_changes(vty, NULL);
     701             : }
     702             : 
     703             : 
     704             : static struct cmd_node vrf_node = {
     705             :         .name = "vrf",
     706             :         .node = VRF_NODE,
     707             :         .parent_node = CONFIG_NODE,
     708             :         .prompt = "%s(config-vrf)# ",
     709             : };
     710             : 
     711             : /*
     712             :  * Debug CLI for vrf's
     713             :  */
     714           0 : DEFUN (vrf_debug,
     715             :       vrf_debug_cmd,
     716             :       "debug vrf",
     717             :       DEBUG_STR
     718             :       "VRF Debugging\n")
     719             : {
     720           0 :         debug_vrf = 1;
     721             : 
     722           0 :         return CMD_SUCCESS;
     723             : }
     724             : 
     725           0 : DEFUN (no_vrf_debug,
     726             :       no_vrf_debug_cmd,
     727             :       "no debug vrf",
     728             :       NO_STR
     729             :       DEBUG_STR
     730             :       "VRF Debugging\n")
     731             : {
     732           0 :         debug_vrf = 0;
     733             : 
     734           0 :         return CMD_SUCCESS;
     735             : }
     736             : 
     737           0 : static int vrf_write_host(struct vty *vty)
     738             : {
     739           0 :         if (debug_vrf)
     740           0 :                 vty_out(vty, "debug vrf\n");
     741             : 
     742           0 :         return 1;
     743             : }
     744             : 
     745             : static int vrf_write_host(struct vty *vty);
     746             : static struct cmd_node vrf_debug_node = {
     747             :         .name = "vrf debug",
     748             :         .node = VRF_DEBUG_NODE,
     749             :         .prompt = "",
     750             :         .config_write = vrf_write_host,
     751             : };
     752             : 
     753           3 : void vrf_install_commands(void)
     754             : {
     755           3 :         install_node(&vrf_debug_node);
     756             : 
     757           3 :         install_element(CONFIG_NODE, &vrf_debug_cmd);
     758           3 :         install_element(ENABLE_NODE, &vrf_debug_cmd);
     759           3 :         install_element(CONFIG_NODE, &no_vrf_debug_cmd);
     760           3 :         install_element(ENABLE_NODE, &no_vrf_debug_cmd);
     761           3 : }
     762             : 
     763           3 : void vrf_cmd_init(int (*writefunc)(struct vty *vty))
     764             : {
     765           3 :         install_element(CONFIG_NODE, &vrf_cmd);
     766           3 :         install_element(CONFIG_NODE, &no_vrf_cmd);
     767           3 :         vrf_node.config_write = writefunc;
     768           3 :         install_node(&vrf_node);
     769           3 :         install_default(VRF_NODE);
     770           3 :         install_element(VRF_NODE, &vrf_exit_cmd);
     771           3 : }
     772             : 
     773           0 : void vrf_set_default_name(const char *default_name)
     774             : {
     775           0 :         snprintf(vrf_default_name, VRF_NAMSIZ, "%s", default_name);
     776           0 : }
     777             : 
     778          10 : const char *vrf_get_default_name(void)
     779             : {
     780          10 :         return vrf_default_name;
     781             : }
     782             : 
     783           3 : int vrf_bind(vrf_id_t vrf_id, int fd, const char *ifname)
     784             : {
     785           3 :         int ret = 0;
     786           3 :         struct interface *ifp;
     787           3 :         struct vrf *vrf;
     788             : 
     789           3 :         if (fd < 0)
     790             :                 return -1;
     791             : 
     792           3 :         if (vrf_id == VRF_UNKNOWN)
     793             :                 return -1;
     794             : 
     795             :         /* can't bind to a VRF that doesn't exist */
     796           3 :         vrf = vrf_lookup_by_id(vrf_id);
     797           3 :         if (!vrf_is_enabled(vrf))
     798             :                 return -1;
     799             : 
     800           3 :         if (ifname && strcmp(ifname, vrf->name)) {
     801             :                 /* binding to a regular interface */
     802             : 
     803             :                 /* can't bind to an interface that doesn't exist */
     804           0 :                 ifp = if_lookup_by_name(ifname, vrf_id);
     805           0 :                 if (!ifp)
     806             :                         return -1;
     807             :         } else {
     808             :                 /* binding to a VRF device */
     809             : 
     810             :                 /* nothing to do for netns */
     811           3 :                 if (vrf_is_backend_netns())
     812             :                         return 0;
     813             : 
     814             :                 /* nothing to do for default vrf */
     815           3 :                 if (vrf_id == VRF_DEFAULT)
     816             :                         return 0;
     817             : 
     818           0 :                 ifname = vrf->name;
     819             :         }
     820             : 
     821             : #ifdef SO_BINDTODEVICE
     822           0 :         ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
     823           0 :                          strlen(ifname) + 1);
     824           0 :         if (ret < 0)
     825           0 :                 zlog_err("bind to interface %s failed, errno=%d", ifname,
     826             :                          errno);
     827             : #endif /* SO_BINDTODEVICE */
     828             :         return ret;
     829             : }
     830           0 : int vrf_getaddrinfo(const char *node, const char *service,
     831             :                     const struct addrinfo *hints, struct addrinfo **res,
     832             :                     vrf_id_t vrf_id)
     833             : {
     834           0 :         int ret, ret2, save_errno;
     835             : 
     836           0 :         ret = vrf_switch_to_netns(vrf_id);
     837           0 :         if (ret < 0)
     838           0 :                 flog_err_sys(EC_LIB_SOCKET, "%s: Can't switch to VRF %u (%s)",
     839             :                              __func__, vrf_id, safe_strerror(errno));
     840           0 :         ret = getaddrinfo(node, service, hints, res);
     841           0 :         save_errno = errno;
     842           0 :         ret2 = vrf_switchback_to_initial();
     843           0 :         if (ret2 < 0)
     844           0 :                 flog_err_sys(EC_LIB_SOCKET,
     845             :                              "%s: Can't switchback from VRF %u (%s)", __func__,
     846             :                              vrf_id, safe_strerror(errno));
     847           0 :         errno = save_errno;
     848           0 :         return ret;
     849             : }
     850             : 
     851           3 : int vrf_ioctl(vrf_id_t vrf_id, int d, unsigned long request, char *params)
     852             : {
     853           3 :         int ret, saved_errno, rc;
     854             : 
     855           3 :         ret = vrf_switch_to_netns(vrf_id);
     856           3 :         if (ret < 0) {
     857           0 :                 flog_err_sys(EC_LIB_SOCKET, "%s: Can't switch to VRF %u (%s)",
     858             :                              __func__, vrf_id, safe_strerror(errno));
     859           0 :                 return 0;
     860             :         }
     861           3 :         rc = ioctl(d, request, params);
     862           3 :         saved_errno = errno;
     863           3 :         ret = vrf_switchback_to_initial();
     864           3 :         if (ret < 0)
     865           0 :                 flog_err_sys(EC_LIB_SOCKET,
     866             :                              "%s: Can't switchback from VRF %u (%s)", __func__,
     867             :                              vrf_id, safe_strerror(errno));
     868           3 :         errno = saved_errno;
     869           3 :         return rc;
     870             : }
     871             : 
     872           0 : int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id,
     873             :                          const char *interfacename)
     874             : {
     875           0 :         int ret, save_errno, ret2;
     876             : 
     877           0 :         ret = vrf_switch_to_netns(vrf_id);
     878           0 :         if (ret < 0)
     879           0 :                 flog_err_sys(EC_LIB_SOCKET, "%s: Can't switch to VRF %u (%s)",
     880             :                              __func__, vrf_id, safe_strerror(errno));
     881           0 :         ret = sockunion_socket(su);
     882           0 :         save_errno = errno;
     883           0 :         ret2 = vrf_switchback_to_initial();
     884           0 :         if (ret2 < 0)
     885           0 :                 flog_err_sys(EC_LIB_SOCKET,
     886             :                              "%s: Can't switchback from VRF %u (%s)", __func__,
     887             :                              vrf_id, safe_strerror(errno));
     888           0 :         errno = save_errno;
     889             : 
     890           0 :         if (ret <= 0)
     891             :                 return ret;
     892           0 :         ret2 = vrf_bind(vrf_id, ret, interfacename);
     893           0 :         if (ret2 < 0) {
     894           0 :                 close(ret);
     895           0 :                 ret = ret2;
     896             :         }
     897             :         return ret;
     898             : }
     899             : 
     900             : /* ------- Northbound callbacks ------- */
     901             : 
     902             : /*
     903             :  * XPath: /frr-vrf:lib/vrf
     904             :  */
     905           0 : static int lib_vrf_create(struct nb_cb_create_args *args)
     906             : {
     907           0 :         const char *vrfname;
     908           0 :         struct vrf *vrfp;
     909             : 
     910           0 :         vrfname = yang_dnode_get_string(args->dnode, "./name");
     911             : 
     912           0 :         if (args->event != NB_EV_APPLY)
     913             :                 return NB_OK;
     914             : 
     915           0 :         vrfp = vrf_get(VRF_UNKNOWN, vrfname);
     916             : 
     917           0 :         SET_FLAG(vrfp->status, VRF_CONFIGURED);
     918           0 :         nb_running_set_entry(args->dnode, vrfp);
     919             : 
     920           0 :         return NB_OK;
     921             : }
     922             : 
     923           0 : static int lib_vrf_destroy(struct nb_cb_destroy_args *args)
     924             : {
     925           0 :         struct vrf *vrfp;
     926             : 
     927           0 :         switch (args->event) {
     928           0 :         case NB_EV_VALIDATE:
     929           0 :                 vrfp = nb_running_get_entry(args->dnode, NULL, true);
     930           0 :                 if (CHECK_FLAG(vrfp->status, VRF_ACTIVE)) {
     931           0 :                         snprintf(args->errmsg, args->errmsg_len,
     932             :                                  "Only inactive VRFs can be deleted");
     933           0 :                         return NB_ERR_VALIDATION;
     934             :                 }
     935             :                 break;
     936             :         case NB_EV_PREPARE:
     937             :         case NB_EV_ABORT:
     938             :                 break;
     939           0 :         case NB_EV_APPLY:
     940           0 :                 vrfp = nb_running_unset_entry(args->dnode);
     941             : 
     942             :                 /* Clear configured flag and invoke delete. */
     943           0 :                 UNSET_FLAG(vrfp->status, VRF_CONFIGURED);
     944           0 :                 vrf_delete(vrfp);
     945           0 :                 break;
     946             :         }
     947             : 
     948             :         return NB_OK;
     949             : }
     950             : 
     951           0 : static const void *lib_vrf_get_next(struct nb_cb_get_next_args *args)
     952             : {
     953           0 :         struct vrf *vrfp = (struct vrf *)args->list_entry;
     954             : 
     955           0 :         if (args->list_entry == NULL) {
     956           0 :                 vrfp = RB_MIN(vrf_name_head, &vrfs_by_name);
     957             :         } else {
     958           0 :                 vrfp = RB_NEXT(vrf_name_head, vrfp);
     959             :         }
     960             : 
     961           0 :         return vrfp;
     962             : }
     963             : 
     964           0 : static int lib_vrf_get_keys(struct nb_cb_get_keys_args *args)
     965             : {
     966           0 :         struct vrf *vrfp = (struct vrf *)args->list_entry;
     967             : 
     968           0 :         args->keys->num = 1;
     969           0 :         strlcpy(args->keys->key[0], vrfp->name, sizeof(args->keys->key[0]));
     970             : 
     971           0 :         return NB_OK;
     972             : }
     973             : 
     974           0 : static const void *lib_vrf_lookup_entry(struct nb_cb_lookup_entry_args *args)
     975             : {
     976           0 :         const char *vrfname = args->keys->key[0];
     977             : 
     978           0 :         struct vrf *vrf = vrf_lookup_by_name(vrfname);
     979             : 
     980           0 :         return vrf;
     981             : }
     982             : 
     983             : /*
     984             :  * XPath: /frr-vrf:lib/vrf/id
     985             :  */
     986             : static struct yang_data *
     987           0 : lib_vrf_state_id_get_elem(struct nb_cb_get_elem_args *args)
     988             : {
     989           0 :         struct vrf *vrfp = (struct vrf *)args->list_entry;
     990             : 
     991           0 :         return yang_data_new_uint32(args->xpath, vrfp->vrf_id);
     992             : }
     993             : 
     994             : /*
     995             :  * XPath: /frr-vrf:lib/vrf/active
     996             :  */
     997             : static struct yang_data *
     998           0 : lib_vrf_state_active_get_elem(struct nb_cb_get_elem_args *args)
     999             : {
    1000           0 :         struct vrf *vrfp = (struct vrf *)args->list_entry;
    1001             : 
    1002           0 :         if (vrfp->status == VRF_ACTIVE)
    1003           0 :                 return yang_data_new_bool(args->xpath, true);
    1004             : 
    1005             :         return NULL;
    1006             : }
    1007             : 
    1008             : /* clang-format off */
    1009             : const struct frr_yang_module_info frr_vrf_info = {
    1010             :         .name = "frr-vrf",
    1011             :         .nodes = {
    1012             :                 {
    1013             :                         .xpath = "/frr-vrf:lib/vrf",
    1014             :                         .cbs = {
    1015             :                                 .create = lib_vrf_create,
    1016             :                                 .destroy = lib_vrf_destroy,
    1017             :                                 .get_next = lib_vrf_get_next,
    1018             :                                 .get_keys = lib_vrf_get_keys,
    1019             :                                 .lookup_entry = lib_vrf_lookup_entry,
    1020             :                         },
    1021             :                         .priority = NB_DFLT_PRIORITY - 2,
    1022             :                 },
    1023             :                 {
    1024             :                         .xpath = "/frr-vrf:lib/vrf/state/id",
    1025             :                         .cbs = {
    1026             :                                 .get_elem = lib_vrf_state_id_get_elem,
    1027             :                         }
    1028             :                 },
    1029             :                 {
    1030             :                         .xpath = "/frr-vrf:lib/vrf/state/active",
    1031             :                         .cbs = {
    1032             :                                 .get_elem = lib_vrf_state_active_get_elem,
    1033             :                         }
    1034             :                 },
    1035             :                 {
    1036             :                         .xpath = NULL,
    1037             :                 },
    1038             :         }
    1039             : };
    1040             : 

Generated by: LCOV version v1.16-topotato