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 <rolf.neugebauer@docker.com>
This commit is contained in:
Rolf Neugebauer 2017-07-10 17:32:27 +01:00
parent 3e034a5ca8
commit 4c74def5c0
10 changed files with 537 additions and 278 deletions

View File

@ -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"]}'

View File

@ -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)

View File

@ -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 <n> Number of concurrent connections in ns [$ARG_CONN]"
echo " -i <n> Number of iterations [$ARG_ITER]"
echo " -l <n> 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

View File

@ -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"

30
test/pkg/ns/Dockerfile Normal file
View File

@ -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"]}'

5
test/pkg/ns/Makefile Normal file
View File

@ -0,0 +1,5 @@
IMAGE=test-ns
NETWORK=1
DEPS=Dockerfile Makefile
include ../../../pkg/package.mk

View File

@ -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": [ ]
}
}

253
test/pkg/ns/runc-net.sh Executable file
View File

@ -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 <n> Number of concurrent connections [$ARG_CONN]"
echo " -s Use short lived connections (default long)"
echo " -i <n> Number of iterations [$ARG_ITER]"
echo " -l <n> 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"

View File

@ -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"

21
test/pkg/ns/template.yml Normal file
View File

@ -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:<hash>
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