Coverage Report

Created: 2026-01-21 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/frr/zebra/zebra_vrf.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 * Copyright (C) 2016 CumulusNetworks
4
 *                    Donald Sharp
5
 *
6
 * This file is part of Quagga
7
 */
8
#include <zebra.h>
9
10
/* for basename */
11
#include <libgen.h>
12
13
#include "log.h"
14
#include "linklist.h"
15
#include "command.h"
16
#include "memory.h"
17
#include "srcdest_table.h"
18
#include "vrf.h"
19
#include "vty.h"
20
21
#include "zebra/zebra_router.h"
22
#include "zebra/rtadv.h"
23
#include "zebra/debug.h"
24
#include "zebra/zapi_msg.h"
25
#include "zebra/rib.h"
26
#include "zebra/zebra_vrf.h"
27
#include "zebra/zebra_rnh.h"
28
#include "zebra/router-id.h"
29
#include "zebra/interface.h"
30
#include "zebra/zebra_mpls.h"
31
#include "zebra/zebra_vxlan.h"
32
#include "zebra/zebra_netns_notify.h"
33
#include "zebra/zebra_routemap.h"
34
#include "zebra/zebra_vrf_clippy.c"
35
#include "zebra/table_manager.h"
36
37
static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi,
38
           safi_t safi);
39
static void zebra_rnhtable_node_cleanup(struct route_table *table,
40
          struct route_node *node);
41
42
2
DEFINE_MTYPE_STATIC(ZEBRA, ZEBRA_VRF, "ZEBRA VRF");
43
2
DEFINE_MTYPE_STATIC(ZEBRA, OTHER_TABLE, "Other Table");
44
2
45
2
/* VRF information update. */
46
2
static void zebra_vrf_add_update(struct zebra_vrf *zvrf)
47
2
{
48
1
  struct listnode *node, *nnode;
49
1
  struct zserv *client;
50
51
1
  if (IS_ZEBRA_DEBUG_EVENT)
52
0
    zlog_debug("MESSAGE: ZEBRA_VRF_ADD %s", zvrf_name(zvrf));
53
54
1
  for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
55
    /* Do not send unsolicited messages to synchronous clients. */
56
0
    if (client->synchronous)
57
0
      continue;
58
59
0
    zsend_vrf_add(client, zvrf);
60
0
  }
61
1
}
62
63
static void zebra_vrf_delete_update(struct zebra_vrf *zvrf)
64
0
{
65
0
  struct listnode *node, *nnode;
66
0
  struct zserv *client;
67
68
0
  if (IS_ZEBRA_DEBUG_EVENT)
69
0
    zlog_debug("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf_name(zvrf));
70
71
0
  for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
72
    /* Do not send unsolicited messages to synchronous clients. */
73
0
    if (client->synchronous)
74
0
      continue;
75
76
0
    zsend_vrf_delete(client, zvrf);
77
0
  }
78
0
}
79
80
void zebra_vrf_update_all(struct zserv *client)
81
0
{
82
0
  struct vrf *vrf;
83
84
0
  RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
85
0
    if (vrf->vrf_id != VRF_UNKNOWN)
86
0
      zsend_vrf_add(client, vrf_info_lookup(vrf->vrf_id));
87
0
  }
88
0
}
89
90
/* Callback upon creating a new VRF. */
91
static int zebra_vrf_new(struct vrf *vrf)
92
1
{
93
1
  struct zebra_vrf *zvrf;
94
95
1
  if (IS_ZEBRA_DEBUG_EVENT)
96
0
    zlog_debug("VRF %s created, id %u", vrf->name, vrf->vrf_id);
97
98
1
  zvrf = zebra_vrf_alloc(vrf);
99
1
  if (!vrf_is_backend_netns())
100
1
    zvrf->zns = zebra_ns_lookup(NS_DEFAULT);
101
102
1
  otable_init(&zvrf->other_tables);
103
104
1
  router_id_init(zvrf);
105
106
  /* Initiate Table Manager per ZNS */
107
1
  table_manager_enable(zvrf);
108
109
1
  return 0;
110
1
}
111
112
/* Callback upon enabling a VRF. */
113
static int zebra_vrf_enable(struct vrf *vrf)
114
1
{
115
1
  struct zebra_vrf *zvrf = vrf->info;
116
1
  struct route_table *table;
117
1
  afi_t afi;
118
1
  safi_t safi;
119
120
1
  assert(zvrf);
121
1
  if (IS_ZEBRA_DEBUG_EVENT)
122
0
    zlog_debug("VRF %s id %u is now active", zvrf_name(zvrf),
123
1
         zvrf_id(zvrf));
124
125
1
  if (vrf_is_backend_netns())
126
0
    zvrf->zns = zebra_ns_lookup((ns_id_t)vrf->vrf_id);
127
1
  else
128
1
    zvrf->zns = zebra_ns_lookup(NS_DEFAULT);
129
130
1
  rtadv_vrf_init(zvrf);
131
132
  /* Inform clients that the VRF is now active. This is an
133
   * add for the clients.
134
   */
135
136
1
  zebra_vrf_add_update(zvrf);
137
  /* Allocate tables */
138
3
  for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
139
6
    for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
140
4
      zebra_vrf_table_create(zvrf, afi, safi);
141
142
2
    table = route_table_init();
143
2
    table->cleanup = zebra_rnhtable_node_cleanup;
144
2
    zvrf->rnh_table[afi] = table;
145
146
2
    table = route_table_init();
147
2
    table->cleanup = zebra_rnhtable_node_cleanup;
148
2
    zvrf->rnh_table_multicast[afi] = table;
149
2
  }
150
151
  /* Kick off any VxLAN-EVPN processing. */
152
1
  zebra_vxlan_vrf_enable(zvrf);
153
154
1
  return 0;
155
1
}
156
157
/* Callback upon disabling a VRF. */
158
static int zebra_vrf_disable(struct vrf *vrf)
159
0
{
160
0
  struct zebra_vrf *zvrf = vrf->info;
161
0
  struct interface *ifp;
162
0
  afi_t afi;
163
0
  safi_t safi;
164
165
0
  assert(zvrf);
166
0
  if (IS_ZEBRA_DEBUG_EVENT)
167
0
    zlog_debug("VRF %s id %u is now inactive", zvrf_name(zvrf),
168
0
         zvrf_id(zvrf));
169
170
  /* Stop any VxLAN-EVPN processing. */
171
0
  zebra_vxlan_vrf_disable(zvrf);
172
173
0
  rtadv_vrf_terminate(zvrf);
174
175
  /* Inform clients that the VRF is now inactive. This is a
176
   * delete for the clients.
177
   */
178
0
  zebra_vrf_delete_update(zvrf);
179
180
  /* If asked to retain routes, there's nothing more to do. */
181
0
  if (CHECK_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN))
182
0
    return 0;
183
184
  /* Remove all routes. */
185
0
  for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
186
0
    route_table_finish(zvrf->rnh_table[afi]);
187
0
    zvrf->rnh_table[afi] = NULL;
188
0
    route_table_finish(zvrf->rnh_table_multicast[afi]);
189
0
    zvrf->rnh_table_multicast[afi] = NULL;
190
191
0
    for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
192
0
      rib_close_table(zvrf->table[afi][safi]);
193
0
  }
194
195
  /* Cleanup Vxlan, MPLS and PW tables. */
196
0
  zebra_vxlan_cleanup_tables(zvrf);
197
0
  zebra_mpls_cleanup_tables(zvrf);
198
0
  zebra_pw_exit(zvrf);
199
200
  /* Remove link-local IPv4 addresses created for BGP unnumbered peering.
201
   */
202
0
  FOR_ALL_INTERFACES (vrf, ifp)
203
0
    if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
204
205
  /* clean-up work queues */
206
0
  meta_queue_free(zrouter.mq, zvrf);
207
208
  /* Cleanup (free) routing tables and NHT tables. */
209
0
  for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
210
    /*
211
     * Set the table pointer to NULL as that
212
     * we no-longer need a copy of it, nor do we
213
     * own this data, the zebra_router structure
214
     * owns these tables.  Once we've cleaned up the
215
     * table, see rib_close_table above
216
     * we no-longer need this pointer.
217
     */
218
0
    for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
219
0
      zebra_router_release_table(zvrf, zvrf->table_id, afi,
220
0
               safi);
221
0
      zvrf->table[afi][safi] = NULL;
222
0
    }
223
0
  }
224
225
0
  return 0;
226
0
}
227
228
static int zebra_vrf_delete(struct vrf *vrf)
229
0
{
230
0
  struct zebra_vrf *zvrf = vrf->info;
231
0
  struct other_route_table *otable;
232
233
0
  assert(zvrf);
234
0
  if (IS_ZEBRA_DEBUG_EVENT)
235
0
    zlog_debug("VRF %s id %u deleted", zvrf_name(zvrf),
236
0
         zvrf_id(zvrf));
237
238
0
  table_manager_disable(zvrf);
239
240
  /* clean-up work queues */
241
0
  meta_queue_free(zrouter.mq, zvrf);
242
243
  /* Free Vxlan and MPLS. */
244
0
  zebra_vxlan_close_tables(zvrf);
245
0
  zebra_mpls_close_tables(zvrf);
246
247
0
  otable = otable_pop(&zvrf->other_tables);
248
0
  while (otable) {
249
0
    zebra_router_release_table(zvrf, otable->table_id,
250
0
             otable->afi, otable->safi);
251
0
    XFREE(MTYPE_OTHER_TABLE, otable);
252
253
0
    otable = otable_pop(&zvrf->other_tables);
254
0
  }
255
256
  /* Cleanup EVPN states for vrf */
257
0
  zebra_vxlan_vrf_delete(zvrf);
258
0
  zebra_routemap_vrf_delete(zvrf);
259
260
0
  list_delete_all_node(zvrf->rid_all_sorted_list);
261
0
  list_delete_all_node(zvrf->rid_lo_sorted_list);
262
263
0
  list_delete_all_node(zvrf->rid6_all_sorted_list);
264
0
  list_delete_all_node(zvrf->rid6_lo_sorted_list);
265
266
0
  otable_fini(&zvrf->other_tables);
267
0
  XFREE(MTYPE_ZEBRA_VRF, zvrf);
268
0
  vrf->info = NULL;
269
270
0
  return 0;
271
0
}
272
273
/* Lookup the routing table in a VRF based on both VRF-Id and table-id.
274
 * NOTE: Table-id is relevant on two modes:
275
 * - case VRF backend is default : on default VRF only
276
 * - case VRF backend is netns : on all VRFs
277
 */
278
struct route_table *zebra_vrf_lookup_table_with_table_id(afi_t afi, safi_t safi,
279
               vrf_id_t vrf_id,
280
               uint32_t table_id)
281
0
{
282
0
  struct zebra_vrf *zvrf = vrf_info_lookup(vrf_id);
283
0
  struct other_route_table ort, *otable;
284
285
0
  if (!zvrf)
286
0
    return NULL;
287
288
0
  if (afi >= AFI_MAX || safi >= SAFI_MAX)
289
0
    return NULL;
290
291
0
  if (table_id == zvrf->table_id)
292
0
    return zebra_vrf_table(afi, safi, vrf_id);
293
294
0
  ort.afi = afi;
295
0
  ort.safi = safi;
296
0
  ort.table_id = table_id;
297
0
  otable = otable_find(&zvrf->other_tables, &ort);
298
299
0
  if (otable)
300
0
    return otable->table;
301
302
0
  return NULL;
303
0
}
304
305
struct route_table *zebra_vrf_get_table_with_table_id(afi_t afi, safi_t safi,
306
                  vrf_id_t vrf_id,
307
                  uint32_t table_id)
308
0
{
309
0
  struct zebra_vrf *zvrf = vrf_info_lookup(vrf_id);
310
0
  struct other_route_table *otable;
311
0
  struct route_table *table;
312
313
0
  table = zebra_vrf_lookup_table_with_table_id(afi, safi, vrf_id,
314
0
                 table_id);
315
316
0
  if (table)
317
0
    goto done;
318
319
  /* Create it as an `other` table */
320
0
  table = zebra_router_get_table(zvrf, table_id, afi, safi);
321
322
0
  otable = XCALLOC(MTYPE_OTHER_TABLE, sizeof(*otable));
323
0
  otable->afi = afi;
324
0
  otable->safi = safi;
325
0
  otable->table_id = table_id;
326
0
  otable->table = table;
327
0
  otable_add(&zvrf->other_tables, otable);
328
329
0
done:
330
0
  return table;
331
0
}
332
333
static void zebra_rnhtable_node_cleanup(struct route_table *table,
334
          struct route_node *node)
335
1.25k
{
336
1.25k
  if (node->info)
337
0
    zebra_free_rnh(node->info);
338
1.25k
}
339
340
/*
341
 * Create a routing table for the specific AFI/SAFI in the given VRF.
342
 */
343
static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi,
344
           safi_t safi)
345
4
{
346
4
  struct route_node *rn;
347
4
  struct prefix p;
348
349
4
  assert(!zvrf->table[afi][safi]);
350
351
4
  zvrf->table[afi][safi] =
352
4
    zebra_router_get_table(zvrf, zvrf->table_id, afi, safi);
353
354
4
  memset(&p, 0, sizeof(p));
355
4
  p.family = afi2family(afi);
356
357
4
  rn = srcdest_rnode_get(zvrf->table[afi][safi], &p, NULL);
358
4
  zebra_rib_create_dest(rn);
359
4
}
360
361
/* Allocate new zebra VRF. */
362
struct zebra_vrf *zebra_vrf_alloc(struct vrf *vrf)
363
1
{
364
1
  struct zebra_vrf *zvrf;
365
366
1
  zvrf = XCALLOC(MTYPE_ZEBRA_VRF, sizeof(struct zebra_vrf));
367
368
1
  zvrf->vrf = vrf;
369
1
  vrf->info = zvrf;
370
371
1
  zebra_vxlan_init_tables(zvrf);
372
1
  zebra_mpls_init_tables(zvrf);
373
1
  zebra_pw_init(zvrf);
374
1
  zvrf->table_id = RT_TABLE_MAIN;
375
  /* by default table ID is default one */
376
1
  return zvrf;
377
1
}
378
379
/* Lookup VRF by identifier.  */
380
struct zebra_vrf *zebra_vrf_lookup_by_id(vrf_id_t vrf_id)
381
7.50k
{
382
7.50k
  return vrf_info_lookup(vrf_id);
383
7.50k
}
384
385
/* Lookup VRF by name.  */
386
struct zebra_vrf *zebra_vrf_lookup_by_name(const char *name)
387
0
{
388
0
  struct vrf *vrf;
389
390
0
  if (!name)
391
0
    name = VRF_DEFAULT_NAME;
392
393
0
  vrf = vrf_lookup_by_name(name);
394
0
  if (vrf)
395
0
    return ((struct zebra_vrf *)vrf->info);
396
397
0
  return NULL;
398
0
}
399
400
/* Lookup the routing table in an enabled VRF. */
401
struct route_table *zebra_vrf_table(afi_t afi, safi_t safi, vrf_id_t vrf_id)
402
880
{
403
880
  struct zebra_vrf *zvrf = vrf_info_lookup(vrf_id);
404
405
880
  if (!zvrf)
406
0
    return NULL;
407
408
880
  if (afi >= AFI_MAX || safi >= SAFI_MAX)
409
0
    return NULL;
410
411
880
  return zvrf->table[afi][safi];
412
880
}
413
414
static int vrf_config_write(struct vty *vty)
415
0
{
416
0
  struct vrf *vrf;
417
0
  struct zebra_vrf *zvrf;
418
419
0
  RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
420
0
    zvrf = vrf->info;
421
422
0
    if (!zvrf)
423
0
      continue;
424
425
0
    if (zvrf_id(zvrf) == VRF_DEFAULT) {
426
0
      if (zvrf->l3vni)
427
0
        vty_out(vty, "vni %u%s\n", zvrf->l3vni,
428
0
          is_l3vni_for_prefix_routes_only(
429
0
            zvrf->l3vni)
430
0
            ? " prefix-routes-only"
431
0
            : "");
432
0
      if (zvrf->zebra_rnh_ip_default_route)
433
0
        vty_out(vty, "ip nht resolve-via-default\n");
434
435
0
      if (zvrf->zebra_rnh_ipv6_default_route)
436
0
        vty_out(vty, "ipv6 nht resolve-via-default\n");
437
438
0
      if (zvrf->tbl_mgr
439
0
          && (zvrf->tbl_mgr->start || zvrf->tbl_mgr->end))
440
0
        vty_out(vty, "ip table range %u %u\n",
441
0
          zvrf->tbl_mgr->start,
442
0
          zvrf->tbl_mgr->end);
443
0
    } else {
444
0
      vty_frame(vty, "vrf %s\n", zvrf_name(zvrf));
445
0
      if (zvrf->l3vni)
446
0
        vty_out(vty, " vni %u%s\n", zvrf->l3vni,
447
0
          is_l3vni_for_prefix_routes_only(
448
0
            zvrf->l3vni)
449
0
            ? " prefix-routes-only"
450
0
            : "");
451
0
      zebra_ns_config_write(vty, (struct ns *)vrf->ns_ctxt);
452
0
      if (zvrf->zebra_rnh_ip_default_route)
453
0
        vty_out(vty, " ip nht resolve-via-default\n");
454
455
0
      if (zvrf->zebra_rnh_ipv6_default_route)
456
0
        vty_out(vty, " ipv6 nht resolve-via-default\n");
457
458
0
      if (zvrf->tbl_mgr && vrf_is_backend_netns()
459
0
          && (zvrf->tbl_mgr->start || zvrf->tbl_mgr->end))
460
0
        vty_out(vty, " ip table range %u %u\n",
461
0
          zvrf->tbl_mgr->start,
462
0
          zvrf->tbl_mgr->end);
463
0
    }
464
465
466
0
    zebra_routemap_config_write_protocol(vty, zvrf);
467
0
    router_id_write(vty, zvrf);
468
469
0
    if (zvrf_id(zvrf) != VRF_DEFAULT)
470
0
      vty_endframe(vty, "exit-vrf\n!\n");
471
0
    else
472
0
      vty_out(vty, "!\n");
473
0
  }
474
0
  return 0;
475
0
}
476
477
DEFPY (vrf_netns,
478
       vrf_netns_cmd,
479
       "netns NAME$netns_name",
480
       "Attach VRF to a Namespace\n"
481
       "The file name in " NS_RUN_DIR ", or a full pathname\n")
482
0
{
483
0
  char *pathname = ns_netns_pathname(vty, netns_name);
484
0
  int ret;
485
486
0
  VTY_DECLVAR_CONTEXT(vrf, vrf);
487
488
0
  if (!pathname)
489
0
    return CMD_WARNING_CONFIG_FAILED;
490
491
0
  frr_with_privs(&zserv_privs) {
492
0
    ret = zebra_vrf_netns_handler_create(
493
0
      vty, vrf, pathname, NS_UNKNOWN, NS_UNKNOWN, NS_UNKNOWN);
494
0
  }
495
496
0
  return ret;
497
0
}
498
499
DEFUN (no_vrf_netns,
500
       no_vrf_netns_cmd,
501
       "no netns [NAME]",
502
       NO_STR
503
       "Detach VRF from a Namespace\n"
504
       "The file name in " NS_RUN_DIR ", or a full pathname\n")
505
0
{
506
0
  struct ns *ns = NULL;
507
508
0
  VTY_DECLVAR_CONTEXT(vrf, vrf);
509
510
0
  if (!vrf_is_backend_netns()) {
511
0
    vty_out(vty, "VRF backend is not Netns. Aborting\n");
512
0
    return CMD_WARNING_CONFIG_FAILED;
513
0
  }
514
0
  if (!vrf->ns_ctxt) {
515
0
    vty_out(vty, "VRF %s(%u) is not configured with NetNS\n",
516
0
      vrf->name, vrf->vrf_id);
517
0
    return CMD_WARNING_CONFIG_FAILED;
518
0
  }
519
520
0
  ns = (struct ns *)vrf->ns_ctxt;
521
522
0
  ns->vrf_ctxt = NULL;
523
0
  vrf_disable(vrf);
524
  /* vrf ID from VRF is necessary for Zebra
525
   * so that propagate to other clients is done
526
   */
527
0
  ns_delete(ns);
528
0
  vrf->ns_ctxt = NULL;
529
0
  return CMD_SUCCESS;
530
0
}
531
532
/* if ns_id is different and not VRF_UNKNOWN,
533
 * then update vrf identifier, and enable VRF
534
 */
535
static void vrf_update_vrf_id(ns_id_t ns_id, void *opaqueptr)
536
0
{
537
0
  ns_id_t vrf_id = (vrf_id_t)ns_id;
538
0
  vrf_id_t old_vrf_id;
539
0
  struct vrf *vrf = (struct vrf *)opaqueptr;
540
541
0
  if (!vrf)
542
0
    return;
543
0
  old_vrf_id = vrf->vrf_id;
544
0
  if (vrf_id == vrf->vrf_id)
545
0
    return;
546
0
  if (vrf->vrf_id != VRF_UNKNOWN)
547
0
    RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
548
0
  vrf->vrf_id = vrf_id;
549
0
  RB_INSERT(vrf_id_head, &vrfs_by_id, vrf);
550
0
  if (old_vrf_id == VRF_UNKNOWN)
551
0
    vrf_enable(vrf);
552
0
}
553
554
int zebra_vrf_netns_handler_create(struct vty *vty, struct vrf *vrf,
555
           char *pathname, ns_id_t ns_id,
556
           ns_id_t internal_ns_id,
557
           ns_id_t rel_def_ns_id)
558
0
{
559
0
  struct ns *ns = NULL;
560
561
0
  if (!vrf)
562
0
    return CMD_WARNING_CONFIG_FAILED;
563
0
  if (vrf->vrf_id != VRF_UNKNOWN && vrf->ns_ctxt == NULL) {
564
0
    if (vty)
565
0
      vty_out(vty,
566
0
        "VRF %u is already configured with VRF %s\n",
567
0
        vrf->vrf_id, vrf->name);
568
0
    else
569
0
      zlog_info("VRF %u is already configured with VRF %s",
570
0
          vrf->vrf_id, vrf->name);
571
0
    return CMD_WARNING_CONFIG_FAILED;
572
0
  }
573
0
  if (vrf->ns_ctxt != NULL) {
574
0
    ns = (struct ns *)vrf->ns_ctxt;
575
0
    if (!strcmp(ns->name, pathname)) {
576
0
      if (vty)
577
0
        vty_out(vty,
578
0
          "VRF %u already configured with NETNS %s\n",
579
0
          vrf->vrf_id, ns->name);
580
0
      else
581
0
        zlog_info(
582
0
          "VRF %u already configured with NETNS %s",
583
0
          vrf->vrf_id, ns->name);
584
0
      return CMD_WARNING;
585
0
    }
586
0
  }
587
0
  ns = ns_lookup_name(pathname);
588
0
  if (ns && ns->vrf_ctxt) {
589
0
    struct vrf *vrf2 = (struct vrf *)ns->vrf_ctxt;
590
591
0
    if (vrf2 == vrf)
592
0
      return CMD_SUCCESS;
593
0
    if (vty)
594
0
      vty_out(vty,
595
0
        "NS %s is already configured with VRF %u(%s)\n",
596
0
        ns->name, vrf2->vrf_id, vrf2->name);
597
0
    else
598
0
      zlog_info("NS %s is already configured with VRF %u(%s)",
599
0
          ns->name, vrf2->vrf_id, vrf2->name);
600
0
    return CMD_WARNING_CONFIG_FAILED;
601
0
  }
602
0
  ns = ns_get_created(ns, pathname, ns_id);
603
0
  ns->internal_ns_id = internal_ns_id;
604
0
  ns->relative_default_ns = rel_def_ns_id;
605
0
  ns->vrf_ctxt = (void *)vrf;
606
0
  vrf->ns_ctxt = (void *)ns;
607
  /* update VRF netns NAME */
608
0
  strlcpy(vrf->data.l.netns_name, basename(pathname), NS_NAMSIZ);
609
610
0
  if (!ns_enable(ns, vrf_update_vrf_id)) {
611
0
    if (vty)
612
0
      vty_out(vty, "Can not associate NS %u with NETNS %s\n",
613
0
        ns->ns_id, ns->name);
614
0
    else
615
0
      zlog_info("Can not associate NS %u with NETNS %s",
616
0
          ns->ns_id, ns->name);
617
0
    return CMD_WARNING_CONFIG_FAILED;
618
0
  }
619
620
0
  return CMD_SUCCESS;
621
0
}
622
623
/* Zebra VRF initialization. */
624
void zebra_vrf_init(void)
625
1
{
626
1
  vrf_init(zebra_vrf_new, zebra_vrf_enable, zebra_vrf_disable,
627
1
     zebra_vrf_delete);
628
629
1
  hook_register(zserv_client_close, release_daemon_table_chunks);
630
631
1
  vrf_cmd_init(vrf_config_write);
632
633
1
  if (vrf_is_backend_netns() && ns_have_netns()) {
634
    /* Install NS commands. */
635
0
    install_element(VRF_NODE, &vrf_netns_cmd);
636
0
    install_element(VRF_NODE, &no_vrf_netns_cmd);
637
0
  }
638
1
}