1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 2014 6WIND S.A.
19 #include "nexthop_group.h"
20 #include "lib_errors.h"
21 #include "northbound.h"
22 #include "northbound_cli.h"
24 /* default VRF name value used when VRF backend is not NETNS */
25 #define VRF_DEFAULT_NAME_INTERNAL "default"
27 DEFINE_MTYPE_STATIC(LIB
, VRF
, "VRF");
28 DEFINE_MTYPE_STATIC(LIB
, VRF_BITMAP
, "VRF bit-map");
30 DEFINE_QOBJ_TYPE(vrf
);
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
*);
35 RB_GENERATE(vrf_id_head
, vrf
, id_entry
, vrf_id_compare
);
36 RB_GENERATE(vrf_name_head
, vrf
, name_entry
, vrf_name_compare
);
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
);
41 static int vrf_backend
;
42 static int vrf_backend_configured
;
43 static char vrf_default_name
[VRF_NAMSIZ
] = VRF_DEFAULT_NAME_INTERNAL
;
46 * Turn on/off debug code
49 static int debug_vrf
= 0;
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
*);
61 static int vrf_is_enabled(struct vrf
*vrf
);
63 /* VRF list existance check by name. */
64 struct vrf
*vrf_lookup_by_name(const char *name
)
67 strlcpy(vrf
.name
, name
, sizeof(vrf
.name
));
68 return (RB_FIND(vrf_name_head
, &vrfs_by_name
, &vrf
));
71 static __inline
int vrf_id_compare(const struct vrf
*a
, const struct vrf
*b
)
73 return (a
->vrf_id
- b
->vrf_id
);
76 static int vrf_name_compare(const struct vrf
*a
, const struct vrf
*b
)
78 return strcmp(a
->name
, b
->name
);
81 int vrf_switch_to_netns(vrf_id_t vrf_id
)
84 struct vrf
*vrf
= vrf_lookup_by_id(vrf_id
);
86 /* VRF is default VRF. silently ignore */
87 if (!vrf
|| vrf
->vrf_id
== VRF_DEFAULT
)
88 return 1; /* 1 = default */
89 /* VRF has no NETNS backend. silently ignore */
90 if (vrf
->data
.l
.netns_name
[0] == '\0')
91 return 2; /* 2 = no netns */
92 name
= ns_netns_pathname(NULL
, vrf
->data
.l
.netns_name
);
94 zlog_debug("VRF_SWITCH: %s(%u)", name
, vrf
->vrf_id
);
95 return ns_switch_to_netns(name
);
98 int vrf_switchback_to_initial(void)
100 int ret
= ns_switchback_to_initial();
102 if (ret
== 0 && debug_vrf
)
103 zlog_debug("VRF_SWITCHBACK");
107 /* Get a VRF. If not found, create one.
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
114 struct vrf
*vrf_get(vrf_id_t vrf_id
, const char *name
)
116 struct vrf
*vrf
= NULL
;
119 /* Nothing to see, move along here */
120 if (!name
&& vrf_id
== VRF_UNKNOWN
)
123 /* attempt to find already available VRF
126 vrf
= vrf_lookup_by_name(name
);
127 if (vrf
&& vrf_id
!= VRF_UNKNOWN
128 && vrf
->vrf_id
!= VRF_UNKNOWN
129 && vrf
->vrf_id
!= vrf_id
) {
130 zlog_debug("VRF_GET: avoid %s creation(%u), same name exists (%u)",
131 name
, vrf_id
, vrf
->vrf_id
);
134 /* Try to find VRF both by ID and name */
135 if (!vrf
&& vrf_id
!= VRF_UNKNOWN
)
136 vrf
= vrf_lookup_by_id(vrf_id
);
139 vrf
= XCALLOC(MTYPE_VRF
, sizeof(struct vrf
));
140 vrf
->vrf_id
= VRF_UNKNOWN
;
145 zlog_debug("VRF(%u) %s is created.", vrf_id
,
146 (name
) ? name
: "(NULL)");
150 if (vrf_id
!= VRF_UNKNOWN
&& vrf
->vrf_id
== VRF_UNKNOWN
) {
151 vrf
->vrf_id
= vrf_id
;
152 RB_INSERT(vrf_id_head
, &vrfs_by_id
, vrf
);
156 if (name
&& vrf
->name
[0] != '\0' && strcmp(name
, vrf
->name
)) {
157 /* update the vrf name */
158 RB_REMOVE(vrf_name_head
, &vrfs_by_name
, vrf
);
159 strlcpy(vrf
->data
.l
.netns_name
,
161 strlcpy(vrf
->name
, name
, sizeof(vrf
->name
));
162 RB_INSERT(vrf_name_head
, &vrfs_by_name
, vrf
);
163 } else if (name
&& vrf
->name
[0] == '\0') {
164 strlcpy(vrf
->name
, name
, sizeof(vrf
->name
));
165 RB_INSERT(vrf_name_head
, &vrfs_by_name
, vrf
);
167 if (new &&vrf_master
.vrf_new_hook
)
168 (*vrf_master
.vrf_new_hook
)(vrf
);
173 /* Update a VRF. If not found, create one.
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.
182 struct vrf
*vrf_update(vrf_id_t new_vrf_id
, const char *name
)
184 struct vrf
*vrf
= NULL
;
186 /*Treat VRF add for existing vrf as update
187 * Update VRF ID and also update in VRF ID table
190 vrf
= vrf_lookup_by_name(name
);
191 if (vrf
&& new_vrf_id
!= VRF_UNKNOWN
&& vrf
->vrf_id
!= VRF_UNKNOWN
192 && vrf
->vrf_id
!= new_vrf_id
) {
195 "Vrf Update event: %s old id: %u, new id: %u",
196 name
, vrf
->vrf_id
, new_vrf_id
);
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
206 RB_REMOVE(vrf_id_head
, &vrfs_by_id
, vrf
);
207 vrf
->vrf_id
= new_vrf_id
;
208 RB_INSERT(vrf_id_head
, &vrfs_by_id
, vrf
);
213 * vrf_get is implied creation if it does not exist
215 vrf
= vrf_get(new_vrf_id
, name
);
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()).
223 void vrf_delete(struct vrf
*vrf
)
226 zlog_debug("VRF %s(%u) is to be deleted.", vrf
->name
,
229 if (vrf_is_enabled(vrf
))
232 if (vrf
->vrf_id
!= VRF_UNKNOWN
) {
233 RB_REMOVE(vrf_id_head
, &vrfs_by_id
, vrf
);
234 vrf
->vrf_id
= VRF_UNKNOWN
;
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.
241 if (vrf_is_user_cfged(vrf
))
244 /* Do not delete the VRF if it has interfaces configured in it. */
245 if (!RB_EMPTY(if_name_head
, &vrf
->ifaces_by_name
))
248 if (vrf_master
.vrf_delete_hook
)
249 (*vrf_master
.vrf_delete_hook
)(vrf
);
253 if (vrf
->name
[0] != '\0')
254 RB_REMOVE(vrf_name_head
, &vrfs_by_name
, vrf
);
256 XFREE(MTYPE_VRF
, vrf
);
259 /* Look up a VRF by identifier. */
260 struct vrf
*vrf_lookup_by_id(vrf_id_t vrf_id
)
264 return (RB_FIND(vrf_id_head
, &vrfs_by_id
, &vrf
));
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.
272 * RETURN: 1 - enabled successfully; otherwise, 0.
274 int vrf_enable(struct vrf
*vrf
)
276 if (vrf_is_enabled(vrf
))
280 zlog_debug("VRF %s(%u) is enabled.", vrf
->name
, vrf
->vrf_id
);
282 SET_FLAG(vrf
->status
, VRF_ACTIVE
);
284 if (vrf_master
.vrf_enable_hook
)
285 (*vrf_master
.vrf_enable_hook
)(vrf
);
288 * If we have any nexthop group entries that
289 * are awaiting vrf initialization then
290 * let's let people know about it
292 nexthop_group_enable_vrf(vrf
);
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.
302 void vrf_disable(struct vrf
*vrf
)
304 if (!vrf_is_enabled(vrf
))
307 UNSET_FLAG(vrf
->status
, VRF_ACTIVE
);
310 zlog_debug("VRF %s(%u) is to be disabled.", vrf
->name
,
313 /* Till now, nothing to be done for the default VRF. */
314 // Pending: see why this statement.
318 * When the vrf is disabled let's
319 * handle all nexthop-groups associated
322 nexthop_group_disable_vrf(vrf
);
324 if (vrf_master
.vrf_disable_hook
)
325 (*vrf_master
.vrf_disable_hook
)(vrf
);
328 const char *vrf_id_to_name(vrf_id_t vrf_id
)
332 if (vrf_id
== VRF_DEFAULT
)
333 return VRF_DEFAULT_NAME
;
335 vrf
= vrf_lookup_by_id(vrf_id
);
336 return VRF_LOGNAME(vrf
);
339 /* Look up the data pointer of the specified VRF. */
340 void *vrf_info_lookup(vrf_id_t vrf_id
)
342 struct vrf
*vrf
= vrf_lookup_by_id(vrf_id
);
343 return vrf
? vrf
->info
: NULL
;
347 * VRF hash for storing set or not.
354 static unsigned int vrf_hash_bitmap_key(const void *data
)
356 const struct vrf_bit_set
*bit
= data
;
361 static bool vrf_hash_bitmap_cmp(const void *a
, const void *b
)
363 const struct vrf_bit_set
*bit1
= a
;
364 const struct vrf_bit_set
*bit2
= b
;
366 return bit1
->vrf_id
== bit2
->vrf_id
;
369 static void *vrf_hash_bitmap_alloc(void *data
)
371 struct vrf_bit_set
*copy
= data
;
372 struct vrf_bit_set
*bit
;
374 bit
= XMALLOC(MTYPE_VRF_BITMAP
, sizeof(*bit
));
375 bit
->vrf_id
= copy
->vrf_id
;
380 static void vrf_hash_bitmap_free(void *data
)
382 struct vrf_bit_set
*bit
= data
;
384 XFREE(MTYPE_VRF_BITMAP
, bit
);
387 vrf_bitmap_t
vrf_bitmap_init(void)
389 return hash_create_size(32, vrf_hash_bitmap_key
, vrf_hash_bitmap_cmp
,
393 void vrf_bitmap_free(vrf_bitmap_t bmap
)
395 struct hash
*vrf_hash
= bmap
;
397 if (vrf_hash
== NULL
)
400 hash_clean(vrf_hash
, vrf_hash_bitmap_free
);
404 void vrf_bitmap_set(vrf_bitmap_t bmap
, vrf_id_t vrf_id
)
406 struct vrf_bit_set lookup
= { .vrf_id
= vrf_id
};
407 struct hash
*vrf_hash
= bmap
;
408 struct vrf_bit_set
*bit
;
410 if (vrf_hash
== NULL
|| vrf_id
== VRF_UNKNOWN
)
413 bit
= hash_get(vrf_hash
, &lookup
, vrf_hash_bitmap_alloc
);
417 void vrf_bitmap_unset(vrf_bitmap_t bmap
, vrf_id_t vrf_id
)
419 struct vrf_bit_set lookup
= { .vrf_id
= vrf_id
};
420 struct hash
*vrf_hash
= bmap
;
421 struct vrf_bit_set
*bit
;
423 if (vrf_hash
== NULL
|| vrf_id
== VRF_UNKNOWN
)
426 bit
= hash_get(vrf_hash
, &lookup
, vrf_hash_bitmap_alloc
);
430 int vrf_bitmap_check(vrf_bitmap_t bmap
, vrf_id_t vrf_id
)
432 struct vrf_bit_set lookup
= { .vrf_id
= vrf_id
};
433 struct hash
*vrf_hash
= bmap
;
434 struct vrf_bit_set
*bit
;
436 if (vrf_hash
== NULL
|| vrf_id
== VRF_UNKNOWN
)
439 bit
= hash_lookup(vrf_hash
, &lookup
);
446 static void vrf_autocomplete(vector comps
, struct cmd_token
*token
)
448 struct vrf
*vrf
= NULL
;
450 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
451 vector_set(comps
, XSTRDUP(MTYPE_COMPLETION
, vrf
->name
));
454 static const struct cmd_variable_handler vrf_var_handlers
[] = {
457 .completions
= vrf_autocomplete
,
460 .varname
= "vrf_name",
461 .completions
= vrf_autocomplete
,
464 .varname
= "nexthop_vrf",
465 .completions
= vrf_autocomplete
,
467 {.completions
= NULL
},
470 /* Initialize VRF module. */
471 void vrf_init(int (*create
)(struct vrf
*), int (*enable
)(struct vrf
*),
472 int (*disable
)(struct vrf
*), int (*destroy
)(struct vrf
*))
474 struct vrf
*default_vrf
;
476 /* initialise NS, in case VRF backend if NETNS */
479 zlog_debug("%s: Initializing VRF subsystem", __func__
);
481 vrf_master
.vrf_new_hook
= create
;
482 vrf_master
.vrf_enable_hook
= enable
;
483 vrf_master
.vrf_disable_hook
= disable
;
484 vrf_master
.vrf_delete_hook
= destroy
;
486 /* The default VRF always exists. */
487 default_vrf
= vrf_get(VRF_DEFAULT
, VRF_DEFAULT_NAME
);
489 flog_err(EC_LIB_VRF_START
,
490 "vrf_init: failed to create the default VRF!");
493 if (vrf_is_backend_netns()) {
496 strlcpy(default_vrf
->data
.l
.netns_name
,
497 VRF_DEFAULT_NAME
, NS_NAMSIZ
);
498 ns
= ns_lookup(NS_DEFAULT
);
499 ns
->vrf_ctxt
= default_vrf
;
500 default_vrf
->ns_ctxt
= ns
;
503 /* Enable the default VRF. */
504 if (!vrf_enable(default_vrf
)) {
505 flog_err(EC_LIB_VRF_START
,
506 "vrf_init: failed to enable the default VRF!");
510 cmd_variable_handler_register(vrf_var_handlers
);
513 static void vrf_terminate_single(struct vrf
*vrf
)
515 /* Clear configured flag and invoke delete. */
517 UNSET_FLAG(vrf
->status
, VRF_CONFIGURED
);
522 /* Terminate VRF module. */
523 void vrf_terminate(void)
525 struct vrf
*vrf
, *tmp
;
528 zlog_debug("%s: Shutting down vrf subsystem", __func__
);
530 RB_FOREACH_SAFE (vrf
, vrf_id_head
, &vrfs_by_id
, tmp
) {
531 if (vrf
->vrf_id
== VRF_DEFAULT
)
534 vrf_terminate_single(vrf
);
537 RB_FOREACH_SAFE (vrf
, vrf_name_head
, &vrfs_by_name
, tmp
) {
538 if (vrf
->vrf_id
== VRF_DEFAULT
)
541 vrf_terminate_single(vrf
);
544 /* Finally terminate default VRF */
545 vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
547 vrf_terminate_single(vrf
);
550 int vrf_socket(int domain
, int type
, int protocol
, vrf_id_t vrf_id
,
551 const char *interfacename
)
553 int ret
, save_errno
, ret2
;
555 ret
= vrf_switch_to_netns(vrf_id
);
557 flog_err_sys(EC_LIB_SOCKET
, "%s: Can't switch to VRF %u (%s)",
558 __func__
, vrf_id
, safe_strerror(errno
));
560 ret
= socket(domain
, type
, protocol
);
562 ret2
= vrf_switchback_to_initial();
564 flog_err_sys(EC_LIB_SOCKET
,
565 "%s: Can't switchback from VRF %u (%s)", __func__
,
566 vrf_id
, safe_strerror(errno
));
570 ret2
= vrf_bind(vrf_id
, ret
, interfacename
);
578 int vrf_is_backend_netns(void)
580 return (vrf_backend
== VRF_BACKEND_NETNS
);
583 int vrf_get_backend(void)
585 if (!vrf_backend_configured
)
586 return VRF_BACKEND_UNKNOWN
;
590 int vrf_configure_backend(enum vrf_backend_type backend
)
592 /* Work around issue in old gcc */
594 case VRF_BACKEND_UNKNOWN
:
595 case VRF_BACKEND_NETNS
:
596 case VRF_BACKEND_VRF_LITE
:
598 case VRF_BACKEND_MAX
:
602 vrf_backend
= backend
;
603 vrf_backend_configured
= 1;
608 /* vrf CLI commands */
612 "Exit current mode and down to previous mode\n")
618 DEFUN_YANG_NOSH (vrf
,
621 "Select a VRF to configure\n"
625 const char *vrfname
= argv
[idx_name
]->arg
;
626 char xpath_list
[XPATH_MAXLEN
];
630 if (strlen(vrfname
) > VRF_NAMSIZ
) {
632 "%% VRF name %s invalid: length exceeds %d bytes\n",
633 vrfname
, VRF_NAMSIZ
);
634 return CMD_WARNING_CONFIG_FAILED
;
637 snprintf(xpath_list
, sizeof(xpath_list
), FRR_VRF_KEY_XPATH
, vrfname
);
639 nb_cli_enqueue_change(vty
, xpath_list
, NB_OP_CREATE
, NULL
);
640 ret
= nb_cli_apply_changes_clear_pending(vty
, "%s", xpath_list
);
641 if (ret
== CMD_SUCCESS
) {
642 VTY_PUSH_XPATH(VRF_NODE
, xpath_list
);
643 vrf
= vrf_lookup_by_name(vrfname
);
645 VTY_PUSH_CONTEXT(VRF_NODE
, vrf
);
655 "Delete a pseudo VRF's configuration\n"
658 const char *vrfname
= argv
[2]->arg
;
659 char xpath_list
[XPATH_MAXLEN
];
663 vrfp
= vrf_lookup_by_name(vrfname
);
668 if (CHECK_FLAG(vrfp
->status
, VRF_ACTIVE
)) {
669 vty_out(vty
, "%% Only inactive VRFs can be deleted\n");
670 return CMD_WARNING_CONFIG_FAILED
;
673 if (vrf_get_backend() == VRF_BACKEND_VRF_LITE
) {
675 * Remove the VRF interface config when removing the VRF.
677 snprintf(xpath_list
, sizeof(xpath_list
),
678 "/frr-interface:lib/interface[name='%s']", vrfname
);
679 nb_cli_enqueue_change(vty
, xpath_list
, NB_OP_DESTROY
, NULL
);
682 snprintf(xpath_list
, sizeof(xpath_list
), FRR_VRF_KEY_XPATH
, vrfname
);
684 nb_cli_enqueue_change(vty
, xpath_list
, NB_OP_DESTROY
, NULL
);
685 return nb_cli_apply_changes(vty
, NULL
);
689 static struct cmd_node vrf_node
= {
692 .parent_node
= CONFIG_NODE
,
693 .prompt
= "%s(config-vrf)# ",
697 * Debug CLI for vrf's
722 static int vrf_write_host(struct vty
*vty
)
725 vty_out(vty
, "debug vrf\n");
730 static int vrf_write_host(struct vty
*vty
);
731 static struct cmd_node vrf_debug_node
= {
733 .node
= VRF_DEBUG_NODE
,
735 .config_write
= vrf_write_host
,
738 void vrf_install_commands(void)
740 install_node(&vrf_debug_node
);
742 install_element(CONFIG_NODE
, &vrf_debug_cmd
);
743 install_element(ENABLE_NODE
, &vrf_debug_cmd
);
744 install_element(CONFIG_NODE
, &no_vrf_debug_cmd
);
745 install_element(ENABLE_NODE
, &no_vrf_debug_cmd
);
748 void vrf_cmd_init(int (*writefunc
)(struct vty
*vty
))
750 install_element(CONFIG_NODE
, &vrf_cmd
);
751 install_element(CONFIG_NODE
, &no_vrf_cmd
);
752 vrf_node
.config_write
= writefunc
;
753 install_node(&vrf_node
);
754 install_default(VRF_NODE
);
755 install_element(VRF_NODE
, &vrf_exit_cmd
);
758 void vrf_set_default_name(const char *default_name
)
760 snprintf(vrf_default_name
, VRF_NAMSIZ
, "%s", default_name
);
763 const char *vrf_get_default_name(void)
765 return vrf_default_name
;
768 int vrf_bind(vrf_id_t vrf_id
, int fd
, const char *ifname
)
771 struct interface
*ifp
;
777 if (vrf_id
== VRF_UNKNOWN
)
780 /* can't bind to a VRF that doesn't exist */
781 vrf
= vrf_lookup_by_id(vrf_id
);
782 if (!vrf_is_enabled(vrf
))
785 if (ifname
&& strcmp(ifname
, vrf
->name
)) {
786 /* binding to a regular interface */
788 /* can't bind to an interface that doesn't exist */
789 ifp
= if_lookup_by_name(ifname
, vrf_id
);
793 /* binding to a VRF device */
795 /* nothing to do for netns */
796 if (vrf_is_backend_netns())
799 /* nothing to do for default vrf */
800 if (vrf_id
== VRF_DEFAULT
)
806 #ifdef SO_BINDTODEVICE
807 ret
= setsockopt(fd
, SOL_SOCKET
, SO_BINDTODEVICE
, ifname
,
810 zlog_err("bind to interface %s failed, errno=%d", ifname
,
812 #endif /* SO_BINDTODEVICE */
815 int vrf_getaddrinfo(const char *node
, const char *service
,
816 const struct addrinfo
*hints
, struct addrinfo
**res
,
819 int ret
, ret2
, save_errno
;
821 ret
= vrf_switch_to_netns(vrf_id
);
823 flog_err_sys(EC_LIB_SOCKET
, "%s: Can't switch to VRF %u (%s)",
824 __func__
, vrf_id
, safe_strerror(errno
));
825 ret
= getaddrinfo(node
, service
, hints
, res
);
827 ret2
= vrf_switchback_to_initial();
829 flog_err_sys(EC_LIB_SOCKET
,
830 "%s: Can't switchback from VRF %u (%s)", __func__
,
831 vrf_id
, safe_strerror(errno
));
836 int vrf_ioctl(vrf_id_t vrf_id
, int d
, unsigned long request
, char *params
)
838 int ret
, saved_errno
, rc
;
840 ret
= vrf_switch_to_netns(vrf_id
);
842 flog_err_sys(EC_LIB_SOCKET
, "%s: Can't switch to VRF %u (%s)",
843 __func__
, vrf_id
, safe_strerror(errno
));
846 rc
= ioctl(d
, request
, params
);
848 ret
= vrf_switchback_to_initial();
850 flog_err_sys(EC_LIB_SOCKET
,
851 "%s: Can't switchback from VRF %u (%s)", __func__
,
852 vrf_id
, safe_strerror(errno
));
857 int vrf_sockunion_socket(const union sockunion
*su
, vrf_id_t vrf_id
,
858 const char *interfacename
)
860 int ret
, save_errno
, ret2
;
862 ret
= vrf_switch_to_netns(vrf_id
);
864 flog_err_sys(EC_LIB_SOCKET
, "%s: Can't switch to VRF %u (%s)",
865 __func__
, vrf_id
, safe_strerror(errno
));
866 ret
= sockunion_socket(su
);
868 ret2
= vrf_switchback_to_initial();
870 flog_err_sys(EC_LIB_SOCKET
,
871 "%s: Can't switchback from VRF %u (%s)", __func__
,
872 vrf_id
, safe_strerror(errno
));
877 ret2
= vrf_bind(vrf_id
, ret
, interfacename
);
885 /* ------- Northbound callbacks ------- */
888 * XPath: /frr-vrf:lib/vrf
890 static int lib_vrf_create(struct nb_cb_create_args
*args
)
895 vrfname
= yang_dnode_get_string(args
->dnode
, "./name");
897 if (args
->event
!= NB_EV_APPLY
)
900 vrfp
= vrf_get(VRF_UNKNOWN
, vrfname
);
902 SET_FLAG(vrfp
->status
, VRF_CONFIGURED
);
903 nb_running_set_entry(args
->dnode
, vrfp
);
908 static int lib_vrf_destroy(struct nb_cb_destroy_args
*args
)
912 switch (args
->event
) {
914 vrfp
= nb_running_get_entry(args
->dnode
, NULL
, true);
915 if (CHECK_FLAG(vrfp
->status
, VRF_ACTIVE
)) {
916 snprintf(args
->errmsg
, args
->errmsg_len
,
917 "Only inactive VRFs can be deleted");
918 return NB_ERR_VALIDATION
;
925 vrfp
= nb_running_unset_entry(args
->dnode
);
927 /* Clear configured flag and invoke delete. */
928 UNSET_FLAG(vrfp
->status
, VRF_CONFIGURED
);
936 static const void *lib_vrf_get_next(struct nb_cb_get_next_args
*args
)
938 struct vrf
*vrfp
= (struct vrf
*)args
->list_entry
;
940 if (args
->list_entry
== NULL
) {
941 vrfp
= RB_MIN(vrf_name_head
, &vrfs_by_name
);
943 vrfp
= RB_NEXT(vrf_name_head
, vrfp
);
949 static int lib_vrf_get_keys(struct nb_cb_get_keys_args
*args
)
951 struct vrf
*vrfp
= (struct vrf
*)args
->list_entry
;
954 strlcpy(args
->keys
->key
[0], vrfp
->name
, sizeof(args
->keys
->key
[0]));
959 static const void *lib_vrf_lookup_entry(struct nb_cb_lookup_entry_args
*args
)
961 const char *vrfname
= args
->keys
->key
[0];
963 struct vrf
*vrf
= vrf_lookup_by_name(vrfname
);
969 * XPath: /frr-vrf:lib/vrf/id
971 static struct yang_data
*
972 lib_vrf_state_id_get_elem(struct nb_cb_get_elem_args
*args
)
974 struct vrf
*vrfp
= (struct vrf
*)args
->list_entry
;
976 return yang_data_new_uint32(args
->xpath
, vrfp
->vrf_id
);
980 * XPath: /frr-vrf:lib/vrf/active
982 static struct yang_data
*
983 lib_vrf_state_active_get_elem(struct nb_cb_get_elem_args
*args
)
985 struct vrf
*vrfp
= (struct vrf
*)args
->list_entry
;
987 if (vrfp
->status
== VRF_ACTIVE
)
988 return yang_data_new_bool(args
->xpath
, true);
993 /* clang-format off */
994 const struct frr_yang_module_info frr_vrf_info
= {
998 .xpath
= "/frr-vrf:lib/vrf",
1000 .create
= lib_vrf_create
,
1001 .destroy
= lib_vrf_destroy
,
1002 .get_next
= lib_vrf_get_next
,
1003 .get_keys
= lib_vrf_get_keys
,
1004 .lookup_entry
= lib_vrf_lookup_entry
,
1006 .priority
= NB_DFLT_PRIORITY
- 2,
1009 .xpath
= "/frr-vrf:lib/vrf/state/id",
1011 .get_elem
= lib_vrf_state_id_get_elem
,
1015 .xpath
= "/frr-vrf:lib/vrf/state/active",
1017 .get_elem
= lib_vrf_state_active_get_elem
,