[lxc-devel] [PATCH 1/1] lxc: manually move NICs back to host after container stops

Serge Hallyn serge.hallyn at ubuntu.com
Fri Mar 7 18:24:27 UTC 2014


This prevents things like bridges from being destroyed by the kernel.

My hope is that just doing this will be enough to also ensure that
the device will be available to be renamed immediately, so that
we don't need to do a retry loop.

Tested with a dummy device.  renaming dummy0 to dummy5 in container,
then shutting down container, returns dummy0 to the host.

Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
 src/lxc/conf.c  | 40 +++++++++++++++++++++++++++++++++++++++-
 src/lxc/conf.h  |  2 +-
 src/lxc/start.c | 26 +++++++++++++++++++++++++-
 3 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 1cb058d..58a9b4f 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2558,11 +2558,49 @@ static int setup_network(struct lxc_list *network)
 	return 0;
 }
 
-void lxc_rename_phys_nics_on_shutdown(struct lxc_conf *conf)
+/* try to move physical nics to the init netns */
+void restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf)
+{
+	int i, ret, oldfd;
+	char path[MAXPATHLEN];
+
+	if (netnsfd < 0)
+		return;
+
+	ret = snprintf(path, MAXPATHLEN, "/proc/self/ns/net");
+	if (ret < 0 || ret >= MAXPATHLEN) {
+		WARN("Failed to open monitor netns fd");
+		return;
+	}
+	if ((oldfd = open(path, O_RDONLY)) < 0) {
+		SYSERROR("Failed to open monitor netns fd");
+		return;
+	}
+	if (setns(netnsfd, 0) != 0) {
+		SYSERROR("Failed to enter container netns to reset nics");
+		close(oldfd);
+		return;
+	}
+	for (i=0; i<conf->num_savednics; i++) {
+		struct saved_nic *s = &conf->saved_nics[i];
+		if (lxc_netdev_move_by_index(s->ifindex, 1))
+			WARN("Error moving nic index:%d back to host netns",
+					s->ifindex);
+	}
+	if (setns(oldfd, 0) != 0)
+		SYSERROR("Failed to re-enter monitor's netns");
+	close(oldfd);
+}
+
+void lxc_rename_phys_nics_on_shutdown(int netnsfd, struct lxc_conf *conf)
 {
 	int i;
 
+	if (conf->num_savednics == 0)
+		return;
+
 	INFO("running to reset %d nic names", conf->num_savednics);
+	restore_phys_nics_to_netns(netnsfd, conf);
 	for (i=0; i<conf->num_savednics; i++) {
 		struct saved_nic *s = &conf->saved_nics[i];
 		INFO("resetting nic %d to %s", s->ifindex, s->orig_name);
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index 4591470..2804212 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -369,7 +369,7 @@ extern int lxc_clear_groups(struct lxc_conf *c);
 struct cgroup_process_info;
 extern int lxc_setup(struct lxc_handler *handler);
 
-extern void lxc_rename_phys_nics_on_shutdown(struct lxc_conf *conf);
+extern void lxc_rename_phys_nics_on_shutdown(int netnsfd, struct lxc_conf *conf);
 
 extern int find_unmapped_nsuid(struct lxc_conf *conf, enum idtype idtype);
 extern int mapped_hostid(unsigned id, struct lxc_conf *conf, enum idtype idtype);
diff --git a/src/lxc/start.c b/src/lxc/start.c
index eb1c659..bae01e4 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -1000,12 +1000,33 @@ out_abort:
 	return -1;
 }
 
+int get_netns_fd(int pid)
+{
+	char path[MAXPATHLEN];
+	int ret, fd;
+
+	ret = snprintf(path, MAXPATHLEN, "/proc/%d/ns/net", pid);
+	if (ret < 0 || ret >= MAXPATHLEN) {
+		WARN("Failed to pin netns file for pid %d", pid);
+		return -1;
+	}
+
+	fd = open(path, O_RDONLY);
+	if (fd < 0) {
+		WARN("Failed to pin netns file %s for pid %d: %s",
+				path, pid, strerror(errno));
+		return -1;
+	}
+	return fd;
+}
+
 int __lxc_start(const char *name, struct lxc_conf *conf,
 		struct lxc_operations* ops, void *data, const char *lxcpath)
 {
 	struct lxc_handler *handler;
 	int err = -1;
 	int status;
+	int netnsfd = -1;
 
 	handler = lxc_init(name, conf, lxcpath);
 	if (!handler) {
@@ -1032,6 +1053,8 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
 		goto out_fini_nonet;
 	}
 
+	netnsfd = get_netns_fd(handler->pid);
+
 	err = lxc_poll(name, handler);
 	if (err) {
 		ERROR("mainloop exited with an error");
@@ -1065,7 +1088,8 @@ int __lxc_start(const char *name, struct lxc_conf *conf,
 		}
         }
 
-	lxc_rename_phys_nics_on_shutdown(handler->conf);
+	lxc_rename_phys_nics_on_shutdown(netnsfd, handler->conf);
+	close(netnsfd);
 
 	if (handler->pinfd >= 0) {
 		close(handler->pinfd);
-- 
1.9.0



More information about the lxc-devel mailing list