netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: David Ahern <dsa@cumulusnetworks.com>
To: netdev@vger.kernel.org, stephen@networkplumber.org, luto@amacapital.net
Cc: David Ahern <dsa@cumulusnetworks.com>
Subject: [PATCH iproute2 3/4] ip vrf: Handle VRF nesting in namespace
Date: Thu, 16 Feb 2017 08:58:57 -0800	[thread overview]
Message-ID: <1487264338-17588-4-git-send-email-dsa@cumulusnetworks.com> (raw)
In-Reply-To: <1487264338-17588-1-git-send-email-dsa@cumulusnetworks.com>

Since cgroups are not namespace aware, the directory heirarchy used by
ip vrf should account for network namespaces. In this case, change the
path from CGRP/BASE/vrf/NAME to CGRP/BASE/NETNS/vrf/NAME where CGRP is
the cgroup2 mount path, BASE in any base heirarchy inherited before VRF
is applied and NAME is the VRF name.

The intent is as follows: a user logs into the box into some namespace
with a name known to iproute2. Some other policy may have put the
process into a BASE heirarchy. From there the user executes a task in
a VRF and in doing so the task heirarchy becomes CGRP/BASE/NETNS/vrf/NAME.
The namespace level is omitted for the default namespace.

Reported-by: Andy Lutomirski <luto@amacapital.net>
Signed-off-by: David Ahern <dsa@cumulusnetworks.com>
---
 ip/ipvrf.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 55 insertions(+), 8 deletions(-)

diff --git a/ip/ipvrf.c b/ip/ipvrf.c
index 8d61d0718c66..cb7f9fa6d1db 100644
--- a/ip/ipvrf.c
+++ b/ip/ipvrf.c
@@ -134,8 +134,8 @@ static void read_cgroup_pids(const char *base_path, char *name)
 	close(fd);
 }
 
-/* recurse path looking for PATH/vrf/NAME */
-static int recurse_dir(char *base_path, char *name)
+/* recurse path looking for PATH[/NETNS]/vrf/NAME */
+static int recurse_dir(char *base_path, char *name, const char *netns)
 {
 	char path[PATH_MAX];
 	struct dirent *de;
@@ -152,7 +152,15 @@ static int recurse_dir(char *base_path, char *name)
 			continue;
 
 		if (!strcmp(de->d_name, "vrf")) {
-			read_cgroup_pids(base_path, name);
+			const char *pdir = strrchr(base_path, '/');
+
+			/* found a 'vrf' directory. if it is for the given
+			 * namespace then dump the cgroup pids
+			 */
+			if (*netns == '\0' ||
+			    (pdir && !strcmp(pdir+1, netns)))
+				read_cgroup_pids(base_path, name);
+
 			continue;
 		}
 
@@ -165,7 +173,7 @@ static int recurse_dir(char *base_path, char *name)
 			continue;
 
 		if (S_ISDIR(fstat.st_mode)) {
-			rc = recurse_dir(path, name);
+			rc = recurse_dir(path, name, netns);
 			if (rc != 0)
 				goto out;
 		}
@@ -178,10 +186,25 @@ static int recurse_dir(char *base_path, char *name)
 	return rc;
 }
 
+static int ipvrf_get_netns(char *netns, int len)
+{
+	if (netns_identify_pid("self", netns, len-3)) {
+		fprintf(stderr, "Failed to get name of network namespace: %s\n",
+			strerror(errno));
+		return -1;
+	}
+
+	if (*netns != '\0')
+		strcat(netns, "-ns");
+
+	return 0;
+}
+
 static int ipvrf_pids(int argc, char **argv)
 {
 	char *mnt, *vrf;
-	int ret;
+	char netns[256];
+	int ret = -1;
 
 	if (argc != 1) {
 		fprintf(stderr, "Invalid arguments\n");
@@ -194,8 +217,12 @@ static int ipvrf_pids(int argc, char **argv)
 	if (!mnt)
 		return -1;
 
-	ret = recurse_dir(mnt, vrf);
+	if (ipvrf_get_netns(netns, sizeof(netns)) < 0)
+		goto out;
+
+	ret = recurse_dir(mnt, vrf, netns);
 
+out:
 	free(mnt);
 
 	return ret;
@@ -316,7 +343,7 @@ static int vrf_path(char *vpath, size_t len)
 static int vrf_switch(const char *name)
 {
 	char path[PATH_MAX], *mnt, pid[16];
-	char vpath[PATH_MAX];
+	char vpath[PATH_MAX], netns[256];
 	int ifindex = 0;
 	int rc = -1, len, fd = -1;
 
@@ -332,17 +359,37 @@ static int vrf_switch(const char *name)
 	if (!mnt)
 		return -1;
 
+	/* -1 on length to add '/' to the end */
+	if (ipvrf_get_netns(netns, sizeof(netns) - 1) < 0)
+		return -1;
+
 	if (vrf_path(vpath, sizeof(vpath)) < 0) {
 		fprintf(stderr, "Failed to get base cgroup path: %s\n",
 			strerror(errno));
 		return -1;
 	}
 
+	/* if path already ends in netns then don't add it again */
+	if (*netns != '\0') {
+		char *pdir = strrchr(vpath, '/');
+
+		if (!pdir)
+			pdir = vpath;
+		else
+			pdir++;
+
+		if (strcmp(pdir, netns) == 0)
+			*pdir = '\0';
+
+		strcat(netns, "/");
+	}
+
 	/* path to cgroup; make sure buffer has room to cat "/cgroup.procs"
 	 * to the end of the path
 	 */
 	len = snprintf(path, sizeof(path) - sizeof(CGRP_PROC_FILE),
-		       "%s%s/vrf/%s", mnt, vpath, ifindex ? name : "");
+		       "%s%s/%svrf/%s",
+		       mnt, vpath, netns, ifindex ? name : "");
 	if (len > sizeof(path) - sizeof(CGRP_PROC_FILE)) {
 		fprintf(stderr, "Invalid path to cgroup2 mount\n");
 		goto out;
-- 
2.1.4

  parent reply	other threads:[~2017-02-16 16:59 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-02-16 16:58 [PATCH iproute2 0/4] ip vrf: updates to handle cgroup hiearchy and namespace nesting David Ahern
2017-02-16 16:58 ` [PATCH iproute2 1/4] ip vrf: Handle vrf in a cgroup hierarchy David Ahern
2017-02-16 16:58 ` [PATCH iproute2 2/4] ip netns: refactor netns_identify David Ahern
2017-02-16 16:58 ` David Ahern [this message]
2017-02-16 16:58 ` [PATCH iproute2 4/4] ip vrf: Detect invalid vrf name in pids command David Ahern
2017-02-19  0:11 ` [PATCH iproute2 0/4] ip vrf: updates to handle cgroup hiearchy and namespace nesting Stephen Hemminger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1487264338-17588-4-git-send-email-dsa@cumulusnetworks.com \
    --to=dsa@cumulusnetworks.com \
    --cc=luto@amacapital.net \
    --cc=netdev@vger.kernel.org \
    --cc=stephen@networkplumber.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).