]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
nspawn: explicitly remove veth links we created after use 3111/head
authorLennart Poettering <lennart@poettering.net>
Mon, 25 Apr 2016 11:42:20 +0000 (13:42 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 25 Apr 2016 11:44:24 +0000 (13:44 +0200)
Sometimes the kernel keeps veth links pinned after the namespace they have been
joined to died. Let's hence explicitly remove veth links after use.

Fixes: #2173
src/nspawn/nspawn-network.c
src/nspawn/nspawn-network.h
src/nspawn/nspawn.c

index 74a0ae865b40f929c36865d5917b9bcf20da9747..f2b7e4dd797ccfb1ec638a27bb3b15d5fb65c781 100644 (file)
@@ -538,3 +538,50 @@ int veth_extra_parse(char ***l, const char *p) {
         a = b = NULL;
         return 0;
 }
+
+static int remove_one_veth_link(sd_netlink *rtnl, const char *name) {
+        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
+        int r;
+
+        if (isempty(name))
+                return 0;
+
+        r = sd_rtnl_message_new_link(rtnl, &m, RTM_DELLINK, 0);
+        if (r < 0)
+                return log_error_errno(r, "Failed to allocate netlink message: %m");
+
+        r = sd_netlink_message_append_string(m, IFLA_IFNAME, name);
+        if (r < 0)
+                return log_error_errno(r, "Failed to add netlink interface name: %m");
+
+        r = sd_netlink_call(rtnl, m, 0, NULL);
+        if (r == -ENODEV) /* Already gone */
+                return 0;
+        if (r < 0)
+                return log_error_errno(r, "Failed to remove veth interface %s: %m", name);
+
+        return 1;
+}
+
+int remove_veth_links(const char *primary, char **pairs) {
+        _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL;
+        char **a, **b;
+        int r;
+
+        /* In some cases the kernel might pin the veth links between host and container even after the namespace
+         * died. Hence, let's better remove them explicitly too. */
+
+        if (isempty(primary) && strv_isempty(pairs))
+                return 0;
+
+        r = sd_netlink_open(&rtnl);
+        if (r < 0)
+                return log_error_errno(r, "Failed to connect to netlink: %m");
+
+        remove_one_veth_link(rtnl, primary);
+
+        STRV_FOREACH_PAIR(a, b, pairs)
+                remove_one_veth_link(rtnl, *a);
+
+        return 0;
+}
index 9ab1606d1c5a8ae67c54eb4ffd24b4a400eb5522..c5036ab470e2dea5558f718b665f4a9cef39959c 100644 (file)
@@ -34,3 +34,5 @@ int setup_ipvlan(const char *machine_name, pid_t pid, char **ifaces);
 int move_network_interfaces(pid_t pid, char **ifaces);
 
 int veth_extra_parse(char ***l, const char *p);
+
+int remove_veth_links(const char *primary, char **pairs);
index e1d37d383a2eaa09554688e2be748496ebe72955..d687df8a091231727de30925a31e982fe4ce702b 100644 (file)
@@ -3713,6 +3713,7 @@ int main(int argc, char *argv[]) {
                 }
 
                 expose_port_flush(arg_expose_ports, &exposed);
+                (void) remove_veth_links(veth_name, arg_network_veth_extra);
         }
 
 finish:
@@ -3745,6 +3746,7 @@ finish:
         }
 
         expose_port_flush(arg_expose_ports, &exposed);
+        (void) remove_veth_links(veth_name, arg_network_veth_extra);
 
         free(arg_directory);
         free(arg_template);