]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
lxc: manually move NICs back to host after container stops
authorSerge Hallyn <serge.hallyn@ubuntu.com>
Fri, 7 Mar 2014 18:24:27 +0000 (12:24 -0600)
committerStéphane Graber <stgraber@ubuntu.com>
Fri, 7 Mar 2014 19:28:38 +0000 (14:28 -0500)
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@ubuntu.com>
Acked-by: Stéphane Graber <stgraber@ubuntu.com>
src/lxc/conf.c
src/lxc/conf.h
src/lxc/start.c

index 1cb058d0c02636d43d87b8369006f139ddc6da48..58a9b4f275eeeab76c2643097dddf4a22dcb07f3 100644 (file)
@@ -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);
index 4591470df9121fb980e9b6b0394bcee50570e056..28042121bf2806583d206cc1a95ba840ba7b5471 100644 (file)
@@ -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);
index eb1c6595581b4385932b120b8676db8fdb85d6f2..bae01e49c33cc93ef2c38688d9d058a3b9266b23 100644 (file)
@@ -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);