]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_vrf.c
zebra: Start carrying safi for rnh processing
[mirror_frr.git] / zebra / zebra_vrf.c
CommitLineData
7c551956
DS
1/*
2 * Copyright (C) 2016 CumulusNetworks
3 * Donald Sharp
4 *
5 * This file is part of Quagga
6 *
7 * Quagga is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2, or (at your option) any
10 * later version.
11 *
12 * Quagga is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
896014f4
DL
17 * You should have received a copy of the GNU General Public License along
18 * with this program; see the file COPYING; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
7c551956
DS
20 */
21#include <zebra.h>
22
23#include "log.h"
24#include "linklist.h"
f30c50b9 25#include "command.h"
4a1ab8e4 26#include "memory.h"
05737783 27#include "srcdest_table.h"
78dd30b2 28#include "vrf.h"
82f97584 29#include "vty.h"
78dd30b2 30
89272910 31#include "zebra/zebra_router.h"
df9c8c57 32#include "zebra/rtadv.h"
7c551956 33#include "zebra/debug.h"
bf094f69 34#include "zebra/zapi_msg.h"
7c551956
DS
35#include "zebra/rib.h"
36#include "zebra/zebra_vrf.h"
5a8dfcd8 37#include "zebra/zebra_rnh.h"
7c551956 38#include "zebra/router-id.h"
5a8dfcd8 39#include "zebra/interface.h"
7758e3f3 40#include "zebra/zebra_mpls.h"
13d60d35 41#include "zebra/zebra_vxlan.h"
3bc34908 42#include "zebra/zebra_netns_notify.h"
7cf16e19 43#include "zebra/zebra_routemap.h"
37cb0475
IR
44#ifndef VTYSH_EXTRACT_PL
45#include "zebra/zebra_vrf_clippy.c"
46#endif
7c551956 47
9d97533e 48static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi,
49 safi_t safi);
50static void zebra_rnhtable_node_cleanup(struct route_table *table,
51 struct route_node *node);
52
bf8d3d6a
DL
53DEFINE_MTYPE_STATIC(ZEBRA, ZEBRA_VRF, "ZEBRA VRF");
54DEFINE_MTYPE_STATIC(ZEBRA, OTHER_TABLE, "Other Table");
d8612e65 55
7c551956 56/* VRF information update. */
d62a17ae 57static void zebra_vrf_add_update(struct zebra_vrf *zvrf)
7c551956 58{
d62a17ae 59 struct listnode *node, *nnode;
60 struct zserv *client;
7c551956 61
d62a17ae 62 if (IS_ZEBRA_DEBUG_EVENT)
63 zlog_debug("MESSAGE: ZEBRA_VRF_ADD %s", zvrf_name(zvrf));
7c551956 64
17da84a4
KS
65 for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
66 /* Do not send unsolicited messages to synchronous clients. */
67 if (client->synchronous)
68 continue;
69
d62a17ae 70 zsend_vrf_add(client, zvrf);
17da84a4 71 }
7c551956
DS
72}
73
d62a17ae 74static void zebra_vrf_delete_update(struct zebra_vrf *zvrf)
7c551956 75{
d62a17ae 76 struct listnode *node, *nnode;
77 struct zserv *client;
7c551956 78
d62a17ae 79 if (IS_ZEBRA_DEBUG_EVENT)
80 zlog_debug("MESSAGE: ZEBRA_VRF_DELETE %s", zvrf_name(zvrf));
7c551956 81
17da84a4
KS
82 for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
83 /* Do not send unsolicited messages to synchronous clients. */
84 if (client->synchronous)
85 continue;
86
d62a17ae 87 zsend_vrf_delete(client, zvrf);
17da84a4 88 }
7c551956
DS
89}
90
d62a17ae 91void zebra_vrf_update_all(struct zserv *client)
7c551956 92{
d62a17ae 93 struct vrf *vrf;
7c551956 94
a2addae8 95 RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
4691b65a 96 if (vrf->vrf_id != VRF_UNKNOWN)
d62a17ae 97 zsend_vrf_add(client, vrf_info_lookup(vrf->vrf_id));
98 }
7c551956
DS
99}
100
101/* Callback upon creating a new VRF. */
d62a17ae 102static int zebra_vrf_new(struct vrf *vrf)
7c551956 103{
d62a17ae 104 struct zebra_vrf *zvrf;
7c551956 105
d62a17ae 106 if (IS_ZEBRA_DEBUG_EVENT)
14a4d9d0 107 zlog_debug("VRF %s created, id %u", vrf->name, vrf->vrf_id);
7c551956 108
ec64a634 109 zvrf = zebra_vrf_alloc(vrf);
91b1421e
PG
110 if (!vrf_is_backend_netns())
111 zvrf->zns = zebra_ns_lookup(NS_DEFAULT);
d8612e65
DS
112
113 otable_init(&zvrf->other_tables);
114
fbb65ff5 115 router_id_init(zvrf);
d62a17ae 116 return 0;
7c551956
DS
117}
118
119/* Callback upon enabling a VRF. */
d62a17ae 120static int zebra_vrf_enable(struct vrf *vrf)
7c551956 121{
d62a17ae 122 struct zebra_vrf *zvrf = vrf->info;
9d97533e 123 struct route_table *table;
d62a17ae 124 afi_t afi;
125 safi_t safi;
126
127 assert(zvrf);
84915b0a 128 if (IS_ZEBRA_DEBUG_EVENT)
996c9314
LB
129 zlog_debug("VRF %s id %u is now active", zvrf_name(zvrf),
130 zvrf_id(zvrf));
d62a17ae 131
fbb65ff5
PG
132 if (vrf_is_backend_netns())
133 zvrf->zns = zebra_ns_lookup((ns_id_t)vrf->vrf_id);
134 else
135 zvrf->zns = zebra_ns_lookup(NS_DEFAULT);
df9c8c57 136#if defined(HAVE_RTADV)
7c2ddfb9 137 rtadv_vrf_init(zvrf);
df9c8c57
PG
138#endif
139
84915b0a 140 /* Inform clients that the VRF is now active. This is an
141 * add for the clients.
142 */
d62a17ae 143
8288a24f 144 zebra_vrf_add_update(zvrf);
9d97533e 145 /* Allocate tables */
146 for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
147 for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
148 zebra_vrf_table_create(zvrf, afi, safi);
149
150 table = route_table_init();
151 table->cleanup = zebra_rnhtable_node_cleanup;
152 zvrf->rnh_table[afi] = table;
9d97533e 153 }
154
84915b0a 155 /* Kick off any VxLAN-EVPN processing. */
156 zebra_vxlan_vrf_enable(zvrf);
157
d62a17ae 158 return 0;
7c551956
DS
159}
160
161/* Callback upon disabling a VRF. */
d62a17ae 162static int zebra_vrf_disable(struct vrf *vrf)
7c551956 163{
d62a17ae 164 struct zebra_vrf *zvrf = vrf->info;
9d97533e 165 struct interface *ifp;
d62a17ae 166 afi_t afi;
167 safi_t safi;
9d97533e 168 unsigned i;
d62a17ae 169
84915b0a 170 assert(zvrf);
171 if (IS_ZEBRA_DEBUG_EVENT)
996c9314
LB
172 zlog_debug("VRF %s id %u is now inactive", zvrf_name(zvrf),
173 zvrf_id(zvrf));
d62a17ae 174
84915b0a 175 /* Stop any VxLAN-EVPN processing. */
176 zebra_vxlan_vrf_disable(zvrf);
d62a17ae 177
df9c8c57 178#if defined(HAVE_RTADV)
aab5893a 179 rtadv_vrf_terminate(zvrf);
df9c8c57
PG
180#endif
181
84915b0a 182 /* Inform clients that the VRF is now inactive. This is a
183 * delete for the clients.
184 */
d62a17ae 185 zebra_vrf_delete_update(zvrf);
186
9d97533e 187 /* If asked to retain routes, there's nothing more to do. */
188 if (CHECK_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN))
189 return 0;
190
191 /* Remove all routes. */
192 for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
41dc8c14
DS
193 route_table_finish(zvrf->rnh_table[afi]);
194 zvrf->rnh_table[afi] = NULL;
41dc8c14 195
9d97533e 196 for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
197 rib_close_table(zvrf->table[afi][safi]);
9d97533e 198 }
199
200 /* Cleanup Vxlan, MPLS and PW tables. */
201 zebra_vxlan_cleanup_tables(zvrf);
202 zebra_mpls_cleanup_tables(zvrf);
203 zebra_pw_exit(zvrf);
204
996c9314
LB
205 /* Remove link-local IPv4 addresses created for BGP unnumbered peering.
206 */
9d97533e 207 FOR_ALL_INTERFACES (vrf, ifp)
208 if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
209
210 /* clean-up work queues */
211 for (i = 0; i < MQ_SIZE; i++) {
212 struct listnode *lnode, *nnode;
213 struct route_node *rnode;
214 rib_dest_t *dest;
215
ea45a4e7 216 for (ALL_LIST_ELEMENTS(zrouter.mq->subq[i], lnode, nnode,
996c9314 217 rnode)) {
9d97533e 218 dest = rib_dest_from_rnode(rnode);
219 if (dest && rib_dest_vrf(dest) == zvrf) {
220 route_unlock_node(rnode);
ea45a4e7
DS
221 list_delete_node(zrouter.mq->subq[i], lnode);
222 zrouter.mq->size--;
9d97533e 223 }
d62a17ae 224 }
9d97533e 225 }
7c551956 226
9d97533e 227 /* Cleanup (free) routing tables and NHT tables. */
228 for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
89272910
DS
229 /*
230 * Set the table pointer to NULL as that
231 * we no-longer need a copy of it, nor do we
232 * own this data, the zebra_router structure
233 * owns these tables. Once we've cleaned up the
234 * table, see rib_close_table above
235 * we no-longer need this pointer.
236 */
bd4fb615
DS
237 for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
238 zebra_router_release_table(zvrf, zvrf->table_id, afi,
239 safi);
9d97533e 240 zvrf->table[afi][safi] = NULL;
bd4fb615 241 }
5a8dfcd8
RW
242 }
243
d62a17ae 244 return 0;
7c551956
DS
245}
246
d62a17ae 247static int zebra_vrf_delete(struct vrf *vrf)
7c551956 248{
d62a17ae 249 struct zebra_vrf *zvrf = vrf->info;
d8612e65 250 struct other_route_table *otable;
d62a17ae 251 struct route_table *table;
d62a17ae 252 afi_t afi;
253 safi_t safi;
254 unsigned i;
255
256 assert(zvrf);
84915b0a 257 if (IS_ZEBRA_DEBUG_EVENT)
996c9314
LB
258 zlog_debug("VRF %s id %u deleted", zvrf_name(zvrf),
259 zvrf_id(zvrf));
5a8dfcd8 260
d62a17ae 261 /* clean-up work queues */
262 for (i = 0; i < MQ_SIZE; i++) {
263 struct listnode *lnode, *nnode;
264 struct route_node *rnode;
265 rib_dest_t *dest;
266
ea45a4e7 267 for (ALL_LIST_ELEMENTS(zrouter.mq->subq[i], lnode, nnode,
996c9314 268 rnode)) {
d62a17ae 269 dest = rib_dest_from_rnode(rnode);
270 if (dest && rib_dest_vrf(dest) == zvrf) {
271 route_unlock_node(rnode);
ea45a4e7
DS
272 list_delete_node(zrouter.mq->subq[i], lnode);
273 zrouter.mq->size--;
d62a17ae 274 }
275 }
5a8dfcd8 276 }
5a8dfcd8 277
84915b0a 278 /* Free Vxlan and MPLS. */
279 zebra_vxlan_close_tables(zvrf);
280 zebra_mpls_close_tables(zvrf);
281
d62a17ae 282 /* release allocated memory */
283 for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
d62a17ae 284 for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
285 table = zvrf->table[afi][safi];
9d97533e 286 if (table) {
bd4fb615
DS
287 zebra_router_release_table(zvrf, zvrf->table_id,
288 afi, safi);
289 zvrf->table[afi][safi] = NULL;
9d97533e 290 }
d62a17ae 291 }
5a8dfcd8 292
41dc8c14
DS
293 if (zvrf->rnh_table[afi])
294 route_table_finish(zvrf->rnh_table[afi]);
5a8dfcd8 295 }
b7cfce93 296
d8612e65
DS
297 otable = otable_pop(&zvrf->other_tables);
298 while (otable) {
299 zebra_router_release_table(zvrf, otable->table_id,
300 otable->afi, otable->safi);
301 XFREE(MTYPE_OTHER_TABLE, otable);
302
303 otable = otable_pop(&zvrf->other_tables);
304 }
305
84915b0a 306 /* Cleanup EVPN states for vrf */
b7cfce93
MK
307 zebra_vxlan_vrf_delete(zvrf);
308
d62a17ae 309 list_delete_all_node(zvrf->rid_all_sorted_list);
310 list_delete_all_node(zvrf->rid_lo_sorted_list);
d8612e65 311
cdc09a4b
MS
312 list_delete_all_node(zvrf->rid6_all_sorted_list);
313 list_delete_all_node(zvrf->rid6_lo_sorted_list);
314
d8612e65 315 otable_fini(&zvrf->other_tables);
d62a17ae 316 XFREE(MTYPE_ZEBRA_VRF, zvrf);
317 vrf->info = NULL;
5a8dfcd8 318
d62a17ae 319 return 0;
7c551956
DS
320}
321
ecbc5a37
PG
322static int zebra_vrf_update(struct vrf *vrf)
323{
324 struct zebra_vrf *zvrf = vrf->info;
325
326 assert(zvrf);
327 if (IS_ZEBRA_DEBUG_EVENT)
328 zlog_debug("VRF %s id %u, name updated", vrf->name,
329 zvrf_id(zvrf));
330 zebra_vrf_add_update(zvrf);
331 return 0;
332}
333
7c551956 334/* Lookup the routing table in a VRF based on both VRF-Id and table-id.
e9748a89
PG
335 * NOTE: Table-id is relevant on two modes:
336 * - case VRF backend is default : on default VRF only
337 * - case VRF backend is netns : on all VRFs
7c551956 338 */
c7c0b007
SW
339struct route_table *zebra_vrf_lookup_table_with_table_id(afi_t afi, safi_t safi,
340 vrf_id_t vrf_id,
341 uint32_t table_id)
7c551956 342{
8ab39b7f 343 struct zebra_vrf *zvrf = vrf_info_lookup(vrf_id);
d8612e65 344 struct other_route_table ort, *otable;
8ab39b7f
DS
345
346 if (!zvrf)
347 return NULL;
d62a17ae 348
349 if (afi >= AFI_MAX || safi >= SAFI_MAX)
350 return NULL;
351
8ab39b7f
DS
352 if (table_id == zvrf->table_id)
353 return zebra_vrf_table(afi, safi, vrf_id);
d62a17ae 354
d8612e65
DS
355 ort.afi = afi;
356 ort.safi = safi;
357 ort.table_id = table_id;
358 otable = otable_find(&zvrf->other_tables, &ort);
c7c0b007 359
d8612e65
DS
360 if (otable)
361 return otable->table;
362
c7c0b007
SW
363 return NULL;
364}
365
366struct route_table *zebra_vrf_get_table_with_table_id(afi_t afi, safi_t safi,
367 vrf_id_t vrf_id,
368 uint32_t table_id)
369{
370 struct zebra_vrf *zvrf = vrf_info_lookup(vrf_id);
371 struct other_route_table *otable;
372 struct route_table *table;
373
374 table = zebra_vrf_lookup_table_with_table_id(afi, safi, vrf_id,
375 table_id);
376
377 if (table)
378 goto done;
379
380 /* Create it as an `other` table */
d8612e65
DS
381 table = zebra_router_get_table(zvrf, table_id, afi, safi);
382
383 otable = XCALLOC(MTYPE_OTHER_TABLE, sizeof(*otable));
384 otable->afi = afi;
385 otable->safi = safi;
386 otable->table_id = table_id;
387 otable->table = table;
388 otable_add(&zvrf->other_tables, otable);
d62a17ae 389
c7c0b007 390done:
d62a17ae 391 return table;
7c551956
DS
392}
393
d62a17ae 394static void zebra_rnhtable_node_cleanup(struct route_table *table,
395 struct route_node *node)
5a8dfcd8 396{
d62a17ae 397 if (node->info)
398 zebra_free_rnh(node->info);
5a8dfcd8
RW
399}
400
7c551956
DS
401/*
402 * Create a routing table for the specific AFI/SAFI in the given VRF.
403 */
d62a17ae 404static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi,
405 safi_t safi)
7c551956 406{
c86ba6c2
DS
407 struct route_node *rn;
408 struct prefix p;
409
d62a17ae 410 assert(!zvrf->table[afi][safi]);
411
ea66cec4
DS
412 zvrf->table[afi][safi] =
413 zebra_router_get_table(zvrf, zvrf->table_id, afi, safi);
c86ba6c2
DS
414
415 memset(&p, 0, sizeof(p));
416 p.family = afi2family(afi);
417
418 rn = srcdest_rnode_get(zvrf->table[afi][safi], &p, NULL);
419 zebra_rib_create_dest(rn);
7c551956
DS
420}
421
422/* Allocate new zebra VRF. */
ec64a634 423struct zebra_vrf *zebra_vrf_alloc(struct vrf *vrf)
7c551956 424{
d62a17ae 425 struct zebra_vrf *zvrf;
d62a17ae 426
427 zvrf = XCALLOC(MTYPE_ZEBRA_VRF, sizeof(struct zebra_vrf));
428
ec64a634
DS
429 zvrf->vrf = vrf;
430 vrf->info = zvrf;
431
d62a17ae 432 zebra_vxlan_init_tables(zvrf);
433 zebra_mpls_init_tables(zvrf);
6833ae01 434 zebra_pw_init(zvrf);
e9748a89
PG
435 zvrf->table_id = RT_TABLE_MAIN;
436 /* by default table ID is default one */
d62a17ae 437 return zvrf;
7c551956
DS
438}
439
440/* Lookup VRF by identifier. */
d62a17ae 441struct zebra_vrf *zebra_vrf_lookup_by_id(vrf_id_t vrf_id)
7c551956 442{
d62a17ae 443 return vrf_info_lookup(vrf_id);
7c551956
DS
444}
445
51bdc5f8 446/* Lookup VRF by name. */
d62a17ae 447struct zebra_vrf *zebra_vrf_lookup_by_name(const char *name)
871d39b3 448{
d62a17ae 449 struct vrf *vrf;
871d39b3 450
d62a17ae 451 if (!name)
452 name = VRF_DEFAULT_NAME;
a3d21ef3 453
d62a17ae 454 vrf = vrf_lookup_by_name(name);
455 if (vrf)
456 return ((struct zebra_vrf *)vrf->info);
51bdc5f8 457
d62a17ae 458 return NULL;
871d39b3
DS
459}
460
7c551956 461/* Lookup the routing table in an enabled VRF. */
d62a17ae 462struct route_table *zebra_vrf_table(afi_t afi, safi_t safi, vrf_id_t vrf_id)
7c551956 463{
d62a17ae 464 struct zebra_vrf *zvrf = vrf_info_lookup(vrf_id);
7c551956 465
d62a17ae 466 if (!zvrf)
467 return NULL;
7c551956 468
d62a17ae 469 if (afi >= AFI_MAX || safi >= SAFI_MAX)
470 return NULL;
7c551956 471
d62a17ae 472 return zvrf->table[afi][safi];
7c551956
DS
473}
474
d62a17ae 475static int vrf_config_write(struct vty *vty)
f30c50b9 476{
d62a17ae 477 struct vrf *vrf;
478 struct zebra_vrf *zvrf;
479
a2addae8 480 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
d62a17ae 481 zvrf = vrf->info;
1e9f448f
DS
482
483 if (!zvrf)
484 continue;
485
a5654735
MK
486 if (zvrf_id(zvrf) == VRF_DEFAULT) {
487 if (zvrf->l3vni)
8d0f01f1
CS
488 vty_out(vty, "vni %u%s\n", zvrf->l3vni,
489 is_l3vni_for_prefix_routes_only(
490 zvrf->l3vni)
491 ? " prefix-routes-only"
492 : "");
5a0bdc78
PG
493 if (zvrf->zebra_rnh_ip_default_route)
494 vty_out(vty, "ip nht resolve-via-default\n");
495
496 if (zvrf->zebra_rnh_ipv6_default_route)
497 vty_out(vty, "ipv6 nht resolve-via-default\n");
c319e19d
QY
498 } else {
499 vty_frame(vty, "vrf %s\n", zvrf_name(zvrf));
22bd3e94 500 if (zvrf->l3vni)
996c9314
LB
501 vty_out(vty, " vni %u%s\n", zvrf->l3vni,
502 is_l3vni_for_prefix_routes_only(
503 zvrf->l3vni)
504 ? " prefix-routes-only"
505 : "");
b95c1883 506 zebra_ns_config_write(vty, (struct ns *)vrf->ns_ctxt);
5a0bdc78
PG
507 if (zvrf->zebra_rnh_ip_default_route)
508 vty_out(vty, " ip nht resolve-via-default\n");
509
510 if (zvrf->zebra_rnh_ipv6_default_route)
511 vty_out(vty, " ipv6 nht resolve-via-default\n");
22bd3e94 512 }
37728041 513
5a0bdc78 514
7cf16e19 515 zebra_routemap_config_write_protocol(vty, zvrf);
03fba42e 516 router_id_write(vty, zvrf);
7cf16e19 517
c319e19d 518 if (zvrf_id(zvrf) != VRF_DEFAULT)
07679ad9 519 vty_endframe(vty, "exit-vrf\n!\n");
7cf16e19 520 else
521 vty_out(vty, "!\n");
d62a17ae 522 }
523 return 0;
f30c50b9
RW
524}
525
37cb0475
IR
526DEFPY (vrf_netns,
527 vrf_netns_cmd,
528 "netns NAME$netns_name",
529 "Attach VRF to a Namespace\n"
530 "The file name in " NS_RUN_DIR ", or a full pathname\n")
531{
532 char *pathname = ns_netns_pathname(vty, netns_name);
533 int ret;
534
535 VTY_DECLVAR_CONTEXT(vrf, vrf);
536
537 if (!pathname)
538 return CMD_WARNING_CONFIG_FAILED;
539
540 frr_with_privs(&zserv_privs) {
541 ret = vrf_netns_handler_create(vty, vrf, pathname,
542 NS_UNKNOWN,
543 NS_UNKNOWN,
544 NS_UNKNOWN);
545 }
546
547 return ret;
548}
549
550DEFUN (no_vrf_netns,
551 no_vrf_netns_cmd,
552 "no netns [NAME]",
553 NO_STR
554 "Detach VRF from a Namespace\n"
555 "The file name in " NS_RUN_DIR ", or a full pathname\n")
556{
557 struct ns *ns = NULL;
558
559 VTY_DECLVAR_CONTEXT(vrf, vrf);
560
561 if (!vrf_is_backend_netns()) {
562 vty_out(vty, "VRF backend is not Netns. Aborting\n");
563 return CMD_WARNING_CONFIG_FAILED;
564 }
565 if (!vrf->ns_ctxt) {
566 vty_out(vty, "VRF %s(%u) is not configured with NetNS\n",
567 vrf->name, vrf->vrf_id);
568 return CMD_WARNING_CONFIG_FAILED;
569 }
570
571 ns = (struct ns *)vrf->ns_ctxt;
572
573 ns->vrf_ctxt = NULL;
574 vrf_disable(vrf);
575 /* vrf ID from VRF is necessary for Zebra
576 * so that propagate to other clients is done
577 */
578 ns_delete(ns);
579 vrf->ns_ctxt = NULL;
580 return CMD_SUCCESS;
581}
582
7c551956 583/* Zebra VRF initialization. */
d62a17ae 584void zebra_vrf_init(void)
7c551956 585{
996c9314 586 vrf_init(zebra_vrf_new, zebra_vrf_enable, zebra_vrf_disable,
ecbc5a37 587 zebra_vrf_delete, zebra_vrf_update);
7c551956 588
cfc369c4 589 vrf_cmd_init(vrf_config_write);
37cb0475
IR
590
591 if (vrf_is_backend_netns() && ns_have_netns()) {
592 /* Install NS commands. */
593 install_element(VRF_NODE, &vrf_netns_cmd);
594 install_element(VRF_NODE, &no_vrf_netns_cmd);
595 }
7c551956 596}