Line data Source code
1 : /*
2 : * VRF functions.
3 : * Copyright (C) 2014 6WIND S.A.
4 : *
5 : * This file is part of GNU Zebra.
6 : *
7 : * GNU Zebra is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU General Public License as published
9 : * by the Free Software Foundation; either version 2, or (at your
10 : * option) any later version.
11 : *
12 : * GNU Zebra 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 :
22 : #include <zebra.h>
23 :
24 : #include "if.h"
25 : #include "vrf.h"
26 : #include "vrf_int.h"
27 : #include "prefix.h"
28 : #include "table.h"
29 : #include "log.h"
30 : #include "memory.h"
31 : #include "command.h"
32 : #include "ns.h"
33 : #include "privs.h"
34 : #include "nexthop_group.h"
35 : #include "lib_errors.h"
36 : #include "northbound.h"
37 : #include "northbound_cli.h"
38 :
39 : /* default VRF name value used when VRF backend is not NETNS */
40 : #define VRF_DEFAULT_NAME_INTERNAL "default"
41 :
42 22 : DEFINE_MTYPE_STATIC(LIB, VRF, "VRF");
43 22 : DEFINE_MTYPE_STATIC(LIB, VRF_BITMAP, "VRF bit-map");
44 :
45 : DEFINE_QOBJ_TYPE(vrf);
46 :
47 : static __inline int vrf_id_compare(const struct vrf *, const struct vrf *);
48 : static __inline int vrf_name_compare(const struct vrf *, const struct vrf *);
49 :
50 1489 : RB_GENERATE(vrf_id_head, vrf, id_entry, vrf_id_compare);
51 38 : RB_GENERATE(vrf_name_head, vrf, name_entry, vrf_name_compare);
52 :
53 : struct vrf_id_head vrfs_by_id = RB_INITIALIZER(&vrfs_by_id);
54 : struct vrf_name_head vrfs_by_name = RB_INITIALIZER(&vrfs_by_name);
55 :
56 : static int vrf_backend;
57 : static int vrf_backend_configured;
58 : static char vrf_default_name[VRF_NAMSIZ] = VRF_DEFAULT_NAME_INTERNAL;
59 :
60 : /*
61 : * Turn on/off debug code
62 : * for vrf.
63 : */
64 : static int debug_vrf = 0;
65 :
66 : /* Holding VRF hooks */
67 : static struct vrf_master {
68 : int (*vrf_new_hook)(struct vrf *);
69 : int (*vrf_delete_hook)(struct vrf *);
70 : int (*vrf_enable_hook)(struct vrf *);
71 : int (*vrf_disable_hook)(struct vrf *);
72 : } vrf_master = {
73 : 0,
74 : };
75 :
76 : static int vrf_is_enabled(struct vrf *vrf);
77 :
78 : /* VRF list existance check by name. */
79 44 : struct vrf *vrf_lookup_by_name(const char *name)
80 : {
81 44 : struct vrf vrf;
82 44 : strlcpy(vrf.name, name, sizeof(vrf.name));
83 44 : return (RB_FIND(vrf_name_head, &vrfs_by_name, &vrf));
84 : }
85 :
86 1489 : static __inline int vrf_id_compare(const struct vrf *a, const struct vrf *b)
87 : {
88 1489 : return (a->vrf_id - b->vrf_id);
89 : }
90 :
91 38 : static int vrf_name_compare(const struct vrf *a, const struct vrf *b)
92 : {
93 38 : return strcmp(a->name, b->name);
94 : }
95 :
96 15 : int vrf_switch_to_netns(vrf_id_t vrf_id)
97 : {
98 15 : char *name;
99 15 : struct vrf *vrf = vrf_lookup_by_id(vrf_id);
100 :
101 : /* VRF is default VRF. silently ignore */
102 15 : if (!vrf || vrf->vrf_id == VRF_DEFAULT)
103 : return 1; /* 1 = default */
104 : /* VRF has no NETNS backend. silently ignore */
105 0 : if (vrf->data.l.netns_name[0] == '\0')
106 : return 2; /* 2 = no netns */
107 0 : name = ns_netns_pathname(NULL, vrf->data.l.netns_name);
108 0 : if (debug_vrf)
109 0 : zlog_debug("VRF_SWITCH: %s(%u)", name, vrf->vrf_id);
110 0 : return ns_switch_to_netns(name);
111 : }
112 :
113 15 : int vrf_switchback_to_initial(void)
114 : {
115 15 : int ret = ns_switchback_to_initial();
116 :
117 15 : if (ret == 0 && debug_vrf)
118 0 : zlog_debug("VRF_SWITCHBACK");
119 15 : return ret;
120 : }
121 :
122 : /* Get a VRF. If not found, create one.
123 : * Arg:
124 : * name - The name of the vrf. May be NULL if unknown.
125 : * vrf_id - The vrf_id of the vrf. May be VRF_UNKNOWN if unknown
126 : * Description: Please note that this routine can be called with just the name
127 : * and 0 vrf-id
128 : */
129 38 : struct vrf *vrf_get(vrf_id_t vrf_id, const char *name)
130 : {
131 38 : struct vrf *vrf = NULL;
132 38 : int new = 0;
133 :
134 : /* Nothing to see, move along here */
135 38 : if (!name && vrf_id == VRF_UNKNOWN)
136 : return NULL;
137 :
138 : /* attempt to find already available VRF
139 : */
140 38 : if (name)
141 30 : vrf = vrf_lookup_by_name(name);
142 38 : if (vrf && vrf_id != VRF_UNKNOWN
143 20 : && vrf->vrf_id != VRF_UNKNOWN
144 20 : && vrf->vrf_id != vrf_id) {
145 0 : zlog_debug("VRF_GET: avoid %s creation(%u), same name exists (%u)",
146 : name, vrf_id, vrf->vrf_id);
147 0 : return NULL;
148 : }
149 : /* Try to find VRF both by ID and name */
150 38 : if (!vrf && vrf_id != VRF_UNKNOWN)
151 14 : vrf = vrf_lookup_by_id(vrf_id);
152 :
153 38 : if (vrf == NULL) {
154 6 : vrf = XCALLOC(MTYPE_VRF, sizeof(struct vrf));
155 6 : vrf->vrf_id = VRF_UNKNOWN;
156 6 : QOBJ_REG(vrf, vrf);
157 6 : new = 1;
158 :
159 6 : if (debug_vrf)
160 0 : zlog_debug("VRF(%u) %s is created.", vrf_id,
161 : (name) ? name : "(NULL)");
162 : }
163 :
164 : /* Set identifier */
165 38 : if (vrf_id != VRF_UNKNOWN && vrf->vrf_id == VRF_UNKNOWN) {
166 6 : vrf->vrf_id = vrf_id;
167 6 : RB_INSERT(vrf_id_head, &vrfs_by_id, vrf);
168 : }
169 :
170 : /* Set name */
171 38 : if (name && vrf->name[0] != '\0' && strcmp(name, vrf->name)) {
172 : /* update the vrf name */
173 0 : RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf);
174 0 : strlcpy(vrf->data.l.netns_name,
175 : name, NS_NAMSIZ);
176 0 : strlcpy(vrf->name, name, sizeof(vrf->name));
177 0 : RB_INSERT(vrf_name_head, &vrfs_by_name, vrf);
178 30 : } else if (name && vrf->name[0] == '\0') {
179 6 : strlcpy(vrf->name, name, sizeof(vrf->name));
180 6 : RB_INSERT(vrf_name_head, &vrfs_by_name, vrf);
181 : }
182 38 : if (new &&vrf_master.vrf_new_hook)
183 6 : (*vrf_master.vrf_new_hook)(vrf);
184 :
185 : return vrf;
186 : }
187 :
188 : /* Update a VRF. If not found, create one.
189 : * Arg:
190 : * name - The name of the vrf.
191 : * vrf_id - The vrf_id of the vrf.
192 : * Description: This function first finds the vrf using its name. If the vrf is
193 : * found and the vrf-id of the existing vrf does not match the new vrf id, it
194 : * will disable the existing vrf and update it with new vrf-id. If the vrf is
195 : * not found, it will create the vrf with given name and the new vrf id.
196 : */
197 0 : struct vrf *vrf_update(vrf_id_t new_vrf_id, const char *name)
198 : {
199 0 : struct vrf *vrf = NULL;
200 :
201 : /*Treat VRF add for existing vrf as update
202 : * Update VRF ID and also update in VRF ID table
203 : */
204 0 : if (name)
205 0 : vrf = vrf_lookup_by_name(name);
206 0 : if (vrf && new_vrf_id != VRF_UNKNOWN && vrf->vrf_id != VRF_UNKNOWN
207 0 : && vrf->vrf_id != new_vrf_id) {
208 0 : if (debug_vrf) {
209 0 : zlog_debug(
210 : "Vrf Update event: %s old id: %u, new id: %u",
211 : name, vrf->vrf_id, new_vrf_id);
212 : }
213 :
214 : /*Disable the vrf to simulate implicit delete
215 : * so that all stale routes are deleted
216 : * This vrf will be enabled down the line
217 : */
218 0 : vrf_disable(vrf);
219 :
220 :
221 0 : RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
222 0 : vrf->vrf_id = new_vrf_id;
223 0 : RB_INSERT(vrf_id_head, &vrfs_by_id, vrf);
224 :
225 : } else {
226 :
227 : /*
228 : * vrf_get is implied creation if it does not exist
229 : */
230 0 : vrf = vrf_get(new_vrf_id, name);
231 : }
232 0 : return vrf;
233 : }
234 :
235 : /* Delete a VRF. This is called when the underlying VRF goes away, a
236 : * pre-configured VRF is deleted or when shutting down (vrf_terminate()).
237 : */
238 6 : void vrf_delete(struct vrf *vrf)
239 : {
240 6 : if (debug_vrf)
241 6 : zlog_debug("VRF %s(%u) is to be deleted.", vrf->name,
242 : vrf->vrf_id);
243 :
244 6 : if (vrf_is_enabled(vrf))
245 0 : vrf_disable(vrf);
246 :
247 6 : if (vrf->vrf_id != VRF_UNKNOWN) {
248 6 : RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
249 6 : vrf->vrf_id = VRF_UNKNOWN;
250 : }
251 :
252 : /* If the VRF is user configured, it'll stick around, just remove
253 : * the ID mapping. Interfaces assigned to this VRF should've been
254 : * removed already as part of the VRF going down.
255 : */
256 6 : if (vrf_is_user_cfged(vrf))
257 : return;
258 :
259 : /* Do not delete the VRF if it has interfaces configured in it. */
260 6 : if (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name))
261 : return;
262 :
263 6 : if (vrf_master.vrf_delete_hook)
264 6 : (*vrf_master.vrf_delete_hook)(vrf);
265 :
266 6 : QOBJ_UNREG(vrf);
267 :
268 6 : if (vrf->name[0] != '\0')
269 6 : RB_REMOVE(vrf_name_head, &vrfs_by_name, vrf);
270 :
271 6 : XFREE(MTYPE_VRF, vrf);
272 : }
273 :
274 : /* Look up a VRF by identifier. */
275 1495 : struct vrf *vrf_lookup_by_id(vrf_id_t vrf_id)
276 : {
277 1495 : struct vrf vrf;
278 1495 : vrf.vrf_id = vrf_id;
279 1495 : return (RB_FIND(vrf_id_head, &vrfs_by_id, &vrf));
280 : }
281 :
282 : /*
283 : * Enable a VRF - that is, let the VRF be ready to use.
284 : * The VRF_ENABLE_HOOK callback will be called to inform
285 : * that they can allocate resources in this VRF.
286 : *
287 : * RETURN: 1 - enabled successfully; otherwise, 0.
288 : */
289 10 : int vrf_enable(struct vrf *vrf)
290 : {
291 10 : if (vrf_is_enabled(vrf))
292 : return 1;
293 :
294 6 : if (debug_vrf)
295 0 : zlog_debug("VRF %s(%u) is enabled.", vrf->name, vrf->vrf_id);
296 :
297 6 : SET_FLAG(vrf->status, VRF_ACTIVE);
298 :
299 6 : if (vrf_master.vrf_enable_hook)
300 6 : (*vrf_master.vrf_enable_hook)(vrf);
301 :
302 : /*
303 : * If we have any nexthop group entries that
304 : * are awaiting vrf initialization then
305 : * let's let people know about it
306 : */
307 6 : nexthop_group_enable_vrf(vrf);
308 :
309 6 : return 1;
310 : }
311 :
312 : /*
313 : * Disable a VRF - that is, let the VRF be unusable.
314 : * The VRF_DELETE_HOOK callback will be called to inform
315 : * that they must release the resources in the VRF.
316 : */
317 6 : void vrf_disable(struct vrf *vrf)
318 : {
319 6 : if (!vrf_is_enabled(vrf))
320 : return;
321 :
322 6 : UNSET_FLAG(vrf->status, VRF_ACTIVE);
323 :
324 6 : if (debug_vrf)
325 0 : zlog_debug("VRF %s(%u) is to be disabled.", vrf->name,
326 : vrf->vrf_id);
327 :
328 : /* Till now, nothing to be done for the default VRF. */
329 : // Pending: see why this statement.
330 :
331 :
332 : /*
333 : * When the vrf is disabled let's
334 : * handle all nexthop-groups associated
335 : * with this vrf
336 : */
337 6 : nexthop_group_disable_vrf(vrf);
338 :
339 6 : if (vrf_master.vrf_disable_hook)
340 6 : (*vrf_master.vrf_disable_hook)(vrf);
341 : }
342 :
343 5 : const char *vrf_id_to_name(vrf_id_t vrf_id)
344 : {
345 5 : struct vrf *vrf;
346 :
347 5 : if (vrf_id == VRF_DEFAULT)
348 5 : return VRF_DEFAULT_NAME;
349 :
350 0 : vrf = vrf_lookup_by_id(vrf_id);
351 0 : return VRF_LOGNAME(vrf);
352 : }
353 :
354 : /* Look up the data pointer of the specified VRF. */
355 810 : void *vrf_info_lookup(vrf_id_t vrf_id)
356 : {
357 810 : struct vrf *vrf = vrf_lookup_by_id(vrf_id);
358 810 : return vrf ? vrf->info : NULL;
359 : }
360 :
361 : /*
362 : * VRF hash for storing set or not.
363 : */
364 : struct vrf_bit_set {
365 : vrf_id_t vrf_id;
366 : bool set;
367 : };
368 :
369 20 : static unsigned int vrf_hash_bitmap_key(const void *data)
370 : {
371 20 : const struct vrf_bit_set *bit = data;
372 :
373 20 : return bit->vrf_id;
374 : }
375 :
376 4 : static bool vrf_hash_bitmap_cmp(const void *a, const void *b)
377 : {
378 4 : const struct vrf_bit_set *bit1 = a;
379 4 : const struct vrf_bit_set *bit2 = b;
380 :
381 4 : return bit1->vrf_id == bit2->vrf_id;
382 : }
383 :
384 16 : static void *vrf_hash_bitmap_alloc(void *data)
385 : {
386 16 : struct vrf_bit_set *copy = data;
387 16 : struct vrf_bit_set *bit;
388 :
389 16 : bit = XMALLOC(MTYPE_VRF_BITMAP, sizeof(*bit));
390 16 : bit->vrf_id = copy->vrf_id;
391 :
392 16 : return bit;
393 : }
394 :
395 10 : static void vrf_hash_bitmap_free(void *data)
396 : {
397 10 : struct vrf_bit_set *bit = data;
398 :
399 10 : XFREE(MTYPE_VRF_BITMAP, bit);
400 10 : }
401 :
402 996 : vrf_bitmap_t vrf_bitmap_init(void)
403 : {
404 996 : return hash_create_size(32, vrf_hash_bitmap_key, vrf_hash_bitmap_cmp,
405 : "VRF BIT HASH");
406 : }
407 :
408 804 : void vrf_bitmap_free(vrf_bitmap_t bmap)
409 : {
410 804 : struct hash *vrf_hash = bmap;
411 :
412 804 : if (vrf_hash == NULL)
413 : return;
414 :
415 804 : hash_clean(vrf_hash, vrf_hash_bitmap_free);
416 804 : hash_free(vrf_hash);
417 : }
418 :
419 16 : void vrf_bitmap_set(vrf_bitmap_t bmap, vrf_id_t vrf_id)
420 : {
421 16 : struct vrf_bit_set lookup = { .vrf_id = vrf_id };
422 16 : struct hash *vrf_hash = bmap;
423 16 : struct vrf_bit_set *bit;
424 :
425 16 : if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
426 0 : return;
427 :
428 16 : bit = hash_get(vrf_hash, &lookup, vrf_hash_bitmap_alloc);
429 16 : bit->set = true;
430 : }
431 :
432 0 : void vrf_bitmap_unset(vrf_bitmap_t bmap, vrf_id_t vrf_id)
433 : {
434 0 : struct vrf_bit_set lookup = { .vrf_id = vrf_id };
435 0 : struct hash *vrf_hash = bmap;
436 0 : struct vrf_bit_set *bit;
437 :
438 0 : if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
439 0 : return;
440 :
441 0 : bit = hash_get(vrf_hash, &lookup, vrf_hash_bitmap_alloc);
442 0 : bit->set = false;
443 : }
444 :
445 512 : int vrf_bitmap_check(vrf_bitmap_t bmap, vrf_id_t vrf_id)
446 : {
447 512 : struct vrf_bit_set lookup = { .vrf_id = vrf_id };
448 512 : struct hash *vrf_hash = bmap;
449 512 : struct vrf_bit_set *bit;
450 :
451 512 : if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN)
452 : return 0;
453 :
454 512 : bit = hash_lookup(vrf_hash, &lookup);
455 512 : if (bit)
456 4 : return bit->set;
457 :
458 : return 0;
459 : }
460 :
461 0 : static void vrf_autocomplete(vector comps, struct cmd_token *token)
462 : {
463 0 : struct vrf *vrf = NULL;
464 :
465 0 : RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
466 0 : vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name));
467 0 : }
468 :
469 : static const struct cmd_variable_handler vrf_var_handlers[] = {
470 : {
471 : .varname = "vrf",
472 : .completions = vrf_autocomplete,
473 : },
474 : {
475 : .varname = "vrf_name",
476 : .completions = vrf_autocomplete,
477 : },
478 : {
479 : .varname = "nexthop_vrf",
480 : .completions = vrf_autocomplete,
481 : },
482 : {.completions = NULL},
483 : };
484 :
485 : /* Initialize VRF module. */
486 6 : void vrf_init(int (*create)(struct vrf *), int (*enable)(struct vrf *),
487 : int (*disable)(struct vrf *), int (*destroy)(struct vrf *))
488 : {
489 6 : struct vrf *default_vrf;
490 :
491 : /* initialise NS, in case VRF backend if NETNS */
492 6 : ns_init();
493 6 : if (debug_vrf)
494 0 : zlog_debug("%s: Initializing VRF subsystem", __func__);
495 :
496 6 : vrf_master.vrf_new_hook = create;
497 6 : vrf_master.vrf_enable_hook = enable;
498 6 : vrf_master.vrf_disable_hook = disable;
499 6 : vrf_master.vrf_delete_hook = destroy;
500 :
501 : /* The default VRF always exists. */
502 6 : default_vrf = vrf_get(VRF_DEFAULT, VRF_DEFAULT_NAME);
503 6 : if (!default_vrf) {
504 0 : flog_err(EC_LIB_VRF_START,
505 : "vrf_init: failed to create the default VRF!");
506 0 : exit(1);
507 : }
508 6 : if (vrf_is_backend_netns()) {
509 0 : struct ns *ns;
510 :
511 0 : strlcpy(default_vrf->data.l.netns_name,
512 : VRF_DEFAULT_NAME, NS_NAMSIZ);
513 0 : ns = ns_lookup(NS_DEFAULT);
514 0 : ns->vrf_ctxt = default_vrf;
515 0 : default_vrf->ns_ctxt = ns;
516 : }
517 :
518 : /* Enable the default VRF. */
519 6 : if (!vrf_enable(default_vrf)) {
520 0 : flog_err(EC_LIB_VRF_START,
521 : "vrf_init: failed to enable the default VRF!");
522 0 : exit(1);
523 : }
524 :
525 6 : cmd_variable_handler_register(vrf_var_handlers);
526 6 : }
527 :
528 6 : static void vrf_terminate_single(struct vrf *vrf)
529 : {
530 : /* Clear configured flag and invoke delete. */
531 6 : vrf_disable(vrf);
532 6 : UNSET_FLAG(vrf->status, VRF_CONFIGURED);
533 6 : if_terminate(vrf);
534 6 : vrf_delete(vrf);
535 6 : }
536 :
537 : /* Terminate VRF module. */
538 6 : void vrf_terminate(void)
539 : {
540 6 : struct vrf *vrf, *tmp;
541 :
542 6 : if (debug_vrf)
543 0 : zlog_debug("%s: Shutting down vrf subsystem", __func__);
544 :
545 18 : RB_FOREACH_SAFE (vrf, vrf_id_head, &vrfs_by_id, tmp) {
546 6 : if (vrf->vrf_id == VRF_DEFAULT)
547 6 : continue;
548 :
549 0 : vrf_terminate_single(vrf);
550 : }
551 :
552 18 : RB_FOREACH_SAFE (vrf, vrf_name_head, &vrfs_by_name, tmp) {
553 6 : if (vrf->vrf_id == VRF_DEFAULT)
554 6 : continue;
555 :
556 0 : vrf_terminate_single(vrf);
557 : }
558 :
559 : /* Finally terminate default VRF */
560 6 : vrf = vrf_lookup_by_id(VRF_DEFAULT);
561 6 : if (vrf)
562 6 : vrf_terminate_single(vrf);
563 6 : }
564 :
565 9 : int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id,
566 : const char *interfacename)
567 : {
568 9 : int ret, save_errno, ret2;
569 :
570 9 : ret = vrf_switch_to_netns(vrf_id);
571 9 : if (ret < 0)
572 0 : flog_err_sys(EC_LIB_SOCKET, "%s: Can't switch to VRF %u (%s)",
573 : __func__, vrf_id, safe_strerror(errno));
574 :
575 9 : ret = socket(domain, type, protocol);
576 9 : save_errno = errno;
577 9 : ret2 = vrf_switchback_to_initial();
578 9 : if (ret2 < 0)
579 0 : flog_err_sys(EC_LIB_SOCKET,
580 : "%s: Can't switchback from VRF %u (%s)", __func__,
581 : vrf_id, safe_strerror(errno));
582 9 : errno = save_errno;
583 9 : if (ret <= 0)
584 : return ret;
585 9 : ret2 = vrf_bind(vrf_id, ret, interfacename);
586 9 : if (ret2 < 0) {
587 0 : close(ret);
588 0 : ret = ret2;
589 : }
590 : return ret;
591 : }
592 :
593 163 : int vrf_is_backend_netns(void)
594 : {
595 163 : return (vrf_backend == VRF_BACKEND_NETNS);
596 : }
597 :
598 303 : int vrf_get_backend(void)
599 : {
600 303 : if (!vrf_backend_configured)
601 : return VRF_BACKEND_UNKNOWN;
602 303 : return vrf_backend;
603 : }
604 :
605 6 : int vrf_configure_backend(enum vrf_backend_type backend)
606 : {
607 : /* Work around issue in old gcc */
608 6 : switch (backend) {
609 : case VRF_BACKEND_UNKNOWN:
610 : case VRF_BACKEND_NETNS:
611 : case VRF_BACKEND_VRF_LITE:
612 : break;
613 : case VRF_BACKEND_MAX:
614 : return -1;
615 : }
616 :
617 6 : vrf_backend = backend;
618 6 : vrf_backend_configured = 1;
619 :
620 6 : return 0;
621 : }
622 :
623 : /* vrf CLI commands */
624 0 : DEFUN_NOSH(vrf_exit,
625 : vrf_exit_cmd,
626 : "exit-vrf",
627 : "Exit current mode and down to previous mode\n")
628 : {
629 0 : cmd_exit(vty);
630 0 : return CMD_SUCCESS;
631 : }
632 :
633 0 : DEFUN_YANG_NOSH (vrf,
634 : vrf_cmd,
635 : "vrf NAME",
636 : "Select a VRF to configure\n"
637 : "VRF's name\n")
638 : {
639 0 : int idx_name = 1;
640 0 : const char *vrfname = argv[idx_name]->arg;
641 0 : char xpath_list[XPATH_MAXLEN];
642 0 : struct vrf *vrf;
643 0 : int ret;
644 :
645 0 : if (strlen(vrfname) > VRF_NAMSIZ) {
646 0 : vty_out(vty,
647 : "%% VRF name %s invalid: length exceeds %d bytes\n",
648 : vrfname, VRF_NAMSIZ);
649 0 : return CMD_WARNING_CONFIG_FAILED;
650 : }
651 :
652 0 : snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH, vrfname);
653 :
654 0 : nb_cli_enqueue_change(vty, xpath_list, NB_OP_CREATE, NULL);
655 0 : ret = nb_cli_apply_changes_clear_pending(vty, "%s", xpath_list);
656 0 : if (ret == CMD_SUCCESS) {
657 0 : VTY_PUSH_XPATH(VRF_NODE, xpath_list);
658 0 : vrf = vrf_lookup_by_name(vrfname);
659 0 : if (vrf)
660 0 : VTY_PUSH_CONTEXT(VRF_NODE, vrf);
661 : }
662 :
663 : return ret;
664 : }
665 :
666 0 : DEFUN_YANG (no_vrf,
667 : no_vrf_cmd,
668 : "no vrf NAME",
669 : NO_STR
670 : "Delete a pseudo VRF's configuration\n"
671 : "VRF's name\n")
672 : {
673 0 : const char *vrfname = argv[2]->arg;
674 0 : char xpath_list[XPATH_MAXLEN];
675 :
676 0 : struct vrf *vrfp;
677 :
678 0 : vrfp = vrf_lookup_by_name(vrfname);
679 :
680 0 : if (vrfp == NULL)
681 : return CMD_SUCCESS;
682 :
683 0 : if (CHECK_FLAG(vrfp->status, VRF_ACTIVE)) {
684 0 : vty_out(vty, "%% Only inactive VRFs can be deleted\n");
685 0 : return CMD_WARNING_CONFIG_FAILED;
686 : }
687 :
688 0 : if (vrf_get_backend() == VRF_BACKEND_VRF_LITE) {
689 : /*
690 : * Remove the VRF interface config when removing the VRF.
691 : */
692 0 : snprintf(xpath_list, sizeof(xpath_list),
693 : "/frr-interface:lib/interface[name='%s']", vrfname);
694 0 : nb_cli_enqueue_change(vty, xpath_list, NB_OP_DESTROY, NULL);
695 : }
696 :
697 0 : snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH, vrfname);
698 :
699 0 : nb_cli_enqueue_change(vty, xpath_list, NB_OP_DESTROY, NULL);
700 0 : return nb_cli_apply_changes(vty, NULL);
701 : }
702 :
703 :
704 : static struct cmd_node vrf_node = {
705 : .name = "vrf",
706 : .node = VRF_NODE,
707 : .parent_node = CONFIG_NODE,
708 : .prompt = "%s(config-vrf)# ",
709 : };
710 :
711 : /*
712 : * Debug CLI for vrf's
713 : */
714 0 : DEFUN (vrf_debug,
715 : vrf_debug_cmd,
716 : "debug vrf",
717 : DEBUG_STR
718 : "VRF Debugging\n")
719 : {
720 0 : debug_vrf = 1;
721 :
722 0 : return CMD_SUCCESS;
723 : }
724 :
725 0 : DEFUN (no_vrf_debug,
726 : no_vrf_debug_cmd,
727 : "no debug vrf",
728 : NO_STR
729 : DEBUG_STR
730 : "VRF Debugging\n")
731 : {
732 0 : debug_vrf = 0;
733 :
734 0 : return CMD_SUCCESS;
735 : }
736 :
737 0 : static int vrf_write_host(struct vty *vty)
738 : {
739 0 : if (debug_vrf)
740 0 : vty_out(vty, "debug vrf\n");
741 :
742 0 : return 1;
743 : }
744 :
745 : static int vrf_write_host(struct vty *vty);
746 : static struct cmd_node vrf_debug_node = {
747 : .name = "vrf debug",
748 : .node = VRF_DEBUG_NODE,
749 : .prompt = "",
750 : .config_write = vrf_write_host,
751 : };
752 :
753 6 : void vrf_install_commands(void)
754 : {
755 6 : install_node(&vrf_debug_node);
756 :
757 6 : install_element(CONFIG_NODE, &vrf_debug_cmd);
758 6 : install_element(ENABLE_NODE, &vrf_debug_cmd);
759 6 : install_element(CONFIG_NODE, &no_vrf_debug_cmd);
760 6 : install_element(ENABLE_NODE, &no_vrf_debug_cmd);
761 6 : }
762 :
763 6 : void vrf_cmd_init(int (*writefunc)(struct vty *vty))
764 : {
765 6 : install_element(CONFIG_NODE, &vrf_cmd);
766 6 : install_element(CONFIG_NODE, &no_vrf_cmd);
767 6 : vrf_node.config_write = writefunc;
768 6 : install_node(&vrf_node);
769 6 : install_default(VRF_NODE);
770 6 : install_element(VRF_NODE, &vrf_exit_cmd);
771 6 : }
772 :
773 0 : void vrf_set_default_name(const char *default_name)
774 : {
775 0 : snprintf(vrf_default_name, VRF_NAMSIZ, "%s", default_name);
776 0 : }
777 :
778 28 : const char *vrf_get_default_name(void)
779 : {
780 28 : return vrf_default_name;
781 : }
782 :
783 9 : int vrf_bind(vrf_id_t vrf_id, int fd, const char *ifname)
784 : {
785 9 : int ret = 0;
786 9 : struct interface *ifp;
787 9 : struct vrf *vrf;
788 :
789 9 : if (fd < 0)
790 : return -1;
791 :
792 9 : if (vrf_id == VRF_UNKNOWN)
793 : return -1;
794 :
795 : /* can't bind to a VRF that doesn't exist */
796 9 : vrf = vrf_lookup_by_id(vrf_id);
797 9 : if (!vrf_is_enabled(vrf))
798 : return -1;
799 :
800 9 : if (ifname && strcmp(ifname, vrf->name)) {
801 : /* binding to a regular interface */
802 :
803 : /* can't bind to an interface that doesn't exist */
804 0 : ifp = if_lookup_by_name(ifname, vrf_id);
805 0 : if (!ifp)
806 : return -1;
807 : } else {
808 : /* binding to a VRF device */
809 :
810 : /* nothing to do for netns */
811 9 : if (vrf_is_backend_netns())
812 : return 0;
813 :
814 : /* nothing to do for default vrf */
815 9 : if (vrf_id == VRF_DEFAULT)
816 : return 0;
817 :
818 0 : ifname = vrf->name;
819 : }
820 :
821 : #ifdef SO_BINDTODEVICE
822 0 : ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
823 0 : strlen(ifname) + 1);
824 0 : if (ret < 0)
825 0 : zlog_err("bind to interface %s failed, errno=%d", ifname,
826 : errno);
827 : #endif /* SO_BINDTODEVICE */
828 : return ret;
829 : }
830 0 : int vrf_getaddrinfo(const char *node, const char *service,
831 : const struct addrinfo *hints, struct addrinfo **res,
832 : vrf_id_t vrf_id)
833 : {
834 0 : int ret, ret2, save_errno;
835 :
836 0 : ret = vrf_switch_to_netns(vrf_id);
837 0 : if (ret < 0)
838 0 : flog_err_sys(EC_LIB_SOCKET, "%s: Can't switch to VRF %u (%s)",
839 : __func__, vrf_id, safe_strerror(errno));
840 0 : ret = getaddrinfo(node, service, hints, res);
841 0 : save_errno = errno;
842 0 : ret2 = vrf_switchback_to_initial();
843 0 : if (ret2 < 0)
844 0 : flog_err_sys(EC_LIB_SOCKET,
845 : "%s: Can't switchback from VRF %u (%s)", __func__,
846 : vrf_id, safe_strerror(errno));
847 0 : errno = save_errno;
848 0 : return ret;
849 : }
850 :
851 6 : int vrf_ioctl(vrf_id_t vrf_id, int d, unsigned long request, char *params)
852 : {
853 6 : int ret, saved_errno, rc;
854 :
855 6 : ret = vrf_switch_to_netns(vrf_id);
856 6 : if (ret < 0) {
857 0 : flog_err_sys(EC_LIB_SOCKET, "%s: Can't switch to VRF %u (%s)",
858 : __func__, vrf_id, safe_strerror(errno));
859 0 : return 0;
860 : }
861 6 : rc = ioctl(d, request, params);
862 6 : saved_errno = errno;
863 6 : ret = vrf_switchback_to_initial();
864 6 : if (ret < 0)
865 0 : flog_err_sys(EC_LIB_SOCKET,
866 : "%s: Can't switchback from VRF %u (%s)", __func__,
867 : vrf_id, safe_strerror(errno));
868 6 : errno = saved_errno;
869 6 : return rc;
870 : }
871 :
872 0 : int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id,
873 : const char *interfacename)
874 : {
875 0 : int ret, save_errno, ret2;
876 :
877 0 : ret = vrf_switch_to_netns(vrf_id);
878 0 : if (ret < 0)
879 0 : flog_err_sys(EC_LIB_SOCKET, "%s: Can't switch to VRF %u (%s)",
880 : __func__, vrf_id, safe_strerror(errno));
881 0 : ret = sockunion_socket(su);
882 0 : save_errno = errno;
883 0 : ret2 = vrf_switchback_to_initial();
884 0 : if (ret2 < 0)
885 0 : flog_err_sys(EC_LIB_SOCKET,
886 : "%s: Can't switchback from VRF %u (%s)", __func__,
887 : vrf_id, safe_strerror(errno));
888 0 : errno = save_errno;
889 :
890 0 : if (ret <= 0)
891 : return ret;
892 0 : ret2 = vrf_bind(vrf_id, ret, interfacename);
893 0 : if (ret2 < 0) {
894 0 : close(ret);
895 0 : ret = ret2;
896 : }
897 : return ret;
898 : }
899 :
900 : /* ------- Northbound callbacks ------- */
901 :
902 : /*
903 : * XPath: /frr-vrf:lib/vrf
904 : */
905 12 : static int lib_vrf_create(struct nb_cb_create_args *args)
906 : {
907 12 : const char *vrfname;
908 12 : struct vrf *vrfp;
909 :
910 12 : vrfname = yang_dnode_get_string(args->dnode, "./name");
911 :
912 12 : if (args->event != NB_EV_APPLY)
913 : return NB_OK;
914 :
915 4 : vrfp = vrf_get(VRF_UNKNOWN, vrfname);
916 :
917 4 : SET_FLAG(vrfp->status, VRF_CONFIGURED);
918 4 : nb_running_set_entry(args->dnode, vrfp);
919 :
920 4 : return NB_OK;
921 : }
922 :
923 0 : static int lib_vrf_destroy(struct nb_cb_destroy_args *args)
924 : {
925 0 : struct vrf *vrfp;
926 :
927 0 : switch (args->event) {
928 0 : case NB_EV_VALIDATE:
929 0 : vrfp = nb_running_get_entry(args->dnode, NULL, true);
930 0 : if (CHECK_FLAG(vrfp->status, VRF_ACTIVE)) {
931 0 : snprintf(args->errmsg, args->errmsg_len,
932 : "Only inactive VRFs can be deleted");
933 0 : return NB_ERR_VALIDATION;
934 : }
935 : break;
936 : case NB_EV_PREPARE:
937 : case NB_EV_ABORT:
938 : break;
939 0 : case NB_EV_APPLY:
940 0 : vrfp = nb_running_unset_entry(args->dnode);
941 :
942 : /* Clear configured flag and invoke delete. */
943 0 : UNSET_FLAG(vrfp->status, VRF_CONFIGURED);
944 0 : vrf_delete(vrfp);
945 0 : break;
946 : }
947 :
948 : return NB_OK;
949 : }
950 :
951 0 : static const void *lib_vrf_get_next(struct nb_cb_get_next_args *args)
952 : {
953 0 : struct vrf *vrfp = (struct vrf *)args->list_entry;
954 :
955 0 : if (args->list_entry == NULL) {
956 0 : vrfp = RB_MIN(vrf_name_head, &vrfs_by_name);
957 : } else {
958 0 : vrfp = RB_NEXT(vrf_name_head, vrfp);
959 : }
960 :
961 0 : return vrfp;
962 : }
963 :
964 0 : static int lib_vrf_get_keys(struct nb_cb_get_keys_args *args)
965 : {
966 0 : struct vrf *vrfp = (struct vrf *)args->list_entry;
967 :
968 0 : args->keys->num = 1;
969 0 : strlcpy(args->keys->key[0], vrfp->name, sizeof(args->keys->key[0]));
970 :
971 0 : return NB_OK;
972 : }
973 :
974 0 : static const void *lib_vrf_lookup_entry(struct nb_cb_lookup_entry_args *args)
975 : {
976 0 : const char *vrfname = args->keys->key[0];
977 :
978 0 : struct vrf *vrf = vrf_lookup_by_name(vrfname);
979 :
980 0 : return vrf;
981 : }
982 :
983 : /*
984 : * XPath: /frr-vrf:lib/vrf/id
985 : */
986 : static struct yang_data *
987 0 : lib_vrf_state_id_get_elem(struct nb_cb_get_elem_args *args)
988 : {
989 0 : struct vrf *vrfp = (struct vrf *)args->list_entry;
990 :
991 0 : return yang_data_new_uint32(args->xpath, vrfp->vrf_id);
992 : }
993 :
994 : /*
995 : * XPath: /frr-vrf:lib/vrf/active
996 : */
997 : static struct yang_data *
998 0 : lib_vrf_state_active_get_elem(struct nb_cb_get_elem_args *args)
999 : {
1000 0 : struct vrf *vrfp = (struct vrf *)args->list_entry;
1001 :
1002 0 : if (vrfp->status == VRF_ACTIVE)
1003 0 : return yang_data_new_bool(args->xpath, true);
1004 :
1005 : return NULL;
1006 : }
1007 :
1008 : /* clang-format off */
1009 : const struct frr_yang_module_info frr_vrf_info = {
1010 : .name = "frr-vrf",
1011 : .nodes = {
1012 : {
1013 : .xpath = "/frr-vrf:lib/vrf",
1014 : .cbs = {
1015 : .create = lib_vrf_create,
1016 : .destroy = lib_vrf_destroy,
1017 : .get_next = lib_vrf_get_next,
1018 : .get_keys = lib_vrf_get_keys,
1019 : .lookup_entry = lib_vrf_lookup_entry,
1020 : },
1021 : .priority = NB_DFLT_PRIORITY - 2,
1022 : },
1023 : {
1024 : .xpath = "/frr-vrf:lib/vrf/state/id",
1025 : .cbs = {
1026 : .get_elem = lib_vrf_state_id_get_elem,
1027 : }
1028 : },
1029 : {
1030 : .xpath = "/frr-vrf:lib/vrf/state/active",
1031 : .cbs = {
1032 : .get_elem = lib_vrf_state_active_get_elem,
1033 : }
1034 : },
1035 : {
1036 : .xpath = NULL,
1037 : },
1038 : }
1039 : };
1040 :
|