summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrediano Ziglio <fziglio@redhat.com>2016-10-11 13:05:57 +0100
committerFrediano Ziglio <fziglio@redhat.com>2016-10-11 13:06:15 +0100
commit5fe7fcb3d758b8cd1e73de153ef3dacdf25379aa (patch)
treec5e30c9919c868a1897a9f6ba9c88ac1140e1cd5
parent7f3912b19cbc8a3865d5d24cde179af76d324a72 (diff)
Make test work even for remote case
Use network namespaces to test the remote case using a single machine. Server is run in a subprocess with a different namespace. Client and server are connected with a veth interface. Signed-off-by: Frediano Ziglio <fziglio@redhat.com>
-rw-r--r--tests/bandwidth.c21
-rw-r--r--tests/common.c160
-rw-r--r--tests/common.h4
-rw-r--r--tests/delay.c21
-rw-r--r--tests/ping.c4
5 files changed, 186 insertions, 24 deletions
diff --git a/tests/bandwidth.c b/tests/bandwidth.c
index a422de4..564ded3 100644
--- a/tests/bandwidth.c
+++ b/tests/bandwidth.c
@@ -12,6 +12,7 @@
static unsigned current_bw = 0;
static int udp_socks[2] = { -1, -1 };
+static bool remote = false;
typedef struct {
uint8_t data[1024];
@@ -111,7 +112,10 @@ test_bandwidth(unsigned bw)
unsigned expected = 1024 * 1024 * bw / 8 / 10 + 1 * (1024 + MIN_IP_UDP_HEADER);
// launch program with given latency
- launch_latency("10 %uMbit --framing-bytes 0", bw);
+ if (remote)
+ launch_latency_remote("10 %uMbit --framing-bytes 0", bw);
+ else
+ launch_latency("10 %uMbit --framing-bytes 0", bw);
create_udp_pair(udp_socks);
// one direction
@@ -139,13 +143,22 @@ test_bandwidth(unsigned bw)
kill_latency();
}
-int main(void)
+static void
+all_tests(void)
{
- printf("Testing bandwidth limitation\n");
-
test_bandwidth(2);
test_bandwidth(4);
test_bandwidth(8);
test_bandwidth(16);
+}
+
+int main(void)
+{
+ printf("Testing bandwidth limitation\n");
+
+ all_tests();
+ remote = true;
+ all_tests();
+
return 0;
}
diff --git a/tests/common.c b/tests/common.c
index d103f1d..2155280 100644
--- a/tests/common.c
+++ b/tests/common.c
@@ -1,11 +1,36 @@
#include "common.h"
#include <stdarg.h>
#include <errno.h>
+#include <err.h>
#include <signal.h>
+#include <sched.h>
#include <sys/wait.h>
#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
static pid_t latency_pid = -1;
+static pid_t server_pid = -1;
+static bool cleanup_registered = false;
+
+static void
+cleanup_atexit(void)
+{
+ if (latency_pid != -1)
+ kill(SIGKILL, latency_pid);
+ if (server_pid != -1)
+ kill(SIGKILL, server_pid);
+}
+
+static void
+register_cleanup(void)
+{
+ if (cleanup_registered)
+ return;
+ atexit(cleanup_atexit);
+ cleanup_registered = true;
+}
bool
latency_running(void)
@@ -16,7 +41,7 @@ latency_running(void)
int sock = socket(AF_INET, SOCK_DGRAM, 0);
assert(sock >= 0);
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &socktrue, sizeof(socktrue));
- setup_addr(&addr, "192.168.127.2", 0);
+ setup_addr(&addr, "192.168.127.0", 0);
bool res;
if (bind(sock, &addr.generic, sizeof(addr)) == 0) {
res = true;
@@ -28,9 +53,20 @@ latency_running(void)
return res;
}
-void
-launch_latency(const char *fmt, ...)
+static int
+get_process_netns(pid_t pid)
+{
+ char ns_path[128];
+ sprintf(ns_path, "/proc/%u/ns/net", (unsigned) pid);
+ int ns = open(ns_path, O_RDONLY);
+ assert(ns >= 0);
+ return ns;
+}
+
+static void
+launch_latency_client(bool local, const char *fmt, va_list ap)
{
+ register_cleanup();
assert(latency_pid == -1);
while (latency_running()) {
@@ -39,14 +75,14 @@ launch_latency(const char *fmt, ...)
}
char cmd[1024];
- va_list ap;
- strcpy(cmd, "exec ../latency ");
+ if (local)
+ strcpy(cmd, "exec ../latency ");
+ else
+ strcpy(cmd, "exec ../latency --client 192.168.128.2 ");
size_t cmd_len = strlen(cmd);
- va_start(ap, fmt);
vsnprintf(cmd + cmd_len, sizeof(cmd) - cmd_len, fmt, ap);
- va_end(ap);
printf("starting %s\n", cmd);
latency_pid = fork();
@@ -66,31 +102,103 @@ launch_latency(const char *fmt, ...)
usleep(50000);
}
+void
+launch_latency(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ launch_latency_client(true, fmt, ap);
+ va_end(ap);
+}
+
+void
+launch_latency_remote(const char *fmt, ...)
+{
+ register_cleanup();
+ assert(latency_pid == -1 && server_pid == -1);
+
+ if (unshare(CLONE_NEWNET))
+ err(1, "unshare");
+ assert(system("ifconfig lo 127.0.0.1 netmask 255.255.255.0 up") == 0);
+
+ int pipe_fds[2];
+
+ assert(pipe(pipe_fds) == 0);
+
+ server_pid = fork();
+ assert(server_pid != -1);
+
+ char c;
+ if (server_pid == 0) {
+ char cmd[256];
+
+ close(pipe_fds[0]);
+ pipe_fds[0] = -1;
+
+ if (unshare(CLONE_NEWNET))
+ err(1, "unshare");
+ assert(system("ifconfig lo 127.0.0.1 netmask 255.255.255.0 up") == 0);
+ sprintf(cmd, "ip link add server type veth peer name client netns %d", (int) getppid());
+ assert(system(cmd) == 0);
+ assert(system("ifconfig server 192.168.128.2 netmask 255.255.255.0 up") == 0);
+ c = 'x';
+ write(pipe_fds[1], &c, 1);
+ close(pipe_fds[1]);
+ execl("../latency", "latency", "--server", "--framing-bytes", "0", NULL);
+ exit(1);
+ }
+
+ close(pipe_fds[1]);
+ pipe_fds[1] = -1;
+ assert(read(pipe_fds[0], &c, 1) == 1);
+ assert(c == 'x');
+ assert(system("ifconfig client 192.168.128.3 netmask 255.255.255.0 up") == 0);
+
+ va_list ap;
+ va_start(ap, fmt);
+ launch_latency_client(false, fmt, ap);
+ va_end(ap);
+}
+
static void
handle_alarm(int sig)
{
}
-void
-kill_latency(void)
+static void
+kill_pid(pid_t *p_pid)
{
- assert(latency_pid != -1);
- kill(latency_pid, SIGTERM);
+ assert(*p_pid != -1);
+ kill(*p_pid, SIGTERM);
// handle some timeout
signal(SIGALRM, handle_alarm);
alarm(1);
int status;
- pid_t pid = waitpid(latency_pid, &status, 0);
+ pid_t pid = waitpid(*p_pid, &status, 0);
alarm(0);
signal(SIGALRM, SIG_DFL);
- assert(pid == latency_pid);
+ assert(pid == *p_pid);
assert(WIFEXITED(status));
assert(WEXITSTATUS(status) == 0);
- latency_pid = -1;
+ *p_pid = -1;
+}
+
+void
+kill_latency(void)
+{
+ kill_pid(&latency_pid);
+ if (server_pid != -1) {
+ kill_pid(&server_pid);
+
+ int parent_ns = get_process_netns(getppid());
+ assert(setns(parent_ns, 0) == 0);
+ close(parent_ns);
+ }
}
void
@@ -123,20 +231,40 @@ create_udp_pair(int socks[2])
assert(getsockname(sock, &addr.generic, &addr_len) == 0);
ports[0] = ntohs(addr.inet.sin_port);
+ const char *remote_listen_ip = "192.168.127.2";
+ const char *remote_connect_ip = "192.168.127.3";
+
+ int save_ns = -1;
+ if (server_pid != -1) {
+ save_ns = get_process_netns(getpid());
+
+ int server_ns = get_process_netns(server_pid);
+ assert(setns(server_ns, 0) == 0);
+ close(server_ns);
+
+ remote_listen_ip = "192.168.127.0";
+ remote_connect_ip = "192.168.127.1";
+ }
+
sock = socket(AF_INET, SOCK_DGRAM, 0);
assert(sock >= 0);
socks[1] = sock;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &socktrue, sizeof(socktrue));
- setup_addr(&addr, "192.168.127.2", 0);
+ setup_addr(&addr, remote_listen_ip, 0);
assert(bind(sock, &addr.generic, sizeof(addr)) == 0);
addr_len = sizeof(addr);
assert(getsockname(sock, &addr.generic, &addr_len) == 0);
ports[1] = ntohs(addr.inet.sin_port);
+ if (save_ns != -1) {
+ assert(setns(save_ns, 0) == 0);
+ close(save_ns);
+ }
+
// make a pair from the above ones
setup_addr(&addr, "192.168.127.1", ports[1]);
assert(connect(socks[0], &addr.generic, sizeof(addr)) == 0);
- setup_addr(&addr, "192.168.127.3", ports[0]);
+ setup_addr(&addr, remote_connect_ip, ports[0]);
assert(connect(socks[1], &addr.generic, sizeof(addr)) == 0);
}
diff --git a/tests/common.h b/tests/common.h
index 9c72998..a6d11b3 100644
--- a/tests/common.h
+++ b/tests/common.h
@@ -1,4 +1,5 @@
#undef NDEBUG
+#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
@@ -15,6 +16,9 @@ bool latency_running(void);
/** launch a program with given parameters */
void launch_latency(const char *fmt, ...);
+/** launch a program with given parameters */
+void launch_latency_remote(const char *fmt, ...);
+
/** kill latency process */
void kill_latency(void);
diff --git a/tests/delay.c b/tests/delay.c
index aea5512..9202f57 100644
--- a/tests/delay.c
+++ b/tests/delay.c
@@ -6,6 +6,7 @@
static unsigned test_num = 0;
static int udp_socks[2] = { -1, -1 };
static const char payload_id[8] = "DELAY\0\0";
+static bool remote = false;
typedef struct {
char id[8];
@@ -43,7 +44,10 @@ test_latency(unsigned latency)
{
++test_num;
// launch program with given latency
- launch_latency("%u 100M", latency);
+ if (remote)
+ launch_latency_remote("%u 100M", latency);
+ else
+ launch_latency("%u 100M", latency);
create_udp_pair(udp_socks);
// send some payload and wait
@@ -79,13 +83,22 @@ test_latency(unsigned latency)
kill_latency();
}
-int main(void)
+static void
+all_tests(void)
{
- printf("Testing delay introduced is correct\n");
-
test_latency(10);
test_latency(100);
test_latency(200);
test_latency(280);
+}
+
+int main(void)
+{
+ printf("Testing delay introduced is correct\n");
+
+ all_tests();
+ remote = true;
+ all_tests();
+
return 0;
}
diff --git a/tests/ping.c b/tests/ping.c
index 95831fc..ae7bb37 100644
--- a/tests/ping.c
+++ b/tests/ping.c
@@ -8,5 +8,9 @@ int main(void)
launch_latency("10 100M");
assert(system("ping -c1 192.168.127.1") == 0);
kill_latency();
+
+ launch_latency_remote("10 100M");
+ assert(system("ping -c1 192.168.127.1") == 0);
+ kill_latency();
return 0;
}