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