From 03aff2d8489e91b493ad24b8d8d8918831e156d8 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Mon, 26 Mar 2018 12:22:18 +0200 Subject: zebra: add an indirection table for ns_id This list "table" is created in the case the netns backend for VRF is used. This contains the mapping between the NSID value read from the 'ip netns list' and the ns id external used to create the VRF value from vrf context. This mapping is necessary in order to reserve default 0 value for vrf_default. Signed-off-by: Philippe Guibert --- lib/netns_linux.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- lib/netns_other.c | 5 +++++ lib/ns.h | 10 +++++++++- lib/vrf.c | 12 +++++++++--- lib/vrf.h | 3 ++- 5 files changed, 80 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/netns_linux.c b/lib/netns_linux.c index 3d61cecc0..c215b4151 100644 --- a/lib/netns_linux.c +++ b/lib/netns_linux.c @@ -59,6 +59,26 @@ static int ns_default_ns_fd; static int ns_debug; +struct ns_map_nsid { + RB_ENTRY(ns_map_nsid) id_entry; + ns_id_t ns_id_external; + ns_id_t ns_id; +}; + +static __inline int ns_map_compare(const struct ns_map_nsid *a, + const struct ns_map_nsid *b) +{ + return (a->ns_id - b->ns_id); +} + +RB_HEAD(ns_map_nsid_head, ns_map_nsid); +RB_PROTOTYPE(ns_map_nsid_head, ns_map_nsid, id_entry, ns_map_compare); +RB_GENERATE(ns_map_nsid_head, ns_map_nsid, id_entry, ns_map_compare); +struct ns_map_nsid_head ns_map_nsid_list = RB_INITIALIZER(&ns_map_nsid_list); + +static ns_id_t ns_id_external_numbering; + + #ifndef CLONE_NEWNET #define CLONE_NEWNET 0x40000000 /* New network namespace (lo, device, names sockets, etc) */ @@ -262,6 +282,38 @@ static void ns_disable_internal(struct ns *ns) } } +/* VRF list existance check by name. */ +static struct ns_map_nsid *ns_map_nsid_lookup_by_nsid(ns_id_t ns_id) +{ + struct ns_map_nsid ns_map; + + ns_map.ns_id = ns_id; + return (RB_FIND(ns_map_nsid_head, &ns_map_nsid_list, &ns_map)); +} + +ns_id_t ns_map_nsid_with_external(ns_id_t ns_id, bool maporunmap) +{ + struct ns_map_nsid *ns_map; + vrf_id_t ns_id_external; + + ns_map = ns_map_nsid_lookup_by_nsid(ns_id); + if (ns_map && !maporunmap) { + ns_id_external = ns_map->ns_id_external; + RB_REMOVE(ns_map_nsid_head, &ns_map_nsid_list, ns_map); + return ns_id_external; + } + if (ns_map) + return ns_map->ns_id_external; + ns_map = XCALLOC(MTYPE_NS, sizeof(struct ns_map_nsid)); + /* increase vrf_id + * default vrf is the first one : 0 + */ + ns_map->ns_id_external = ns_id_external_numbering++; + ns_map->ns_id = ns_id; + RB_INSERT(ns_map_nsid_head, &ns_map_nsid_list, ns_map); + return ns_map->ns_id_external; +} + struct ns *ns_get_created(struct ns *ns, char *name, ns_id_t ns_id) { return ns_get_created_internal(ns, name, ns_id); @@ -430,7 +482,7 @@ void ns_init(void) } /* Initialize NS module. */ -void ns_init_management(ns_id_t default_ns_id) +void ns_init_management(ns_id_t default_ns_id, ns_id_t internal_ns) { int fd; @@ -444,6 +496,8 @@ void ns_init_management(ns_id_t default_ns_id) fd = open(NS_DEFAULT_NAME, O_RDONLY); default_ns->fd = fd; } + default_ns->internal_ns_id = internal_ns; + /* Set the default NS name. */ default_ns->name = XSTRDUP(MTYPE_NS_NAME, NS_DEFAULT_NAME); if (ns_debug) diff --git a/lib/netns_other.c b/lib/netns_other.c index 2402dd17d..4c7be05fa 100644 --- a/lib/netns_other.c +++ b/lib/netns_other.c @@ -153,6 +153,11 @@ int ns_enable(struct ns *ns, int (*func)(ns_id_t, void *)) return 0; } +ns_id_t ns_map_nsid_with_external(ns_id_t ns_id, bool maporunmap) +{ + return NS_UNKNOWN; +} + struct ns *ns_get_created(struct ns *ns, char *name, ns_id_t ns_id) { return NULL; diff --git a/lib/ns.h b/lib/ns.h index fac91a40d..ba857b630 100644 --- a/lib/ns.h +++ b/lib/ns.h @@ -46,6 +46,9 @@ struct ns { /* Identifier, same as the vector index */ ns_id_t ns_id; + /* Identifier, mapped on the NSID value */ + ns_id_t internal_ns_id; + /* Name */ char *name; @@ -100,7 +103,7 @@ extern void ns_terminate(void); /* API to initialize NETNS managerment * parameter is the default ns_id */ -extern void ns_init_management(ns_id_t ns_id); +extern void ns_init_management(ns_id_t ns_id, ns_id_t internal_ns_idx); /* @@ -133,6 +136,11 @@ extern int ns_have_netns(void); /* API to get context information of a NS */ extern void *ns_info_lookup(ns_id_t ns_id); +/* API to map internal ns id value with + * user friendly ns id external value + */ +extern ns_id_t ns_map_nsid_with_external(ns_id_t ns_id, bool maporunmap); + /* * NS init routine * should be called from backendx diff --git a/lib/vrf.c b/lib/vrf.c index 8593cf289..b493f832f 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -539,7 +539,8 @@ void vrf_configure_backend(int vrf_backend_netns) vrf_backend = vrf_backend_netns; } -int vrf_handler_create(struct vty *vty, const char *vrfname, struct vrf **vrf) +int vrf_handler_create(struct vty *vty, const char *vrfname, + struct vrf **vrf) { struct vrf *vrfp; @@ -566,7 +567,7 @@ int vrf_handler_create(struct vty *vty, const char *vrfname, struct vrf **vrf) } int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname, - ns_id_t ns_id) + ns_id_t ns_id, ns_id_t internal_ns_id) { struct ns *ns = NULL; @@ -613,6 +614,7 @@ int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname, return CMD_WARNING_CONFIG_FAILED; } ns = ns_get_created(ns, pathname, ns_id); + ns->internal_ns_id = internal_ns_id; ns->vrf_ctxt = (void *)vrf; vrf->ns_ctxt = (void *)ns; /* update VRF netns NAME */ @@ -718,7 +720,8 @@ DEFUN_NOSH (vrf_netns, vrf_daemon_privs->change(ZPRIVS_RAISE)) zlog_err("%s: Can't raise privileges", __func__); - ret = vrf_netns_handler_create(vty, vrf, pathname, NS_UNKNOWN); + ret = vrf_netns_handler_create(vty, vrf, pathname, + NS_UNKNOWN, NS_UNKNOWN); if (vrf_daemon_privs && vrf_daemon_privs->change(ZPRIVS_LOWER)) @@ -827,6 +830,9 @@ vrf_id_t vrf_get_default_id(void) if (vrf) return vrf->vrf_id; + /* backend netns is only known by zebra + * for other daemons, we return VRF_DEFAULT_INTERNAL + */ if (vrf_is_backend_netns()) return ns_get_default_id(); else diff --git a/lib/vrf.h b/lib/vrf.h index 85a530927..8aa0fc221 100644 --- a/lib/vrf.h +++ b/lib/vrf.h @@ -272,7 +272,8 @@ extern int vrf_handler_create(struct vty *vty, const char *name, * should be called from zebra only */ extern int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, - char *pathname, ns_id_t ns_id); + char *pathname, ns_id_t ext_ns_id, + ns_id_t ns_id); /* used internally to enable or disable VRF. * Notify a change in the VRF ID of the VRF -- cgit v1.2.3