#include "ns.h"
#include "log.h"
#include "memory.h"
-
#include "command.h"
#include "vty.h"
#include "vrf.h"
+#include "lib_errors.h"
DEFINE_MTYPE_STATIC(LIB, NS, "NetNS Context")
DEFINE_MTYPE_STATIC(LIB, NS_NAME, "NetNS Name")
+/* default NS ID value used when VRF backend is not NETNS */
+#define NS_DEFAULT_INTERNAL 0
+
static inline int ns_compare(const struct ns *ns, const struct ns *ns2);
static struct ns *ns_lookup_name_internal(const char *name);
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) */
zlog_info("NS %s is created.", ns->name);
}
if (ns_master.ns_new_hook)
- (*ns_master.ns_new_hook) (ns);
+ (*ns_master.ns_new_hook)(ns);
return ns;
}
}
if (!ns_is_enabled(ns)) {
- zlog_err("Can not enable NS %u: %s!", ns->ns_id,
- safe_strerror(errno));
+ flog_err_sys(EC_LIB_SYSTEM_CALL,
+ "Can not enable NS %u: %s!", ns->ns_id,
+ safe_strerror(errno));
return 0;
}
/* Non default NS. leave */
if (ns->ns_id == NS_UNKNOWN) {
- zlog_err("Can not enable NS %s %u: Invalid NSID",
+ flog_err(EC_LIB_NS,
+ "Can not enable NS %s %u: Invalid NSID",
ns->name, ns->ns_id);
return 0;
}
{
if (ns_is_enabled(ns)) {
if (ns_debug)
- zlog_info("NS %u is to be disabled.",
- ns->ns_id);
+ zlog_info("NS %u is to be disabled.", ns->ns_id);
if (ns_master.ns_disable_hook)
(*ns_master.ns_disable_hook)(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 map)
+{
+ 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 && !map) {
+ 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);
}
/* Look up the data pointer of the specified VRF. */
-void *
-ns_info_lookup(ns_id_t ns_id)
+void *ns_info_lookup(ns_id_t ns_id)
{
struct ns *ns = ns_lookup_internal(ns_id);
if (!result) {
if (vty)
- vty_out(vty, "Invalid pathname: %s\n",
+ vty_out(vty, "Invalid pathname for %s: %s\n",
+ pathname,
safe_strerror(errno));
else
- zlog_warn("Invalid pathname: %s",
+ flog_warn(EC_LIB_LINUX_NS,
+ "Invalid pathname for %s: %s", pathname,
safe_strerror(errno));
return NULL;
}
if (check_base != NULL && strlen(check_base) + 1 > NS_NAMSIZ) {
if (vty)
vty_out(vty, "NS name (%s) invalid: too long (>%d)\n",
- check_base, NS_NAMSIZ-1);
+ check_base, NS_NAMSIZ - 1);
else
- zlog_warn("NS name (%s) invalid: too long (>%d)",
- check_base, NS_NAMSIZ-1);
+ flog_warn(EC_LIB_LINUX_NS,
+ "NS name (%s) invalid: too long (>%d)",
+ check_base, NS_NAMSIZ - 1);
return NULL;
}
return pathname;
if (ns_initialised == 1)
return;
errno = 0;
-#ifdef HAVE_NETNS
- if (have_netns_enabled < 0)
+ if (have_netns())
ns_default_ns_fd = open(NS_DEFAULT_NAME, O_RDONLY);
- else
+ else {
ns_default_ns_fd = -1;
-#else
- ns_default_ns_fd = -1;
- default_ns = NULL;
-#endif /* HAVE_NETNS */
- if (ns_default_ns_fd == -1)
- zlog_err("NS initialisation failure (%s)",
- safe_strerror(errno));
+ default_ns = NULL;
+ }
ns_current_ns_fd = -1;
ns_initialised = 1;
}
/* 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;
ns_init();
default_ns = ns_get_created_internal(NULL, NULL, default_ns_id);
if (!default_ns) {
- zlog_err("%s: failed to create the default NS!",
+ flog_err(EC_LIB_NS, "%s: failed to create the default NS!",
__func__);
exit(1);
}
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)
- zlog_info("%s: default NSID is %u",
- __func__, default_ns->ns_id);
+ zlog_info("%s: default NSID is %u", __func__,
+ default_ns->ns_id);
/* Enable the default NS. */
if (!ns_enable(default_ns, NULL)) {
- zlog_err("%s: failed to enable the default NS!",
+ flog_err(EC_LIB_NS, "%s: failed to enable the default NS!",
__func__);
exit(1);
}
{
if (default_ns)
return default_ns->ns_id;
- return NS_UNKNOWN;
+ return NS_DEFAULT_INTERNAL;
}
-