[CRIU] [PATCH 12/12] test: check veth devices from two network namespaces

Andrei Vagin avagin at openvz.org
Tue Mar 21 17:28:53 PDT 2017


From: Andrei Vagin <avagin at virtuozzo.com>

We shave a test case for external veth devices. This test case
checks veth devices which are living in two dumped network
namespaces.

Signed-off-by: Andrei Vagin <avagin at virtuozzo.com>
---
 test/zdtm/static/Makefile            |   3 +
 test/zdtm/static/netns_sub_veth.c    | 179 +++++++++++++++++++++++++++++++++++
 test/zdtm/static/netns_sub_veth.desc |   6 ++
 3 files changed, 188 insertions(+)
 create mode 100644 test/zdtm/static/netns_sub_veth.c
 create mode 100644 test/zdtm/static/netns_sub_veth.desc

diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile
index 02bf54d..afbda07 100644
--- a/test/zdtm/static/Makefile
+++ b/test/zdtm/static/Makefile
@@ -180,6 +180,7 @@ TST_NOFILE	:=				\
 		userns00			\
 		userns01			\
 		userns02			\
+		netns_sub_veth			\
 #		jobctl00			\
 
 ifneq ($(SRCARCH),arm)
@@ -454,6 +455,8 @@ stopped01:	override CFLAGS += -DZDTM_STOPPED_KILL
 stopped02:	override CFLAGS += -DZDTM_STOPPED_TKILL
 stopped12:	override CFLAGS += -DZDTM_STOPPED_KILL -DZDTM_STOPPED_TKILL
 clone_fs:		override LDLIBS += -pthread
+netns_sub_veth:		override CFLAGS += -I/usr/include/libnl3
+netns_sub_veth:		override LDLIBS += -lnl-3 -l nl-route-3
 
 socket-tcp-fin-wait1:	override CFLAGS += -D ZDTM_TCP_FIN_WAIT1
 socket-tcp-fin-wait2:	override CFLAGS += -D ZDTM_TCP_FIN_WAIT2
diff --git a/test/zdtm/static/netns_sub_veth.c b/test/zdtm/static/netns_sub_veth.c
new file mode 100644
index 0000000..6262456
--- /dev/null
+++ b/test/zdtm/static/netns_sub_veth.c
@@ -0,0 +1,179 @@
+#define _GNU_SOURCE
+#include <sched.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <linux/if.h>
+#include <sys/ioctl.h>
+
+#include <netinet/ether.h>
+#include <netlink/netlink.h>
+#include <netlink/route/link.h>
+
+#include "zdtmtst.h"
+
+const char *test_doc	= "Check dump and restore a few network namespaces";
+
+#define ID_MAP "0 0 1"
+static int init_proc_id_maps(pid_t pid)
+{
+	char path[128];
+	int fd;
+
+	snprintf(path, sizeof(path), "/proc/%d/uid_map", pid);
+	fd = open(path, O_WRONLY);
+	if (fd < 0) {
+		pr_perror("Unable to open %s", path);
+		return -1;
+	}
+	if (write(fd, ID_MAP, sizeof(ID_MAP)) != sizeof(ID_MAP)) {
+		pr_perror("Unable to write into %s", path);
+		return -1;
+	}
+	close(fd);
+
+	snprintf(path, sizeof(path), "/proc/%d/gid_map", pid);
+	fd = open(path, O_WRONLY);
+	if (fd < 0) {
+		pr_perror("Unable to open %s", path);
+		return -1;
+	}
+	if (write(fd, ID_MAP, sizeof(ID_MAP)) != sizeof(ID_MAP)) {
+		pr_perror("Unable to write into %s", path);
+		return -1;
+	}
+	close(fd);
+
+	return 0;
+}
+
+#ifndef NSIO
+#define NSIO    0xb7
+#define NS_GET_USERNS   _IO(NSIO, 0x1)
+#define NS_GET_PARENT   _IO(NSIO, 0x2)
+#endif
+
+int main(int argc, char **argv)
+{
+	task_waiter_t lock;
+	pid_t pid[2];
+	int status = -1, ret, i;
+        struct rtnl_link *link = NULL, *new;
+	struct nl_sock *sk;
+	int has_index = 1;
+	bool userns;
+
+	test_init(argc, argv);
+	task_waiter_init(&lock);
+
+	userns = getenv("ZDTM_USERNS") != NULL;
+	if (userns) {
+		int fd, ufd;
+		fd = open("/proc/self/ns/net", O_RDONLY);
+		if (fd < 0) {
+			pr_perror("Unable to open /proc/self/ns/net");
+			return 1;
+		}
+		ufd = ioctl(fd, NS_GET_USERNS);
+		if (ufd < 0) {
+			userns = false;
+		} else
+			close(ufd);
+		close(fd);
+	}
+
+	for (i = 0; i < 2; i++) {
+		pid[i] = fork();
+		if (pid[i] < 0) {
+			pr_perror("fork");
+			return -1;
+		}
+		if (pid[i] == 0) {
+			if (userns && unshare(CLONE_NEWUSER))
+				return 1;
+			if (unshare(CLONE_NEWNET))
+				return 1;
+
+			task_waiter_complete(&lock, i);
+			test_waitsig();
+
+			return 0;
+		}
+		task_waiter_wait4(&lock, i);
+		if (userns && init_proc_id_maps(pid[i]))
+			return 1;
+	}
+
+	sk = nl_socket_alloc();
+	if (sk == NULL)
+		return -1;
+
+	ret = nl_connect(sk, NETLINK_ROUTE);
+	if (ret < 0) {
+		nl_socket_free(sk);
+		pr_err("Unable to connect socket: %s", nl_geterror(ret));
+		return -1;
+	}
+
+	if (system("ip link add name zdtmbr type bridge"))
+		return -1;
+
+	for (i = 0; i < 2; i++) {
+		char cmd[4096];
+
+		snprintf(cmd, sizeof(cmd), "ip link add name zdtm%d index %d netns %d type veth peer name zdtm%d index %d",
+				i, i * 10 + 12, pid[i], i, i * 10 + 12);
+		if (system(cmd)) {
+			has_index = 0;
+			snprintf(cmd, sizeof(cmd), "ip link add name zdtm%d netns %d type veth peer name zdtm%d", i, pid[i], i);
+			if (system(cmd))
+				return 1;
+		}
+		snprintf(cmd, sizeof(cmd), "ip link set dev zdtm%d master zdtmbr", i);
+		if (system(cmd))
+			return 1;
+	}
+
+	test_daemon();
+	test_waitsig();
+
+	for (i = 0; i < 2; i++) {
+		link = rtnl_link_alloc();
+		new = rtnl_link_alloc();
+		if (has_index)
+			rtnl_link_set_ifindex(link, i * 10 + 12);
+		else {
+			char name[43];
+			snprintf(name, sizeof(name), "zdtm%d", i);
+			rtnl_link_set_name(link, name);
+			rtnl_link_set_name(new, name);
+		}
+		rtnl_link_set_flags(new, IFF_UP);
+		ret = rtnl_link_change(sk, link, new, 0);
+		if (ret) {
+			fail("Unable to up the link: %s", nl_geterror(ret));
+			return 1;
+		}
+	}
+
+	for (i = 0; i < 2; i++) {
+		kill(pid[i], SIGTERM);
+		waitpid(pid[i], &status, 0);
+		if (status) {
+			fail();
+			return 1;
+		}
+	}
+
+	pass();
+	return 0;
+}
diff --git a/test/zdtm/static/netns_sub_veth.desc b/test/zdtm/static/netns_sub_veth.desc
new file mode 100644
index 0000000..ea9e15c
--- /dev/null
+++ b/test/zdtm/static/netns_sub_veth.desc
@@ -0,0 +1,6 @@
+{
+	'deps': ['/sbin/ip', '/bin/sh'],
+	'flags': 'suid',
+	'flavor': 'ns uns',
+	'feature': 'link_nsid',
+}
-- 
2.7.4



More information about the CRIU mailing list