]> git.proxmox.com Git - mirror_frr.git/commitdiff
zebra: add an indirection table for ns_id
authorPhilippe Guibert <philippe.guibert@6wind.com>
Mon, 26 Mar 2018 10:22:18 +0000 (12:22 +0200)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Fri, 13 Apr 2018 14:40:32 +0000 (16:40 +0200)
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>
lib/netns_linux.c
lib/netns_other.c
lib/ns.h
lib/vrf.c
lib/vrf.h
zebra/zebra_netns_notify.c
zebra/zebra_ns.c

index 3d61cecc03e94d7d9dbc0267fae01d088db04a08..c215b4151be75aca4153fdc0f9148003852ccf17 100644 (file)
@@ -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)
index 2402dd17d6e6909bd52f6b3cff606c3ce2902169..4c7be05fab2524b393fb8e3c34cae919fa5b7afe 100644 (file)
@@ -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;
index fac91a40da1c88a167e6d78472216290515f13f6..ba857b630ea440849d87228034f9dbcd1d33e580 100644 (file)
--- 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
index 8593cf289ff70a78e8b842a46c4a616049896a7c..b493f832f3383cc14b79ec2244f5fe8332df54a9 100644 (file)
--- 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
index 85a5309279b8e7c47e2250010c55115f5867cdc6..8aa0fc2215b2d938e9a860db3e612d42413e1b85 100644 (file)
--- 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
index f9beb32ac4751ba09715e0e4dad6b1d2407463cd..30f850597c65c0b848ceddb96115bf4a4a37a71a 100644 (file)
@@ -70,7 +70,7 @@ static void zebra_ns_notify_create_context_from_entry_name(const char *name)
        char *netnspath = ns_netns_pathname(NULL, name);
        struct vrf *vrf;
        int ret;
-       ns_id_t ns_id;
+       ns_id_t ns_id, ns_id_external;
 
        if (netnspath == NULL)
                return;
@@ -80,8 +80,9 @@ static void zebra_ns_notify_create_context_from_entry_name(const char *name)
        ns_id = zebra_ns_id_get(netnspath);
        if (zserv_privs.change(ZPRIVS_LOWER))
                zlog_err("Can't lower privileges");
+       ns_id_external = ns_map_nsid_with_external(ns_id, true);
        /* if VRF with NS ID already present */
-       vrf = vrf_lookup_by_id((vrf_id_t)ns_id);
+       vrf = vrf_lookup_by_id((vrf_id_t)ns_id_external);
        if (vrf) {
                zlog_warn(
                        "NS notify : same NSID used by VRF %s. Ignore NS %s creation",
@@ -90,15 +91,18 @@ static void zebra_ns_notify_create_context_from_entry_name(const char *name)
        }
        if (vrf_handler_create(NULL, name, &vrf) != CMD_SUCCESS) {
                zlog_warn("NS notify : failed to create VRF %s", name);
+               ns_map_nsid_with_external(ns_id, false);
                return;
        }
        if (zserv_privs.change(ZPRIVS_RAISE))
                zlog_err("Can't raise privileges");
-       ret = vrf_netns_handler_create(NULL, vrf, netnspath, ns_id);
+       ret = vrf_netns_handler_create(NULL, vrf, netnspath,
+                                      ns_id_external, ns_id);
        if (zserv_privs.change(ZPRIVS_LOWER))
                zlog_err("Can't lower privileges");
        if (ret != CMD_SUCCESS) {
                zlog_warn("NS notify : failed to create NS %s", netnspath);
+               ns_map_nsid_with_external(ns_id, false);
                return;
        }
        zlog_info("NS notify : created VRF %s NS %s", name, netnspath);
index 7393f767afa3d20b72c67670c5b40e84cca94e32..52cf4351bc43374b615545315defffc2759cacb9 100644 (file)
@@ -274,6 +274,7 @@ int zebra_ns_disable(ns_id_t ns_id, void **info)
 int zebra_ns_init(void)
 {
        ns_id_t ns_id;
+       ns_id_t ns_id_external;
 
        dzns = zebra_ns_alloc();
 
@@ -282,8 +283,8 @@ int zebra_ns_init(void)
        ns_id = zebra_ns_id_get_default();
        if (zserv_privs.change(ZPRIVS_LOWER))
                zlog_err("Can't lower privileges");
-
-       ns_init_management(ns_id);
+       ns_id_external = ns_map_nsid_with_external(ns_id, true);
+       ns_init_management(ns_id_external, ns_id);
 
        logicalrouter_init(logicalrouter_config_write);
 
@@ -295,7 +296,7 @@ int zebra_ns_init(void)
        zebra_vrf_init();
 
        /* Default NS is activated */
-       zebra_ns_enable(ns_id, (void **)&dzns);
+       zebra_ns_enable(ns_id_external, (void **)&dzns);
 
        if (vrf_is_backend_netns()) {
                ns_add_hook(NS_NEW_HOOK, zebra_ns_new);