3 * Copyright (C) 2014 6WIND S.A.
5 * This file is part of GNU Zebra.
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.
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.
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
34 #include "nexthop_group.h"
35 #include "lib_errors.h"
36 #include "northbound.h"
37 #include "northbound_cli.h"
39 /* default VRF name value used when VRF backend is not NETNS */
40 #define VRF_DEFAULT_NAME_INTERNAL "default"
42 DEFINE_MTYPE_STATIC(LIB
, VRF
, "VRF");
43 DEFINE_MTYPE_STATIC(LIB
, VRF_BITMAP
, "VRF bit-map");
45 DEFINE_QOBJ_TYPE(vrf
);
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
*);
50 RB_GENERATE(vrf_id_head
, vrf
, id_entry
, vrf_id_compare
);
51 RB_GENERATE(vrf_name_head
, vrf
, name_entry
, vrf_name_compare
);
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
);
56 static int vrf_backend
;
57 static int vrf_backend_configured
;
58 static char vrf_default_name
[VRF_NAMSIZ
] = VRF_DEFAULT_NAME_INTERNAL
;
61 * Turn on/off debug code
64 static int debug_vrf
= 0;
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
*);
76 static int vrf_is_enabled(struct vrf
*vrf
);
78 /* VRF list existance check by name. */
79 struct vrf
*vrf_lookup_by_name(const char *name
)
82 strlcpy(vrf
.name
, name
, sizeof(vrf
.name
));
83 return (RB_FIND(vrf_name_head
, &vrfs_by_name
, &vrf
));
86 static __inline
int vrf_id_compare(const struct vrf
*a
, const struct vrf
*b
)
88 return (a
->vrf_id
- b
->vrf_id
);
91 static int vrf_name_compare(const struct vrf
*a
, const struct vrf
*b
)
93 return strcmp(a
->name
, b
->name
);
96 int vrf_switch_to_netns(vrf_id_t vrf_id
)
99 struct vrf
*vrf
= vrf_lookup_by_id(vrf_id
);
101 /* VRF is default VRF. silently ignore */
102 if (!vrf
|| vrf
->vrf_id
== VRF_DEFAULT
)
103 return 1; /* 1 = default */
104 /* VRF has no NETNS backend. silently ignore */
105 if (vrf
->data
.l
.netns_name
[0] == '\0')
106 return 2; /* 2 = no netns */
107 name
= ns_netns_pathname(NULL
, vrf
->data
.l
.netns_name
);
109 zlog_debug("VRF_SWITCH: %s(%u)", name
, vrf
->vrf_id
);
110 return ns_switch_to_netns(name
);
113 int vrf_switchback_to_initial(void)
115 int ret
= ns_switchback_to_initial();
117 if (ret
== 0 && debug_vrf
)
118 zlog_debug("VRF_SWITCHBACK");
122 /* Get a VRF. If not found, create one.
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
129 struct vrf
*vrf_get(vrf_id_t vrf_id
, const char *name
)
131 struct vrf
*vrf
= NULL
;
134 /* Nothing to see, move along here */
135 if (!name
&& vrf_id
== VRF_UNKNOWN
)
138 /* attempt to find already available VRF
141 vrf
= vrf_lookup_by_name(name
);
142 if (vrf
&& vrf_id
!= VRF_UNKNOWN
143 && vrf
->vrf_id
!= VRF_UNKNOWN
144 && vrf
->vrf_id
!= vrf_id
) {
145 zlog_debug("VRF_GET: avoid %s creation(%u), same name exists (%u)",
146 name
, vrf_id
, vrf
->vrf_id
);
149 /* Try to find VRF both by ID and name */
150 if (!vrf
&& vrf_id
!= VRF_UNKNOWN
)
151 vrf
= vrf_lookup_by_id(vrf_id
);
154 vrf
= XCALLOC(MTYPE_VRF
, sizeof(struct vrf
));
155 vrf
->vrf_id
= VRF_UNKNOWN
;
160 zlog_debug("VRF(%u) %s is created.", vrf_id
,
161 (name
) ? name
: "(NULL)");
165 if (vrf_id
!= VRF_UNKNOWN
&& vrf
->vrf_id
== VRF_UNKNOWN
) {
166 vrf
->vrf_id
= vrf_id
;
167 RB_INSERT(vrf_id_head
, &vrfs_by_id
, vrf
);
171 if (name
&& vrf
->name
[0] != '\0' && strcmp(name
, vrf
->name
)) {
172 /* update the vrf name */
173 RB_REMOVE(vrf_name_head
, &vrfs_by_name
, vrf
);
174 strlcpy(vrf
->data
.l
.netns_name
,
176 strlcpy(vrf
->name
, name
, sizeof(vrf
->name
));
177 RB_INSERT(vrf_name_head
, &vrfs_by_name
, vrf
);
178 } else if (name
&& vrf
->name
[0] == '\0') {
179 strlcpy(vrf
->name
, name
, sizeof(vrf
->name
));
180 RB_INSERT(vrf_name_head
, &vrfs_by_name
, vrf
);
182 if (new &&vrf_master
.vrf_new_hook
)
183 (*vrf_master
.vrf_new_hook
)(vrf
);
188 /* Update a VRF. If not found, create one.
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.
197 struct vrf
*vrf_update(vrf_id_t new_vrf_id
, const char *name
)
199 struct vrf
*vrf
= NULL
;
201 /*Treat VRF add for existing vrf as update
202 * Update VRF ID and also update in VRF ID table
205 vrf
= vrf_lookup_by_name(name
);
206 if (vrf
&& new_vrf_id
!= VRF_UNKNOWN
&& vrf
->vrf_id
!= VRF_UNKNOWN
207 && vrf
->vrf_id
!= new_vrf_id
) {
210 "Vrf Update event: %s old id: %u, new id: %u",
211 name
, vrf
->vrf_id
, new_vrf_id
);
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
221 RB_REMOVE(vrf_id_head
, &vrfs_by_id
, vrf
);
222 vrf
->vrf_id
= new_vrf_id
;
223 RB_INSERT(vrf_id_head
, &vrfs_by_id
, vrf
);
228 * vrf_get is implied creation if it does not exist
230 vrf
= vrf_get(new_vrf_id
, name
);
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()).
238 void vrf_delete(struct vrf
*vrf
)
241 zlog_debug("VRF %s(%u) is to be deleted.", vrf
->name
,
244 if (vrf_is_enabled(vrf
))
247 if (vrf
->vrf_id
!= VRF_UNKNOWN
) {
248 RB_REMOVE(vrf_id_head
, &vrfs_by_id
, vrf
);
249 vrf
->vrf_id
= VRF_UNKNOWN
;
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.
256 if (vrf_is_user_cfged(vrf
))
259 /* Do not delete the VRF if it has interfaces configured in it. */
260 if (!RB_EMPTY(if_name_head
, &vrf
->ifaces_by_name
))
263 if (vrf_master
.vrf_delete_hook
)
264 (*vrf_master
.vrf_delete_hook
)(vrf
);
268 if (vrf
->name
[0] != '\0')
269 RB_REMOVE(vrf_name_head
, &vrfs_by_name
, vrf
);
271 XFREE(MTYPE_VRF
, vrf
);
274 /* Look up a VRF by identifier. */
275 struct vrf
*vrf_lookup_by_id(vrf_id_t vrf_id
)
279 return (RB_FIND(vrf_id_head
, &vrfs_by_id
, &vrf
));
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.
287 * RETURN: 1 - enabled successfully; otherwise, 0.
289 int vrf_enable(struct vrf
*vrf
)
291 if (vrf_is_enabled(vrf
))
295 zlog_debug("VRF %s(%u) is enabled.", vrf
->name
, vrf
->vrf_id
);
297 SET_FLAG(vrf
->status
, VRF_ACTIVE
);
299 if (vrf_master
.vrf_enable_hook
)
300 (*vrf_master
.vrf_enable_hook
)(vrf
);
303 * If we have any nexthop group entries that
304 * are awaiting vrf initialization then
305 * let's let people know about it
307 nexthop_group_enable_vrf(vrf
);
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.
317 void vrf_disable(struct vrf
*vrf
)
319 if (!vrf_is_enabled(vrf
))
322 UNSET_FLAG(vrf
->status
, VRF_ACTIVE
);
325 zlog_debug("VRF %s(%u) is to be disabled.", vrf
->name
,
328 /* Till now, nothing to be done for the default VRF. */
329 // Pending: see why this statement.
333 * When the vrf is disabled let's
334 * handle all nexthop-groups associated
337 nexthop_group_disable_vrf(vrf
);
339 if (vrf_master
.vrf_disable_hook
)
340 (*vrf_master
.vrf_disable_hook
)(vrf
);
343 const char *vrf_id_to_name(vrf_id_t vrf_id
)
347 if (vrf_id
== VRF_DEFAULT
)
348 return VRF_DEFAULT_NAME
;
350 vrf
= vrf_lookup_by_id(vrf_id
);
351 return VRF_LOGNAME(vrf
);
354 /* Look up the data pointer of the specified VRF. */
355 void *vrf_info_lookup(vrf_id_t vrf_id
)
357 struct vrf
*vrf
= vrf_lookup_by_id(vrf_id
);
358 return vrf
? vrf
->info
: NULL
;
362 * VRF hash for storing set or not.
369 static unsigned int vrf_hash_bitmap_key(const void *data
)
371 const struct vrf_bit_set
*bit
= data
;
376 static bool vrf_hash_bitmap_cmp(const void *a
, const void *b
)
378 const struct vrf_bit_set
*bit1
= a
;
379 const struct vrf_bit_set
*bit2
= b
;
381 return bit1
->vrf_id
== bit2
->vrf_id
;
384 static void *vrf_hash_bitmap_alloc(void *data
)
386 struct vrf_bit_set
*copy
= data
;
387 struct vrf_bit_set
*bit
;
389 bit
= XMALLOC(MTYPE_VRF_BITMAP
, sizeof(*bit
));
390 bit
->vrf_id
= copy
->vrf_id
;
395 static void vrf_hash_bitmap_free(void *data
)
397 struct vrf_bit_set
*bit
= data
;
399 XFREE(MTYPE_VRF_BITMAP
, bit
);
402 vrf_bitmap_t
vrf_bitmap_init(void)
404 return hash_create_size(32, vrf_hash_bitmap_key
, vrf_hash_bitmap_cmp
,
408 void vrf_bitmap_free(vrf_bitmap_t bmap
)
410 struct hash
*vrf_hash
= bmap
;
412 if (vrf_hash
== NULL
)
415 hash_clean(vrf_hash
, vrf_hash_bitmap_free
);
419 void vrf_bitmap_set(vrf_bitmap_t bmap
, vrf_id_t vrf_id
)
421 struct vrf_bit_set lookup
= { .vrf_id
= vrf_id
};
422 struct hash
*vrf_hash
= bmap
;
423 struct vrf_bit_set
*bit
;
425 if (vrf_hash
== NULL
|| vrf_id
== VRF_UNKNOWN
)
428 bit
= hash_get(vrf_hash
, &lookup
, vrf_hash_bitmap_alloc
);
432 void vrf_bitmap_unset(vrf_bitmap_t bmap
, vrf_id_t vrf_id
)
434 struct vrf_bit_set lookup
= { .vrf_id
= vrf_id
};
435 struct hash
*vrf_hash
= bmap
;
436 struct vrf_bit_set
*bit
;
438 if (vrf_hash
== NULL
|| vrf_id
== VRF_UNKNOWN
)
441 bit
= hash_get(vrf_hash
, &lookup
, vrf_hash_bitmap_alloc
);
445 int vrf_bitmap_check(vrf_bitmap_t bmap
, vrf_id_t vrf_id
)
447 struct vrf_bit_set lookup
= { .vrf_id
= vrf_id
};
448 struct hash
*vrf_hash
= bmap
;
449 struct vrf_bit_set
*bit
;
451 if (vrf_hash
== NULL
|| vrf_id
== VRF_UNKNOWN
)
454 bit
= hash_lookup(vrf_hash
, &lookup
);
461 static void vrf_autocomplete(vector comps
, struct cmd_token
*token
)
463 struct vrf
*vrf
= NULL
;
465 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
466 vector_set(comps
, XSTRDUP(MTYPE_COMPLETION
, vrf
->name
));
469 static const struct cmd_variable_handler vrf_var_handlers
[] = {
472 .completions
= vrf_autocomplete
,
475 .varname
= "vrf_name",
476 .completions
= vrf_autocomplete
,
479 .varname
= "nexthop_vrf",
480 .completions
= vrf_autocomplete
,
482 {.completions
= NULL
},
485 /* Initialize VRF module. */
486 void vrf_init(int (*create
)(struct vrf
*), int (*enable
)(struct vrf
*),
487 int (*disable
)(struct vrf
*), int (*destroy
)(struct vrf
*))
489 struct vrf
*default_vrf
;
491 /* initialise NS, in case VRF backend if NETNS */
494 zlog_debug("%s: Initializing VRF subsystem", __func__
);
496 vrf_master
.vrf_new_hook
= create
;
497 vrf_master
.vrf_enable_hook
= enable
;
498 vrf_master
.vrf_disable_hook
= disable
;
499 vrf_master
.vrf_delete_hook
= destroy
;
501 /* The default VRF always exists. */
502 default_vrf
= vrf_get(VRF_DEFAULT
, VRF_DEFAULT_NAME
);
504 flog_err(EC_LIB_VRF_START
,
505 "vrf_init: failed to create the default VRF!");
508 if (vrf_is_backend_netns()) {
511 strlcpy(default_vrf
->data
.l
.netns_name
,
512 VRF_DEFAULT_NAME
, NS_NAMSIZ
);
513 ns
= ns_lookup(NS_DEFAULT
);
514 ns
->vrf_ctxt
= default_vrf
;
515 default_vrf
->ns_ctxt
= ns
;
518 /* Enable the default VRF. */
519 if (!vrf_enable(default_vrf
)) {
520 flog_err(EC_LIB_VRF_START
,
521 "vrf_init: failed to enable the default VRF!");
525 cmd_variable_handler_register(vrf_var_handlers
);
528 static void vrf_terminate_single(struct vrf
*vrf
)
530 /* Clear configured flag and invoke delete. */
532 UNSET_FLAG(vrf
->status
, VRF_CONFIGURED
);
537 /* Terminate VRF module. */
538 void vrf_terminate(void)
540 struct vrf
*vrf
, *tmp
;
543 zlog_debug("%s: Shutting down vrf subsystem", __func__
);
545 RB_FOREACH_SAFE (vrf
, vrf_id_head
, &vrfs_by_id
, tmp
) {
546 if (vrf
->vrf_id
== VRF_DEFAULT
)
549 vrf_terminate_single(vrf
);
552 RB_FOREACH_SAFE (vrf
, vrf_name_head
, &vrfs_by_name
, tmp
) {
553 if (vrf
->vrf_id
== VRF_DEFAULT
)
556 vrf_terminate_single(vrf
);
559 /* Finally terminate default VRF */
560 vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
562 vrf_terminate_single(vrf
);
565 int vrf_socket(int domain
, int type
, int protocol
, vrf_id_t vrf_id
,
566 const char *interfacename
)
568 int ret
, save_errno
, ret2
;
570 ret
= vrf_switch_to_netns(vrf_id
);
572 flog_err_sys(EC_LIB_SOCKET
, "%s: Can't switch to VRF %u (%s)",
573 __func__
, vrf_id
, safe_strerror(errno
));
575 ret
= socket(domain
, type
, protocol
);
577 ret2
= vrf_switchback_to_initial();
579 flog_err_sys(EC_LIB_SOCKET
,
580 "%s: Can't switchback from VRF %u (%s)", __func__
,
581 vrf_id
, safe_strerror(errno
));
585 ret2
= vrf_bind(vrf_id
, ret
, interfacename
);
593 int vrf_is_backend_netns(void)
595 return (vrf_backend
== VRF_BACKEND_NETNS
);
598 int vrf_get_backend(void)
600 if (!vrf_backend_configured
)
601 return VRF_BACKEND_UNKNOWN
;
605 int vrf_configure_backend(enum vrf_backend_type backend
)
607 /* Work around issue in old gcc */
609 case VRF_BACKEND_UNKNOWN
:
610 case VRF_BACKEND_NETNS
:
611 case VRF_BACKEND_VRF_LITE
:
613 case VRF_BACKEND_MAX
:
617 vrf_backend
= backend
;
618 vrf_backend_configured
= 1;
623 /* vrf CLI commands */
627 "Exit current mode and down to previous mode\n")
633 DEFUN_YANG_NOSH (vrf
,
636 "Select a VRF to configure\n"
640 const char *vrfname
= argv
[idx_name
]->arg
;
641 char xpath_list
[XPATH_MAXLEN
];
645 if (strlen(vrfname
) > VRF_NAMSIZ
) {
647 "%% VRF name %s invalid: length exceeds %d bytes\n",
648 vrfname
, VRF_NAMSIZ
);
649 return CMD_WARNING_CONFIG_FAILED
;
652 snprintf(xpath_list
, sizeof(xpath_list
), FRR_VRF_KEY_XPATH
, vrfname
);
654 nb_cli_enqueue_change(vty
, xpath_list
, NB_OP_CREATE
, NULL
);
655 ret
= nb_cli_apply_changes_clear_pending(vty
, "%s", xpath_list
);
656 if (ret
== CMD_SUCCESS
) {
657 VTY_PUSH_XPATH(VRF_NODE
, xpath_list
);
658 vrf
= vrf_lookup_by_name(vrfname
);
660 VTY_PUSH_CONTEXT(VRF_NODE
, vrf
);
670 "Delete a pseudo VRF's configuration\n"
673 const char *vrfname
= argv
[2]->arg
;
674 char xpath_list
[XPATH_MAXLEN
];
678 vrfp
= vrf_lookup_by_name(vrfname
);
683 if (CHECK_FLAG(vrfp
->status
, VRF_ACTIVE
)) {
684 vty_out(vty
, "%% Only inactive VRFs can be deleted\n");
685 return CMD_WARNING_CONFIG_FAILED
;
688 if (vrf_get_backend() == VRF_BACKEND_VRF_LITE
) {
690 * Remove the VRF interface config when removing the VRF.
692 snprintf(xpath_list
, sizeof(xpath_list
),
693 "/frr-interface:lib/interface[name='%s']", vrfname
);
694 nb_cli_enqueue_change(vty
, xpath_list
, NB_OP_DESTROY
, NULL
);
697 snprintf(xpath_list
, sizeof(xpath_list
), FRR_VRF_KEY_XPATH
, vrfname
);
699 nb_cli_enqueue_change(vty
, xpath_list
, NB_OP_DESTROY
, NULL
);
700 return nb_cli_apply_changes(vty
, NULL
);
704 static struct cmd_node vrf_node
= {
707 .parent_node
= CONFIG_NODE
,
708 .prompt
= "%s(config-vrf)# ",
712 * Debug CLI for vrf's
737 static int vrf_write_host(struct vty
*vty
)
740 vty_out(vty
, "debug vrf\n");
745 static int vrf_write_host(struct vty
*vty
);
746 static struct cmd_node vrf_debug_node
= {
748 .node
= VRF_DEBUG_NODE
,
750 .config_write
= vrf_write_host
,
753 void vrf_install_commands(void)
755 install_node(&vrf_debug_node
);
757 install_element(CONFIG_NODE
, &vrf_debug_cmd
);
758 install_element(ENABLE_NODE
, &vrf_debug_cmd
);
759 install_element(CONFIG_NODE
, &no_vrf_debug_cmd
);
760 install_element(ENABLE_NODE
, &no_vrf_debug_cmd
);
763 void vrf_cmd_init(int (*writefunc
)(struct vty
*vty
))
765 install_element(CONFIG_NODE
, &vrf_cmd
);
766 install_element(CONFIG_NODE
, &no_vrf_cmd
);
767 vrf_node
.config_write
= writefunc
;
768 install_node(&vrf_node
);
769 install_default(VRF_NODE
);
770 install_element(VRF_NODE
, &vrf_exit_cmd
);
773 void vrf_set_default_name(const char *default_name
)
775 snprintf(vrf_default_name
, VRF_NAMSIZ
, "%s", default_name
);
778 const char *vrf_get_default_name(void)
780 return vrf_default_name
;
783 int vrf_bind(vrf_id_t vrf_id
, int fd
, const char *ifname
)
786 struct interface
*ifp
;
792 if (vrf_id
== VRF_UNKNOWN
)
795 /* can't bind to a VRF that doesn't exist */
796 vrf
= vrf_lookup_by_id(vrf_id
);
797 if (!vrf_is_enabled(vrf
))
800 if (ifname
&& strcmp(ifname
, vrf
->name
)) {
801 /* binding to a regular interface */
803 /* can't bind to an interface that doesn't exist */
804 ifp
= if_lookup_by_name(ifname
, vrf_id
);
808 /* binding to a VRF device */
810 /* nothing to do for netns */
811 if (vrf_is_backend_netns())
814 /* nothing to do for default vrf */
815 if (vrf_id
== VRF_DEFAULT
)
821 #ifdef SO_BINDTODEVICE
822 ret
= setsockopt(fd
, SOL_SOCKET
, SO_BINDTODEVICE
, ifname
,
825 zlog_err("bind to interface %s failed, errno=%d", ifname
,
827 #endif /* SO_BINDTODEVICE */
830 int vrf_getaddrinfo(const char *node
, const char *service
,
831 const struct addrinfo
*hints
, struct addrinfo
**res
,
834 int ret
, ret2
, save_errno
;
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
));
840 ret
= getaddrinfo(node
, service
, hints
, res
);
842 ret2
= vrf_switchback_to_initial();
844 flog_err_sys(EC_LIB_SOCKET
,
845 "%s: Can't switchback from VRF %u (%s)", __func__
,
846 vrf_id
, safe_strerror(errno
));
851 int vrf_ioctl(vrf_id_t vrf_id
, int d
, unsigned long request
, char *params
)
853 int ret
, saved_errno
, rc
;
855 ret
= vrf_switch_to_netns(vrf_id
);
857 flog_err_sys(EC_LIB_SOCKET
, "%s: Can't switch to VRF %u (%s)",
858 __func__
, vrf_id
, safe_strerror(errno
));
861 rc
= ioctl(d
, request
, params
);
863 ret
= vrf_switchback_to_initial();
865 flog_err_sys(EC_LIB_SOCKET
,
866 "%s: Can't switchback from VRF %u (%s)", __func__
,
867 vrf_id
, safe_strerror(errno
));
872 int vrf_sockunion_socket(const union sockunion
*su
, vrf_id_t vrf_id
,
873 const char *interfacename
)
875 int ret
, save_errno
, ret2
;
877 ret
= vrf_switch_to_netns(vrf_id
);
879 flog_err_sys(EC_LIB_SOCKET
, "%s: Can't switch to VRF %u (%s)",
880 __func__
, vrf_id
, safe_strerror(errno
));
881 ret
= sockunion_socket(su
);
883 ret2
= vrf_switchback_to_initial();
885 flog_err_sys(EC_LIB_SOCKET
,
886 "%s: Can't switchback from VRF %u (%s)", __func__
,
887 vrf_id
, safe_strerror(errno
));
892 ret2
= vrf_bind(vrf_id
, ret
, interfacename
);
900 /* ------- Northbound callbacks ------- */
903 * XPath: /frr-vrf:lib/vrf
905 static int lib_vrf_create(struct nb_cb_create_args
*args
)
910 vrfname
= yang_dnode_get_string(args
->dnode
, "./name");
912 if (args
->event
!= NB_EV_APPLY
)
915 vrfp
= vrf_get(VRF_UNKNOWN
, vrfname
);
917 SET_FLAG(vrfp
->status
, VRF_CONFIGURED
);
918 nb_running_set_entry(args
->dnode
, vrfp
);
923 static int lib_vrf_destroy(struct nb_cb_destroy_args
*args
)
927 switch (args
->event
) {
929 vrfp
= nb_running_get_entry(args
->dnode
, NULL
, true);
930 if (CHECK_FLAG(vrfp
->status
, VRF_ACTIVE
)) {
931 snprintf(args
->errmsg
, args
->errmsg_len
,
932 "Only inactive VRFs can be deleted");
933 return NB_ERR_VALIDATION
;
940 vrfp
= nb_running_unset_entry(args
->dnode
);
942 /* Clear configured flag and invoke delete. */
943 UNSET_FLAG(vrfp
->status
, VRF_CONFIGURED
);
951 static const void *lib_vrf_get_next(struct nb_cb_get_next_args
*args
)
953 struct vrf
*vrfp
= (struct vrf
*)args
->list_entry
;
955 if (args
->list_entry
== NULL
) {
956 vrfp
= RB_MIN(vrf_name_head
, &vrfs_by_name
);
958 vrfp
= RB_NEXT(vrf_name_head
, vrfp
);
964 static int lib_vrf_get_keys(struct nb_cb_get_keys_args
*args
)
966 struct vrf
*vrfp
= (struct vrf
*)args
->list_entry
;
969 strlcpy(args
->keys
->key
[0], vrfp
->name
, sizeof(args
->keys
->key
[0]));
974 static const void *lib_vrf_lookup_entry(struct nb_cb_lookup_entry_args
*args
)
976 const char *vrfname
= args
->keys
->key
[0];
978 struct vrf
*vrf
= vrf_lookup_by_name(vrfname
);
984 * XPath: /frr-vrf:lib/vrf/id
986 static struct yang_data
*
987 lib_vrf_state_id_get_elem(struct nb_cb_get_elem_args
*args
)
989 struct vrf
*vrfp
= (struct vrf
*)args
->list_entry
;
991 return yang_data_new_uint32(args
->xpath
, vrfp
->vrf_id
);
995 * XPath: /frr-vrf:lib/vrf/active
997 static struct yang_data
*
998 lib_vrf_state_active_get_elem(struct nb_cb_get_elem_args
*args
)
1000 struct vrf
*vrfp
= (struct vrf
*)args
->list_entry
;
1002 if (vrfp
->status
== VRF_ACTIVE
)
1003 return yang_data_new_bool(args
->xpath
, true);
1008 /* clang-format off */
1009 const struct frr_yang_module_info frr_vrf_info
= {
1013 .xpath
= "/frr-vrf:lib/vrf",
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
,
1021 .priority
= NB_DFLT_PRIORITY
- 2,
1024 .xpath
= "/frr-vrf:lib/vrf/state/id",
1026 .get_elem
= lib_vrf_state_id_get_elem
,
1030 .xpath
= "/frr-vrf:lib/vrf/state/active",
1032 .get_elem
= lib_vrf_state_active_get_elem
,