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 hash_clean_and_free(&vrf_hash
, vrf_hash_bitmap_free
);
400 void vrf_bitmap_set(vrf_bitmap_t bmap
, vrf_id_t vrf_id
)
402 struct vrf_bit_set lookup
= { .vrf_id
= vrf_id
};
403 struct hash
*vrf_hash
= bmap
;
404 struct vrf_bit_set
*bit
;
406 if (vrf_hash
== NULL
|| vrf_id
== VRF_UNKNOWN
)
409 bit
= hash_get(vrf_hash
, &lookup
, vrf_hash_bitmap_alloc
);
413 void vrf_bitmap_unset(vrf_bitmap_t bmap
, vrf_id_t vrf_id
)
415 struct vrf_bit_set lookup
= { .vrf_id
= vrf_id
};
416 struct hash
*vrf_hash
= bmap
;
417 struct vrf_bit_set
*bit
;
419 if (vrf_hash
== NULL
|| vrf_id
== VRF_UNKNOWN
)
422 bit
= hash_get(vrf_hash
, &lookup
, vrf_hash_bitmap_alloc
);
426 int vrf_bitmap_check(vrf_bitmap_t bmap
, vrf_id_t vrf_id
)
428 struct vrf_bit_set lookup
= { .vrf_id
= vrf_id
};
429 struct hash
*vrf_hash
= bmap
;
430 struct vrf_bit_set
*bit
;
432 if (vrf_hash
== NULL
|| vrf_id
== VRF_UNKNOWN
)
435 bit
= hash_lookup(vrf_hash
, &lookup
);
442 static void vrf_autocomplete(vector comps
, struct cmd_token
*token
)
444 struct vrf
*vrf
= NULL
;
446 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
447 vector_set(comps
, XSTRDUP(MTYPE_COMPLETION
, vrf
->name
));
450 static const struct cmd_variable_handler vrf_var_handlers
[] = {
453 .completions
= vrf_autocomplete
,
456 .varname
= "vrf_name",
457 .completions
= vrf_autocomplete
,
460 .varname
= "nexthop_vrf",
461 .completions
= vrf_autocomplete
,
463 {.completions
= NULL
},
466 /* Initialize VRF module. */
467 void vrf_init(int (*create
)(struct vrf
*), int (*enable
)(struct vrf
*),
468 int (*disable
)(struct vrf
*), int (*destroy
)(struct vrf
*))
470 struct vrf
*default_vrf
;
472 /* initialise NS, in case VRF backend if NETNS */
475 zlog_debug("%s: Initializing VRF subsystem", __func__
);
477 vrf_master
.vrf_new_hook
= create
;
478 vrf_master
.vrf_enable_hook
= enable
;
479 vrf_master
.vrf_disable_hook
= disable
;
480 vrf_master
.vrf_delete_hook
= destroy
;
482 /* The default VRF always exists. */
483 default_vrf
= vrf_get(VRF_DEFAULT
, VRF_DEFAULT_NAME
);
485 flog_err(EC_LIB_VRF_START
,
486 "vrf_init: failed to create the default VRF!");
489 if (vrf_is_backend_netns()) {
492 strlcpy(default_vrf
->data
.l
.netns_name
,
493 VRF_DEFAULT_NAME
, NS_NAMSIZ
);
494 ns
= ns_lookup(NS_DEFAULT
);
495 ns
->vrf_ctxt
= default_vrf
;
496 default_vrf
->ns_ctxt
= ns
;
499 /* Enable the default VRF. */
500 if (!vrf_enable(default_vrf
)) {
501 flog_err(EC_LIB_VRF_START
,
502 "vrf_init: failed to enable the default VRF!");
506 cmd_variable_handler_register(vrf_var_handlers
);
509 static void vrf_terminate_single(struct vrf
*vrf
)
511 /* Clear configured flag and invoke delete. */
513 UNSET_FLAG(vrf
->status
, VRF_CONFIGURED
);
518 /* Terminate VRF module. */
519 void vrf_terminate(void)
521 struct vrf
*vrf
, *tmp
;
524 zlog_debug("%s: Shutting down vrf subsystem", __func__
);
526 RB_FOREACH_SAFE (vrf
, vrf_id_head
, &vrfs_by_id
, tmp
) {
527 if (vrf
->vrf_id
== VRF_DEFAULT
)
530 vrf_terminate_single(vrf
);
533 RB_FOREACH_SAFE (vrf
, vrf_name_head
, &vrfs_by_name
, tmp
) {
534 if (vrf
->vrf_id
== VRF_DEFAULT
)
537 vrf_terminate_single(vrf
);
540 /* Finally terminate default VRF */
541 vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
543 vrf_terminate_single(vrf
);
546 int vrf_socket(int domain
, int type
, int protocol
, vrf_id_t vrf_id
,
547 const char *interfacename
)
549 int ret
, save_errno
, ret2
;
551 ret
= vrf_switch_to_netns(vrf_id
);
553 flog_err_sys(EC_LIB_SOCKET
, "%s: Can't switch to VRF %u (%s)",
554 __func__
, vrf_id
, safe_strerror(errno
));
556 ret
= socket(domain
, type
, protocol
);
558 ret2
= vrf_switchback_to_initial();
560 flog_err_sys(EC_LIB_SOCKET
,
561 "%s: Can't switchback from VRF %u (%s)", __func__
,
562 vrf_id
, safe_strerror(errno
));
566 ret2
= vrf_bind(vrf_id
, ret
, interfacename
);
574 int vrf_is_backend_netns(void)
576 return (vrf_backend
== VRF_BACKEND_NETNS
);
579 int vrf_get_backend(void)
581 if (!vrf_backend_configured
)
582 return VRF_BACKEND_UNKNOWN
;
586 int vrf_configure_backend(enum vrf_backend_type backend
)
588 /* Work around issue in old gcc */
590 case VRF_BACKEND_UNKNOWN
:
591 case VRF_BACKEND_NETNS
:
592 case VRF_BACKEND_VRF_LITE
:
594 case VRF_BACKEND_MAX
:
598 vrf_backend
= backend
;
599 vrf_backend_configured
= 1;
604 /* vrf CLI commands */
608 "Exit current mode and down to previous mode\n")
614 DEFUN_YANG_NOSH (vrf
,
617 "Select a VRF to configure\n"
621 const char *vrfname
= argv
[idx_name
]->arg
;
622 char xpath_list
[XPATH_MAXLEN
];
626 if (strlen(vrfname
) > VRF_NAMSIZ
) {
628 "%% VRF name %s invalid: length exceeds %d bytes\n",
629 vrfname
, VRF_NAMSIZ
);
630 return CMD_WARNING_CONFIG_FAILED
;
633 snprintf(xpath_list
, sizeof(xpath_list
), FRR_VRF_KEY_XPATH
, vrfname
);
635 nb_cli_enqueue_change(vty
, xpath_list
, NB_OP_CREATE
, NULL
);
636 ret
= nb_cli_apply_changes_clear_pending(vty
, "%s", xpath_list
);
637 if (ret
== CMD_SUCCESS
) {
638 VTY_PUSH_XPATH(VRF_NODE
, xpath_list
);
639 vrf
= vrf_lookup_by_name(vrfname
);
641 VTY_PUSH_CONTEXT(VRF_NODE
, vrf
);
651 "Delete a pseudo VRF's configuration\n"
654 const char *vrfname
= argv
[2]->arg
;
655 char xpath_list
[XPATH_MAXLEN
];
659 vrfp
= vrf_lookup_by_name(vrfname
);
664 if (CHECK_FLAG(vrfp
->status
, VRF_ACTIVE
)) {
665 vty_out(vty
, "%% Only inactive VRFs can be deleted\n");
666 return CMD_WARNING_CONFIG_FAILED
;
669 if (vrf_get_backend() == VRF_BACKEND_VRF_LITE
) {
671 * Remove the VRF interface config when removing the VRF.
673 snprintf(xpath_list
, sizeof(xpath_list
),
674 "/frr-interface:lib/interface[name='%s']", vrfname
);
675 nb_cli_enqueue_change(vty
, xpath_list
, NB_OP_DESTROY
, NULL
);
678 snprintf(xpath_list
, sizeof(xpath_list
), FRR_VRF_KEY_XPATH
, vrfname
);
680 nb_cli_enqueue_change(vty
, xpath_list
, NB_OP_DESTROY
, NULL
);
681 return nb_cli_apply_changes(vty
, NULL
);
685 static struct cmd_node vrf_node
= {
688 .parent_node
= CONFIG_NODE
,
689 .prompt
= "%s(config-vrf)# ",
693 * Debug CLI for vrf's
718 static int vrf_write_host(struct vty
*vty
)
721 vty_out(vty
, "debug vrf\n");
726 static int vrf_write_host(struct vty
*vty
);
727 static struct cmd_node vrf_debug_node
= {
729 .node
= VRF_DEBUG_NODE
,
731 .config_write
= vrf_write_host
,
734 void vrf_install_commands(void)
736 install_node(&vrf_debug_node
);
738 install_element(CONFIG_NODE
, &vrf_debug_cmd
);
739 install_element(ENABLE_NODE
, &vrf_debug_cmd
);
740 install_element(CONFIG_NODE
, &no_vrf_debug_cmd
);
741 install_element(ENABLE_NODE
, &no_vrf_debug_cmd
);
744 void vrf_cmd_init(int (*writefunc
)(struct vty
*vty
))
746 install_element(CONFIG_NODE
, &vrf_cmd
);
747 install_element(CONFIG_NODE
, &no_vrf_cmd
);
748 vrf_node
.config_write
= writefunc
;
749 install_node(&vrf_node
);
750 install_default(VRF_NODE
);
751 install_element(VRF_NODE
, &vrf_exit_cmd
);
754 void vrf_set_default_name(const char *default_name
)
756 snprintf(vrf_default_name
, VRF_NAMSIZ
, "%s", default_name
);
759 const char *vrf_get_default_name(void)
761 return vrf_default_name
;
764 int vrf_bind(vrf_id_t vrf_id
, int fd
, const char *ifname
)
767 struct interface
*ifp
;
773 if (vrf_id
== VRF_UNKNOWN
)
776 /* can't bind to a VRF that doesn't exist */
777 vrf
= vrf_lookup_by_id(vrf_id
);
778 if (!vrf_is_enabled(vrf
))
781 if (ifname
&& strcmp(ifname
, vrf
->name
)) {
782 /* binding to a regular interface */
784 /* can't bind to an interface that doesn't exist */
785 ifp
= if_lookup_by_name(ifname
, vrf_id
);
789 /* binding to a VRF device */
791 /* nothing to do for netns */
792 if (vrf_is_backend_netns())
795 /* nothing to do for default vrf */
796 if (vrf_id
== VRF_DEFAULT
)
802 #ifdef SO_BINDTODEVICE
803 ret
= setsockopt(fd
, SOL_SOCKET
, SO_BINDTODEVICE
, ifname
,
806 zlog_err("bind to interface %s failed, errno=%d", ifname
,
808 #endif /* SO_BINDTODEVICE */
811 int vrf_getaddrinfo(const char *node
, const char *service
,
812 const struct addrinfo
*hints
, struct addrinfo
**res
,
815 int ret
, ret2
, save_errno
;
817 ret
= vrf_switch_to_netns(vrf_id
);
819 flog_err_sys(EC_LIB_SOCKET
, "%s: Can't switch to VRF %u (%s)",
820 __func__
, vrf_id
, safe_strerror(errno
));
821 ret
= getaddrinfo(node
, service
, hints
, res
);
823 ret2
= vrf_switchback_to_initial();
825 flog_err_sys(EC_LIB_SOCKET
,
826 "%s: Can't switchback from VRF %u (%s)", __func__
,
827 vrf_id
, safe_strerror(errno
));
832 int vrf_ioctl(vrf_id_t vrf_id
, int d
, unsigned long request
, char *params
)
834 int ret
, saved_errno
, rc
;
836 ret
= vrf_switch_to_netns(vrf_id
);
838 flog_err_sys(EC_LIB_SOCKET
, "%s: Can't switch to VRF %u (%s)",
839 __func__
, vrf_id
, safe_strerror(errno
));
842 rc
= ioctl(d
, request
, params
);
844 ret
= vrf_switchback_to_initial();
846 flog_err_sys(EC_LIB_SOCKET
,
847 "%s: Can't switchback from VRF %u (%s)", __func__
,
848 vrf_id
, safe_strerror(errno
));
853 int vrf_sockunion_socket(const union sockunion
*su
, vrf_id_t vrf_id
,
854 const char *interfacename
)
856 int ret
, save_errno
, ret2
;
858 ret
= vrf_switch_to_netns(vrf_id
);
860 flog_err_sys(EC_LIB_SOCKET
, "%s: Can't switch to VRF %u (%s)",
861 __func__
, vrf_id
, safe_strerror(errno
));
862 ret
= sockunion_socket(su
);
864 ret2
= vrf_switchback_to_initial();
866 flog_err_sys(EC_LIB_SOCKET
,
867 "%s: Can't switchback from VRF %u (%s)", __func__
,
868 vrf_id
, safe_strerror(errno
));
873 ret2
= vrf_bind(vrf_id
, ret
, interfacename
);
881 /* ------- Northbound callbacks ------- */
884 * XPath: /frr-vrf:lib/vrf
886 static int lib_vrf_create(struct nb_cb_create_args
*args
)
891 vrfname
= yang_dnode_get_string(args
->dnode
, "./name");
893 if (args
->event
!= NB_EV_APPLY
)
896 vrfp
= vrf_get(VRF_UNKNOWN
, vrfname
);
898 SET_FLAG(vrfp
->status
, VRF_CONFIGURED
);
899 nb_running_set_entry(args
->dnode
, vrfp
);
904 static int lib_vrf_destroy(struct nb_cb_destroy_args
*args
)
908 switch (args
->event
) {
910 vrfp
= nb_running_get_entry(args
->dnode
, NULL
, true);
911 if (CHECK_FLAG(vrfp
->status
, VRF_ACTIVE
)) {
912 snprintf(args
->errmsg
, args
->errmsg_len
,
913 "Only inactive VRFs can be deleted");
914 return NB_ERR_VALIDATION
;
921 vrfp
= nb_running_unset_entry(args
->dnode
);
923 /* Clear configured flag and invoke delete. */
924 UNSET_FLAG(vrfp
->status
, VRF_CONFIGURED
);
932 static const void *lib_vrf_get_next(struct nb_cb_get_next_args
*args
)
934 struct vrf
*vrfp
= (struct vrf
*)args
->list_entry
;
936 if (args
->list_entry
== NULL
) {
937 vrfp
= RB_MIN(vrf_name_head
, &vrfs_by_name
);
939 vrfp
= RB_NEXT(vrf_name_head
, vrfp
);
945 static int lib_vrf_get_keys(struct nb_cb_get_keys_args
*args
)
947 struct vrf
*vrfp
= (struct vrf
*)args
->list_entry
;
950 strlcpy(args
->keys
->key
[0], vrfp
->name
, sizeof(args
->keys
->key
[0]));
955 static const void *lib_vrf_lookup_entry(struct nb_cb_lookup_entry_args
*args
)
957 const char *vrfname
= args
->keys
->key
[0];
959 struct vrf
*vrf
= vrf_lookup_by_name(vrfname
);
965 * XPath: /frr-vrf:lib/vrf/id
967 static struct yang_data
*
968 lib_vrf_state_id_get_elem(struct nb_cb_get_elem_args
*args
)
970 struct vrf
*vrfp
= (struct vrf
*)args
->list_entry
;
972 return yang_data_new_uint32(args
->xpath
, vrfp
->vrf_id
);
976 * XPath: /frr-vrf:lib/vrf/active
978 static struct yang_data
*
979 lib_vrf_state_active_get_elem(struct nb_cb_get_elem_args
*args
)
981 struct vrf
*vrfp
= (struct vrf
*)args
->list_entry
;
983 if (vrfp
->status
== VRF_ACTIVE
)
984 return yang_data_new_bool(args
->xpath
, true);
989 /* clang-format off */
990 const struct frr_yang_module_info frr_vrf_info
= {
994 .xpath
= "/frr-vrf:lib/vrf",
996 .create
= lib_vrf_create
,
997 .destroy
= lib_vrf_destroy
,
998 .get_next
= lib_vrf_get_next
,
999 .get_keys
= lib_vrf_get_keys
,
1000 .lookup_entry
= lib_vrf_lookup_entry
,
1002 .priority
= NB_DFLT_PRIORITY
- 2,
1005 .xpath
= "/frr-vrf:lib/vrf/state/id",
1007 .get_elem
= lib_vrf_state_id_get_elem
,
1011 .xpath
= "/frr-vrf:lib/vrf/state/active",
1013 .get_elem
= lib_vrf_state_active_get_elem
,