// SPDX-License-Identifier: GPL-2.0-or-later /* * VRF related header. * Copyright (C) 2014 6WIND S.A. */ #ifndef _ZEBRA_VRF_H #define _ZEBRA_VRF_H #include "openbsd-tree.h" #include "linklist.h" #include "qobj.h" #include "vty.h" #include "ns.h" #ifdef __cplusplus extern "C" { #endif /* The default VRF ID */ #define VRF_UNKNOWN UINT32_MAX /* Pending: May need to refine this. */ #ifndef IFLA_VRF_MAX enum { IFLA_VRF_UNSPEC, IFLA_VRF_TABLE, __IFLA_VRF_MAX }; #define IFLA_VRF_MAX (__IFLA_VRF_MAX - 1) #endif #define VRF_NAMSIZ 36 #define NS_NAMSIZ 36 /* * The command strings */ #define VRF_CMD_HELP_STR "Specify the VRF\nThe VRF name\n" #define VRF_ALL_CMD_HELP_STR "Specify the VRF\nAll VRFs\n" #define VRF_FULL_CMD_HELP_STR "Specify the VRF\nThe VRF name\nAll VRFs\n" #define FRR_VRF_XPATH "/frr-vrf:lib/vrf" #define FRR_VRF_KEY_XPATH "/frr-vrf:lib/vrf[name='%s']" /* * Pass some OS specific data up through * to the daemons */ struct vrf_data { union { struct { uint32_t table_id; char netns_name[NS_NAMSIZ]; } l; }; }; struct vrf { RB_ENTRY(vrf) id_entry, name_entry; /* Identifier, same as the vector index */ vrf_id_t vrf_id; /* Name */ char name[VRF_NAMSIZ + 1]; /* Zebra internal VRF status */ uint8_t status; #define VRF_ACTIVE (1 << 0) /* VRF is up in kernel */ #define VRF_CONFIGURED (1 << 1) /* VRF has some FRR configuration */ /* Interfaces belonging to this VRF */ struct if_name_head ifaces_by_name; struct if_index_head ifaces_by_index; /* User data */ void *info; /* The table_id from the kernel */ struct vrf_data data; /* Back pointer to namespace context */ void *ns_ctxt; QOBJ_FIELDS; }; RB_HEAD(vrf_id_head, vrf); RB_PROTOTYPE(vrf_id_head, vrf, id_entry, vrf_id_compare) RB_HEAD(vrf_name_head, vrf); RB_PROTOTYPE(vrf_name_head, vrf, name_entry, vrf_name_compare) DECLARE_QOBJ_TYPE(vrf); /* Allow VRF with netns as backend */ enum vrf_backend_type { VRF_BACKEND_VRF_LITE, VRF_BACKEND_NETNS, VRF_BACKEND_UNKNOWN, VRF_BACKEND_MAX, }; extern struct vrf_id_head vrfs_by_id; extern struct vrf_name_head vrfs_by_name; extern struct vrf *vrf_lookup_by_id(vrf_id_t); extern struct vrf *vrf_lookup_by_name(const char *); extern struct vrf *vrf_get(vrf_id_t, const char *); extern struct vrf *vrf_update(vrf_id_t new_vrf_id, const char *name); extern const char *vrf_id_to_name(vrf_id_t vrf_id); #define VRF_LOGNAME(V) V ? V->name : "Unknown" #define VRF_GET_ID(V, NAME, USE_JSON) \ do { \ struct vrf *_vrf; \ if (!(_vrf = vrf_lookup_by_name(NAME))) { \ if (USE_JSON) { \ vty_out(vty, "{}\n"); \ } else { \ vty_out(vty, "%% VRF %s not found\n", NAME); \ } \ return CMD_WARNING; \ } \ if (_vrf->vrf_id == VRF_UNKNOWN) { \ if (USE_JSON) { \ vty_out(vty, "{}\n"); \ } else { \ vty_out(vty, "%% VRF %s not active\n", NAME); \ } \ return CMD_WARNING; \ } \ (V) = _vrf->vrf_id; \ } while (0) /* * Check whether the VRF is enabled. */ static inline int vrf_is_enabled(struct vrf *vrf) { return vrf && CHECK_FLAG(vrf->status, VRF_ACTIVE); } /* check if the vrf is user configured */ static inline int vrf_is_user_cfged(struct vrf *vrf) { return vrf && CHECK_FLAG(vrf->status, VRF_CONFIGURED); } static inline uint32_t vrf_interface_count(struct vrf *vrf) { uint32_t count = 0; struct interface *ifp; RB_FOREACH (ifp, if_name_head, &vrf->ifaces_by_name) { /* skip the l3mdev */ if (strncmp(ifp->name, vrf->name, VRF_NAMSIZ) == 0) continue; count++; } return count; } /* * Utilities to obtain the user data */ /* Look up the data pointer of the specified VRF. */ extern void *vrf_info_lookup(vrf_id_t); /* * VRF bit-map: maintaining flags, one bit per VRF ID */ typedef void *vrf_bitmap_t; #define VRF_BITMAP_NULL NULL extern void vrf_bitmap_init(vrf_bitmap_t *pbmap); extern void vrf_bitmap_free(vrf_bitmap_t *pbmap); extern void vrf_bitmap_set(vrf_bitmap_t *pbmap, vrf_id_t vrf_id); extern void vrf_bitmap_unset(vrf_bitmap_t *pbmap, vrf_id_t vrf_id); extern int vrf_bitmap_check(vrf_bitmap_t *pbmap, vrf_id_t vrf_id); /* * VRF initializer/destructor * * create -> Called back when a new VRF is created. This * can be either through these 3 options: * 1) CLI mentions a vrf before OS knows about it * 2) OS calls zebra and we create the vrf from OS * callback * 3) zebra calls individual protocols to notify * about the new vrf * * enable -> Called back when a VRF is actually usable from * an OS perspective ( 2 and 3 above ) * * disable -> Called back when a VRF is being deleted from * the system ( 2 and 3 ) above * * delete -> Called back when a vrf is being deleted from * the system ( 2 and 3 ) above. */ extern void vrf_init(int (*create)(struct vrf *vrf), int (*enable)(struct vrf *vrf), int (*disable)(struct vrf *vrf), int (*destroy)(struct vrf *vrf)); /* * Iterate over custom VRFs and round up by processing the default VRF. */ typedef void (*vrf_iter_func)(struct vrf *vrf); extern void vrf_iterate(vrf_iter_func fnc); /* * Call vrf_terminate when the protocol is being shutdown */ extern void vrf_terminate(void); /* * Utilities to create networks objects, * or call network operations */ /* * Create a new socket associated with a VRF. * * This is a wrapper that ensures correct behavior when using namespace VRFs. * In the namespace case, the socket is created within the namespace. In the * non-namespace case, this is equivalent to socket(). * * If name is provided, this is provided to vrf_bind() to bind the socket to * the VRF. This is only relevant when using VRF-lite. * * Summary: * - Namespace: pass vrf_id but not name * - VRF-lite: pass vrf_id and name of VRF device to bind to * - VRF-lite, no binding: pass vrf_id but not name, or just use socket() */ extern int vrf_socket(int domain, int type, int protocol, vrf_id_t vrf_id, const char *name); extern int vrf_sockunion_socket(const union sockunion *su, vrf_id_t vrf_id, const char *name); /* * Binds a socket to an interface (ifname) in a VRF (vrf_id). * * If ifname is NULL or is equal to the VRF name then bind to a VRF device. * Otherwise, bind to the specified interface in the specified VRF. * * Returns 0 on success and -1 on failure. */ extern int vrf_bind(vrf_id_t vrf_id, int fd, const char *ifname); /* VRF ioctl operations */ extern int vrf_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res, vrf_id_t vrf_id); extern int vrf_ioctl(vrf_id_t vrf_id, int d, unsigned long request, char *args); /* The default VRF ID */ #define VRF_DEFAULT 0 /* Must be called only during startup, before config is read */ extern void vrf_set_default_name(const char *default_name); extern const char *vrf_get_default_name(void); #define VRF_DEFAULT_NAME vrf_get_default_name() /* VRF switch from NETNS */ extern int vrf_switch_to_netns(vrf_id_t vrf_id); extern int vrf_switchback_to_initial(void); /* * VRF backend routines * should be called from zebra only */ /* VRF vty command initialisation */ extern void vrf_cmd_init(int (*writefunc)(struct vty *vty)); /* VRF vty debugging */ extern void vrf_install_commands(void); /* * VRF utilities */ /* * API for configuring VRF backend */ extern int vrf_configure_backend(enum vrf_backend_type backend); extern int vrf_get_backend(void); extern int vrf_is_backend_netns(void); /* used internally to enable or disable VRF. * Notify a change in the VRF ID of the VRF */ extern void vrf_disable(struct vrf *vrf); extern int vrf_enable(struct vrf *vrf); extern void vrf_delete(struct vrf *vrf); extern const struct frr_yang_module_info frr_vrf_info; extern const struct frr_yang_module_info frr_vrf_cli_info; #ifdef __cplusplus } #endif #endif /*_ZEBRA_VRF_H*/