summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2018-01-16 13:59:58 +0100
committerPhilippe Guibert <philippe.guibert@6wind.com>2018-02-27 11:11:24 +0100
commitec31f30d28b65a4820a44ac658e677840ed6f88b (patch)
tree12d7828e18031db13e71f2fa0d5f8070246fb966
parentzebra: collect and get netnamespaces information (diff)
downloadfrr-ec31f30d28b65a4820a44ac658e677840ed6f88b.tar.xz
frr-ec31f30d28b65a4820a44ac658e677840ed6f88b.zip
zebra: upon startup, a NSID is assigned to default netns
when the netns backend is selected for VRF, the default VRF is being assigned a NSID. This avoids the need to handle the case where if the incoming NSID was 0 for a non default VRF, then a specific handling had to be done to keep 0 value for default VRF. In most cases, as the first NETNS to get a NSID will be the default VRF, most probably the default VRF will be assigned to 0, while the other ones will have their value incremented. On some cases, where the NSID is already assigned for NETNS, including default VRF, then the default VRF value will be the one derived from the NSID of default VRF, thus keeping consistency between VRF IDs and NETNS IDs. Default NS is attempted to be created. Actually, some VMs may have the netns feature, but the NS initialisation fails because that folder is not present. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
-rw-r--r--lib/ns.c35
-rw-r--r--lib/ns.h14
-rw-r--r--lib/vrf.c15
-rw-r--r--lib/vrf.h10
-rw-r--r--zebra/zebra_netns_id.c41
-rw-r--r--zebra/zebra_netns_id.h1
-rw-r--r--zebra/zebra_ns.c12
7 files changed, 108 insertions, 20 deletions
diff --git a/lib/ns.c b/lib/ns.c
index 9aa350992..17d70a12f 100644
--- a/lib/ns.c
+++ b/lib/ns.c
@@ -51,6 +51,7 @@ RB_GENERATE(ns_head, ns, entry, ns_compare)
struct ns_head ns_tree = RB_INITIALIZER(&ns_tree);
+static struct ns *default_ns;
static int ns_current_ns_fd;
static int ns_default_ns_fd;
@@ -71,16 +72,12 @@ static inline int setns(int fd, int nstype)
#endif /* HAVE_SETNS */
#ifdef HAVE_NETNS
-
-#define NS_DEFAULT_NAME "/proc/self/ns/net"
static int have_netns_enabled = -1;
-
-#else /* !HAVE_NETNS */
-
-#define NS_DEFAULT_NAME "Default-logical-router"
-
#endif /* HAVE_NETNS */
+/* default NS ID value used when VRF backend is not NETNS */
+#define NS_DEFAULT_INTERNAL 0
+
static int have_netns(void)
{
#ifdef HAVE_NETNS
@@ -625,24 +622,28 @@ void ns_init(void)
}
#endif /* HAVE_NETNS */
ns_default_ns_fd = -1;
+ default_ns = NULL;
}
/* Initialize NS module. */
-void ns_init_zebra(void)
+void ns_init_zebra(ns_id_t default_ns_id)
{
- struct ns *default_ns;
+ int fd;
ns_init();
- /* The default NS always exists. */
- default_ns = ns_get(NS_DEFAULT);
- ns_current_ns_fd = -1;
+ default_ns = ns_get(default_ns_id);
if (!default_ns) {
zlog_err("ns_init: failed to create the default NS!");
exit(1);
}
-
+ if (have_netns()) {
+ fd = open(NS_DEFAULT_NAME, O_RDONLY);
+ default_ns->fd = fd;
+ }
+ ns_current_ns_fd = -1;
/* Set the default NS name. */
default_ns->name = XSTRDUP(MTYPE_NS_NAME, NS_DEFAULT_NAME);
+ zlog_info("ns_init: default NSID is %u", default_ns->ns_id);
/* Enable the default NS. */
if (!ns_enable(default_ns)) {
@@ -739,3 +740,11 @@ int ns_socket(int domain, int type, int protocol, ns_id_t ns_id)
return ret;
}
+
+ns_id_t ns_get_default_id(void)
+{
+ if (default_ns)
+ return default_ns->ns_id;
+ return NS_UNKNOWN;
+}
+
diff --git a/lib/ns.h b/lib/ns.h
index 73482d4d5..44257ab0c 100644
--- a/lib/ns.h
+++ b/lib/ns.h
@@ -30,12 +30,17 @@
typedef u_int32_t ns_id_t;
/* the default NS ID */
-#define NS_DEFAULT 0
#define NS_UNKNOWN UINT32_MAX
/* Default netns directory (Linux) */
#define NS_RUN_DIR "/var/run/netns"
+#ifdef HAVE_NETNS
+#define NS_DEFAULT_NAME "/proc/self/ns/net"
+#else /* !HAVE_NETNS */
+#define NS_DEFAULT_NAME "Default-logical-router"
+#endif /* HAVE_NETNS */
+
struct ns {
RB_ENTRY(ns) entry;
@@ -85,7 +90,7 @@ extern void ns_add_hook(int type, int (*)(struct ns *));
* NS initializer/destructor
*/
extern void ns_init(void);
-extern void ns_init_zebra(void);
+extern void ns_init_zebra(ns_id_t ns_id);
extern void ns_terminate(void);
/*
@@ -101,10 +106,15 @@ extern char *ns_netns_pathname(struct vty *vty, const char *name);
extern void *ns_info_lookup(ns_id_t ns_id);
extern void ns_walk_func(int (*func)(struct ns *));
extern const char *ns_get_name(struct ns *ns);
+extern ns_id_t ns_get_default_id(void);
/* API that can be used by all daemons */
extern int ns_switchback_to_initial(void);
extern int ns_switch_to_netns(const char *netns_name);
extern void ns_init(void);
+
+/* The default NS ID */
+#define NS_DEFAULT ns_get_default_id()
+
#endif /*_ZEBRA_NS_H*/
diff --git a/lib/vrf.c b/lib/vrf.c
index 787105235..f4dc237eb 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -34,6 +34,9 @@
#include "command.h"
#include "ns.h"
+/* default VRF ID value used when VRF backend is not NETNS */
+#define VRF_DEFAULT_INTERNAL 0
+
DEFINE_MTYPE_STATIC(LIB, VRF, "VRF")
DEFINE_MTYPE_STATIC(LIB, VRF_BITMAP, "VRF bit-map")
@@ -646,3 +649,15 @@ void vrf_cmd_init(int (*writefunc)(struct vty *vty))
install_default(VRF_NODE);
ns_cmd_init();
}
+
+vrf_id_t vrf_get_default_id(void)
+{
+ struct vrf *vrf = vrf_lookup_by_name(VRF_DEFAULT_NAME);
+
+ if (vrf)
+ return vrf->vrf_id;
+ if (vrf_is_backend_netns())
+ return ns_get_default_id();
+ else
+ return VRF_DEFAULT_INTERNAL;
+}
diff --git a/lib/vrf.h b/lib/vrf.h
index 4bdc183b5..9553d4380 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -27,11 +27,7 @@
#include "qobj.h"
#include "vty.h"
-/* The default NS ID */
-#define NS_DEFAULT 0
-
/* The default VRF ID */
-#define VRF_DEFAULT 0
#define VRF_UNKNOWN UINT32_MAX
/* Pending: May need to refine this. */
@@ -208,6 +204,7 @@ extern void vrf_cmd_init(int (*writefunc)(struct vty *vty));
/*
* VRF utilities
*/
+extern vrf_id_t vrf_get_default_id(void);
/* Create a socket serving for the given VRF */
extern int vrf_socket(int, int, int, vrf_id_t);
@@ -236,4 +233,9 @@ extern int vrf_enable(struct vrf *vrf);
* VRF Debugging
*/
extern void vrf_install_commands(void);
+
+
+/* The default VRF ID */
+#define VRF_DEFAULT vrf_get_default_id()
+
#endif /*_ZEBRA_VRF_H*/
diff --git a/zebra/zebra_netns_id.c b/zebra/zebra_netns_id.c
index c5e792bd7..966d6ed0d 100644
--- a/zebra/zebra_netns_id.c
+++ b/zebra/zebra_netns_id.c
@@ -20,6 +20,7 @@
#include <zebra.h>
#include "ns.h"
+#include "vrf.h"
#include "log.h"
#if defined(HAVE_NETLINK)
@@ -35,6 +36,9 @@
#include "zebra_netns_id.h"
+/* default NS ID value used when VRF backend is not NETNS */
+#define NS_DEFAULT_INTERNAL 0
+
/* in case NEWNSID not available, the NSID will be locally obtained
*/
#define NS_BASE_NSID 0
@@ -312,3 +316,40 @@ ns_id_t zebra_ns_id_get(const char *netnspath)
return zebra_ns_id_get_fallback(netnspath);
}
#endif /* ! defined(HAVE_NETLINK) */
+
+#ifdef HAVE_NETNS
+static void zebra_ns_create_netns_directory(void)
+{
+ /* check that /var/run/netns is created */
+ /* S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH */
+ if (mkdir(NS_RUN_DIR, 0755)) {
+ if (errno != EEXIST) {
+ zlog_warn("NS check: failed to access %s", NS_RUN_DIR);
+ return;
+ }
+ }
+}
+#endif
+
+ns_id_t zebra_ns_id_get_default(void)
+{
+#ifdef HAVE_NETNS
+ int fd;
+#endif /* !HAVE_NETNS */
+
+#ifdef HAVE_NETNS
+ if (vrf_is_backend_netns())
+ zebra_ns_create_netns_directory();
+ fd = open(NS_DEFAULT_NAME, O_RDONLY);
+
+ if (fd == -1)
+ return NS_DEFAULT_INTERNAL;
+ if (!vrf_is_backend_netns())
+ return NS_DEFAULT_INTERNAL;
+ close(fd);
+ return zebra_ns_id_get((char *)NS_DEFAULT_NAME);
+#else /* HAVE_NETNS */
+ return NS_DEFAULT_INTERNAL;
+#endif /* !HAVE_NETNS */
+}
+
diff --git a/zebra/zebra_netns_id.h b/zebra/zebra_netns_id.h
index 18fdf50cf..d6530e669 100644
--- a/zebra/zebra_netns_id.h
+++ b/zebra/zebra_netns_id.h
@@ -21,5 +21,6 @@
#include "ns.h"
extern ns_id_t zebra_ns_id_get(const char *netnspath);
+extern ns_id_t zebra_ns_id_get_default(void);
#endif /* __ZEBRA_NS_ID_H__ */
diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c
index 50551c9b3..da5b22def 100644
--- a/zebra/zebra_ns.c
+++ b/zebra/zebra_ns.c
@@ -34,6 +34,9 @@
#include "zebra_vxlan.h"
#include "debug.h"
#include "zebra_netns_notify.h"
+#include "zebra_netns_id.h"
+
+extern struct zebra_privs_t zserv_privs;
DEFINE_MTYPE(ZEBRA, ZEBRA_NS, "Zebra Name Space")
@@ -229,9 +232,16 @@ int zebra_ns_disable(ns_id_t ns_id, void **info)
int zebra_ns_init(void)
{
+ ns_id_t ns_id;
+
dzns = zebra_ns_alloc();
- ns_init_zebra();
+ if (zserv_privs.change(ZPRIVS_RAISE))
+ zlog_err("Can't raise privileges");
+ ns_id = zebra_ns_id_get_default();
+ if (zserv_privs.change(ZPRIVS_LOWER))
+ zlog_err("Can't lower privileges");
+ ns_init_zebra(ns_id);
ns_init();