From 4c74def5c0d331a9cc291a56a6947e0a9a0db5ab Mon Sep 17 00:00:00 2001 From: Rolf Neugebauer Date: Mon, 10 Jul 2017 17:32:27 +0100 Subject: [PATCH] tests: Update the netns test package to use runc and rename it to ns The previous version just created a network name space which does not allow us to also test additional namespaces, e.g. for unix domain sockets. This commit uses runc to create a fully namespaced container to run a test in. It creates a container, configures the network interfaces in the new network namespace before starting the container. A OCI config.json template is used and then customised for a given test based on command line arguments. Finally, instead of iperf, we use the socket stress test from https://github.com/linuxkit/virtsock as it provides finer-grained control over the traffic patterns (e.g. long lived vs lots of short lived connections). Signed-off-by: Rolf Neugebauer --- test/pkg/netns/Dockerfile | 16 -- test/pkg/netns/Makefile | 15 -- test/pkg/netns/netns.sh | 199 ------------------------ test/pkg/netns/runp.sh | 48 ------ test/pkg/ns/Dockerfile | 30 ++++ test/pkg/ns/Makefile | 5 + test/pkg/ns/config.template.json | 37 +++++ test/pkg/ns/runc-net.sh | 253 +++++++++++++++++++++++++++++++ test/pkg/ns/runp-runc-net.sh | 191 +++++++++++++++++++++++ test/pkg/ns/template.yml | 21 +++ 10 files changed, 537 insertions(+), 278 deletions(-) delete mode 100644 test/pkg/netns/Dockerfile delete mode 100644 test/pkg/netns/Makefile delete mode 100755 test/pkg/netns/netns.sh delete mode 100755 test/pkg/netns/runp.sh create mode 100644 test/pkg/ns/Dockerfile create mode 100644 test/pkg/ns/Makefile create mode 100644 test/pkg/ns/config.template.json create mode 100755 test/pkg/ns/runc-net.sh create mode 100644 test/pkg/ns/runp-runc-net.sh create mode 100644 test/pkg/ns/template.yml diff --git a/test/pkg/netns/Dockerfile b/test/pkg/netns/Dockerfile deleted file mode 100644 index 978dc312b..000000000 --- a/test/pkg/netns/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -FROM linuxkit/alpine:3d57ded3edd54e616210cf0c17e3bc15eed9d03a AS mirror -RUN mkdir -p /out/etc/apk && cp -r /etc/apk/* /out/etc/apk/ -RUN apk add --no-cache --initdb -p /out \ - alpine-baselayout \ - busybox \ - iperf3 \ - iproute2 \ - musl -RUN rm -rf /out/etc/apk /out/lib/apk /out/var/cache - -FROM scratch -COPY --from=mirror /out/ / -COPY netns.sh runp.sh / - -LABEL org.mobyproject.config='{"pid": "host", "net":"host", "binds": ["/dev:/dev","/sys:/sys"], "capabilities": ["all"]}' - diff --git a/test/pkg/netns/Makefile b/test/pkg/netns/Makefile deleted file mode 100644 index 73502cef9..000000000 --- a/test/pkg/netns/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -.PHONY: tag push -default: push - -ORG?=linuxkit -IMAGE=test-netns -DEPS=Dockerfile Makefile - -HASH?=$(shell git ls-tree HEAD -- ../$(notdir $(CURDIR)) | awk '{print $$3}') - -tag: $(DEPS) - docker build --squash --no-cache -t $(ORG)/$(IMAGE):$(HASH) . - -push: tag - DOCKER_CONTENT_TRUST=1 docker pull $(ORG)/$(IMAGE):$(HASH) || \ - DOCKER_CONTENT_TRUST=1 docker push $(ORG)/$(IMAGE):$(HASH) diff --git a/test/pkg/netns/netns.sh b/test/pkg/netns/netns.sh deleted file mode 100755 index e64852955..000000000 --- a/test/pkg/netns/netns.sh +++ /dev/null @@ -1,199 +0,0 @@ -#! /bin/sh - -# Initialise the Random Number Seed with the PID -RANDOM=$$ - -# defaults -ARG_TYPE=veth -ARG_PROTO=tcp -ARG_IP=4 -ARG_CONN=1 -ARG_ITER=10 -ARG_LEN=20 -ARG_REUSE=0 - -usage() { - echo "Stress test for network namespace using iperf" - echo " -t loopback|veth Type of test [$ARG_TYPE]" - echo " -p tcp|udp Protocol to use [$ARG_PROTO]" - echo " -ip 4|6 IP version to use [$ARG_IP]" - echo " -c Number of concurrent connections in ns [$ARG_CONN]" - echo " -i Number of iterations [$ARG_ITER]" - echo " -l Maximum length of test before killing [$ARG_LEN]" - echo " -r Re-use network namespace name" -} - -# parse arguments -while [[ $# -gt 0 ]]; do - key="$1" - - case $key in - -t) - ARG_TYPE="$2" - shift - ;; - -p) - ARG_PROTO="$2" - shift - ;; - -ip) - ARG_IP="$2" - shift - ;; - -c) - ARG_CONN="$2" - shift - ;; - -i) - ARG_ITER="$2" - shift - ;; - -l) - ARG_LEN="$2" - shift - ;; - -r) - ARG_REUSE=1 - ;; - *) - usage - exit 1 - ;; - esac - shift -done - -echo "PID=$$" - -# Kill a random bit (client, server, network namespace, device) first -# before cleaning up -kill_all() { - ns=$1 - pid_client=$2 - pid_server=$3 - host_dev=$4 - ns_dev=$5 - - R=$(($RANDOM%$#)) - case $R in - 0) - echo "$ns: Remove namespace first" - ip netns del "$ns" > /dev/nukk 2>&1 || true - ;; - 1) - echo "$ns: Kill client processes first" - kill "$pid_client" > /dev/null 2>&1 || true - ;; - 2) - echo "$ns: Kill server process first" - kill "$pid_server" > /dev/null 2>&1 || true - ;; - 3) - echo "$ns: Remove host netdev first" - ip link del "$host_dev" - ;; - 4) - echo "$ns: Remove netns netdev first" - ip netns exec "$ns" ip link del "$ns_dev" - ;; - esac - kill "$pid_client" > /dev/null 2>&1 || true - kill "$pid_server" > /dev/null 2>&1 || true - ip netns del "$ns" > /dev/null 2>&1 || true - [ "$host_dev"x != x ] && (ip link del "$host_dev" > /dev/null 2>&1 || true) || true - [ "$ns_dev"x != x ] && (ip netns exec "$ns" ip link del "$ns_dev" > /dev/null 2>&1 || true) || true -} - -# Run sock_stress in loopback mode in a network namespace -loopback_run() { - id=$1 # unique ID for this run, used to create namespace - ip=$2 # 4 or 6 to select IP version to use - pr=$3 # protocol tcp or udp - - # Use our PID as the ID to get unique namespaces - if [ "$ARG_REUSE" = "1" ]; then - ns="ns_$$" - else - ns="ns_$$_$id" - fi - ip netns add "$ns" - ip netns exec "$ns" ip link set lo up - - ip netns exec "$ns" iperf3 -s --logfile /dev/null & - pid_server=$! - sleep 1 - [ "$pr" = "udp" ] && o="-u" - ip netns exec "$ns" iperf3 -"$ip" "$o" -P "$ARG_CONN" -c localhost -t 10000 -i 20 & - pid_client=$! - - # wait for a while before killing processes - sleep $(((RANDOM % $ARG_LEN )+1)) - - kill_all "$ns" "$pid_client" "$pid_server" -} - -# Run sock_stress in with the client in a namespace -veth_run() { - id=$1 # unique ID for this run, used to create namespace - ip=$2 # 4 or 6 to select IP version to use - pr=$3 # tcp or udp - - # Use our PID as the ID to get unique namespaces - if [ "$ARG_REUSE" = "1" ]; then - ns="ns_$$" - else - ns="ns_$$_$id" - fi - dev_host="h-$$-$id" - dev_ns="n-$$-$id" - ip netns add "$ns" - ip netns exec "$ns" ip link set lo up - - ip link add "$dev_host" type veth peer name "$dev_ns" - ip link set "$dev_ns" netns "$ns" - - # derive IP addresses based on PID and $id - if [ "$ip" = "4" ]; then - sub0=$(($$%255)) - sub1=$(($id%255)) - mask=24 - ip_host="10.$sub0.$sub1.1" - ip_ns="10.$sub0.$sub1.2" - else - # Make sure IPv6 is enabled on the interface - echo 0 > /proc/sys/net/ipv6/conf/"$dev_host"/disable_ipv6 - sub0=$(printf "%x" $(($$%65535))) - sub1=$(printf "%x" $(($id%65535))) - mask=64 - ip_host="2001:$sub0:$sub1::1" - ip_ns="2001:$sub0:$sub1::2" - fi - ip -"$ip" addr add "$ip_host"/"$mask" dev "$dev_host" - ip link set "$dev_host" up - - ip netns exec "$ns" ip -"$ip" addr add "$ip_ns"/"$mask" dev "$dev_ns" - ip netns exec "$ns" ip link set "$dev_ns" up - sleep 2 # for IPv6 it takes a little while for the link to come up - - ip netns exec "$ns" iperf3 -s --logfile /dev/null & - pid_server=$! - sleep 1 - [ "$pr" = "udp" ] && o="-u" - iperf3 -"$ip" "$o" -P "$ARG_CONN" -c "$ip_ns" -t 10000 -i 20 & - pid_client=$! - - # wait for a while before killing processes - sleep $(((RANDOM % $ARG_LEN )+1)) - - kill_all "$ns" "$pid_client" "$pid_server" "$dev_host" "$dev_ns" -} - -for i in $(seq 1 "$ARG_ITER"); do - case $ARG_TYPE in - veth) - veth_run "$i" "$ARG_IP" "$ARG_PROTO" - ;; - loopback) - loopback_run "$i" "$ARG_IP" "$ARG_PROTO" - esac -done diff --git a/test/pkg/netns/runp.sh b/test/pkg/netns/runp.sh deleted file mode 100755 index a81dcb936..000000000 --- a/test/pkg/netns/runp.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh - -ITER=$1 -shift - -rm -rf ./logs -mkdir -p ./logs - -fail() { - for f in ./logs/*; do - echo - echo "=== $f ===" - cat $f - done - echo - dmesg - echo "Test FAILED with $1" - exit 1 -} - -ns_before=$(ip netns list | wc -l) - -pids="" -for i in $(seq 1 "$ITER"); do - "$@" > "./logs/$1-$i.log" 2>&1 & - pid=$! - pids="$pids $pid" - echo "Test $i started with PID=$pid" -done - -for pid in $pids; do - wait "$pid" - [ $? -eq 0 ] || fail "$pid return non-zero" -done - -dmesg | grep -q 'Call Trace:' && fail "Kernel backtrace" - -# A message like: -# unregister_netdevice: waiting for lo to become free. Usage count = 1 -# is somewhat benign as it just waits for the ref count to go to 0. However -# it may become a problem if we have to many of them -nd=$(dmesg | grep -q 'unregister_netdevice' | wc -l) -[ "$nd" -gt 10 ] && fail "unregister_netdevice more than 10 times" - -ns_after=$(ip netns list | wc -l) -[ "$ns_before" != "$ns_after" ] && fail "NS leak: $ns_before != $ns_after" - -echo "netns test suite PASSED" diff --git a/test/pkg/ns/Dockerfile b/test/pkg/ns/Dockerfile new file mode 100644 index 000000000..4226ccaa1 --- /dev/null +++ b/test/pkg/ns/Dockerfile @@ -0,0 +1,30 @@ +FROM linuxkit/alpine:34af9cb1990debd17fae6d4198c62ce3910d9908 AS mirror +RUN mkdir -p /out/etc/apk && cp -r /etc/apk/* /out/etc/apk/ +RUN apk add --no-cache --initdb -p /out \ + alpine-baselayout \ + busybox \ + iproute2 \ + jq \ + musl +RUN rm -rf /out/etc/apk /out/lib/apk /out/var/cache + +FROM linuxkit/alpine:34af9cb1990debd17fae6d4198c62ce3910d9908 AS build +RUN apk add --no-cache \ + build-base \ + git \ + go \ + musl-dev +ENV GOPATH=/go PATH=$PATH:/go/bin +ENV VIRTSOCK_COMMIT=0416e3d85541e7a067fd000c69f50997b5d47c93 +RUN git clone https://github.com/linuxkit/virtsock.git /go/src/github.com/linuxkit/virtsock && \ + cd /go/src/github.com/linuxkit/virtsock && \ + git checkout $VIRTSOCK_COMMIT && \ + make bin/sock_stress.linux + + +FROM scratch +COPY --from=mirror /out/ / +COPY --from=build /go/src/github.com/linuxkit/virtsock/bin/sock_stress.linux /rootfs/sock_stress +COPY config.template.json *.sh / + +LABEL org.mobyproject.config='{"pid": "host", "net":"host", "binds": ["/dev:/dev","/sys:/sys", "/usr/bin/runc:/usr/bin/runc"], "capabilities": ["all"]}' diff --git a/test/pkg/ns/Makefile b/test/pkg/ns/Makefile new file mode 100644 index 000000000..8969b4257 --- /dev/null +++ b/test/pkg/ns/Makefile @@ -0,0 +1,5 @@ +IMAGE=test-ns +NETWORK=1 +DEPS=Dockerfile Makefile + +include ../../../pkg/package.mk diff --git a/test/pkg/ns/config.template.json b/test/pkg/ns/config.template.json new file mode 100644 index 000000000..a036b7f9c --- /dev/null +++ b/test/pkg/ns/config.template.json @@ -0,0 +1,37 @@ +{ + "ociVersion": "1.0.0-rc5-dev", + "platform": { + "os": "linux", + "arch": "amd64" + }, + "process": { + "consoleSize": {"height": 0, "width": 0}, + "user": { }, + "args": [ ], + "cwd": "/", + "capabilities": { + "bounding": [ ], + "effective": [ ], + "inheritable": [ ], + "permitted": [ ] + } + }, + "root": { "path": "/rootfs" }, + "mounts": [ + { "destination": "/proc", "type": "proc", "source": "proc" }, + { "destination": "/dev", "type": "tmpfs", "source": "tmpfs" }, + { "destination": "/sys", "type": "sysfs", "source": "sysfs" } + ], + "linux": { + "resources": {}, + "namespaces": [ + { "type": "pid" }, + { "type": "network" }, + { "type": "mount" }, + { "type": "ipc" } + ] + }, + "hooks": { + "prestart": [ ] + } +} diff --git a/test/pkg/ns/runc-net.sh b/test/pkg/ns/runc-net.sh new file mode 100755 index 000000000..9e6b2f7de --- /dev/null +++ b/test/pkg/ns/runc-net.sh @@ -0,0 +1,253 @@ +#! /bin/sh + +# This script creates a container with runc and then runs sock_stress +# (a flexible stress program for UDP/TCP/virtio/Hyper-V/Unix Domain +# sockets). It configures networking either for IPv4 or IPv6 and bind +# mounts a directory for the Unix Domain Socket. After a randomised +# amount of time (maximum set with -t) it kills the sockstress tests +# or the container. This process is repeated several times (-i). +# +# For networking, currently only veth pairs are used. But we plan to +# extent this in the future. +# +# sock_stress supports multiple concurrent connections and sends a +# configurable amount of data over the socket from a client to a +# server, which echoes the data back. By configuring the amount of +# data sent per connection, sock_stress can be used to create a large +# number of short-lived connections (-s). By default a random, +# relatively large amount of data is transferred. +# +# By default the server is run in the container, with the client in +# the parent namespace. the -r option reverses this. + +# set -x + +# Initialise the Random Number Seed with the PID +RANDOM=$$ + +# defaults for arguments +ARG_PROTO=tcp +ARG_IP=4 +ARG_CONN=1 +ARG_SHORT=0 +ARG_ITER=20 +ARG_TIME=10 +ARG_REV=0 + +usage() { + echo "Stress test for network namespace using sock_stress" + echo " -p tcp|udp|unix Protocol to use [$ARG_PROTO]" + echo " -ip 4|6 IP version to use if tcp|udp [$ARG_IP]" + echo " -c Number of concurrent connections [$ARG_CONN]" + echo " -s Use short lived connections (default long)" + echo " -i Number of iterations [$ARG_ITER]" + echo " -l Maximum time of test before killing in s [$ARG_LEN]" + echo " -r Reverse (client in container)" +} + +echo "$@" + +# parse arguments +while [[ $# -gt 0 ]]; do + key="$1" + + case $key in + -p) + ARG_PROTO="$2" + shift + ;; + -ip) + ARG_IP="$2" + shift + ;; + -c) + ARG_CONN="$2" + shift + ;; + -s) + ARG_SHORT=1 + ;; + -i) + ARG_ITER="$2" + shift + ;; + -l) + ARG_TIME="$2" + shift + ;; + -r) + ARG_REV=1 + ;; + *) + usage + exit 1 + ;; + esac + shift +done + +# Work out the maximum length of a connection. For short connections +# (ie many connections we transfer a max of 4k for long connections +# (lots of data) we transfer up to 8G per connection) +[ "$ARG_SHORT" = "1" ] && MAX_LEN=4096 || MAX_LEN=8388608 +[ "$ARG_PROTO" = "unix" ] && ARG_IP= + +# Make sure we do IPv6 if asked for +if [ "$ARG_IP" = "6" ]; then + echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6 + echo 0 > /proc/sys/net/ipv6/conf/default/disable_ipv6 + echo 1 > /proc/sys/net/ipv6/conf/all/forwarding + echo 1 > /proc/sys/net/ipv6/conf/default/forwarding +fi + +veth_ipv4() { + nspid="$1" + h_ip="$2" + n_ip="$3" + mask=24 + + # create veth pair and assign the peer to the namespace + h_dev="h_$nspid" + n_dev="n_$nspid" + ip link add "$h_dev" type veth peer name "$n_dev" + ip link set "$n_dev" netns "$nspid" + + # set up address and up the devices. Host first + ip addr add "$h_ip"/"$mask" dev "$h_dev" + ip link set "$h_dev" up + + ip netns exec "$nspid" ip addr add "$n_ip"/"$mask" dev "$n_dev" + ip netns exec "$nspid" ip link set lo up + ip netns exec "$nspid" ip link set "$n_dev" up + sleep 2 # Wait for link to settle +} + +veth_ipv6() { + nspid="$1" + h_ip="$2" + n_ip="$3" + mask=64 + + # create veth pair and assign the peer to the namespace + h_dev="h_$nspid" + n_dev="n_$nspid" + ip link add "$h_dev" type veth peer name "$n_dev" + ip link set "$n_dev" netns "$nspid" + + # set up address and up the devices. Host first + ip -6 addr add "$h_ip"/"$mask" dev "$h_dev" + ip link set "$h_dev" up + + ip netns exec "$nspid" ip -6 addr add "$n_ip"/"$mask" dev "$n_dev" + ip netns exec "$nspid" ip link set lo up + ip netns exec "$nspid" ip link set "$n_dev" up + sleep 2 # Wait for link to settle +} + +PID="$$" +echo "PID=$PID" +D="/test/$PID" +mkdir -p "$D" + +## +## Create a runc config.json file based on the template +## +cp /config.template.json "$D"/config.json + +# Add a bind mount for unix domain sockets. +BMOUNT="[{\"destination\": \"/data\", \"type\": \"bind\", \"source\": \"$D\", \"options\": [\"rw\", \"rbind\", \"rprivate\"]}]" +jq --argjson args "$BMOUNT" '.mounts |= . + $args' \ + "$D"/config.json > "$D"/foo.json && mv "$D"/foo.json "$D"/config.json + +## +## Run the test $ARG_ITER time +## +for i in $(seq 1 "$ARG_ITER"); do + # Work out IP addresses + if [ "$ARG_IP" = "6" ]; then + sub0=$(($PID%65535)); sub1=$(($i%65535)) + h_ip="2001:$sub0:$sub1::1"; h_ip_addr="[$h_ip]" + n_ip="2001:$sub0:$sub1::2"; n_ip_addr="[$n_ip]" + else + sub0=$(($PID%255)); sub1=$(($i%255)) + h_ip="10.$sub0.$sub1.1"; h_ip_addr="$h_ip" + n_ip="10.$sub0.$sub1.2"; n_ip_addr="$n_ip" + fi + + if [ "$ARG_REV" = "0" ]; then + # Server in container + if [ "$ARG_PROTO" = "unix" ]; then + SADDR="/data/stress.sock" + CADDR="$D/stress.sock" + else + SADDR="$n_ip_addr" + CADDR="$n_ip_addr" + fi + C_CMD="[\"/sock_stress\", \"-s\", \"$ARG_PROTO$ARG_IP://$SADDR\"]" + H_CMD="/rootfs/sock_stress -c $ARG_PROTO$ARG_IP://$CADDR -i 10000000 -l $MAX_LEN -p $ARG_CONN -v 1" + else + # Client in container + if [ "$ARG_PROTO" = "unix" ]; then + CADDR="/data/stress.sock" + SADDR="$D/stress.sock" + else + SADDR="$h_ip_addr" + CADDR="$h_ip_addr" + fi + C_CMD="[\"/sock_stress\", \"-c\", \"$ARG_PROTO$ARG_IP://$CADDR\", \"-i\", \"10000000\", \"-l\", \"$MAX_LEN\", \"-p\", \"$ARG_CONN\", \"-v\", \"1\"]" + H_CMD="/rootfs/sock_stress -s $ARG_PROTO$ARG_IP://$SADDR" + fi + + # Splice container command into json + jq --argjson args "$C_CMD" '.process.args = $args' \ + "$D"/config.json > "$D"/foo.json && mv "$D"/foo.json "$D"/config.json + + # Create container, get the namespace ID, and set up symlink for ip utils + CNAME="c-$PID-$i" + runc create -b "$D" "$CNAME" + nspid=$(runc list -f json | jq --arg id "$CNAME" -r '.[] | select(.id==$id) | .pid') + mkdir -p /var/run/netns && \ + ln -s /proc/"$nspid"/ns/net /var/run/netns/"$nspid" + + # Configure network + if [ "$ARG_IP" = "6" ]; then + veth_ipv6 "$nspid" "$h_ip" "$n_ip" + else + veth_ipv4 "$nspid" "$h_ip" "$n_ip" + fi + + # Run + if [ "$ARG_REV" = "0" ]; then + runc start "$CNAME" + sleep 2 # Wait for container to start + $H_CMD & + pid_host=$! + else + $H_CMD & + pid_host=$! + sleep 1 # Wait for server to start + runc start "$CNAME" + fi + + # wait for a while before killing processes + sleep $(((RANDOM % $ARG_TIME )+1)) + + R=$(($RANDOM%2)) + case $R in + 0) + echo "Kill test first" + kill -9 "$pid_host" + runc kill "$CNAME" + runc delete "$CNAME" + ;; + 1) + echo "Kill container first" + runc kill "$CNAME" + runc delete "$CNAME" + kill -9 "$pid_host" + ;; + esac + + rm /var/run/netns/"$nspid" +done +rm -rf "$D" diff --git a/test/pkg/ns/runp-runc-net.sh b/test/pkg/ns/runp-runc-net.sh new file mode 100644 index 000000000..68147dcee --- /dev/null +++ b/test/pkg/ns/runp-runc-net.sh @@ -0,0 +1,191 @@ +#!/bin/sh + +# This script runs multiple runc-net.sh scripts in parallel. It either +# runs identical versions of runc-net.sh with the arguments supplied +# or a number of pre-defined. + +ITER=$1 +shift + +rm -rf ./logs +mkdir -p ./logs + +fail() { + for f in ./logs/*; do + echo + echo "=== $f ===" + cat "$f" + done + echo + dmesg + echo "Test FAILED with $1" + exit 1 +} + +pids="" +case "$ITER" in + "mix") + echo "Running a mix /runc-net.sh with servers in containers" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 4 -s > ./logs/01.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 4 -s > ./logs/02.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 6 -s > ./logs/03.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 6 -s > ./logs/04.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p unix -s > ./logs/05.log 2>&1 & + pid=$!; pids="$pids $pid" + + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 4 > ./logs/06.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 4 > ./logs/07.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 6 > ./logs/08.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 6 > ./logs/09.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p unix > ./logs/10.log 2>&1 & + pid=$!; pids="$pids $pid" + ;; + "mix-reverse") + echo "Running a mix /runc-net.sh with clients in containers" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 4 -s -r > ./logs/01.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 4 -s -r > ./logs/02.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 6 -s -r > ./logs/03.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 6 -s -r > ./logs/04.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p unix -s -r > ./logs/05.log 2>&1 & + pid=$!; pids="$pids $pid" + + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 4 -r > ./logs/06.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 4 -r > ./logs/07.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 6 -r > ./logs/08.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 6 -r > ./logs/09.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p unix -r > ./logs/10.log 2>&1 & + pid=$!; pids="$pids $pid" + ;; + "mix-ipv4") + echo "Running a mix /runc-net.sh tests with IPv4 only" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 4 -s > ./logs/01.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 4 -s > ./logs/02.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 4 -s -r > ./logs/03.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 4 -s -r > ./logs/04.log 2>&1 & + pid=$!; pids="$pids $pid" + + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 4 > ./logs/05.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 4 > ./logs/06.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 4 -r > ./logs/07.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 4 -r > ./logs/08.log 2>&1 & + pid=$!; pids="$pids $pid" + ;; + "mix-ipv6") + echo "Running a mix /runc-net.sh tests with IPv6 only" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 6 -s > ./logs/01.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 6 -s > ./logs/02.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 6 -s -r > ./logs/03.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 6 -s -r > ./logs/04.log 2>&1 & + pid=$!; pids="$pids $pid" + + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 6 > ./logs/05.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 6 > ./logs/06.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 6 -r > ./logs/07.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 6 -r > ./logs/08.log 2>&1 & + pid=$!; pids="$pids $pid" + ;; + "mix-tcp") + echo "Running a mix /runc-net.sh tests with TCP only" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 4 -s > ./logs/01.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 4 -s -r > ./logs/02.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 4 > ./logs/03.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 4 -r > ./logs/04.log 2>&1 & + pid=$!; pids="$pids $pid" + + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 6 -s > ./logs/01.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 6 -s -r > ./logs/02.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 6 > ./logs/03.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p tcp -ip 6 -r > ./logs/04.log 2>&1 & + pid=$!; pids="$pids $pid" + ;; + "mix-udp") + echo "Running a mix /runc-net.sh tests with UDP only" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 4 -s > ./logs/01.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 4 -s -r > ./logs/02.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 4 > ./logs/03.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 4 -r > ./logs/04.log 2>&1 & + pid=$!; pids="$pids $pid" + + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 6 -s > ./logs/01.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 6 -s -r > ./logs/02.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 6 > ./logs/03.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p udp -ip 6 -r > ./logs/04.log 2>&1 & + pid=$!; pids="$pids $pid" + ;; + "mix-unix") + echo "Running a mix /runc-net.sh tests with unix domain sockets" + /runc-net.sh -i 30 -l 10 -c 5 -p unix -s > ./logs/01.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p unix > ./logs/02.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p unix -s -r > ./logs/03.log 2>&1 & + pid=$!; pids="$pids $pid" + /runc-net.sh -i 30 -l 10 -c 5 -p unix -r > ./logs/04.log 2>&1 & + pid=$!; pids="$pids $pid" + ;; + *) + echo "Running $ITER instances of /runc-net.sh $@" + + for i in $(seq 1 "$ITER"); do + /runc-net.sh $@ > "./logs/$1-$i.log" & + pid=$!; pids="$pids $pid" + echo "Test $i started with PID=$pid" + done + ;; +esac + +for pid in $pids; do + wait "$pid" + [ $? -eq 0 ] || fail "$pid return non-zero" +done + +dmesg | grep -q 'Call Trace:' && fail "Kernel backtrace" + +# A message like: +# unregister_netdevice: waiting for lo to become free. Usage count = 1 +# is somewhat benign as it just waits for the ref count to go to 0. However +# it may become a problem if we have to many of them +nd=$(dmesg | grep -q 'unregister_netdevice' | wc -l) +[ "$nd" -gt 10 ] && fail "unregister_netdevice more than 10 times" + +echo "netns test suite PASSED" diff --git a/test/pkg/ns/template.yml b/test/pkg/ns/template.yml new file mode 100644 index 000000000..b61ed8c0b --- /dev/null +++ b/test/pkg/ns/template.yml @@ -0,0 +1,21 @@ +# Sample YAML file for manual testing +kernel: + image: linuxkit/kernel:4.9.38 + cmdline: "console=ttyS0" +init: + - linuxkit/init:d049e7b2074da5cd699a27defb47eb101142455d + - linuxkit/runc:d5cbeb95bdafedb82ad2cf11cff1a5da7fcae630 +onboot: + - name: test-ns + image: linuxkit/test-ns: + command: ["/bin/sh", "/runp-runc-net.sh", "mix-unix"] + # command: ["/bin/sh", "/runc-net.sh", "-l", "5", "-i", "2", "-c", "5", "-p", "unix", "-ip", "6"] + mounts: # for runc + - type: cgroup + options: ["rw"] + - name: poweroff + image: linuxkit/poweroff:bce51402e293da0b653923a43c3c7be6e0effa05 + command: ["/bin/sh", "/poweroff.sh", "3"] +trust: + org: + - linuxkit