From 9fb0bd805e883f294eab3cb41cbba80ff2062616 Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Sat, 17 Dec 2016 06:30:41 +0300 Subject: [PATCH] test: check veth devices from two network namespaces 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 --- test/zdtm/static/Makefile | 1 + test/zdtm/static/netns_sub_veth.c | 179 +++++++++++++++++++++++++++ test/zdtm/static/netns_sub_veth.desc | 6 + 3 files changed, 186 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 555400a82..04ed36a5d 100644 --- a/test/zdtm/static/Makefile +++ b/test/zdtm/static/Makefile @@ -196,6 +196,7 @@ TST_NOFILE := \ userns00 \ userns01 \ userns02 \ + netns_sub_veth \ # jobctl00 \ include ../Makefile.inc diff --git a/test/zdtm/static/netns_sub_veth.c b/test/zdtm/static/netns_sub_veth.c new file mode 100644 index 000000000..626245604 --- /dev/null +++ b/test/zdtm/static/netns_sub_veth.c @@ -0,0 +1,179 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 000000000..ea9e15c8a --- /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', +}