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