back to topotato report
topotato coverage report
Current view: top level - lib - vrf.c (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 258 421 61.3 %
Date: 2023-11-16 17:19:14 Functions: 38 108 35.2 %

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

Generated by: LCOV version v1.16-topotato