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) */
}
}
+/* 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);
}
/* 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;
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)
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;
/* 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;
/* 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);
/*
/* 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
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;
}
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;
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 */
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))
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
* 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
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;
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",
}
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);
int zebra_ns_init(void)
{
ns_id_t ns_id;
+ ns_id_t ns_id_external;
dzns = zebra_ns_alloc();
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);
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);