summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-04-25 17:36:51 +0200
committerDaniel Mack <github@zonque.org>2016-04-25 17:36:51 +0200
commitd2773e59de3dd970d861e9f996bc48de20ef4314 (patch)
treed971c138bb0cbf5a421a6e4ebe7c41330685a361
parent4f4d6ee4be1c5d3bb2f3ebce7d2d332285963830 (diff)
nspawn: explicitly remove veth links after use (#3111)
* sd-netlink: permit RTM_DELLINK messages with no ifindex This is useful for removing network interfaces by name. * nspawn: explicitly remove veth links we created after use 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
-rw-r--r--src/libsystemd/sd-netlink/rtnl-message.c1
-rw-r--r--src/nspawn/nspawn-network.c47
-rw-r--r--src/nspawn/nspawn-network.h2
-rw-r--r--src/nspawn/nspawn.c2
4 files changed, 51 insertions, 1 deletions
diff --git a/src/libsystemd/sd-netlink/rtnl-message.c b/src/libsystemd/sd-netlink/rtnl-message.c
index 255526bf32..f251536a89 100644
--- a/src/libsystemd/sd-netlink/rtnl-message.c
+++ b/src/libsystemd/sd-netlink/rtnl-message.c
@@ -402,7 +402,6 @@ int sd_rtnl_message_new_link(sd_netlink *rtnl, sd_netlink_message **ret,
int r;
assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
- assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
assert_return(ret, -EINVAL);
r = message_new(rtnl, ret, nlmsg_type);
diff --git a/src/nspawn/nspawn-network.c b/src/nspawn/nspawn-network.c
index 74a0ae865b..f2b7e4dd79 100644
--- a/src/nspawn/nspawn-network.c
+++ b/src/nspawn/nspawn-network.c
@@ -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;
+}
diff --git a/src/nspawn/nspawn-network.h b/src/nspawn/nspawn-network.h
index 9ab1606d1c..c5036ab470 100644
--- a/src/nspawn/nspawn-network.h
+++ b/src/nspawn/nspawn-network.h
@@ -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);
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index e1d37d383a..d687df8a09 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -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);