summaryrefslogtreecommitdiff
path: root/lib/netns_linux.c
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2018-03-26 12:22:18 +0200
committerPhilippe Guibert <philippe.guibert@6wind.com>2018-04-13 16:40:32 +0200
commit03aff2d8489e91b493ad24b8d8d8918831e156d8 (patch)
tree304e168835778c15f11d2c2ba9d96109e944dcb4 /lib/netns_linux.c
parent0c2bac388029e12e4c21177cda02e72712f28efb (diff)
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 <philippe.guibert@6wind.com>
Diffstat (limited to 'lib/netns_linux.c')
-rw-r--r--lib/netns_linux.c56
1 files changed, 55 insertions, 1 deletions
diff --git a/lib/netns_linux.c b/lib/netns_linux.c
index 3d61cecc03..c215b4151b 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)