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