summaryrefslogtreecommitdiff
path: root/tools/testing/selftests/net/rds
diff options
context:
space:
mode:
Diffstat (limited to 'tools/testing/selftests/net/rds')
-rw-r--r--tools/testing/selftests/net/rds/Makefile11
-rw-r--r--tools/testing/selftests/net/rds/README.txt5
-rw-r--r--tools/testing/selftests/net/rds/config6
-rwxr-xr-xtools/testing/selftests/net/rds/config.sh37
-rwxr-xr-xtools/testing/selftests/net/rds/run.sh7
-rw-r--r--tools/testing/selftests/net/rds/settings1
-rwxr-xr-xtools/testing/selftests/net/rds/test.py108
7 files changed, 106 insertions, 69 deletions
diff --git a/tools/testing/selftests/net/rds/Makefile b/tools/testing/selftests/net/rds/Makefile
index 612a7219990e..fe363be8e358 100644
--- a/tools/testing/selftests/net/rds/Makefile
+++ b/tools/testing/selftests/net/rds/Makefile
@@ -5,8 +5,15 @@ all:
TEST_PROGS := run.sh
-TEST_FILES := include.sh test.py
+TEST_FILES := \
+ include.sh \
+ settings \
+ test.py \
+# end of TEST_FILES
-EXTRA_CLEAN := /tmp/rds_logs include.sh
+EXTRA_CLEAN := \
+ include.sh \
+ /tmp/rds_logs \
+# end of EXTRA_CLEAN
include ../../lib.mk
diff --git a/tools/testing/selftests/net/rds/README.txt b/tools/testing/selftests/net/rds/README.txt
index cbde2951ab13..c6fe003d503b 100644
--- a/tools/testing/selftests/net/rds/README.txt
+++ b/tools/testing/selftests/net/rds/README.txt
@@ -31,8 +31,11 @@ EXAMPLE:
# Alternatly create a gcov disabled .config
tools/testing/selftests/net/rds/config.sh
+ # Config paths may also be specified with the -c flag
+ tools/testing/selftests/net/rds/config.sh -c .config.local
+
# build the kernel
- vng --build --config tools/testing/selftests/net/config
+ vng --build --config .config
# launch the tests in a VM
vng -v --rwdir ./ --run . --user root --cpus 4 -- \
diff --git a/tools/testing/selftests/net/rds/config b/tools/testing/selftests/net/rds/config
new file mode 100644
index 000000000000..3d62d0c750a8
--- /dev/null
+++ b/tools/testing/selftests/net/rds/config
@@ -0,0 +1,6 @@
+CONFIG_MODULES=n
+CONFIG_NET_NS=y
+CONFIG_NET_SCH_NETEM=y
+CONFIG_RDS=y
+CONFIG_RDS_TCP=y
+CONFIG_VETH=y
diff --git a/tools/testing/selftests/net/rds/config.sh b/tools/testing/selftests/net/rds/config.sh
index 791c8dbe1095..29a79314dd60 100755
--- a/tools/testing/selftests/net/rds/config.sh
+++ b/tools/testing/selftests/net/rds/config.sh
@@ -6,15 +6,20 @@ set -u
set -x
unset KBUILD_OUTPUT
+CONF_FILE=""
+FLAGS=()
GENERATE_GCOV_REPORT=0
-while getopts "g" opt; do
+while getopts "gc:" opt; do
case ${opt} in
g)
GENERATE_GCOV_REPORT=1
;;
+ c)
+ CONF_FILE=$OPTARG
+ ;;
:)
- echo "USAGE: config.sh [-g]"
+ echo "USAGE: config.sh [-g] [-c config]"
exit 1
;;
?)
@@ -24,30 +29,32 @@ while getopts "g" opt; do
esac
done
-CONF_FILE="tools/testing/selftests/net/config"
+if [[ "$CONF_FILE" != "" ]]; then
+ FLAGS=(--file "$CONF_FILE")
+fi
# no modules
-scripts/config --file "$CONF_FILE" --disable CONFIG_MODULES
+scripts/config "${FLAGS[@]}" --disable CONFIG_MODULES
# enable RDS
-scripts/config --file "$CONF_FILE" --enable CONFIG_RDS
-scripts/config --file "$CONF_FILE" --enable CONFIG_RDS_TCP
+scripts/config "${FLAGS[@]}" --enable CONFIG_RDS
+scripts/config "${FLAGS[@]}" --enable CONFIG_RDS_TCP
if [ "$GENERATE_GCOV_REPORT" -eq 1 ]; then
# instrument RDS and only RDS
- scripts/config --file "$CONF_FILE" --enable CONFIG_GCOV_KERNEL
- scripts/config --file "$CONF_FILE" --disable GCOV_PROFILE_ALL
- scripts/config --file "$CONF_FILE" --enable GCOV_PROFILE_RDS
+ scripts/config "${FLAGS[@]}" --enable CONFIG_GCOV_KERNEL
+ scripts/config "${FLAGS[@]}" --disable GCOV_PROFILE_ALL
+ scripts/config "${FLAGS[@]}" --enable GCOV_PROFILE_RDS
else
- scripts/config --file "$CONF_FILE" --disable CONFIG_GCOV_KERNEL
- scripts/config --file "$CONF_FILE" --disable GCOV_PROFILE_ALL
- scripts/config --file "$CONF_FILE" --disable GCOV_PROFILE_RDS
+ scripts/config "${FLAGS[@]}" --disable CONFIG_GCOV_KERNEL
+ scripts/config "${FLAGS[@]}" --disable GCOV_PROFILE_ALL
+ scripts/config "${FLAGS[@]}" --disable GCOV_PROFILE_RDS
fi
# need network namespaces to run tests with veth network interfaces
-scripts/config --file "$CONF_FILE" --enable CONFIG_NET_NS
-scripts/config --file "$CONF_FILE" --enable CONFIG_VETH
+scripts/config "${FLAGS[@]}" --enable CONFIG_NET_NS
+scripts/config "${FLAGS[@]}" --enable CONFIG_VETH
# simulate packet loss
-scripts/config --file "$CONF_FILE" --enable CONFIG_NET_SCH_NETEM
+scripts/config "${FLAGS[@]}" --enable CONFIG_NET_SCH_NETEM
diff --git a/tools/testing/selftests/net/rds/run.sh b/tools/testing/selftests/net/rds/run.sh
index 8aee244f582a..897d17d1b8db 100755
--- a/tools/testing/selftests/net/rds/run.sh
+++ b/tools/testing/selftests/net/rds/run.sh
@@ -19,6 +19,9 @@ if test -f "$build_include"; then
build_dir="$mk_build_dir"
fi
+# Source settings for timeout value (also used by ksft runner)
+source "$current_dir"/settings
+
# This test requires kernel source and the *.gcda data therein
# Locate the top level of the kernel source, and the net/rds
# subfolder with the appropriate *.gcno object files
@@ -194,8 +197,8 @@ set +e
echo running RDS tests...
echo Traces will be logged to "$TRACE_FILE"
rm -f "$TRACE_FILE"
-strace -T -tt -o "$TRACE_FILE" python3 "$(dirname "$0")/test.py" --timeout 400 -d "$LOG_DIR" \
- -l "$PLOSS" -c "$PCORRUPT" -u "$PDUP"
+strace -T -tt -o "$TRACE_FILE" python3 "$(dirname "$0")/test.py" \
+ --timeout "$timeout" -d "$LOG_DIR" -l "$PLOSS" -c "$PCORRUPT" -u "$PDUP"
test_rc=$?
dmesg > "${LOG_DIR}/dmesg.out"
diff --git a/tools/testing/selftests/net/rds/settings b/tools/testing/selftests/net/rds/settings
new file mode 100644
index 000000000000..d2009a64589c
--- /dev/null
+++ b/tools/testing/selftests/net/rds/settings
@@ -0,0 +1 @@
+timeout=400
diff --git a/tools/testing/selftests/net/rds/test.py b/tools/testing/selftests/net/rds/test.py
index 4a7178d11193..93e23e8b256c 100755
--- a/tools/testing/selftests/net/rds/test.py
+++ b/tools/testing/selftests/net/rds/test.py
@@ -11,9 +11,8 @@ import signal
import socket
import subprocess
import sys
-import atexit
-from pwd import getpwuid
-from os import stat
+import tempfile
+import shutil
# Allow utils module to be imported from different directory
this_dir = os.path.dirname(os.path.realpath(__file__))
@@ -23,45 +22,54 @@ from lib.py.utils import ip
libc = ctypes.cdll.LoadLibrary('libc.so.6')
setns = libc.setns
-net0 = 'net0'
-net1 = 'net1'
+NET0 = 'net0'
+NET1 = 'net1'
-veth0 = 'veth0'
-veth1 = 'veth1'
+VETH0 = 'veth0'
+VETH1 = 'veth1'
# Helper function for creating a socket inside a network namespace.
# We need this because otherwise RDS will detect that the two TCP
# sockets are on the same interface and use the loop transport instead
# of the TCP transport.
-def netns_socket(netns, *args):
+def netns_socket(netns, *sock_args):
+ """
+ Creates sockets inside of network namespace
+
+ :param netns: the name of the network namespace
+ :param sock_args: socket family and type
+ """
u0, u1 = socket.socketpair(socket.AF_UNIX, socket.SOCK_SEQPACKET)
child = os.fork()
if child == 0:
# change network namespace
- with open(f'/var/run/netns/{netns}') as f:
+ with open(f'/var/run/netns/{netns}', encoding='utf-8') as f:
try:
- ret = setns(f.fileno(), 0)
+ setns(f.fileno(), 0)
except IOError as e:
print(e.errno)
print(e)
# create socket in target namespace
- s = socket.socket(*args)
+ sock = socket.socket(*sock_args)
# send resulting socket to parent
- socket.send_fds(u0, [], [s.fileno()])
+ socket.send_fds(u0, [], [sock.fileno()])
sys.exit(0)
# receive socket from child
- _, s, _, _ = socket.recv_fds(u1, 0, 1)
+ _, fds, _, _ = socket.recv_fds(u1, 0, 1)
os.waitpid(child, 0)
u0.close()
u1.close()
- return socket.fromfd(s[0], *args)
+ return socket.fromfd(fds[0], *sock_args)
-def signal_handler(sig, frame):
+def signal_handler(_sig, _frame):
+ """
+ Test timed out signal handler
+ """
print('Test timed out')
sys.exit(1)
@@ -81,13 +89,13 @@ parser.add_argument('-u', '--duplicate', help="Simulate tcp packet duplication",
type=int, default=0)
args = parser.parse_args()
logdir=args.logdir
-packet_loss=str(args.loss)+'%'
-packet_corruption=str(args.corruption)+'%'
-packet_duplicate=str(args.duplicate)+'%'
+PACKET_LOSS=str(args.loss)+'%'
+PACKET_CORRUPTION=str(args.corruption)+'%'
+PACKET_DUPLICATE=str(args.duplicate)+'%'
-ip(f"netns add {net0}")
-ip(f"netns add {net1}")
-ip(f"link add type veth")
+ip(f"netns add {NET0}")
+ip(f"netns add {NET1}")
+ip("link add type veth")
addrs = [
# we technically don't need different port numbers, but this will
@@ -99,38 +107,38 @@ addrs = [
# move interfaces to separate namespaces so they can no longer be
# bound directly; this prevents rds from switching over from the tcp
# transport to the loop transport.
-ip(f"link set {veth0} netns {net0} up")
-ip(f"link set {veth1} netns {net1} up")
+ip(f"link set {VETH0} netns {NET0} up")
+ip(f"link set {VETH1} netns {NET1} up")
# add addresses
-ip(f"-n {net0} addr add {addrs[0][0]}/32 dev {veth0}")
-ip(f"-n {net1} addr add {addrs[1][0]}/32 dev {veth1}")
+ip(f"-n {NET0} addr add {addrs[0][0]}/32 dev {VETH0}")
+ip(f"-n {NET1} addr add {addrs[1][0]}/32 dev {VETH1}")
# add routes
-ip(f"-n {net0} route add {addrs[1][0]}/32 dev {veth0}")
-ip(f"-n {net1} route add {addrs[0][0]}/32 dev {veth1}")
+ip(f"-n {NET0} route add {addrs[1][0]}/32 dev {VETH0}")
+ip(f"-n {NET1} route add {addrs[0][0]}/32 dev {VETH1}")
# sanity check that our two interfaces/addresses are correctly set up
# and communicating by doing a single ping
-ip(f"netns exec {net0} ping -c 1 {addrs[1][0]}")
+ip(f"netns exec {NET0} ping -c 1 {addrs[1][0]}")
# Start a packet capture on each network
-for net in [net0, net1]:
- tcpdump_pid = os.fork()
- if tcpdump_pid == 0:
- pcap = logdir+'/'+net+'.pcap'
- subprocess.check_call(['touch', pcap])
- user = getpwuid(stat(pcap).st_uid).pw_name
- ip(f"netns exec {net} /usr/sbin/tcpdump -Z {user} -i any -w {pcap}")
- sys.exit(0)
+tcpdump_procs = []
+for net in [NET0, NET1]:
+ pcap = logdir+'/'+net+'.pcap'
+ fd, pcap_tmp = tempfile.mkstemp(suffix=".pcap", prefix=f"{net}-", dir="/tmp")
+ p = subprocess.Popen(
+ ['ip', 'netns', 'exec', net,
+ '/usr/sbin/tcpdump', '-i', 'any', '-w', pcap_tmp])
+ tcpdump_procs.append((p, pcap_tmp, pcap, fd))
# simulate packet loss, duplication and corruption
-for net, iface in [(net0, veth0), (net1, veth1)]:
+for net, iface in [(NET0, VETH0), (NET1, VETH1)]:
ip(f"netns exec {net} /usr/sbin/tc qdisc add dev {iface} root netem \
- corrupt {packet_corruption} loss {packet_loss} duplicate \
- {packet_duplicate}")
+ corrupt {PACKET_CORRUPTION} loss {PACKET_LOSS} duplicate \
+ {PACKET_DUPLICATE}")
# add a timeout
if args.timeout > 0:
@@ -138,8 +146,8 @@ if args.timeout > 0:
signal.signal(signal.SIGALRM, signal_handler)
sockets = [
- netns_socket(net0, socket.AF_RDS, socket.SOCK_SEQPACKET),
- netns_socket(net1, socket.AF_RDS, socket.SOCK_SEQPACKET),
+ netns_socket(NET0, socket.AF_RDS, socket.SOCK_SEQPACKET),
+ netns_socket(NET1, socket.AF_RDS, socket.SOCK_SEQPACKET),
]
for s, addr in zip(sockets, addrs):
@@ -150,9 +158,7 @@ fileno_to_socket = {
s.fileno(): s for s in sockets
}
-addr_to_socket = {
- addr: s for addr, s in zip(addrs, sockets)
-}
+addr_to_socket = dict(zip(addrs, sockets))
socket_to_addr = {
s: addr for addr, s in zip(addrs, sockets)
@@ -166,14 +172,14 @@ ep = select.epoll()
for s in sockets:
ep.register(s, select.EPOLLRDNORM)
-n = 50000
+NUM_PACKETS = 50000
nr_send = 0
nr_recv = 0
-while nr_send < n:
+while nr_send < NUM_PACKETS:
# Send as much as we can without blocking
print("sending...", nr_send, nr_recv)
- while nr_send < n:
+ while nr_send < NUM_PACKETS:
send_data = hashlib.sha256(
f'packet {nr_send}'.encode('utf-8')).hexdigest().encode('utf-8')
@@ -212,7 +218,7 @@ while nr_send < n:
break
# exercise net/rds/tcp.c:rds_tcp_sysctl_reset()
- for net in [net0, net1]:
+ for net in [NET0, NET1]:
ip(f"netns exec {net} /usr/sbin/sysctl net.rds.tcp.rds_tcp_rcvbuf=10000")
ip(f"netns exec {net} /usr/sbin/sysctl net.rds.tcp.rds_tcp_sndbuf=10000")
@@ -242,7 +248,11 @@ for s in sockets:
print(f"getsockopt(): {nr_success}/{nr_error}")
print("Stopping network packet captures")
-subprocess.check_call(['killall', '-q', 'tcpdump'])
+for p, pcap_tmp, pcap, fd in tcpdump_procs:
+ p.terminate()
+ p.wait()
+ os.close(fd)
+ shutil.move(pcap_tmp, pcap)
# We're done sending and receiving stuff, now let's check if what
# we received is what we sent.