[lxc-devel] [PATCH] fill missing netdev fields for unprivileged containers

S.Çağlar Onur caglar at 10ur.org
Sun Feb 16 21:20:48 UTC 2014


lxc-user-nic now returns the names of the interfaces and
unpriv_assign_nic function parses that information to fill
missing netdev->veth_attr.pair and netdev->name.

With this patch get_running_config_item started to provide
correct information;

>>> import lxc; c = lxc.Container("rubik"); c.get_running_config_item("lxc.network.0.name"); c.get_running_config_item("lxc.network.0.veth.pair");
'eth0'
'veth9MT2L4'
>>>

and lxc-info started to show network stats;

lxc-info -n rubik
Name:           rubik
State:          RUNNING
PID:            23061
IP:             10.0.3.233
CPU use:        3.86 seconds
BlkIO use:      88.00 KiB
Memory use:     6.53 MiB
KMem use:       0 bytes
Link:           veth9MT2L4
 TX bytes:      3.45 KiB
 RX bytes:      8.83 KiB
 Total bytes:   12.29 KiB

Signed-off-by: S.Çağlar Onur <caglar at 10ur.org>
---
 src/lxc/conf.c         | 67 ++++++++++++++++++++++++++++++++++++++++++--------
 src/lxc/lxc_user_nic.c |  2 ++
 2 files changed, 59 insertions(+), 10 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index e5df68b..10f46ae 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -3014,6 +3014,10 @@ void lxc_delete_network(struct lxc_handler *handler)
 static int unpriv_assign_nic(struct lxc_netdev *netdev, pid_t pid)
 {
 	pid_t child;
+	int bytes, pipefd[2];
+	char *token, *saveptr = NULL;
+	/* lxc-user-nic returns "interface_name:interface_name" format */
+	char buffer[IFNAMSIZ*2 + 1];
 
 	if (netdev->type != LXC_NET_VETH) {
 		ERROR("nic type %d not support for unprivileged use",
@@ -3021,23 +3025,66 @@ static int unpriv_assign_nic(struct lxc_netdev *netdev, pid_t pid)
 		return -1;
 	}
 
+	if(pipe(pipefd) < 0) {
+		SYSERROR("pipe failed");
+		return -1;
+	}
+
 	if ((child = fork()) < 0) {
 		SYSERROR("fork");
+		close(pipefd[0]);
+		close(pipefd[1]);
+		return -1;
+	}
+
+	if (child == 0) { // child
+		/* close the read-end of the pipe */
+		close(pipefd[0]);
+		/* redirect the stdout to write-end of the pipe */
+		dup2(pipefd[1], STDOUT_FILENO);
+		/* close the write-end of the pipe */
+		close(pipefd[0]);
+
+		// Call lxc-user-nic pid type bridge
+		char pidstr[20];
+		char *args[] = {LXC_USERNIC_PATH, pidstr, "veth", netdev->link, netdev->name, NULL };
+		snprintf(pidstr, 19, "%lu", (unsigned long) pid);
+		pidstr[19] = '\0';
+		execvp(args[0], args);
+		SYSERROR("execvp lxc-user-nic");
+		exit(1);
+	}
+
+	/* close the write-end of the pipe */
+	close(pipefd[1]);
+
+	bytes = read(pipefd[0], &buffer, IFNAMSIZ*2 + 1);
+	if (bytes < 0) {
+		SYSERROR("read failed");
+	}
+	buffer[bytes - 1] = '\0';
+
+	if (wait_for_pid(child) != 0) {
+		close(pipefd[0]);
 		return -1;
 	}
 
-	if (child > 0)
-		return wait_for_pid(child);
+	/* close the read-end of the pipe */
+	close(pipefd[0]);
+
+	/* fill netdev->name field */
+	token = strtok_r(buffer, ":", &saveptr);
+	if (!token)
+		return -1;
+	netdev->name = strdup(token);
 
-	// Call lxc-user-nic pid type bridge
+	/* fill netdev->veth_attr.pair field */
+	token = strtok_r(NULL, ":", &saveptr);
+	if (!token)
+		return -1;
+	netdev->priv.veth_attr.pair = strdup(token);
 
-	char pidstr[20];
-	char *args[] = {LXC_USERNIC_PATH, pidstr, "veth", netdev->link, netdev->name, NULL };
-	snprintf(pidstr, 19, "%lu", (unsigned long) pid);
-	pidstr[19] = '\0';
-	execvp(args[0], args);
-	SYSERROR("execvp lxc-user-nic");
-	exit(1);
+	return 0;
 }
 
 int lxc_assign_network(struct lxc_list *network, pid_t pid)
diff --git a/src/lxc/lxc_user_nic.c b/src/lxc/lxc_user_nic.c
index a2f0c96..ce79177 100644
--- a/src/lxc/lxc_user_nic.c
+++ b/src/lxc/lxc_user_nic.c
@@ -599,5 +599,7 @@ int main(int argc, char *argv[])
 		exit(1);
 	}
 
+	// write the name of the interface pair to the stdout - like eth0:veth9MT2L4
+	fprintf(stdout, "%s:%s\n", vethname, nicname);
 	exit(0);
 }
-- 
1.8.3.2



More information about the lxc-devel mailing list