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