[5/6] veth: Make --external support --veth-pair

Submitted by Pavel Emelianov on Sept. 20, 2016, 1:26 p.m.

Details

Message ID 57E1391F.6060106@virtuozzo.com
State Rejected
Series "Unify external resources in CLI"
Headers show

Commit Message

Pavel Emelianov Sept. 20, 2016, 1:26 p.m.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
---
 criu/crtools.c            |   5 +-
 criu/include/cr_options.h |   1 -
 criu/net.c                | 123 +++++++++++++++++++++++++---------------------
 images/rpc.proto          |   2 +-
 4 files changed, 68 insertions(+), 63 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/crtools.c b/criu/crtools.c
index 6c3c3b5..53fce47 100644
--- a/criu/crtools.c
+++ b/criu/crtools.c
@@ -59,7 +59,6 @@  void init_opts(void)
 	/* Default options */
 	opts.final_state = TASK_DEAD;
 	INIT_LIST_HEAD(&opts.ext_unixsk_ids);
-	INIT_LIST_HEAD(&opts.veth_pairs);
 	INIT_LIST_HEAD(&opts.ext_mounts);
 	INIT_LIST_HEAD(&opts.inherit_fds);
 	INIT_LIST_HEAD(&opts.external);
@@ -835,6 +834,7 @@  usage:
 "                            dev[maj:min]:VAL\n"
 "                        Formats of RES on restore:\n"
 "                            dev[VAL]:DEVPATH\n"
+"                            veth[IFNAME]:OUTNAME{@BRIDGE}\n"
 "\n"
 "* Special resources support:\n"
 "  -x|--" USK_EXT_PARAM " [inode,...]\n"
@@ -845,9 +845,6 @@  usage:
 "  -r|--root PATH        change the root filesystem (when run in mount namespace)\n"
 "  --evasive-devices     use any path to a device file if the original one\n"
 "                        is inaccessible\n"
-"  --veth-pair IN=OUT    map inside veth device name to outside one\n"
-"                        can optionally append @<bridge-name> to OUT for moving\n"
-"                        the outside veth to the named bridge\n"
 "  --link-remap          allow one to link unlinked files back when possible\n"
 "  --ghost-limit size    limit max size of deleted file contents inside image\n"
 "  --action-script FILE  add an external action script\n"
diff --git a/criu/include/cr_options.h b/criu/include/cr_options.h
index 7711a7a..95dd878 100644
--- a/criu/include/cr_options.h
+++ b/criu/include/cr_options.h
@@ -72,7 +72,6 @@  struct cr_options {
 	char			*root;
 	char			*pidfile;
 	char			*freeze_cgroup;
-	struct list_head	veth_pairs;
 	struct list_head	ext_mounts;
 	struct list_head	inherit_fds;
 	struct list_head	external;
diff --git a/criu/net.c b/criu/net.c
index 080c617..564ca6d 100644
--- a/criu/net.c
+++ b/criu/net.c
@@ -29,6 +29,7 @@ 
 #include "string.h"
 #include "sysctl.h"
 #include "kerndat.h"
+#include "external.h"
 
 #include "protobuf.h"
 #include "images/netdev.pb-c.h"
@@ -904,12 +905,25 @@  enum {
 #define IFLA_NET_NS_FD	28
 #endif
 
+static void veth_peer_info(NetDeviceEntry *nde, struct newlink_req *req)
+{
+	char key[100], *val;
+
+	snprintf(key, sizeof(key), "veth[%s]", nde->name);
+	val = external_lookup_by_key(key);
+	if (!IS_ERR_OR_NULL(val)) {
+		char *aux;
+
+		aux = strchrnul(val, '@');
+		addattr_l(&req->h, sizeof(*req), IFLA_IFNAME, val, aux - val - 1);		
+	}
+}
+
 static int veth_link_info(NetDeviceEntry *nde, struct newlink_req *req)
 {
 	int ns_fd = get_service_fd(NS_FD_OFF);
 	struct rtattr *veth_data, *peer_data;
 	struct ifinfomsg ifm;
-	struct veth_pair *n;
 
 	BUG_ON(ns_fd < 0);
 
@@ -920,12 +934,7 @@  static int veth_link_info(NetDeviceEntry *nde, struct newlink_req *req)
 	peer_data = NLMSG_TAIL(&req->h);
 	memset(&ifm, 0, sizeof(ifm));
 	addattr_l(&req->h, sizeof(*req), VETH_INFO_PEER, &ifm, sizeof(ifm));
-	list_for_each_entry(n, &opts.veth_pairs, node) {
-		if (!strcmp(nde->name, n->inside))
-			break;
-	}
-	if (&n->node != &opts.veth_pairs)
-		addattr_l(&req->h, sizeof(*req), IFLA_IFNAME, n->outside, strlen(n->outside));
+	veth_peer_info(nde, req);
 	addattr_l(&req->h, sizeof(*req), IFLA_NET_NS_FD, &ns_fd, sizeof(ns_fd));
 	peer_data->rta_len = (void *)NLMSG_TAIL(&req->h) - (void *)peer_data;
 	veth_data->rta_len = (void *)NLMSG_TAIL(&req->h) - (void *)veth_data;
@@ -1620,33 +1629,11 @@  void network_unlock(void)
 
 int veth_pair_add(char *in, char *out)
 {
-	char *aux;
-	struct veth_pair *n;
-
-	n = xmalloc(sizeof(*n));
-	if (n == NULL)
-		return -1;
-
-	n->inside = in;
-	n->outside = out;
-	/*
-	 * Does the out string specify a bridge for
-	 * moving the outside end of the veth pair to?
-	 */
-	aux = strrchr(out, '@');
-	if (aux) {
-		*aux++ = '\0';
-		n->bridge = aux;
-	} else {
-		n->bridge = NULL;
-	}
+	char *e_str;
 
-	list_add(&n->node, &opts.veth_pairs);
-	if (n->bridge)
-		pr_debug("Added %s:%s@%s veth map\n", in, out, aux);
-	else
-		pr_debug("Added %s:%s veth map\n", in, out);
-	return 0;
+	e_str = xmalloc(200); /* For 3 IFNAMSIZ + 8 service characters */
+	snprintf(e_str, 200, "veth[%s]:%s", in, out);
+	return add_external(e_str);
 }
 
 /*
@@ -1727,20 +1714,26 @@  int collect_net_namespaces(bool for_dump)
 
 struct ns_desc net_ns_desc = NS_DESC_ENTRY(CLONE_NEWNET, "net");
 
-int move_veth_to_bridge(void)
+static int move_to_bridge(struct external *ext, void *arg)
 {
-	int s;
+	int s = *(int *)arg;
 	int ret;
-	struct veth_pair *n;
+	char *out, *br;
 	struct ifreq ifr;
 
-	s = -1;
-	ret = 0;
-	list_for_each_entry(n, &opts.veth_pairs, node) {
-		if (n->bridge == NULL)
-			continue;
+	out = external_val(ext);
+	if (!out)
+		return -1;
+
+	br = strchr(out, '@');
+	if (!br)
+		return 0;
 
-		pr_debug("\tMoving dev %s to bridge %s\n", n->outside, n->bridge);
+	*br = '\0';
+	br++;
+
+	{
+		pr_debug("\tMoving dev %s to bridge %s\n", out, br);
 
 		if (s == -1) {
 			s = socket(AF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC, 0);
@@ -1754,18 +1747,17 @@  int move_veth_to_bridge(void)
 		 * Add the device to the bridge. This is equivalent to:
 		 * $ brctl addif <bridge> <device>
 		 */
-		ifr.ifr_ifindex = if_nametoindex(n->outside);
+		ifr.ifr_ifindex = if_nametoindex(out);
 		if (ifr.ifr_ifindex == 0) {
-			pr_perror("Can't get index of %s", n->outside);
+			pr_perror("Can't get index of %s", out);
 			ret = -1;
-			break;
+			goto out;
 		}
-		strlcpy(ifr.ifr_name, n->bridge, IFNAMSIZ);
+		strlcpy(ifr.ifr_name, br, IFNAMSIZ);
 		ret = ioctl(s, SIOCBRADDIF, &ifr);
 		if (ret < 0) {
-			pr_perror("Can't add interface %s to bridge %s",
-				n->outside, n->bridge);
-			break;
+			pr_perror("Can't add interface %s to bridge %s", out, br);
+			goto out;
 		}
 
 		/*
@@ -1773,24 +1765,41 @@  int move_veth_to_bridge(void)
 		 * $ ip link set dev <device> up
 		 */
 		ifr.ifr_ifindex = 0;
-		strlcpy(ifr.ifr_name, n->outside, IFNAMSIZ);
+		strlcpy(ifr.ifr_name, out, IFNAMSIZ);
 		ret = ioctl(s, SIOCGIFFLAGS, &ifr);
 		if (ret < 0) {
-			pr_perror("Can't get flags of interface %s", n->outside);
-			break;
+			pr_perror("Can't get flags of interface %s", out);
+			goto out;
 		}
+
+		ret = 0;
 		if (ifr.ifr_flags & IFF_UP)
-			continue;
+			goto out;
+
 		ifr.ifr_flags |= IFF_UP;
 		ret = ioctl(s, SIOCSIFFLAGS, &ifr);
 		if (ret < 0) {
 			pr_perror("Can't set flags of interface %s to 0x%x",
-				n->outside, ifr.ifr_flags);
-			break;
+				out, ifr.ifr_flags);
+			goto out;
 		}
+
+		ret = 0;
 	}
+out:
+	br--;
+	*br = '@';
+	*(int *)arg = s;
+	return ret;
+}
+
+int move_veth_to_bridge(void)
+{
+	int sk = -1, ret;
+
+	ret = external_for_each_type("veth", move_to_bridge, &sk);
+	if (sk >= 0)
+		close(sk);
 
-	if (s >= 0)
-		close(s);
 	return ret;
 }
diff --git a/images/rpc.proto b/images/rpc.proto
index 9b36178..0ae130c 100644
--- a/images/rpc.proto
+++ b/images/rpc.proto
@@ -71,7 +71,7 @@  message criu_opts {
 
 	optional int32			work_dir_fd	= 17;
 	optional bool			link_remap	= 18;
-	repeated criu_veth_pair		veths		= 19;
+	repeated criu_veth_pair		veths		= 19; /* DEPRECATED, use external instead */
 
 	optional uint32			cpu_cap		= 20 [default = 0xffffffff];
 	optional bool			force_irmap	= 21;