Coverage Report

Created: 2025-08-28 06:29

/src/frr/lib/vrf.c
Line
Count
Source (jump to first uncovered line)
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
DEFINE_MTYPE_STATIC(LIB, VRF, "VRF");
28
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
RB_GENERATE(vrf_id_head, vrf, id_entry, vrf_id_compare);
36
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
struct vrf *vrf_lookup_by_name(const char *name)
65
7
{
66
7
  struct vrf vrf;
67
7
  strlcpy(vrf.name, name, sizeof(vrf.name));
68
7
  return (RB_FIND(vrf_name_head, &vrfs_by_name, &vrf));
69
7
}
70
71
static __inline int vrf_id_compare(const struct vrf *a, const struct vrf *b)
72
1.23k
{
73
1.23k
  return (a->vrf_id - b->vrf_id);
74
1.23k
}
75
76
static int vrf_name_compare(const struct vrf *a, const struct vrf *b)
77
5
{
78
5
  return strcmp(a->name, b->name);
79
5
}
80
81
int vrf_switch_to_netns(vrf_id_t vrf_id)
82
0
{
83
0
  char *name;
84
0
  struct vrf *vrf = vrf_lookup_by_id(vrf_id);
85
86
  /* VRF is default VRF. silently ignore */
87
0
  if (!vrf || vrf->vrf_id == VRF_DEFAULT)
88
0
    return 1; /* 1 = default */
89
  /* VRF has no NETNS backend. silently ignore */
90
0
  if (vrf->data.l.netns_name[0] == '\0')
91
0
    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
0
}
97
98
int vrf_switchback_to_initial(void)
99
0
{
100
0
  int ret = ns_switchback_to_initial();
101
102
0
  if (ret == 0 && debug_vrf)
103
0
    zlog_debug("VRF_SWITCHBACK");
104
0
  return ret;
105
0
}
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
struct vrf *vrf_get(vrf_id_t vrf_id, const char *name)
115
6
{
116
6
  struct vrf *vrf = NULL;
117
6
  int new = 0;
118
119
  /* Nothing to see, move along here */
120
6
  if (!name && vrf_id == VRF_UNKNOWN)
121
0
    return NULL;
122
123
  /* attempt to find already available VRF
124
   */
125
6
  if (name)
126
6
    vrf = vrf_lookup_by_name(name);
127
6
  if (vrf && vrf_id != VRF_UNKNOWN
128
6
      && vrf->vrf_id != VRF_UNKNOWN
129
6
      && vrf->vrf_id != vrf_id) {
130
0
    zlog_debug("VRF_GET: avoid %s creation(%u), same name exists (%u)",
131
0
         name, vrf_id, vrf->vrf_id);
132
0
    return NULL;
133
0
  }
134
  /* Try to find VRF both by ID and name */
135
6
  if (!vrf && vrf_id != VRF_UNKNOWN)
136
2
    vrf = vrf_lookup_by_id(vrf_id);
137
138
6
  if (vrf == NULL) {
139
2
    vrf = XCALLOC(MTYPE_VRF, sizeof(struct vrf));
140
2
    vrf->vrf_id = VRF_UNKNOWN;
141
2
    QOBJ_REG(vrf, vrf);
142
2
    new = 1;
143
144
2
    if (debug_vrf)
145
0
      zlog_debug("VRF(%u) %s is created.", vrf_id,
146
2
           (name) ? name : "(NULL)");
147
2
  }
148
149
  /* Set identifier */
150
6
  if (vrf_id != VRF_UNKNOWN && vrf->vrf_id == VRF_UNKNOWN) {
151
2
    vrf->vrf_id = vrf_id;
152
2
    RB_INSERT(vrf_id_head, &vrfs_by_id, vrf);
153
2
  }
154
155
  /* Set name */
156
6
  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
0
      name, NS_NAMSIZ);
161
0
    strlcpy(vrf->name, name, sizeof(vrf->name));
162
0
    RB_INSERT(vrf_name_head, &vrfs_by_name, vrf);
163
6
  } else if (name && vrf->name[0] == '\0') {
164
2
    strlcpy(vrf->name, name, sizeof(vrf->name));
165
2
    RB_INSERT(vrf_name_head, &vrfs_by_name, vrf);
166
2
  }
167
6
  if (new &&vrf_master.vrf_new_hook)
168
2
    (*vrf_master.vrf_new_hook)(vrf);
169
170
6
  return vrf;
171
6
}
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
struct vrf *vrf_update(vrf_id_t new_vrf_id, const char *name)
183
0
{
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
0
        "Vrf Update event: %s old id: %u, new id: %u",
196
0
        name, vrf->vrf_id, new_vrf_id);
197
0
    }
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
0
  } 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
0
  }
217
0
  return vrf;
218
0
}
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
void vrf_delete(struct vrf *vrf)
224
0
{
225
0
  if (debug_vrf)
226
0
    zlog_debug("VRF %s(%u) is to be deleted.", vrf->name,
227
0
         vrf->vrf_id);
228
229
0
  if (vrf_is_enabled(vrf))
230
0
    vrf_disable(vrf);
231
232
0
  if (vrf->vrf_id != VRF_UNKNOWN) {
233
0
    RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
234
0
    vrf->vrf_id = VRF_UNKNOWN;
235
0
  }
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
0
  if (vrf_is_user_cfged(vrf))
242
0
    return;
243
244
  /* Do not delete the VRF if it has interfaces configured in it. */
245
0
  if (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name))
246
0
    return;
247
248
0
  if (vrf_master.vrf_delete_hook)
249
0
    (*vrf_master.vrf_delete_hook)(vrf);
250
251
0
  QOBJ_UNREG(vrf);
252
253
0
  if (vrf->name[0] != '\0')
254
0
    RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf);
255
256
0
  XFREE(MTYPE_VRF, vrf);
257
0
}
258
259
/* Look up a VRF by identifier. */
260
struct vrf *vrf_lookup_by_id(vrf_id_t vrf_id)
261
1.23k
{
262
1.23k
  struct vrf vrf;
263
1.23k
  vrf.vrf_id = vrf_id;
264
1.23k
  return (RB_FIND(vrf_id_head, &vrfs_by_id, &vrf));
265
1.23k
}
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
int vrf_enable(struct vrf *vrf)
275
2
{
276
2
  if (vrf_is_enabled(vrf))
277
0
    return 1;
278
279
2
  if (debug_vrf)
280
0
    zlog_debug("VRF %s(%u) is enabled.", vrf->name, vrf->vrf_id);
281
282
2
  SET_FLAG(vrf->status, VRF_ACTIVE);
283
284
2
  if (vrf_master.vrf_enable_hook)
285
2
    (*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
2
  nexthop_group_enable_vrf(vrf);
293
294
2
  return 1;
295
2
}
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
void vrf_disable(struct vrf *vrf)
303
0
{
304
0
  if (!vrf_is_enabled(vrf))
305
0
    return;
306
307
0
  UNSET_FLAG(vrf->status, VRF_ACTIVE);
308
309
0
  if (debug_vrf)
310
0
    zlog_debug("VRF %s(%u) is to be disabled.", vrf->name,
311
0
         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
0
  nexthop_group_disable_vrf(vrf);
323
324
0
  if (vrf_master.vrf_disable_hook)
325
0
    (*vrf_master.vrf_disable_hook)(vrf);
326
0
}
327
328
const char *vrf_id_to_name(vrf_id_t vrf_id)
329
0
{
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
0
}
338
339
/* Look up the data pointer of the specified VRF. */
340
void *vrf_info_lookup(vrf_id_t vrf_id)
341
0
{
342
0
  struct vrf *vrf = vrf_lookup_by_id(vrf_id);
343
0
  return vrf ? vrf->info : NULL;
344
0
}
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
static unsigned int vrf_hash_bitmap_key(const void *data)
355
0
{
356
0
  const struct vrf_bit_set *bit = data;
357
358
0
  return bit->vrf_id;
359
0
}
360
361
static bool vrf_hash_bitmap_cmp(const void *a, const void *b)
362
0
{
363
0
  const struct vrf_bit_set *bit1 = a;
364
0
  const struct vrf_bit_set *bit2 = b;
365
366
0
  return bit1->vrf_id == bit2->vrf_id;
367
0
}
368
369
static void *vrf_hash_bitmap_alloc(void *data)
370
0
{
371
0
  struct vrf_bit_set *copy = data;
372
0
  struct vrf_bit_set *bit;
373
374
0
  bit = XMALLOC(MTYPE_VRF_BITMAP, sizeof(*bit));
375
0
  bit->vrf_id = copy->vrf_id;
376
377
0
  return bit;
378
0
}
379
380
static void vrf_hash_bitmap_free(void *data)
381
0
{
382
0
  struct vrf_bit_set *bit = data;
383
384
0
  XFREE(MTYPE_VRF_BITMAP, bit);
385
0
}
386
387
vrf_bitmap_t vrf_bitmap_init(void)
388
192
{
389
192
  return hash_create_size(32, vrf_hash_bitmap_key, vrf_hash_bitmap_cmp,
390
192
        "VRF BIT HASH");
391
192
}
392
393
void vrf_bitmap_free(vrf_bitmap_t bmap)
394
0
{
395
0
  struct hash *vrf_hash = bmap;
396
397
0
  hash_clean_and_free(&vrf_hash, vrf_hash_bitmap_free);
398
0
}
399
400
void vrf_bitmap_set(vrf_bitmap_t bmap, vrf_id_t vrf_id)
401
0
{
402
0
  struct vrf_bit_set lookup = { .vrf_id = vrf_id };
403
0
  struct hash *vrf_hash = bmap;
404
0
  struct vrf_bit_set *bit;
405
406
0
  if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
407
0
    return;
408
409
0
  bit = hash_get(vrf_hash, &lookup, vrf_hash_bitmap_alloc);
410
0
  bit->set = true;
411
0
}
412
413
void vrf_bitmap_unset(vrf_bitmap_t bmap, vrf_id_t vrf_id)
414
0
{
415
0
  struct vrf_bit_set lookup = { .vrf_id = vrf_id };
416
0
  struct hash *vrf_hash = bmap;
417
0
  struct vrf_bit_set *bit;
418
419
0
  if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
420
0
    return;
421
422
0
  bit = hash_get(vrf_hash, &lookup, vrf_hash_bitmap_alloc);
423
0
  bit->set = false;
424
0
}
425
426
int vrf_bitmap_check(vrf_bitmap_t bmap, vrf_id_t vrf_id)
427
3.27k
{
428
3.27k
  struct vrf_bit_set lookup = { .vrf_id = vrf_id };
429
3.27k
  struct hash *vrf_hash = bmap;
430
3.27k
  struct vrf_bit_set *bit;
431
432
3.27k
  if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
433
0
    return 0;
434
435
3.27k
  bit = hash_lookup(vrf_hash, &lookup);
436
3.27k
  if (bit)
437
0
    return bit->set;
438
439
3.27k
  return 0;
440
3.27k
}
441
442
static void vrf_autocomplete(vector comps, struct cmd_token *token)
443
0
{
444
0
  struct vrf *vrf = NULL;
445
446
0
  RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
447
0
    vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name));
448
0
}
449
450
static const struct cmd_variable_handler vrf_var_handlers[] = {
451
  {
452
    .varname = "vrf",
453
    .completions = vrf_autocomplete,
454
  },
455
  {
456
    .varname = "vrf_name",
457
    .completions = vrf_autocomplete,
458
  },
459
  {
460
    .varname = "nexthop_vrf",
461
    .completions = vrf_autocomplete,
462
  },
463
  {.completions = NULL},
464
};
465
466
/* Initialize VRF module. */
467
void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *),
468
        int (*disable)(struct vrf *), int (*destroy)(struct vrf *))
469
2
{
470
2
  struct vrf *default_vrf;
471
472
  /* initialise NS, in case VRF backend if NETNS */
473
2
  ns_init();
474
2
  if (debug_vrf)
475
0
    zlog_debug("%s: Initializing VRF subsystem", __func__);
476
477
2
  vrf_master.vrf_new_hook = create;
478
2
  vrf_master.vrf_enable_hook = enable;
479
2
  vrf_master.vrf_disable_hook = disable;
480
2
  vrf_master.vrf_delete_hook = destroy;
481
482
  /* The default VRF always exists. */
483
2
  default_vrf = vrf_get(VRF_DEFAULT, VRF_DEFAULT_NAME);
484
2
  if (!default_vrf) {
485
0
    flog_err(EC_LIB_VRF_START,
486
0
       "vrf_init: failed to create the default VRF!");
487
0
    exit(1);
488
0
  }
489
2
  if (vrf_is_backend_netns()) {
490
0
    struct ns *ns;
491
492
0
    strlcpy(default_vrf->data.l.netns_name,
493
0
      VRF_DEFAULT_NAME, NS_NAMSIZ);
494
0
    ns = ns_lookup(NS_DEFAULT);
495
0
    ns->vrf_ctxt = default_vrf;
496
0
    default_vrf->ns_ctxt = ns;
497
0
  }
498
499
  /* Enable the default VRF. */
500
2
  if (!vrf_enable(default_vrf)) {
501
0
    flog_err(EC_LIB_VRF_START,
502
0
       "vrf_init: failed to enable the default VRF!");
503
0
    exit(1);
504
0
  }
505
506
2
  cmd_variable_handler_register(vrf_var_handlers);
507
2
}
508
509
static void vrf_terminate_single(struct vrf *vrf)
510
0
{
511
  /* Clear configured flag and invoke delete. */
512
0
  vrf_disable(vrf);
513
0
  UNSET_FLAG(vrf->status, VRF_CONFIGURED);
514
0
  if_terminate(vrf);
515
0
  vrf_delete(vrf);
516
0
}
517
518
/* Terminate VRF module. */
519
void vrf_terminate(void)
520
0
{
521
0
  struct vrf *vrf, *tmp;
522
523
0
  if (debug_vrf)
524
0
    zlog_debug("%s: Shutting down vrf subsystem", __func__);
525
526
0
  RB_FOREACH_SAFE (vrf, vrf_id_head, &vrfs_by_id, tmp) {
527
0
    if (vrf->vrf_id == VRF_DEFAULT)
528
0
      continue;
529
530
0
    vrf_terminate_single(vrf);
531
0
  }
532
533
0
  RB_FOREACH_SAFE (vrf, vrf_name_head, &vrfs_by_name, tmp) {
534
0
    if (vrf->vrf_id == VRF_DEFAULT)
535
0
      continue;
536
537
0
    vrf_terminate_single(vrf);
538
0
  }
539
540
  /* Finally terminate default VRF */
541
0
  vrf = vrf_lookup_by_id(VRF_DEFAULT);
542
0
  if (vrf)
543
0
    vrf_terminate_single(vrf);
544
0
}
545
546
int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
547
         const char *interfacename)
548
0
{
549
0
  int ret, save_errno, ret2;
550
551
0
  ret = vrf_switch_to_netns(vrf_id);
552
0
  if (ret < 0)
553
0
    flog_err_sys(EC_LIB_SOCKET, "%s: Can't switch to VRF %u (%s)",
554
0
           __func__, vrf_id, safe_strerror(errno));
555
556
0
  ret = socket(domain, type, protocol);
557
0
  save_errno = errno;
558
0
  ret2 = vrf_switchback_to_initial();
559
0
  if (ret2 < 0)
560
0
    flog_err_sys(EC_LIB_SOCKET,
561
0
           "%s: Can't switchback from VRF %u (%s)", __func__,
562
0
           vrf_id, safe_strerror(errno));
563
0
  errno = save_errno;
564
0
  if (ret <= 0)
565
0
    return ret;
566
0
  ret2 = vrf_bind(vrf_id, ret, interfacename);
567
0
  if (ret2 < 0) {
568
0
    close(ret);
569
0
    ret = ret2;
570
0
  }
571
0
  return ret;
572
0
}
573
574
int vrf_is_backend_netns(void)
575
2
{
576
2
  return (vrf_backend == VRF_BACKEND_NETNS);
577
2
}
578
579
int vrf_get_backend(void)
580
3
{
581
3
  if (!vrf_backend_configured)
582
1
    return VRF_BACKEND_UNKNOWN;
583
2
  return vrf_backend;
584
3
}
585
586
int vrf_configure_backend(enum vrf_backend_type backend)
587
1
{
588
  /* Work around issue in old gcc */
589
1
  switch (backend) {
590
0
  case VRF_BACKEND_UNKNOWN:
591
0
  case VRF_BACKEND_NETNS:
592
1
  case VRF_BACKEND_VRF_LITE:
593
1
    break;
594
0
  case VRF_BACKEND_MAX:
595
0
    return -1;
596
1
  }
597
598
1
  vrf_backend = backend;
599
1
  vrf_backend_configured = 1;
600
601
1
  return 0;
602
1
}
603
604
/* vrf CLI commands */
605
DEFUN_NOSH(vrf_exit,
606
           vrf_exit_cmd,
607
     "exit-vrf",
608
     "Exit current mode and down to previous mode\n")
609
0
{
610
0
  cmd_exit(vty);
611
0
  return CMD_SUCCESS;
612
0
}
613
614
DEFUN_YANG_NOSH (vrf,
615
       vrf_cmd,
616
       "vrf NAME",
617
       "Select a VRF to configure\n"
618
       "VRF's name\n")
619
0
{
620
0
  int idx_name = 1;
621
0
  const char *vrfname = argv[idx_name]->arg;
622
0
  char xpath_list[XPATH_MAXLEN];
623
0
  struct vrf *vrf;
624
0
  int ret;
625
626
0
  if (strlen(vrfname) > VRF_NAMSIZ) {
627
0
    vty_out(vty,
628
0
      "%% VRF name %s invalid: length exceeds %d bytes\n",
629
0
      vrfname, VRF_NAMSIZ);
630
0
    return CMD_WARNING_CONFIG_FAILED;
631
0
  }
632
633
0
  snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH, vrfname);
634
635
0
  nb_cli_enqueue_change(vty, xpath_list, NB_OP_CREATE, NULL);
636
0
  ret = nb_cli_apply_changes_clear_pending(vty, "%s", xpath_list);
637
0
  if (ret == CMD_SUCCESS) {
638
0
    VTY_PUSH_XPATH(VRF_NODE, xpath_list);
639
0
    vrf = vrf_lookup_by_name(vrfname);
640
0
    if (vrf)
641
0
      VTY_PUSH_CONTEXT(VRF_NODE, vrf);
642
0
  }
643
644
0
  return ret;
645
0
}
646
647
DEFUN_YANG (no_vrf,
648
       no_vrf_cmd,
649
       "no vrf NAME",
650
       NO_STR
651
       "Delete a pseudo VRF's configuration\n"
652
       "VRF's name\n")
653
0
{
654
0
  const char *vrfname = argv[2]->arg;
655
0
  char xpath_list[XPATH_MAXLEN];
656
657
0
  struct vrf *vrfp;
658
659
0
  vrfp = vrf_lookup_by_name(vrfname);
660
661
0
  if (vrfp == NULL)
662
0
    return CMD_SUCCESS;
663
664
0
  if (CHECK_FLAG(vrfp->status, VRF_ACTIVE)) {
665
0
    vty_out(vty, "%% Only inactive VRFs can be deleted\n");
666
0
    return CMD_WARNING_CONFIG_FAILED;
667
0
  }
668
669
0
  if (vrf_get_backend() == VRF_BACKEND_VRF_LITE) {
670
    /*
671
     * Remove the VRF interface config when removing the VRF.
672
     */
673
0
    snprintf(xpath_list, sizeof(xpath_list),
674
0
       "/frr-interface:lib/interface[name='%s']", vrfname);
675
0
    nb_cli_enqueue_change(vty, xpath_list, NB_OP_DESTROY, NULL);
676
0
  }
677
678
0
  snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH, vrfname);
679
680
0
  nb_cli_enqueue_change(vty, xpath_list, NB_OP_DESTROY, NULL);
681
0
  return nb_cli_apply_changes(vty, NULL);
682
0
}
683
684
685
static struct cmd_node vrf_node = {
686
  .name = "vrf",
687
  .node = VRF_NODE,
688
  .parent_node = CONFIG_NODE,
689
  .prompt = "%s(config-vrf)# ",
690
};
691
692
/*
693
 * Debug CLI for vrf's
694
 */
695
DEFUN (vrf_debug,
696
      vrf_debug_cmd,
697
      "debug vrf",
698
      DEBUG_STR
699
      "VRF Debugging\n")
700
0
{
701
0
  debug_vrf = 1;
702
703
0
  return CMD_SUCCESS;
704
0
}
705
706
DEFUN (no_vrf_debug,
707
      no_vrf_debug_cmd,
708
      "no debug vrf",
709
      NO_STR
710
      DEBUG_STR
711
      "VRF Debugging\n")
712
0
{
713
0
  debug_vrf = 0;
714
715
0
  return CMD_SUCCESS;
716
0
}
717
718
static int vrf_write_host(struct vty *vty)
719
0
{
720
0
  if (debug_vrf)
721
0
    vty_out(vty, "debug vrf\n");
722
723
0
  return 1;
724
0
}
725
726
static int vrf_write_host(struct vty *vty);
727
static struct cmd_node vrf_debug_node = {
728
  .name = "vrf debug",
729
  .node = VRF_DEBUG_NODE,
730
  .prompt = "",
731
  .config_write = vrf_write_host,
732
};
733
734
void vrf_install_commands(void)
735
2
{
736
2
  install_node(&vrf_debug_node);
737
738
2
  install_element(CONFIG_NODE, &vrf_debug_cmd);
739
2
  install_element(ENABLE_NODE, &vrf_debug_cmd);
740
2
  install_element(CONFIG_NODE, &no_vrf_debug_cmd);
741
2
  install_element(ENABLE_NODE, &no_vrf_debug_cmd);
742
2
}
743
744
void vrf_cmd_init(int (*writefunc)(struct vty *vty))
745
0
{
746
0
  install_element(CONFIG_NODE, &vrf_cmd);
747
0
  install_element(CONFIG_NODE, &no_vrf_cmd);
748
0
  vrf_node.config_write = writefunc;
749
0
  install_node(&vrf_node);
750
0
  install_default(VRF_NODE);
751
0
  install_element(VRF_NODE, &vrf_exit_cmd);
752
0
}
753
754
void vrf_set_default_name(const char *default_name)
755
0
{
756
0
  snprintf(vrf_default_name, VRF_NAMSIZ, "%s", default_name);
757
0
}
758
759
const char *vrf_get_default_name(void)
760
4
{
761
4
  return vrf_default_name;
762
4
}
763
764
int vrf_bind(vrf_id_t vrf_id, int fd, const char *ifname)
765
0
{
766
0
  int ret = 0;
767
0
  struct interface *ifp;
768
0
  struct vrf *vrf;
769
770
0
  if (fd < 0)
771
0
    return -1;
772
773
0
  if (vrf_id == VRF_UNKNOWN)
774
0
    return -1;
775
776
  /* can't bind to a VRF that doesn't exist */
777
0
  vrf = vrf_lookup_by_id(vrf_id);
778
0
  if (!vrf_is_enabled(vrf))
779
0
    return -1;
780
781
0
  if (ifname && strcmp(ifname, vrf->name)) {
782
    /* binding to a regular interface */
783
784
    /* can't bind to an interface that doesn't exist */
785
0
    ifp = if_lookup_by_name(ifname, vrf_id);
786
0
    if (!ifp)
787
0
      return -1;
788
0
  } else {
789
    /* binding to a VRF device */
790
791
    /* nothing to do for netns */
792
0
    if (vrf_is_backend_netns())
793
0
      return 0;
794
795
    /* nothing to do for default vrf */
796
0
    if (vrf_id == VRF_DEFAULT)
797
0
      return 0;
798
799
0
    ifname = vrf->name;
800
0
  }
801
802
0
#ifdef SO_BINDTODEVICE
803
0
  ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
804
0
       strlen(ifname) + 1);
805
0
  if (ret < 0)
806
0
    zlog_err("bind to interface %s failed, errno=%d", ifname,
807
0
       errno);
808
0
#endif /* SO_BINDTODEVICE */
809
0
  return ret;
810
0
}
811
int vrf_getaddrinfo(const char *node, const char *service,
812
        const struct addrinfo *hints, struct addrinfo **res,
813
        vrf_id_t vrf_id)
814
0
{
815
0
  int ret, ret2, save_errno;
816
817
0
  ret = vrf_switch_to_netns(vrf_id);
818
0
  if (ret < 0)
819
0
    flog_err_sys(EC_LIB_SOCKET, "%s: Can't switch to VRF %u (%s)",
820
0
           __func__, vrf_id, safe_strerror(errno));
821
0
  ret = getaddrinfo(node, service, hints, res);
822
0
  save_errno = errno;
823
0
  ret2 = vrf_switchback_to_initial();
824
0
  if (ret2 < 0)
825
0
    flog_err_sys(EC_LIB_SOCKET,
826
0
           "%s: Can't switchback from VRF %u (%s)", __func__,
827
0
           vrf_id, safe_strerror(errno));
828
0
  errno = save_errno;
829
0
  return ret;
830
0
}
831
832
int vrf_ioctl(vrf_id_t vrf_id, int d, unsigned long request, char *params)
833
0
{
834
0
  int ret, saved_errno, rc;
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
0
           __func__, vrf_id, safe_strerror(errno));
840
0
    return 0;
841
0
  }
842
0
  rc = ioctl(d, request, params);
843
0
  saved_errno = errno;
844
0
  ret = vrf_switchback_to_initial();
845
0
  if (ret < 0)
846
0
    flog_err_sys(EC_LIB_SOCKET,
847
0
           "%s: Can't switchback from VRF %u (%s)", __func__,
848
0
           vrf_id, safe_strerror(errno));
849
0
  errno = saved_errno;
850
0
  return rc;
851
0
}
852
853
int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id,
854
       const char *interfacename)
855
0
{
856
0
  int ret, save_errno, ret2;
857
858
0
  ret = vrf_switch_to_netns(vrf_id);
859
0
  if (ret < 0)
860
0
    flog_err_sys(EC_LIB_SOCKET, "%s: Can't switch to VRF %u (%s)",
861
0
           __func__, vrf_id, safe_strerror(errno));
862
0
  ret = sockunion_socket(su);
863
0
  save_errno = errno;
864
0
  ret2 = vrf_switchback_to_initial();
865
0
  if (ret2 < 0)
866
0
    flog_err_sys(EC_LIB_SOCKET,
867
0
           "%s: Can't switchback from VRF %u (%s)", __func__,
868
0
           vrf_id, safe_strerror(errno));
869
0
  errno = save_errno;
870
871
0
  if (ret <= 0)
872
0
    return ret;
873
0
  ret2 = vrf_bind(vrf_id, ret, interfacename);
874
0
  if (ret2 < 0) {
875
0
    close(ret);
876
0
    ret = ret2;
877
0
  }
878
0
  return ret;
879
0
}
880
881
/* ------- Northbound callbacks ------- */
882
883
/*
884
 * XPath: /frr-vrf:lib/vrf
885
 */
886
static int lib_vrf_create(struct nb_cb_create_args *args)
887
0
{
888
0
  const char *vrfname;
889
0
  struct vrf *vrfp;
890
891
0
  vrfname = yang_dnode_get_string(args->dnode, "./name");
892
893
0
  if (args->event != NB_EV_APPLY)
894
0
    return NB_OK;
895
896
0
  vrfp = vrf_get(VRF_UNKNOWN, vrfname);
897
898
0
  SET_FLAG(vrfp->status, VRF_CONFIGURED);
899
0
  nb_running_set_entry(args->dnode, vrfp);
900
901
0
  return NB_OK;
902
0
}
903
904
static int lib_vrf_destroy(struct nb_cb_destroy_args *args)
905
0
{
906
0
  struct vrf *vrfp;
907
908
0
  switch (args->event) {
909
0
  case NB_EV_VALIDATE:
910
0
    vrfp = nb_running_get_entry(args->dnode, NULL, true);
911
0
    if (CHECK_FLAG(vrfp->status, VRF_ACTIVE)) {
912
0
      snprintf(args->errmsg, args->errmsg_len,
913
0
         "Only inactive VRFs can be deleted");
914
0
      return NB_ERR_VALIDATION;
915
0
    }
916
0
    break;
917
0
  case NB_EV_PREPARE:
918
0
  case NB_EV_ABORT:
919
0
    break;
920
0
  case NB_EV_APPLY:
921
0
    vrfp = nb_running_unset_entry(args->dnode);
922
923
    /* Clear configured flag and invoke delete. */
924
0
    UNSET_FLAG(vrfp->status, VRF_CONFIGURED);
925
0
    vrf_delete(vrfp);
926
0
    break;
927
0
  }
928
929
0
  return NB_OK;
930
0
}
931
932
static const void *lib_vrf_get_next(struct nb_cb_get_next_args *args)
933
0
{
934
0
  struct vrf *vrfp = (struct vrf *)args->list_entry;
935
936
0
  if (args->list_entry == NULL) {
937
0
    vrfp = RB_MIN(vrf_name_head, &vrfs_by_name);
938
0
  } else {
939
0
    vrfp = RB_NEXT(vrf_name_head, vrfp);
940
0
  }
941
942
0
  return vrfp;
943
0
}
944
945
static int lib_vrf_get_keys(struct nb_cb_get_keys_args *args)
946
0
{
947
0
  struct vrf *vrfp = (struct vrf *)args->list_entry;
948
949
0
  args->keys->num = 1;
950
0
  strlcpy(args->keys->key[0], vrfp->name, sizeof(args->keys->key[0]));
951
952
0
  return NB_OK;
953
0
}
954
955
static const void *lib_vrf_lookup_entry(struct nb_cb_lookup_entry_args *args)
956
0
{
957
0
  const char *vrfname = args->keys->key[0];
958
959
0
  struct vrf *vrf = vrf_lookup_by_name(vrfname);
960
961
0
  return vrf;
962
0
}
963
964
/*
965
 * XPath: /frr-vrf:lib/vrf/id
966
 */
967
static struct yang_data *
968
lib_vrf_state_id_get_elem(struct nb_cb_get_elem_args *args)
969
0
{
970
0
  struct vrf *vrfp = (struct vrf *)args->list_entry;
971
972
0
  return yang_data_new_uint32(args->xpath, vrfp->vrf_id);
973
0
}
974
975
/*
976
 * XPath: /frr-vrf:lib/vrf/active
977
 */
978
static struct yang_data *
979
lib_vrf_state_active_get_elem(struct nb_cb_get_elem_args *args)
980
0
{
981
0
  struct vrf *vrfp = (struct vrf *)args->list_entry;
982
983
0
  if (vrfp->status == VRF_ACTIVE)
984
0
    return yang_data_new_bool(args->xpath, true);
985
986
0
  return NULL;
987
0
}
988
989
/* clang-format off */
990
const struct frr_yang_module_info frr_vrf_info = {
991
  .name = "frr-vrf",
992
  .nodes = {
993
    {
994
      .xpath = "/frr-vrf:lib/vrf",
995
      .cbs = {
996
        .create = lib_vrf_create,
997
        .destroy = lib_vrf_destroy,
998
        .get_next = lib_vrf_get_next,
999
        .get_keys = lib_vrf_get_keys,
1000
        .lookup_entry = lib_vrf_lookup_entry,
1001
      },
1002
      .priority = NB_DFLT_PRIORITY - 2,
1003
    },
1004
    {
1005
      .xpath = "/frr-vrf:lib/vrf/state/id",
1006
      .cbs = {
1007
        .get_elem = lib_vrf_state_id_get_elem,
1008
      }
1009
    },
1010
    {
1011
      .xpath = "/frr-vrf:lib/vrf/state/active",
1012
      .cbs = {
1013
        .get_elem = lib_vrf_state_active_get_elem,
1014
      }
1015
    },
1016
    {
1017
      .xpath = NULL,
1018
    },
1019
  }
1020
};
1021