mirror of
https://github.com/linuxkit/linuxkit.git
synced 2025-07-20 17:49:10 +00:00
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:
parent
3e034a5ca8
commit
4c74def5c0
@ -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"]}'
|
||||
|
@ -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)
|
@ -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
|
@ -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
30
test/pkg/ns/Dockerfile
Normal 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
5
test/pkg/ns/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
IMAGE=test-ns
|
||||
NETWORK=1
|
||||
DEPS=Dockerfile Makefile
|
||||
|
||||
include ../../../pkg/package.mk
|
37
test/pkg/ns/config.template.json
Normal file
37
test/pkg/ns/config.template.json
Normal 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
253
test/pkg/ns/runc-net.sh
Executable 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"
|
191
test/pkg/ns/runp-runc-net.sh
Normal file
191
test/pkg/ns/runp-runc-net.sh
Normal 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
21
test/pkg/ns/template.yml
Normal 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
|
Loading…
Reference in New Issue
Block a user