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. */
531 UNSET_FLAG(vrf
->status
, VRF_CONFIGURED
);
536 /* Terminate VRF module. */
537 void vrf_terminate(void)
539 struct vrf
*vrf
, *tmp
;
542 zlog_debug("%s: Shutting down vrf subsystem", __func__
);
544 RB_FOREACH_SAFE (vrf
, vrf_id_head
, &vrfs_by_id
, tmp
) {
545 if (vrf
->vrf_id
== VRF_DEFAULT
)
548 vrf_terminate_single(vrf
);
551 RB_FOREACH_SAFE (vrf
, vrf_name_head
, &vrfs_by_name
, tmp
) {
552 if (vrf
->vrf_id
== VRF_DEFAULT
)
555 vrf_terminate_single(vrf
);
558 /* Finally terminate default VRF */
559 vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
560 vrf_terminate_single(vrf
);
563 int vrf_socket(int domain
, int type
, int protocol
, vrf_id_t vrf_id
,
564 const char *interfacename
)
566 int ret
, save_errno
, ret2
;
568 ret
= vrf_switch_to_netns(vrf_id
);
570 flog_err_sys(EC_LIB_SOCKET
, "%s: Can't switch to VRF %u (%s)",
571 __func__
, vrf_id
, safe_strerror(errno
));
573 ret
= socket(domain
, type
, protocol
);
575 ret2
= vrf_switchback_to_initial();
577 flog_err_sys(EC_LIB_SOCKET
,
578 "%s: Can't switchback from VRF %u (%s)", __func__
,
579 vrf_id
, safe_strerror(errno
));
583 ret2
= vrf_bind(vrf_id
, ret
, interfacename
);
591 int vrf_is_backend_netns(void)
593 return (vrf_backend
== VRF_BACKEND_NETNS
);
596 int vrf_get_backend(void)
598 if (!vrf_backend_configured
)
599 return VRF_BACKEND_UNKNOWN
;
603 int vrf_configure_backend(enum vrf_backend_type backend
)
605 /* Work around issue in old gcc */
607 case VRF_BACKEND_UNKNOWN
:
608 case VRF_BACKEND_NETNS
:
609 case VRF_BACKEND_VRF_LITE
:
615 vrf_backend
= backend
;
616 vrf_backend_configured
= 1;
621 /* vrf CLI commands */
625 "Exit current mode and down to previous mode\n")
631 DEFUN_YANG_NOSH (vrf
,
634 "Select a VRF to configure\n"
638 const char *vrfname
= argv
[idx_name
]->arg
;
639 char xpath_list
[XPATH_MAXLEN
];
643 if (strlen(vrfname
) > VRF_NAMSIZ
) {
645 "%% VRF name %s invalid: length exceeds %d bytes\n",
646 vrfname
, VRF_NAMSIZ
);
647 return CMD_WARNING_CONFIG_FAILED
;
650 snprintf(xpath_list
, sizeof(xpath_list
), FRR_VRF_KEY_XPATH
, vrfname
);
652 nb_cli_enqueue_change(vty
, xpath_list
, NB_OP_CREATE
, NULL
);
653 ret
= nb_cli_apply_changes_clear_pending(vty
, xpath_list
);
654 if (ret
== CMD_SUCCESS
) {
655 VTY_PUSH_XPATH(VRF_NODE
, xpath_list
);
656 vrf
= vrf_lookup_by_name(vrfname
);
658 VTY_PUSH_CONTEXT(VRF_NODE
, vrf
);
668 "Delete a pseudo VRF's configuration\n"
671 const char *vrfname
= argv
[2]->arg
;
672 char xpath_list
[XPATH_MAXLEN
];
676 vrfp
= vrf_lookup_by_name(vrfname
);
681 if (CHECK_FLAG(vrfp
->status
, VRF_ACTIVE
)) {
682 vty_out(vty
, "%% Only inactive VRFs can be deleted\n");
683 return CMD_WARNING_CONFIG_FAILED
;
686 if (vrf_get_backend() == VRF_BACKEND_VRF_LITE
) {
688 * Remove the VRF interface config when removing the VRF.
690 snprintf(xpath_list
, sizeof(xpath_list
),
691 "/frr-interface:lib/interface[name='%s']", vrfname
);
692 nb_cli_enqueue_change(vty
, xpath_list
, NB_OP_DESTROY
, NULL
);
695 snprintf(xpath_list
, sizeof(xpath_list
), FRR_VRF_KEY_XPATH
, vrfname
);
697 nb_cli_enqueue_change(vty
, xpath_list
, NB_OP_DESTROY
, NULL
);
698 return nb_cli_apply_changes(vty
, NULL
);
702 static struct cmd_node vrf_node
= {
705 .parent_node
= CONFIG_NODE
,
706 .prompt
= "%s(config-vrf)# ",
710 * Debug CLI for vrf's
735 static int vrf_write_host(struct vty
*vty
)
738 vty_out(vty
, "debug vrf\n");
743 static int vrf_write_host(struct vty
*vty
);
744 static struct cmd_node vrf_debug_node
= {
746 .node
= VRF_DEBUG_NODE
,
748 .config_write
= vrf_write_host
,
751 void vrf_install_commands(void)
753 install_node(&vrf_debug_node
);
755 install_element(CONFIG_NODE
, &vrf_debug_cmd
);
756 install_element(ENABLE_NODE
, &vrf_debug_cmd
);
757 install_element(CONFIG_NODE
, &no_vrf_debug_cmd
);
758 install_element(ENABLE_NODE
, &no_vrf_debug_cmd
);
761 void vrf_cmd_init(int (*writefunc
)(struct vty
*vty
))
763 install_element(CONFIG_NODE
, &vrf_cmd
);
764 install_element(CONFIG_NODE
, &no_vrf_cmd
);
765 vrf_node
.config_write
= writefunc
;
766 install_node(&vrf_node
);
767 install_default(VRF_NODE
);
768 install_element(VRF_NODE
, &vrf_exit_cmd
);
771 void vrf_set_default_name(const char *default_name
)
773 snprintf(vrf_default_name
, VRF_NAMSIZ
, "%s", default_name
);
776 const char *vrf_get_default_name(void)
778 return vrf_default_name
;
781 int vrf_bind(vrf_id_t vrf_id
, int fd
, const char *ifname
)
784 struct interface
*ifp
;
790 if (vrf_id
== VRF_UNKNOWN
)
793 /* can't bind to a VRF that doesn't exist */
794 vrf
= vrf_lookup_by_id(vrf_id
);
795 if (!vrf_is_enabled(vrf
))
798 if (ifname
&& strcmp(ifname
, vrf
->name
)) {
799 /* binding to a regular interface */
801 /* can't bind to an interface that doesn't exist */
802 ifp
= if_lookup_by_name(ifname
, vrf_id
);
806 /* binding to a VRF device */
808 /* nothing to do for netns */
809 if (vrf_is_backend_netns())
812 /* nothing to do for default vrf */
813 if (vrf_id
== VRF_DEFAULT
)
819 #ifdef SO_BINDTODEVICE
820 ret
= setsockopt(fd
, SOL_SOCKET
, SO_BINDTODEVICE
, ifname
,
823 zlog_err("bind to interface %s failed, errno=%d", ifname
,
825 #endif /* SO_BINDTODEVICE */
828 int vrf_getaddrinfo(const char *node
, const char *service
,
829 const struct addrinfo
*hints
, struct addrinfo
**res
,
832 int ret
, ret2
, save_errno
;
834 ret
= vrf_switch_to_netns(vrf_id
);
836 flog_err_sys(EC_LIB_SOCKET
, "%s: Can't switch to VRF %u (%s)",
837 __func__
, vrf_id
, safe_strerror(errno
));
838 ret
= getaddrinfo(node
, service
, hints
, res
);
840 ret2
= vrf_switchback_to_initial();
842 flog_err_sys(EC_LIB_SOCKET
,
843 "%s: Can't switchback from VRF %u (%s)", __func__
,
844 vrf_id
, safe_strerror(errno
));
849 int vrf_ioctl(vrf_id_t vrf_id
, int d
, unsigned long request
, char *params
)
851 int ret
, saved_errno
, rc
;
853 ret
= vrf_switch_to_netns(vrf_id
);
855 flog_err_sys(EC_LIB_SOCKET
, "%s: Can't switch to VRF %u (%s)",
856 __func__
, vrf_id
, safe_strerror(errno
));
859 rc
= ioctl(d
, request
, params
);
861 ret
= vrf_switchback_to_initial();
863 flog_err_sys(EC_LIB_SOCKET
,
864 "%s: Can't switchback from VRF %u (%s)", __func__
,
865 vrf_id
, safe_strerror(errno
));
870 int vrf_sockunion_socket(const union sockunion
*su
, vrf_id_t vrf_id
,
871 const char *interfacename
)
873 int ret
, save_errno
, ret2
;
875 ret
= vrf_switch_to_netns(vrf_id
);
877 flog_err_sys(EC_LIB_SOCKET
, "%s: Can't switch to VRF %u (%s)",
878 __func__
, vrf_id
, safe_strerror(errno
));
879 ret
= sockunion_socket(su
);
881 ret2
= vrf_switchback_to_initial();
883 flog_err_sys(EC_LIB_SOCKET
,
884 "%s: Can't switchback from VRF %u (%s)", __func__
,
885 vrf_id
, safe_strerror(errno
));
890 ret2
= vrf_bind(vrf_id
, ret
, interfacename
);
898 /* ------- Northbound callbacks ------- */
901 * XPath: /frr-vrf:lib/vrf
903 static int lib_vrf_create(struct nb_cb_create_args
*args
)
908 vrfname
= yang_dnode_get_string(args
->dnode
, "./name");
910 if (args
->event
!= NB_EV_APPLY
)
913 vrfp
= vrf_get(VRF_UNKNOWN
, vrfname
);
915 SET_FLAG(vrfp
->status
, VRF_CONFIGURED
);
916 nb_running_set_entry(args
->dnode
, vrfp
);
921 static int lib_vrf_destroy(struct nb_cb_destroy_args
*args
)
925 switch (args
->event
) {
927 vrfp
= nb_running_get_entry(args
->dnode
, NULL
, true);
928 if (CHECK_FLAG(vrfp
->status
, VRF_ACTIVE
)) {
929 snprintf(args
->errmsg
, args
->errmsg_len
,
930 "Only inactive VRFs can be deleted");
931 return NB_ERR_VALIDATION
;
938 vrfp
= nb_running_unset_entry(args
->dnode
);
940 /* Clear configured flag and invoke delete. */
941 UNSET_FLAG(vrfp
->status
, VRF_CONFIGURED
);
949 static const void *lib_vrf_get_next(struct nb_cb_get_next_args
*args
)
951 struct vrf
*vrfp
= (struct vrf
*)args
->list_entry
;
953 if (args
->list_entry
== NULL
) {
954 vrfp
= RB_MIN(vrf_name_head
, &vrfs_by_name
);
956 vrfp
= RB_NEXT(vrf_name_head
, vrfp
);
962 static int lib_vrf_get_keys(struct nb_cb_get_keys_args
*args
)
964 struct vrf
*vrfp
= (struct vrf
*)args
->list_entry
;
967 strlcpy(args
->keys
->key
[0], vrfp
->name
, sizeof(args
->keys
->key
[0]));
972 static const void *lib_vrf_lookup_entry(struct nb_cb_lookup_entry_args
*args
)
974 const char *vrfname
= args
->keys
->key
[0];
976 struct vrf
*vrf
= vrf_lookup_by_name(vrfname
);
982 * XPath: /frr-vrf:lib/vrf/id
984 static struct yang_data
*
985 lib_vrf_state_id_get_elem(struct nb_cb_get_elem_args
*args
)
987 struct vrf
*vrfp
= (struct vrf
*)args
->list_entry
;
989 return yang_data_new_uint32(args
->xpath
, vrfp
->vrf_id
);
993 * XPath: /frr-vrf:lib/vrf/active
995 static struct yang_data
*
996 lib_vrf_state_active_get_elem(struct nb_cb_get_elem_args
*args
)
998 struct vrf
*vrfp
= (struct vrf
*)args
->list_entry
;
1000 if (vrfp
->status
== VRF_ACTIVE
)
1001 return yang_data_new_bool(
1002 args
->xpath
, vrfp
->status
== VRF_ACTIVE
? true : false);
1007 /* clang-format off */
1008 const struct frr_yang_module_info frr_vrf_info
= {
1012 .xpath
= "/frr-vrf:lib/vrf",
1014 .create
= lib_vrf_create
,
1015 .destroy
= lib_vrf_destroy
,
1016 .get_next
= lib_vrf_get_next
,
1017 .get_keys
= lib_vrf_get_keys
,
1018 .lookup_entry
= lib_vrf_lookup_entry
,
1020 .priority
= NB_DFLT_PRIORITY
- 2,
1023 .xpath
= "/frr-vrf:lib/vrf/state/id",
1025 .get_elem
= lib_vrf_state_id_get_elem
,
1029 .xpath
= "/frr-vrf:lib/vrf/state/active",
1031 .get_elem
= lib_vrf_state_active_get_elem
,