mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-15 07:15:19 +00:00
lib: externalise vrf and ns creation
In addition to have the possibility to create from vty vrf based on a netns backend, the API will be made accessible from external, especially for zebra that will handle the netns discovery part. This commit is externalising following functions: - netns_pathname - ns_handler_create - vrf_handler_create Also, the VRF initialisation case when under NETNS backend is changed, since the NS identifier may not be known at the configuration time,but may be known later, under discovery process. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
parent
fbb65ff504
commit
697d3ec731
89
lib/ns.c
89
lib/ns.c
@ -236,6 +236,7 @@ static int ns_is_enabled(struct ns *ns)
|
|||||||
*/
|
*/
|
||||||
static int ns_enable(struct ns *ns)
|
static int ns_enable(struct ns *ns)
|
||||||
{
|
{
|
||||||
|
int vrf_on = 0;
|
||||||
|
|
||||||
if (!ns_is_enabled(ns)) {
|
if (!ns_is_enabled(ns)) {
|
||||||
if (have_netns()) {
|
if (have_netns()) {
|
||||||
@ -252,13 +253,26 @@ static int ns_enable(struct ns *ns)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Non default NS. leave */
|
||||||
|
if (ns->ns_id == NS_UNKNOWN) {
|
||||||
|
zlog_err("Can not enable NS %s %u: Invalid NSID",
|
||||||
|
ns->name, ns->ns_id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
vrf_on = vrf_update_vrf_id((vrf_id_t)ns->ns_id,
|
||||||
|
(struct vrf *)ns->vrf_ctxt);
|
||||||
if (have_netns())
|
if (have_netns())
|
||||||
zlog_info("NS %u is associated with NETNS %s.",
|
zlog_info("NS %u is associated with NETNS %s.",
|
||||||
ns->ns_id, ns->name);
|
ns->ns_id, ns->name);
|
||||||
|
|
||||||
zlog_info("NS %u is enabled.", ns->ns_id);
|
zlog_info("NS %u is enabled.", ns->ns_id);
|
||||||
|
/* zebra first receives NS enable event,
|
||||||
|
* then VRF enable event
|
||||||
|
*/
|
||||||
if (ns_master.ns_enable_hook)
|
if (ns_master.ns_enable_hook)
|
||||||
(*ns_master.ns_enable_hook)(ns->ns_id, &ns->info);
|
(*ns_master.ns_enable_hook)(ns->ns_id, &ns->info);
|
||||||
|
if (vrf_on == 1)
|
||||||
|
vrf_enable((struct vrf *)ns->vrf_ctxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -310,7 +324,7 @@ void ns_add_hook(int type, int (*func)(ns_id_t, void **))
|
|||||||
* NS realization with NETNS
|
* NS realization with NETNS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static char *ns_netns_pathname(struct vty *vty, const char *name)
|
char *ns_netns_pathname(struct vty *vty, const char *name)
|
||||||
{
|
{
|
||||||
static char pathname[PATH_MAX];
|
static char pathname[PATH_MAX];
|
||||||
char *result;
|
char *result;
|
||||||
@ -325,7 +339,9 @@ static char *ns_netns_pathname(struct vty *vty, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
vty_out(vty, "Invalid pathname: %s\n", safe_strerror(errno));
|
if (vty)
|
||||||
|
vty_out(vty, "Invalid pathname: %s\n",
|
||||||
|
safe_strerror(errno));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return pathname;
|
return pathname;
|
||||||
@ -413,34 +429,34 @@ DEFUN (no_ns_logicalrouter,
|
|||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN_NOSH (ns_netns,
|
int ns_handler_create(struct vty *vty, struct vrf *vrf,
|
||||||
ns_netns_cmd,
|
char *pathname, ns_id_t ns_id)
|
||||||
"netns NAME",
|
|
||||||
"Attach VRF to a Namespace\n"
|
|
||||||
"The file name in " NS_RUN_DIR ", or a full pathname\n")
|
|
||||||
{
|
{
|
||||||
int idx_name = 1;
|
|
||||||
struct ns *ns = NULL;
|
struct ns *ns = NULL;
|
||||||
char *pathname = ns_netns_pathname(vty, argv[idx_name]->arg);
|
|
||||||
|
|
||||||
VTY_DECLVAR_CONTEXT(vrf, vrf);
|
|
||||||
|
|
||||||
if (!pathname)
|
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
|
||||||
|
|
||||||
if (!vrf)
|
if (!vrf)
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
if (vrf->vrf_id != VRF_UNKNOWN && vrf->ns_ctxt == NULL) {
|
if (vrf->vrf_id != VRF_UNKNOWN && vrf->ns_ctxt == NULL) {
|
||||||
vty_out(vty, "VRF %u is already configured with VRF %s\n",
|
if (vty)
|
||||||
|
vty_out(vty,
|
||||||
|
"VRF %u is already configured with VRF %s\n",
|
||||||
|
vrf->vrf_id, vrf->name);
|
||||||
|
else
|
||||||
|
zlog_warn("VRF %u is already configured with VRF %s\n",
|
||||||
vrf->vrf_id, vrf->name);
|
vrf->vrf_id, vrf->name);
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
}
|
}
|
||||||
if (vrf->ns_ctxt != NULL) {
|
if (vrf->ns_ctxt != NULL) {
|
||||||
ns = (struct ns *) vrf->ns_ctxt;
|
ns = (struct ns *) vrf->ns_ctxt;
|
||||||
if (ns && 0 != strcmp(ns->name, pathname)) {
|
if (ns && 0 != strcmp(ns->name, pathname)) {
|
||||||
vty_out(vty, "VRF %u is already configured"
|
if (vty)
|
||||||
|
vty_out(vty,
|
||||||
|
"VRF %u is already configured"
|
||||||
" with NETNS %s\n",
|
" with NETNS %s\n",
|
||||||
vrf->vrf_id, ns->name);
|
vrf->vrf_id, ns->name);
|
||||||
|
else
|
||||||
|
zlog_warn("VRF %u is already configured with NETNS %s",
|
||||||
|
vrf->vrf_id, ns->name);
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -448,24 +464,38 @@ DEFUN_NOSH (ns_netns,
|
|||||||
if (ns && ns->vrf_ctxt) {
|
if (ns && ns->vrf_ctxt) {
|
||||||
struct vrf *vrf2 = (struct vrf *)ns->vrf_ctxt;
|
struct vrf *vrf2 = (struct vrf *)ns->vrf_ctxt;
|
||||||
|
|
||||||
|
if (vty)
|
||||||
vty_out(vty, "NS %s is already configured"
|
vty_out(vty, "NS %s is already configured"
|
||||||
" with VRF %u(%s)\n",
|
" with VRF %u(%s)\n",
|
||||||
ns->name, vrf2->vrf_id, vrf2->name);
|
ns->name, vrf2->vrf_id, vrf2->name);
|
||||||
|
else
|
||||||
|
zlog_warn("NS %s is already configured with VRF %u(%s)",
|
||||||
|
ns->name, vrf2->vrf_id, vrf2->name);
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
} else if (!ns)
|
} else if (!ns)
|
||||||
ns = ns_get_by_name(pathname);
|
ns = ns_get_by_name(pathname);
|
||||||
|
|
||||||
|
if (ns_id != ns->ns_id) {
|
||||||
|
RB_REMOVE(ns_head, &ns_tree, ns);
|
||||||
|
ns->ns_id = ns_id;
|
||||||
|
RB_INSERT(ns_head, &ns_tree, ns);
|
||||||
|
}
|
||||||
|
ns->vrf_ctxt = (void *)vrf;
|
||||||
|
vrf->ns_ctxt = (void *)ns;
|
||||||
if (!ns_enable(ns)) {
|
if (!ns_enable(ns)) {
|
||||||
|
if (vty)
|
||||||
vty_out(vty, "Can not associate NS %u with NETNS %s\n",
|
vty_out(vty, "Can not associate NS %u with NETNS %s\n",
|
||||||
ns->ns_id, ns->name);
|
ns->ns_id, ns->name);
|
||||||
|
else
|
||||||
|
zlog_warn("Can not associate NS %u with NETNS %s",
|
||||||
|
ns->ns_id, ns->name);
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
vrf->ns_ctxt = (void *)ns;
|
|
||||||
ns->vrf_ctxt = (void *)vrf;
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int ns_logicalrouter_config_write(struct vty *vty)
|
static int ns_logicalrouter_config_write(struct vty *vty)
|
||||||
{
|
{
|
||||||
struct ns *ns;
|
struct ns *ns;
|
||||||
@ -481,6 +511,22 @@ static int ns_logicalrouter_config_write(struct vty *vty)
|
|||||||
return write;
|
return write;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFUN_NOSH (ns_netns,
|
||||||
|
ns_netns_cmd,
|
||||||
|
"netns NAME",
|
||||||
|
"Attach VRF to a Namespace\n"
|
||||||
|
"The file name in " NS_RUN_DIR ", or a full pathname\n")
|
||||||
|
{
|
||||||
|
int idx_name = 1;
|
||||||
|
char *pathname = ns_netns_pathname(vty, argv[idx_name]->arg);
|
||||||
|
|
||||||
|
VTY_DECLVAR_CONTEXT(vrf, vrf);
|
||||||
|
|
||||||
|
if (!pathname)
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
return ns_handler_create(vty, vrf, pathname, NS_UNKNOWN);
|
||||||
|
}
|
||||||
|
|
||||||
DEFUN (no_ns_netns,
|
DEFUN (no_ns_netns,
|
||||||
no_ns_netns_cmd,
|
no_ns_netns_cmd,
|
||||||
"no netns [NAME]",
|
"no netns [NAME]",
|
||||||
@ -505,6 +551,13 @@ DEFUN (no_ns_netns,
|
|||||||
ns = (struct ns *)vrf->ns_ctxt;
|
ns = (struct ns *)vrf->ns_ctxt;
|
||||||
|
|
||||||
ns->vrf_ctxt = NULL;
|
ns->vrf_ctxt = NULL;
|
||||||
|
vrf_disable(vrf);
|
||||||
|
/* vrf ID from VRF is necessary for Zebra
|
||||||
|
* so that propagate to other clients is done
|
||||||
|
*/
|
||||||
|
RB_REMOVE(ns_head, &ns_tree, ns);
|
||||||
|
ns->ns_id = NS_UNKNOWN;
|
||||||
|
RB_INSERT(ns_head, &ns_tree, ns);
|
||||||
ns_delete(ns);
|
ns_delete(ns);
|
||||||
vrf->ns_ctxt = NULL;
|
vrf->ns_ctxt = NULL;
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
|
5
lib/ns.h
5
lib/ns.h
@ -24,6 +24,8 @@
|
|||||||
|
|
||||||
#include "openbsd-tree.h"
|
#include "openbsd-tree.h"
|
||||||
#include "linklist.h"
|
#include "linklist.h"
|
||||||
|
#include "vty.h"
|
||||||
|
#include "vrf.h"
|
||||||
|
|
||||||
typedef u_int32_t ns_id_t;
|
typedef u_int32_t ns_id_t;
|
||||||
|
|
||||||
@ -93,5 +95,8 @@ extern void ns_terminate(void);
|
|||||||
/* Create a socket serving for the given NS */
|
/* Create a socket serving for the given NS */
|
||||||
extern int ns_socket(int, int, int, ns_id_t);
|
extern int ns_socket(int, int, int, ns_id_t);
|
||||||
extern void ns_cmd_init(void);
|
extern void ns_cmd_init(void);
|
||||||
|
extern int ns_handler_create(struct vty *vty, struct vrf *vrf,
|
||||||
|
char *pathname, ns_id_t ns_id);
|
||||||
|
extern char *ns_netns_pathname(struct vty *vty, const char *name);
|
||||||
|
|
||||||
#endif /*_ZEBRA_NS_H*/
|
#endif /*_ZEBRA_NS_H*/
|
||||||
|
63
lib/vrf.c
63
lib/vrf.c
@ -64,7 +64,6 @@ struct vrf_master {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int vrf_is_enabled(struct vrf *vrf);
|
static int vrf_is_enabled(struct vrf *vrf);
|
||||||
static void vrf_disable(struct vrf *vrf);
|
|
||||||
|
|
||||||
/* VRF list existance check by name. */
|
/* VRF list existance check by name. */
|
||||||
struct vrf *vrf_lookup_by_name(const char *name)
|
struct vrf *vrf_lookup_by_name(const char *name)
|
||||||
@ -84,6 +83,25 @@ static int vrf_name_compare(const struct vrf *a, const struct vrf *b)
|
|||||||
return strcmp(a->name, b->name);
|
return strcmp(a->name, b->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* return 1 if vrf can be enabled */
|
||||||
|
int vrf_update_vrf_id(vrf_id_t vrf_id, struct vrf *vrf)
|
||||||
|
{
|
||||||
|
vrf_id_t old_vrf_id;
|
||||||
|
|
||||||
|
if (!vrf)
|
||||||
|
return 0;
|
||||||
|
old_vrf_id = vrf->vrf_id;
|
||||||
|
if (vrf_id == vrf->vrf_id)
|
||||||
|
return 0;
|
||||||
|
if (vrf->vrf_id != VRF_UNKNOWN)
|
||||||
|
RB_REMOVE(vrf_id_head, &vrfs_by_id, vrf);
|
||||||
|
vrf->vrf_id = vrf_id;
|
||||||
|
RB_INSERT(vrf_id_head, &vrfs_by_id, vrf);
|
||||||
|
if (old_vrf_id == VRF_UNKNOWN)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get a VRF. If not found, create one.
|
/* Get a VRF. If not found, create one.
|
||||||
* Arg:
|
* Arg:
|
||||||
* name - The name of the vrf. May be NULL if unknown.
|
* name - The name of the vrf. May be NULL if unknown.
|
||||||
@ -223,7 +241,7 @@ int vrf_enable(struct vrf *vrf)
|
|||||||
* The VRF_DELETE_HOOK callback will be called to inform
|
* The VRF_DELETE_HOOK callback will be called to inform
|
||||||
* that they must release the resources in the VRF.
|
* that they must release the resources in the VRF.
|
||||||
*/
|
*/
|
||||||
static void vrf_disable(struct vrf *vrf)
|
void vrf_disable(struct vrf *vrf)
|
||||||
{
|
{
|
||||||
if (!vrf_is_enabled(vrf))
|
if (!vrf_is_enabled(vrf))
|
||||||
return;
|
return;
|
||||||
@ -465,6 +483,32 @@ void vrf_configure_backend(int vrf_backend_netns)
|
|||||||
vrf_backend = vrf_backend_netns;
|
vrf_backend = vrf_backend_netns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int vrf_handler_create(struct vty *vty, const char *vrfname, struct vrf **vrf)
|
||||||
|
{
|
||||||
|
struct vrf *vrfp;
|
||||||
|
|
||||||
|
if (strlen(vrfname) > VRF_NAMSIZ) {
|
||||||
|
if (vty)
|
||||||
|
vty_out(vty,
|
||||||
|
"%% VRF name %s invalid: length exceeds %d bytes\n",
|
||||||
|
vrfname, VRF_NAMSIZ);
|
||||||
|
else
|
||||||
|
zlog_warn(
|
||||||
|
"%% VRF name %s invalid: length exceeds %d bytes\n",
|
||||||
|
vrfname, VRF_NAMSIZ);
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
vrfp = vrf_get(VRF_UNKNOWN, vrfname);
|
||||||
|
|
||||||
|
if (vty)
|
||||||
|
VTY_PUSH_CONTEXT(VRF_NODE, vrfp);
|
||||||
|
|
||||||
|
if (vrf)
|
||||||
|
*vrf = vrfp;
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/* vrf CLI commands */
|
/* vrf CLI commands */
|
||||||
DEFUN_NOSH (vrf,
|
DEFUN_NOSH (vrf,
|
||||||
vrf_cmd,
|
vrf_cmd,
|
||||||
@ -474,21 +518,8 @@ DEFUN_NOSH (vrf,
|
|||||||
{
|
{
|
||||||
int idx_name = 1;
|
int idx_name = 1;
|
||||||
const char *vrfname = argv[idx_name]->arg;
|
const char *vrfname = argv[idx_name]->arg;
|
||||||
struct vrf *vrfp;
|
|
||||||
|
|
||||||
if (strlen(vrfname) > VRF_NAMSIZ) {
|
return vrf_handler_create(vty, vrfname, NULL);
|
||||||
vty_out(vty,
|
|
||||||
"%% VRF name %s is invalid: length exceeds "
|
|
||||||
"%d characters\n",
|
|
||||||
vrfname, VRF_NAMSIZ);
|
|
||||||
return CMD_WARNING_CONFIG_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
vrfp = vrf_get(VRF_UNKNOWN, vrfname);
|
|
||||||
|
|
||||||
VTY_PUSH_CONTEXT(VRF_NODE, vrfp);
|
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN_NOSH (no_vrf,
|
DEFUN_NOSH (no_vrf,
|
||||||
|
10
lib/vrf.h
10
lib/vrf.h
@ -212,6 +212,16 @@ extern int vrf_socket(int, int, int, vrf_id_t);
|
|||||||
extern void vrf_configure_backend(int vrf_backend_netns);
|
extern void vrf_configure_backend(int vrf_backend_netns);
|
||||||
extern int vrf_get_backend(void);
|
extern int vrf_get_backend(void);
|
||||||
extern int vrf_is_backend_netns(void);
|
extern int vrf_is_backend_netns(void);
|
||||||
|
extern int vrf_handler_create(struct vty *vty,
|
||||||
|
const char *name,
|
||||||
|
struct vrf **vrf);
|
||||||
|
|
||||||
|
/* used by NS when vrf backend is NS.
|
||||||
|
* Notify a change in the VRF ID of the VRF
|
||||||
|
*/
|
||||||
|
extern int vrf_update_vrf_id(vrf_id_t vrf_id, struct vrf *vrf);
|
||||||
|
extern void vrf_disable(struct vrf *vrf);
|
||||||
|
extern int vrf_enable(struct vrf *vrf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* VRF Debugging
|
* VRF Debugging
|
||||||
|
Loading…
Reference in New Issue
Block a user