test: Add CI/demo scripts

Not really quick, definitely dirty.

Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
This commit is contained in:
Stefano Brivio 2021-09-27 15:10:35 +02:00
parent ca325e7583
commit 061519b562
31 changed files with 4816 additions and 0 deletions

52
test/build/all Normal file
View file

@ -0,0 +1,52 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/build/all - Build targets, one by one, then all together, check output
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
htools make cc rm uname getconf
test Build passt
host make clean
check ! [ -e passt ]
host CFLAGS="-Werror" make passt
check [ -f passt ]
test Build pasta
host make clean
check ! [ -e pasta ]
host CFLAGS="-Werror" make pasta
check [ -h pasta ]
test Build qrap
host make clean
check ! [ -e qrap ]
host CFLAGS="-Werror" make qrap
check [ -f qrap ]
test Build all
host make clean
check ! [ -e passt ]
check ! [ -e pasta ]
check ! [ -e qrap ]
host CFLAGS="-Werror" make
check [ -f passt ]
check [ -h pasta ]
check [ -f qrap ]
test Build AVX2
host make clean
check ! [ -e passt ]
check ! [ -e pasta ]
check ! [ -e qrap ]
host CFLAGS="-Werror" make avx2
check [ -f passt ]
check [ -h pasta ]
check [ -f qrap ]

34
test/build/install Normal file
View file

@ -0,0 +1,34 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/build/install - Check that binaries and man pages can be installed
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
req build/all
htools make mkdir cp rm man
tempdir TEMP
test Install
host prefix=__TEMP__ make install
check [ -f __TEMP__/bin/passt ]
check [ -h __TEMP__/bin/pasta ]
check [ -f __TEMP__/bin/qrap ]
check man -M __TEMP__/man -W passt
check man -M __TEMP__/man -W pasta
check man -M __TEMP__/man -W qrap
test Uninstall
host prefix=__TEMP__ make uninstall
check ! [ -f __TEMP__/bin/passt ]
check ! [ -h __TEMP__/bin/pasta ]
check ! [ -f __TEMP__/bin/qrap ]
check ! man -M __TEMP__/man -W passt 2>/dev/null
check ! man -M __TEMP__/man -W pasta 2>/dev/null
check ! man -M __TEMP__/man -W qrap 2>/dev/null

1
test/ci Symbolic link
View file

@ -0,0 +1 @@
run

248
test/demo/passt Normal file
View file

@ -0,0 +1,248 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/demo/passt - Quick introduction to passt
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
onlyfor passt
say This is a short introduction to
em passt
say .
nl
nl
sleep 3
say Let's fetch the source
sleep 1
tempdir TEMPDIR
host cd __TEMPDIR__
host git clone https://passt.top/passt
sleep 1
say and build it.
sleep 1
host cd passt
host make avx2
sleep 1
nl
nl
say A quick look at the man page...
sleep 1
hostb man ./passt.1
sleep 5
hostb /ports
sleep 2
hostb n
sleep 2
hostb n
sleep 10
nl
say '-t' to forward TCP ports.
sleep 3
host q
nl
nl
say Let's create a small initramfs image for the guest.
guest cd __TEMPDIR__
guest git clone https://mbuto.lameexcu.se/mbuto
guest cd mbuto
guest ./mbuto -f passt.img -p passt -c lz4
sleep 2
nl
nl
say We want to isolate passt and guest in a
nl
say network namespace. For convenience, we'll
nl
say create it with 'pasta', see also the
nl
say 'pasta' demo above.
sleep 3
passt cd __TEMPDIR__/passt
passt ./pasta
sleep 3
passt /sbin/dhclient
sleep 2
passt /sbin/dhclient -6
sleep 2
nl
nl
say Now let's run 'passt' in the new namespace, and
nl
say enter this namespace from the guest terminal too.
sleep 3
pout TARGET_PID echo $$
sleep 1
passtb ./passt -f -t 5201,5203
sleep 2
guest nsenter -t __TARGET_PID__ -U -n --preserve-credentials
sleep 5
nl
nl
say We're ready to start qemu with the qrap wrapper,
nl
say that we currently need to connect the netdev
nl
say back-end to passt's UNIX domain socket.
sleep 2
hout VMLINUZ echo "/boot/vmlinuz-$(uname -r)"
guest ../passt/qrap 5 kvm -m 4096 -cpu host -smp 4 -kernel __VMLINUZ__ -initrd passt.img -nographic -serial stdio -nodefaults -append "console=ttyS0 virtio-net.napi_tx=1" -device virtio-net-pci,netdev=hostnet0,x-txburst=16384 -netdev socket,fd=5,id=hostnet0
sleep 10
nl
nl
guest ip li sh
sleep 3
say Guest is up. Let's configure IPv4 first...
sleep 2
guest dhclient
sleep 2
guest ip ad sh
sleep 5
nl
say SLAAC is already done, but we can also
nl
say get another address via DHCPv6.
sleep 3
guest dhclient -6
sleep 3
nl
nl
say Let's try to communicate between host and guest.
sleep 2
guestb nc -6 -l -p 5201
sleep 2
host echo "Hello from the host" | nc -N ::1 5201
sleep 5
nl
nl
say Now the other way around... using
nl
say the address of the default gateway.
sleep 2
gout GW ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
sleep 5
hostb nc -l -p 31337
sleep 2
guest echo "Hello from the guest" | nc -N __GW__ 31337
sleep 3
nl
nl
say Let's have a (quick!) look at performance
nl
say more in the "Performance" section below.
sleep 3
host nsenter -t __TARGET_PID__ -U -n --preserve-credentials
guest /sbin/sysctl -w net.core.rmem_max=536870912
guest /sbin/sysctl -w net.core.wmem_max=536870912
guest /sbin/sysctl -w net.core.rmem_default=33554432
guest /sbin/sysctl -w net.core.wmem_default=33554432
guest /sbin/sysctl -w net.ipv4.tcp_rmem="4096 131072 268435456"
guest /sbin/sysctl -w net.ipv4.tcp_wmem="4096 131072 268435456"
guest /sbin/sysctl -w net.ipv4.tcp_timestamps=0
host sysctl -w net.ipv4.tcp_rmem="4096 524288 134217728"
host sysctl -w net.ipv4.tcp_wmem="4096 524288 134217728"
host sysctl -w net.ipv4.tcp_timestamps=0
gout GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
gout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
nl
nl
info Throughput in Gbps, latency in µs
th flow host>guest guest>host
set OPTS -P4 -w 64M -l 1M -i1 --pacing-timer 100000
tr TCP/IPv6 throughput
hostb sleep 10; iperf3 -c ::1 __OPTS__
gout BW iperf3 -s1J | jq -rM ".end.sum_received.bits_per_second"
bw __BW__ 2.0 3.0
sleep 5
guestb sleep 10; iperf3 -c __GW6__%__IFNAME__ -p 5202 __OPTS__ -O3
hout BW iperf3 -s1J -p 5202 | jq -rM ".end.sum_received.bits_per_second"
bw __BW__ 2.0 3.0
tl TCP/IPv6 RR latency
guestb tcp_rr -C 5201 -P 5203 -6 --nolog
sleep 2
hout LAT tcp_rr -C 5201 -P 5203 --nolog -c -H ::1 | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 1000 800
sleep 2
hostb tcp_rr -6 --nolog
sleep 2
gout LAT tcp_rr --nolog -c -H __GW6__%__IFNAME__ | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 1000 800
sleep 2
tl TCP/IPv6 CRR latency
guestb tcp_crr -C 5201 -P 5203 -6 --nolog
sleep 2
hout LAT tcp_crr -C 5201 -P 5203 --nolog -c -H ::1 | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 1000 800
sleep 2
hostb tcp_crr -6 --nolog
sleep 2
gout LAT tcp_crr --nolog -c -H __GW6__%__IFNAME__ | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 1000 800
sleep 2
tr TCP/IPv4 throughput
hostb sleep 10; iperf3 -c 127.0.0.1 __OPTS__
gout BW iperf3 -s1J | jq -rM ".end.sum_received.bits_per_second"
bw __BW__ 2.0 3.0
sleep 5
guestb sleep 10; iperf3 -c __GW__ -p 5202 __OPTS__ -O3
hout BW iperf3 -s1J -p 5202 | jq -rM ".end.sum_received.bits_per_second"
bw __BW__ 2.0 3.0
tl TCP/IPv4 RR latency
guestb tcp_rr -C 5201 -P 5203 -4 --nolog
sleep 2
hout LAT tcp_rr -C 5201 -P 5203 --nolog -c -H 127.0.0.1 | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 1000 800
sleep 2
hostb tcp_rr -4 --nolog
sleep 2
gout LAT tcp_rr --nolog -c -H __GW__ | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 1000 800
sleep 2
tl TCP/IPv4 CRR latency
guestb tcp_crr -C 5201 -P 5203 -4 --nolog
sleep 2
hout LAT tcp_crr -C 5201 -P 5203 --nolog -c -H 127.0.0.1 | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 1000 800
sleep 2
hostb tcp_crr -4 --nolog
sleep 2
gout LAT tcp_crr --nolog -c -H __GW__ | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 1000 800
sleep 2
nl
nl
say Thanks for watching!
sleep 5

274
test/demo/pasta Normal file
View file

@ -0,0 +1,274 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/demo/pasta - Quick introduction to pasta
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
onlyfor pasta
say This is a short introduction to
em pasta
say .
nl
nl
sleep 3
say Let's fetch the source
sleep 1
tempdir TEMPDIR
host cd __TEMPDIR__
host git clone https://passt.top/passt
sleep 1
say and build it.
sleep 1
host cd passt
host make
sleep 1
nl
nl
say A quick look at the man page...
sleep 1
hostb man ./pasta.1
sleep 5
hostb /pasta
sleep 2
hostb n
sleep 2
hostb n
sleep 10
nl
say without TARGET_PID, it will create a namespace.
sleep 3
passt cd __TEMPDIR__/passt
passt ./pasta
sleep 3
nl
nl
say For convenience, let's enter this namespace
nl
say from another terminal.
sleep 3
pout TARGET_PID echo $$
sleep 1
ns nsenter -t __TARGET_PID__ -U -n --preserve-credentials
sleep 5
nl
nl
say Now, we're ready to configure networking.
sleep 2
host q
nl
nl
ns ip li sh
sleep 3
say Let's configure IPv4 first...
sleep 2
ns dhclient
sleep 2
ns ip ad sh
sleep 5
nl
say SLAAC is already done, but we can also
nl
say get another address via DHCPv6.
sleep 3
ns dhclient -6
sleep 3
nl
nl
say Let's try to communicate between host and namespace
sleep 2
nl
say ...there's no need to configure port forwarding,
nl
say pasta detects bound ports and forwards them.
sleep 3
nsb nc -6 -l -p 31337
sleep 2
host echo "Hello from the host" | nc -N ::1 31337
sleep 5
nl
nl
say Now the other way around...
nl
say we can use a loopback address
sleep
hostb nc -l -p 31337
sleep 2
ns echo "Hello from the namespace" | nc -N 127.0.0.1 31337
sleep 5
nl
say or the address of the default gateway.
sleep 2
nsout GW ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
sleep 5
hostb nc -l -p 31337
sleep 2
ns echo "Hello from the namespace" | nc -N __GW__ 31337
sleep 3
nl
nl
say UDP...
sleep 2
ns host -t A passt.top
sleep 3
say seems to work too.
sleep 3
nl
nl
em pasta
say can also take packet captures.
sleep 3
passt exit
sleep 2
temp TEMP
passtb ./pasta -p __TEMP__.pcap
sleep 2
passt
passt /sbin/dhclient
sleep 2
hostb tshark -r __TEMP__.pcap
sleep 5
nl
nl
say And there are tons of totally useless
sleep 1
bsp 14
say absolutely useful features
nl
say you can find described in the man page.
sleep 5
nl
nl
say Let's have a (quick!) look at performance
nl
say more in the "Performance" section below.
sleep 3
passt exit
passt CFLAGS="-g" make avx2
sleep 2
passt perf record -g ./pasta
sleep 2
pout TARGET_PID echo $$
sleep 1
ns nsenter -t __TARGET_PID__ -U -n --preserve-credentials
sleep 5
nl
nl
info Throughput in Gbps, latency in µs
th flow init>ns ns>init
set OPTS -P4 -l 1M -w 32M -i1 --pacing-timer 100000
tr TCP/IPv6 throughput
nsb sleep 10; iperf3 -c ::1 __OPTS__
hout BW iperf3 -s1J | jq -rM ".end.sum_received.bits_per_second"
bw __BW__ 10.0 20.0
sleep 5
hostb sleep 10; iperf3 -c ::1 __OPTS__
nsout BW iperf3 -s1J | jq -rM ".end.sum_received.bits_per_second"
bw __BW__ 10.0 20.0
tl TCP/IPv6 RR latency
hostb tcp_rr -6 --nolog
sleep 2
nsout LAT tcp_rr --nolog -c -H ::1 | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 1000 500
sleep 2
nsb tcp_rr -6 --nolog
sleep 2
hout LAT tcp_rr --nolog -c -H ::1 | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 1000 500
sleep 2
tl TCP/IPv6 CRR latency
hostb tcp_crr -6 --nolog
sleep 2
nsout LAT tcp_crr --nolog -c -H ::1 | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 1000 500
sleep 2
nsb tcp_crr -6 --nolog
sleep 2
hout LAT tcp_crr --nolog -c -H ::1 | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 1000 500
sleep 2
tr TCP/IPv4 throughput
nsb sleep 10; iperf3 -c 127.0.0.1 __OPTS__
hout BW iperf3 -s1J | jq -rM ".end.sum_received.bits_per_second"
bw __BW__ 10.0 20.0
sleep 5
hostb sleep 10; iperf3 -c 127.0.0.1 __OPTS__
nsout BW iperf3 -s1J | jq -rM ".end.sum_received.bits_per_second"
bw __BW__ 10.0 20.0
tl TCP/IPv4 RR latency
hostb tcp_rr -4 --nolog
sleep 2
nsout LAT tcp_rr --nolog -c -H 127.0.0.1 | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 1000 500
sleep 2
nsb tcp_rr -4 --nolog
sleep 2
hout LAT tcp_rr --nolog -c -H 127.0.0.1 | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 1000 500
sleep 2
tl TCP/IPv4 CRR latency
hostb tcp_crr -4 --nolog
sleep 2
nsout LAT tcp_crr --nolog -c -H 127.0.0.1 | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 1000 500
sleep 2
nsb tcp_crr -4 --nolog
sleep 2
hout LAT tcp_crr --nolog -c -H 127.0.0.1 | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 1000 500
sleep 2
sleep 5
passt exit
sleep 2
killp PASST
killp HOST
sleep 2
nsb perf report -g --max-stack 3
sleep 10
nl
nl
say I
em knew
say it.
em syscalls
say .
sleep 5
nl
nl
say Thanks for watching!
sleep 5

70
test/dhcp/passt Normal file
View file

@ -0,0 +1,70 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/dhcp/passt - Check DHCP and DHCPv6 functionality in passt mode
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
onlyfor passt passt_in_ns
gtools ip jq dhclient sed tr
htools ip jq sed tr head
test Interface name
gout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
hout HOST_IFNAME ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").dev'
check [ -n "__IFNAME__" ]
test DHCP: address
guest /sbin/dhclient __IFNAME__
gout ADDR ip -j -4 ad sh|jq -rM '.[] | select(.ifname == "__IFNAME__").addr_info[0].local'
hout HOST_ADDR ip -j -4 ad sh|jq -rM '.[] | select(.ifname == "__HOST_IFNAME__").addr_info[0].local'
check [ "__ADDR__" = "__HOST_ADDR__" ]
test DHCP: route
gout GW ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
hout HOST_GW ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
check [ "__GW__" = "__HOST_GW__" ]
test DHCP: MTU
gout MTU ip -j li sh | jq -rM '.[] | select(.ifname == "__IFNAME__").mtu'
check [ __MTU__ = 65520 ]
test DHCP: DNS
gout DNS sed -n 's/^nameserver \([0-9]*\.\)\(.*\)/\1\2/p' /etc/resolv.conf | tr '\n' ',' | sed 's/\(.*\)/\1\n/g'
hout HOST_DNS sed -n 's/^nameserver \([0-9]*\.\)\(.*\)/\1\2/p' /etc/resolv.conf | head -n3 | tr '\n' ',' | sed 's/\(.*\)/\1\n/g'
check [ "__DNS__" = "__HOST_DNS__" ]
# FQDNs should be terminated by dots, but the guest DHCP client might omit them:
# strip them first
test DHCP: search list
gout SEARCH sed 's/\. / /g' /etc/resolv.conf | sed 's/\.$//g' | sed -n 's/^search \(.*\)/\1/p' | tr ' \n' ',' | sed 's/\(.*\)/\1\n/g'
hout HOST_SEARCH sed 's/\. / /g' /etc/resolv.conf | sed 's/\.$//g' | sed -n 's/^search \(.*\)/\1/p' | tr ' \n' ',' | sed 's/\(.*\)/\1\n/g'
check [ "__SEARCH__" = "__HOST_SEARCH__" ]
test DHCPv6: address
guest /sbin/dhclient -6 __IFNAME__
gout ADDR6 ip -j -6 ad sh|jq -rM '.[] | select(.ifname == "__IFNAME__").addr_info[] | select(.prefixlen == 128).local'
hout HOST_ADDR6 ip -j -6 ad sh|jq -rM '.[] | select(.ifname == "__HOST_IFNAME__").addr_info[] | select(.scope == "global").local'
check [ "__ADDR6__" = "__HOST_ADDR6__" ]
test DHCPv6: route
gout GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
hout HOST_GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
check [ "__GW6__" = "__HOST_GW6__" ]
# Strip interface specifier: interface names might differ between host and guest
test DHCPv6: DNS
gout DNS6 sed -n 's/^nameserver \([^:]*:\)\([^%]*\).*/\1\2/p' /etc/resolv.conf | tr '\n' ',' | sed 's/\(.*\)/\1\n/g'
hout HOST_DNS6 sed -n 's/^nameserver \([^:]*:\)\([^%]*\).*/\1\2/p' /etc/resolv.conf | tr '\n' ',' | sed 's/\(.*\)/\1\n/g'
check [ "__DNS6__" = "__HOST_DNS6__" ]
test DHCPv6: search list
gout SEARCH6 sed 's/\. / /g' /etc/resolv.conf | sed 's/\.$//g' | sed -n 's/^search \(.*\)/\1/p' | tr ' \n' ',' | sed 's/\(.*\)/\1\n/g'
hout HOST_SEARCH6 sed 's/\. / /g' /etc/resolv.conf | sed 's/\.$//g' | sed -n 's/^search \(.*\)/\1/p' | tr ' \n' ',' | sed 's/\(.*\)/\1\n/g'
check [ "__SEARCH6__" = "__HOST_SEARCH6__" ]

46
test/dhcp/pasta Normal file
View file

@ -0,0 +1,46 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/dhcp/pasta - Check DHCP and DHCPv6 functionality in pasta mode
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
onlyfor pasta
nstools ip jq /sbin/udhcpc /sbin/dhclient
htools ip jq
test Interface name
nsout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
check [ -n "__IFNAME__" ]
test DHCP: address
ns /sbin/udhcpc -i __IFNAME__
nsout ADDR ip -j -4 ad sh|jq -rM '.[] | select(.ifname == "__IFNAME__").addr_info[0].local'
hout HOST_ADDR ip -j -4 ad sh|jq -rM '.[] | select(.ifname == "__IFNAME__").addr_info[0].local'
check [ __ADDR__ = __HOST_ADDR__ ]
test DHCP: route
nsout GW ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
hout HOST_GW ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
check [ __GW__ = __HOST_GW__ ]
test DHCP: MTU
nsout MTU ip -j li sh | jq -rM '.[] | select(.ifname == "__IFNAME__").mtu'
check [ __MTU__ = 65520 ]
test DHCPv6: address
ns /sbin/dhclient -6 __IFNAME__
nsout ADDR6 ip -j -6 ad sh|jq -rM '.[] | select(.ifname == "__IFNAME__").addr_info[] | select(.prefixlen == 128).local'
hout HOST_ADDR6 ip -j -6 ad sh|jq -rM '.[] | select(.ifname == "__IFNAME__").addr_info[] | select(.scope == "global").local'
check [ __ADDR6__ = __HOST_ADDR6__ ]
test DHCPv6: route
nsout GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
hout HOST_GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
check [ __GW6__ = __HOST_GW6__ ]

39
test/env/mate-terminal.profile vendored Normal file
View file

@ -0,0 +1,39 @@
[/]
allow-bold=true
background-color='#121212121212'
background-darkness=0.5
background-image=''
background-type='solid'
backspace-binding='ascii-del'
bold-color='#000000000000'
bold-color-same-as-fg=true
copy-selection=false
cursor-blink-mode='on'
cursor-shape='block'
custom-command=''
default-show-menubar=true
default-size-columns=180
default-size-rows=40
delete-binding='escape-sequence'
exit-action='close'
font='Bitstream Vera Sans Mono 9'
foreground-color='#504FA2A26160'
login-shell=false
palette='#000000000000:#FFFF8F8F8F8F:#504FA2A26160:#CBCB6C6C0505:#8E8EA3A2FFFF:#C4C45959C4C4:#0000AAAAAAAA:#AAAAAAAAAAAA:#555455545554:#FFFF8F8F8F8F:#504FA2A26160:#CBCB6C6C0505:#8E8EA3A2FFFF:#C4C45959C4C4:#5554FFFFFFFF:#FFFFFFFFFFFF'
scroll-background=true
scroll-on-keystroke=true
scroll-on-output=false
scrollback-lines=512
scrollback-unlimited=true
scrollbar-position='hidden'
silent-bell=false
title='Terminal'
title-mode='replace'
use-custom-command=false
use-custom-default-size=true
use-skey=true
use-system-font=false
use-theme-colors=false
use-urls=true
visible-name='passt_ci'
word-chars='-A-Za-z0-9,./?%&#:_=+@~'

37
test/icmp/passt_in_ns Normal file
View file

@ -0,0 +1,37 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/icmp/passt_in_ns - Check ICMP/ICMPv6 functionality for passt in ns
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
#
# These tests can work reliably only within an isolated namespace: the host
# might have a net.ipv4.ping_group_range sysctl value not allowing pasta's gid
# to create "ping" sockets. Inside the namespace, there's a single group, which
# is allowed by default to create them.
onlyfor passt_in_ns
nstools ip jq sleep
gtools ping ip jq
test ICMP echo: guest to ns
nsout IFNAME_NS ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
ns ip addr add 192.0.2.1/32 dev __IFNAME_NS__
guest ping -c1 -w1 192.0.2.1
gout RET echo $?
ns ip addr del 192.0.2.1/32 dev __IFNAME_NS__
check [ __RET__ -eq 0 ]
test ICMPv6 echo: guest to ns
ns ip addr add 2001:db8::1 dev __IFNAME_NS__ && sleep 2 # DAD
gout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
guest ping -c1 -w1 2001:db8::1
gout RET echo $?
ns ip addr del 2001:db8::1 dev __IFNAME_NS__
check [ __RET__ -eq 0 ]

276
test/lib/layout Normal file
View file

@ -0,0 +1,276 @@
#!/bin/sh
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/lib/layout - tmux pane layouts
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
# layout_host() - Simple host commands layout with info and host panes
layout_host() {
sleep 3
tmux kill-pane -a -t 0
cmd_write 0 clear
tmux split-window -h -l '35%' -t passt_test:1.0
PANE_HOST=0
PANE_INFO=1
get_info_cols
tmux send-keys -l -t ${PANE_INFO} 'while cat /tmp/.passt_test_log_pipe; do :; done'
tmux send-keys -t ${PANE_INFO} -N 100 C-m
tmux select-pane -t ${PANE_INFO} -T "test log"
tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
tmux select-pane -t ${PANE_HOST} -T "host"
info_layout "host commands only"
sleep 1
}
# layout_pasta() - Panes for host, pasta, and separate one for namespace
layout_pasta() {
sleep 3
tmux kill-pane -a -t 0
cmd_write 0 clear
tmux split-window -v -t passt_test
tmux split-window -h -t passt_test
tmux split-window -h -l '42%' -t passt_test:1.0
PANE_NS=0
PANE_INFO=1
PANE_HOST=2
PANE_PASST=3
get_info_cols
tmux pipe-pane -O -t ${PANE_NS} "cat >> ${LOGDIR}/pane_ns.log"
tmux select-pane -t ${PANE_NS} -T "namespace"
tmux send-keys -l -t ${PANE_INFO} 'while cat /tmp/.passt_test_log_pipe; do :; done'
tmux send-keys -t ${PANE_INFO} -N 100 C-m
tmux select-pane -t ${PANE_INFO} -T "test log"
tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
tmux select-pane -t ${PANE_HOST} -T "host"
tmux pipe-pane -O -t ${PANE_PASST} "cat >> ${LOGDIR}/pane_passt.log"
tmux select-pane -t ${PANE_PASST} -T "pasta"
info_layout "single pasta instance with namespace"
sleep 1
}
# layout_passt() - Panes for host, passt, and guest
layout_passt() {
sleep 3
tmux kill-pane -a -t 0
cmd_write 0 clear
tmux split-window -v -t passt_test
tmux split-window -h -t passt_test
tmux split-window -h -l '42%' -t passt_test:1.0
PANE_GUEST=0
PANE_INFO=1
PANE_HOST=2
PANE_PASST=3
get_info_cols
tmux pipe-pane -O -t ${PANE_GUEST} "cat >> ${LOGDIR}/pane_guest.log"
tmux select-pane -t ${PANE_GUEST} -T "guest"
tmux send-keys -l -t ${PANE_INFO} 'while cat /tmp/.passt_test_log_pipe; do :; done'
tmux send-keys -t ${PANE_INFO} -N 100 C-m
tmux select-pane -t ${PANE_INFO} -T "test log"
tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
tmux select-pane -t ${PANE_HOST} -T "host"
tmux pipe-pane -O -t ${PANE_PASST} "cat >> ${LOGDIR}/pane_passt.log"
tmux select-pane -t ${PANE_PASST} -T "passt"
info_layout "single passt instance with guest"
sleep 1
}
# layout_passt_in_pasta() - Host, passt within pasta, namespace and guest
layout_passt_in_pasta() {
sleep 3
tmux kill-pane -a -t 0
cmd_write 0 clear
tmux split-window -v -l '45%' -t passt_test
tmux split-window -h -t passt_test
tmux split-window -h -l '42%' -t passt_test:1.0
tmux split-window -v -t passt_test:1.0
PANE_GUEST=0
PANE_NS=1
PANE_INFO=2
PANE_HOST=3
PANE_PASST=4
get_info_cols
tmux pipe-pane -O -t ${PANE_GUEST} "cat >> ${LOGDIR}/pane_guest.log"
tmux select-pane -t ${PANE_GUEST} -T "guest"
tmux pipe-pane -O -t ${PANE_NS} "cat >> ${LOGDIR}/pane_ns.log"
tmux select-pane -t ${PANE_NS} -T "namespace"
tmux send-keys -l -t ${PANE_INFO} 'while cat /tmp/.passt_test_log_pipe; do :; done'
tmux send-keys -t ${PANE_INFO} -N 100 C-m
tmux select-pane -t ${PANE_INFO} -T "test log"
tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
tmux select-pane -t ${PANE_HOST} -T "host"
tmux pipe-pane -O -t ${PANE_PASST} "cat >> ${LOGDIR}/pane_passt.log"
tmux select-pane -t ${PANE_PASST} -T "passt in pasta (namespace)"
info_layout "passt and guest in namespace, connected by pasta"
sleep 1
}
# layout_two_guests() - Two guest panes, two passt panes, plus host and log
layout_two_guests() {
sleep 3
tmux kill-pane -a -t 0
cmd_write 0 clear
tmux split-window -v -t passt_test
tmux split-window -h -l '33%'
tmux split-window -h -t passt_test:1.1
tmux split-window -h -l '35%' -t passt_test:1.0
tmux split-window -v -t passt_test:1.0
for i in `seq 0 5`; do
tmux select-pane -t $i -T "${i}"
done
PANE_GUEST_1=0
PANE_GUEST_2=1
PANE_INFO=2
PANE_HOST=3
PANE_PASST_1=4
PANE_PASST_2=5
get_info_cols
tmux pipe-pane -O -t ${PANE_GUEST_1} "cat >> ${LOGDIR}/pane_guest_1.log"
tmux select-pane -t ${PANE_GUEST_1} -T "guest #1 in namespace #1"
tmux pipe-pane -O -t ${PANE_GUEST_2} "cat >> ${LOGDIR}/pane_guest_2.log"
tmux select-pane -t ${PANE_GUEST_2} -T "guest #2 in namespace #2"
tmux send-keys -l -t ${PANE_INFO} 'while cat /tmp/.passt_test_log_pipe; do :; done'
tmux send-keys -t ${PANE_INFO} -N 100 C-m
tmux select-pane -t ${PANE_INFO} -T "test log"
tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
tmux select-pane -t ${PANE_HOST} -T "host"
tmux pipe-pane -O -t ${PANE_PASST_1} "cat >> ${LOGDIR}/pane_passt_1.log"
tmux select-pane -t ${PANE_PASST_1} -T "passt #1 in namespace #1"
tmux pipe-pane -O -t ${PANE_PASST_2} "cat >> ${LOGDIR}/pane_passt_2.log"
tmux select-pane -t ${PANE_PASST_2} -T "passt #2 in namespace #2"
info_layout "two guests, two passt instances, in namespaces"
sleep 1
}
# layout_demo_pasta() - Four panes for pasta demo
layout_demo_pasta() {
sleep 3
tmux kill-pane -a -t 0
cmd_write 0 clear
sleep 1
cmd_write 0 clear
tmux split-window -v -t passt_test
tmux split-window -h -t passt_test
tmux split-window -h -l '42%' -t passt_test:1.0
PANE_NS=0
PANE_INFO=1
PANE_HOST=2
PANE_PASST=3
get_info_cols
tmux pipe-pane -O -t ${PANE_NS} "cat >> ${LOGDIR}/pane_ns.log"
tmux select-pane -t ${PANE_NS} -T "namespace"
tmux send-keys -l -t ${PANE_INFO} 'while cat /tmp/.passt_test_log_pipe; do :; done'
tmux send-keys -t ${PANE_INFO} -N 100 C-m
tmux select-pane -t ${PANE_INFO} -T ""
tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
tmux select-pane -t ${PANE_HOST} -T "host"
tmux pipe-pane -O -t ${PANE_PASST} "cat >> ${LOGDIR}/pane_passt.log"
tmux select-pane -t ${PANE_PASST} -T "pasta"
sleep 1
}
# layout_demo_passt() - Four panes for passt demo
layout_demo_passt() {
sleep 3
tmux kill-pane -a -t 0
cmd_write 0 clear
sleep 1
cmd_write 0 clear
tmux split-window -v -t passt_test
tmux split-window -h -t passt_test
tmux split-window -h -l '42%' -t passt_test:1.0
PANE_GUEST=0
PANE_INFO=1
PANE_HOST=2
PANE_PASST=3
get_info_cols
tmux pipe-pane -O -t ${PANE_GUEST} "cat >> ${LOGDIR}/pane_guest.log"
tmux select-pane -t ${PANE_GUEST} -T "guest"
tmux send-keys -l -t ${PANE_INFO} 'while cat /tmp/.passt_test_log_pipe; do :; done'
tmux send-keys -t ${PANE_INFO} -N 100 C-m
tmux select-pane -t ${PANE_INFO} -T ""
tmux pipe-pane -O -t ${PANE_HOST} "cat >> ${LOGDIR}/pane_host.log"
tmux select-pane -t ${PANE_HOST} -T "host"
tmux pipe-pane -O -t ${PANE_PASST} "cat >> ${LOGDIR}/pane_passt.log"
tmux select-pane -t ${PANE_PASST} -T "passt in pasta (namespace)"
sleep 1
}

262
test/lib/perf_report Executable file
View file

@ -0,0 +1,262 @@
#!/bin/sh
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/lib/perf_report - Prepare JavaScript report for performance tests
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
PERF_LINK_COUNT=0
PERF_JS="${BASEPATH}/perf.js"
PERF_TEMPLATE_HTML="document.write('"'
Throughput in Gbps, latency in µs. Threads are <span style="font-family: monospace;">iperf3</span> processes, <i>passt</i> and <i>pasta</i> are currently single-threaded.<br/>
Click on numbers to show test execution. Measured at head, commit <span style="font-family: monospace;">__commit__</span>.
<style type="text/CSS">
table td { border: 0px solid; padding: 10px; }
table td { text-align: right; }
table th { text-align: center; font-weight: bold; }
table tr:not(:first-of-type) td:not(:first-of-type) { font-family: monospace; font-weight: bolder; }
table.passt tr:nth-child(3n+0) { background-color: #112315; }
table.passt tr:not(:nth-child(3n+0)) td { background-color: #101010; }
table.passt td:nth-child(6n+7) { background-color: #603302; }
table.passt tr:nth-child(1) { background-color: #363e61; }
td:empty { visibility: hidden; }
</style>
<ul>
<li><p>passt</p>
<table class="passt" width="70%">
<tr>
<th/>
<th id="perf_passt_tcp" colspan="__passt_tcp_cols__">TCP, __passt_tcp_threads__ at __passt_tcp_freq__ GHz</th>
<th id="perf_passt_udp" colspan="__passt_udp_cols__">UDP, __passt_udp_threads__ at __passt_udp_freq__ GHz</th>
</tr>
<tr>
<td align="right">MTU:</td>
__passt_tcp_header__
__passt_udp_header__
</tr>
__passt_tcp_LINE__ __passt_udp_LINE__
</table>
<style type="text/CSS">
table td { border: 0px solid; padding: 10px; }
table td { text-align: right; }
table th { text-align: center; font-weight: bold; }
table.pasta tr:nth-child(3n+0) { background-color: #112315; }
table.pasta tr:not(:nth-child(3n+0)) td { background-color: #101010; }
table.pasta td:nth-child(4n+5) { background-color: #603302; }
table.pasta tr:nth-child(1) { background-color: #363e61; }
td:empty { visibility: hidden; }
</style>
</li><li><p>pasta: local connections/traffic</p>
<table class="pasta" width="70%">
<tr>
<th/>
<th id="perf_pasta_lo_tcp" colspan="__pasta_lo_tcp_cols__">TCP, __pasta_lo_tcp_threads__ at __pasta_lo_tcp_freq__ GHz</th>
<th id="perf_pasta_lo_udp" colspan="__pasta_lo_udp_cols__">UDP, __pasta_lo_udp_threads__ at __pasta_lo_udp_freq__ GHz</th>
</th>
<tr>
<td align="right">MTU:</td>
__pasta_lo_tcp_header__
__pasta_lo_udp_header__
</tr>
__pasta_lo_tcp_LINE__ __pasta_lo_udp_LINE__
</table>
</li><li><p>pasta: connections/traffic via tap</p>
<table class="pasta" width="70%">
<tr>
<th/>
<th id="perf_pasta_tap_tcp" colspan="__pasta_tap_tcp_cols__">TCP, __pasta_tap_tcp_threads__ at __pasta_tap_tcp_freq__ GHz</th>
<th id="perf_pasta_tap_udp" colspan="__pasta_tap_udp_cols__">UDP, __pasta_tap_udp_threads__ at __pasta_tap_udp_freq__ GHz</th>
</tr>
<tr>
<td align="right">MTU:</td>
__pasta_tap_tcp_header__
__pasta_tap_udp_header__
</tr>
__pasta_tap_tcp_LINE__ __pasta_tap_udp_LINE__
</table>
</li></ul>'
PERF_TEMPLATE_JS="');
var perf_links = [
"
PERF_TEMPLATE_POST='];
for (var i = 0; i < perf_links.length; i++) {
var obj = document.getElementById(perf_links[i][0]);
obj.addEventListener("click", function(event) {
var ci_video = document.getElementById("ci_video");
var top = ci_video.offsetTop - 5;
event.preventDefault();
ci_video.play();
ci_video.pause();
for (var i = 0; i < perf_links.length; i++) {
if (this.id == perf_links[i][0]) {
ci_video.currentTime = perf_links[i][1] - 10;
}
}
window.scrollTo({ top: top, behavior: "smooth" })
ci_video.play();
}, false);
}
'
# perf_init() - Process first part of template
perf_init() {
echo "${PERF_TEMPLATE_HTML}" > "${PERF_JS}"
perf_report_sub commit "$(echo ${COMMIT} | sed "s/'/\\\'/g")"
}
# perf_fill_lines() - Fill multiple "LINE" directives in template, matching rows
perf_fill_lines() {
while true; do
__file_line="$(sed -n '/__.*_LINE__/{=;q}' "${PERF_JS}")"
[ -z "${__file_line}" ] && break
__line_no=0
__done=0
__line_buf="<tr>"
while true; do
__match_first_td=0
for __t in $(sed -n '/__.*_LINE__/{p;q}' "${PERF_JS}"); do
if [ ${__match_first_td} -eq 1 ]; then
__matching_line_no=0
while true; do
__line_part=
__var_name="$(echo $__t | sed -n 's/__\(.*\)__/\1_'"${__matching_line_no}"'/p')"
[ -z "$(eval echo \$${__var_name})" ] && break
__line_part="$(eval echo \$${__var_name})"
__td_check="$(echo "${__line_part}" | sed -n 's/^<td>\([^>]*\)<\/td>.*$/\1/p')"
if [ "${__td_check}" = "${__td_match}" ]; then
__line_part="$(echo "${__line_part}" | sed -n 's/^<td>[^>]*<\/td>\(.*\)$/\1/p')"
break
fi
__matching_line_no=$((__matching_line_no + 1))
done
else
__var_name="$(echo $__t | sed -n 's/__\(.*\)__/\1_'"${__line_no}"'/p')"
[ -z "$(eval echo \$${__var_name})" ] && __done=1 && break
__line_part="$(eval echo \$${__var_name})"
__td_match="$(echo "${__line_part}" | sed -n 's/^<td>\([^>]*\)<\/td>.*$/\1/p')"
fi
__line_buf="${__line_buf}${__line_part}"
__match_first_td=1
done
[ ${__done} -eq 1 ] && break
__line_no=$((__line_no + 1))
__line_buf="${__line_buf}</tr><tr>"
done
__line_buf="${__line_buf}</tr>"
__line_buf="$(printf '%s\n' "${__line_buf}" | sed -e 's/[]\/$*.^[]/\\&/g')"
sed -i "${__file_line}s/.*/${__line_buf}/" "${PERF_JS}"
done
}
# perf_finish() - Add trailing backslashes and process ending templates
perf_finish() {
perf_fill_lines
sed -i 's/^.*$/&\\/g' "${PERF_JS}"
echo "${PERF_TEMPLATE_JS}" >> "${PERF_JS}"
echo "${PERF_TEMPLATE_POST}" >> "${PERF_JS}"
}
# perf_report_sub() - Apply simple substitutions in template
perf_report_sub() {
__et="$(printf '%s\n' "${1}" | sed -e 's/[\/&]/\\&/g')"
__es="$(printf '%s\n' "${2}" | sed -e 's/[]\/$*.^[]/\\&/g')"
sed -i 's/__'"${__et}"'__/'"${__es}"'/g' "${PERF_JS}"
}
# perf_report_append() - Append generic string to current JavaScript report
perf_report_append() {
echo "${@}" >> "${PERF_JS}"
}
# perf_report_append() - Append generic string to current template buffer
perf_report_append_js() {
PERF_TEMPLATE_JS="${PERF_TEMPLATE_JS}${@}"
}
# perf_report() - Start of single test report
perf_report() {
__mode="${1}"
__proto="${2}"
__threads="${3}"
__freq="${4}"
REPORT_IN="${__mode}_${__proto}"
[ ${__threads} -eq 1 ] && __threads="one thread" || __threads="${__threads} threads"
perf_report_sub "${__mode}_${__proto}_threads" "${__threads}"
perf_report_sub "${__mode}_${__proto}_freq" "${__freq}"
perf_report_append_js "[ 'perf_${__mode}_${__proto}', $(video_time_now) ],"
}
# perf_th() - Table header for a set of tests
perf_th() {
shift
__th_buf=
__cols_count=0
for __arg; do
__th_buf="${__th_buf}<td>${__arg}</td>"
__cols_count=$((__cols_count + 1))
done
perf_report_sub "${REPORT_IN}_header" "${__th_buf}"
perf_report_sub "${REPORT_IN}_cols" ${__cols_count}
}
# perf_tr() - Main table row
perf_tr() {
__line_no=0
shift
while true; do
[ -z "$(eval echo \$${REPORT_IN}_LINE_${__line_no})" ] && break
__line_no=$((__line_no + 1))
done
eval ${REPORT_IN}_LINE_${__line_no}="\"<td>${@}</td>\""
}
# perf_td() - Single cell with test result
perf_td() {
__rewind="${1}"
shift
__line_no=0
while true; do
[ -z "$(eval echo \$${REPORT_IN}_LINE_${__line_no})" ] && break
__line_no=$((__line_no + 1))
done
__line_no=$((__line_no - 1))
[ -z "${1}" ] && __id=0 || __id="perf_${PERF_LINK_COUNT}"
eval ${REPORT_IN}_LINE_${__line_no}=\""\${${REPORT_IN}_LINE_${__line_no}}<td id=\"${__id}\">${1}</td>"\"
[ -z "${1}" ] && return
perf_report_append_js "[ '${__id}', $(($(video_time_now) - ${__rewind})) ],"
PERF_LINK_COUNT=$((PERF_LINK_COUNT + 1))
}
# perf_te() - End of a table, currently unused
pert_te() {
:
}

322
test/lib/setup Executable file
View file

@ -0,0 +1,322 @@
#!/bin/sh
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/lib/setup - Set up and tear down passt and pasta environments
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
VCPUS="$( [ $(nproc) -ge 8 ] && echo 4 || echo $(( $(nproc) / 2 + 1 )) )"
__mem_kib="$(sed -n 's/MemTotal:[ ]*\([0-9]*\) kB/\1/p' /proc/meminfo)"
VMEM="$((${__mem_kib} / 1024 / 8))"
# setup_build() - Set up pane layout for build tests
setup_build() {
MODE=build
layout_host
}
# setup_passt() - Build guest initrd with mbuto, start qemu and passt
setup_passt() {
MODE=passt
layout_passt
__mbuto_dir="$(mktemp -d)"
pane_run GUEST "git -C ${__mbuto_dir} clone https://mbuto.lameexcu.se/mbuto/"
pane_wait GUEST
pane_run GUEST "${__mbuto_dir}/mbuto/mbuto -p passt -c lz4 -f mbuto.img"
pane_wait GUEST
rm -rf "${__mbuto_dir}"
# Ports:
#
# guest | host
# --------------|---------------------
# 10001 as server | forwarded to guest
# 10003 | as server
__opts=
[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt.pcap"
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
pane_run PASST "./passt ${__opts} -f -t 10001 -u 10001"
sleep 1
pane_run GUEST './qrap 5 kvm -m '${VMEM}' -cpu host -smp '${VCPUS} \
'-kernel' "/boot/vmlinuz-$(uname -r)" \
'-initrd mbuto.img -nographic -serial stdio' \
'-nodefaults ' \
'-append "console=ttyS0 mitigations=off apparmor=0 ' \
'virtio-net.napi_tx=1"' \
"-device virtio-net-pci,netdev=hostnet0,x-txburst=16384"\
"-netdev socket,fd=5,id=hostnet0"
pane_wait GUEST
}
# setup_pasta() - Create a network and user namespace, connect pasta to it
setup_pasta() {
MODE=pasta
layout_pasta
pane_run NS "unshare -rUn /bin/sh "
pane_wait NS
pane_run NS 'echo $$'
pane_wait NS
__pasta_pid="$(pane_parse NS)"
# Ports:
#
# ns | host
# ------------------|---------------------
# 10002 as server | spliced to ns
# 10003 spliced to init | as server
__opts=
[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta.pcap"
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
pane_run PASST "./pasta ${__opts} -f -t 10002 -T 10003 -u 10002 -U 10003 ${__pasta_pid}"
sleep 1
}
# setup_passt_in_ns() - Set up namespace (with pasta), run qemu and passt into it
setup_passt_in_ns() {
MODE=passt_in_ns
layout_passt_in_pasta
# Ports:
#
# guest | ns | host
# -------------|--------------------|-----------------
# 10001 as server | forwarded to guest | spliced to ns
# 10002 | as server | spliced to ns
# 10003 | spliced to init | as server
# 10011 as server | forwarded to guest | spliced to ns
# 10012 | as server | spliced to ns
# 10013 | spliced to init | as server
__opts=
[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta_with_passt.pcap"
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
pane_run PASST "./pasta ${__opts} -t 10001,10002,10011,10012 -T 10003,10013 -u 10001,10002,10011,10012 -U 10003,10013"
sleep 1
pane_run PASST ''
pane_wait PASST
pane_run PASST 'echo $$'
pane_wait PASST
__ns_pid="$(pane_parse PASST)"
pane_run GUEST "nsenter -t ${__ns_pid} -U -n --preserve-credentials"
pane_run NS "nsenter -t ${__ns_pid} -U -n --preserve-credentials"
pane_wait GUEST
pane_wait NS
pane_run NS "ip -j li sh | jq -rM '.[] | select(.link_type == \"ether\").ifname'"
pane_wait NS
__ifname="$(pane_parse NS)"
pane_run NS "/sbin/udhcpc -i ${__ifname}"
pane_wait NS
sleep 2
pane_run NS "/sbin/dhclient -6 ${__ifname}"
pane_wait NS
__opts=
[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_in_pasta.pcap"
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
#pane_run PASST "valgrind --max-stackframe=2097208 ./passt -f ${__opts} -t 10001,10011 -u 10001,10011"
pane_run PASST "./passt -f ${__opts} -t 10001,10011 -u 10001,10011"
sleep 1
pane_run GUEST './qrap 5 kvm -m '${VMEM}' -cpu host -smp '${VCPUS} \
'-kernel' "/boot/vmlinuz-$(uname -r)" \
'-initrd mbuto.img -nographic -serial stdio' \
'-nodefaults ' \
'-append "console=ttyS0 mitigations=off apparmor=0 ' \
'virtio-net.napi_tx=1"' \
"-device virtio-net-pci,netdev=hostnet0,x-txburst=131072"\
"-netdev socket,fd=5,id=hostnet0"
pane_wait GUEST
}
# setup_two_guests() - Set up two namespace, run qemu and passt in both of them
setup_two_guests() {
MODE=passt_in_ns
layout_two_guests
# Ports:
#
# guest #1 | guest #2 | ns #1 | ns #2 | host
# --------- |-----------|-----------|------------|------------
# 10001 as server | | to guest | to init | to ns #1
# 10002 | | as server | | to ns #1
# 10003 | | to init | to init | as server
# 10004 | as server | to init | to guest | to ns #2
# 10005 | | | as server | to ns #2
__opts=
[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta_1.pcap"
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
pane_run PASST_1 "./pasta ${__opts} -t 10001,10002 -T 10003,10004 -u 10001,10002 -U 10003,10004"
__opts=
[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/pasta_2.pcap"
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
pane_run PASST_2 "./pasta ${__opts} -t 10004,10005 -T 10003,10001 -u 10004,10005 -U 10003,10001"
sleep 1
pane_run PASST_1 ''
pane_run PASST_2 ''
pane_wait PASST_1
pane_wait PASST_2
pane_run PASST_1 'echo $$'
pane_run PASST_2 'echo $$'
pane_wait PASST_1
pane_wait PASST_2
__ns1_pid="$(pane_parse PASST_1)"
__ns2_pid="$(pane_parse PASST_2)"
pane_run GUEST_1 "nsenter -t ${__ns1_pid} -U -n --preserve-credentials"
pane_run GUEST_2 "nsenter -t ${__ns2_pid} -U -n --preserve-credentials"
pane_run PASST_1 "ip -j li sh | jq -rM '.[] | select(.link_type == \"ether\").ifname'"
pane_wait PASST_1
__ifname="$(pane_parse PASST_1)"
pane_run GUEST_1 "/sbin/udhcpc -i ${__ifname}"
pane_run GUEST_2 "/sbin/udhcpc -i ${__ifname}"
pane_wait GUEST_1
pane_wait GUEST_2
sleep 2
pane_run GUEST_1 "/sbin/dhclient -6 ${__ifname}"
pane_run GUEST_2 "/sbin/dhclient -6 ${__ifname}"
pane_wait GUEST_1
pane_wait GUEST_2
__opts=
[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_1.pcap"
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
pane_run PASST_1 "./passt -f ${__opts} -t 10001 -u 10001"
sleep 1
__opts=
[ ${PCAP} -eq 1 ] && __opts="${__opts} -p /tmp/passt_2.pcap"
[ ${DEBUG} -eq 1 ] && __opts="${__opts} -d"
pane_run PASST_2 "./passt -f ${__opts} -t 10004 -u 10004"
pane_run GUEST_2 'cp mbuto.img mbuto_2.img'
pane_wait GUEST_2
pane_run GUEST_1 './qrap 5 kvm -m '${VMEM}' -cpu host -smp '${VCPUS} \
'-kernel' "/boot/vmlinuz-$(uname -r)" \
'-initrd mbuto.img -nographic -serial stdio' \
'-nodefaults ' \
'-append "console=ttyS0 mitigations=off apparmor=0 ' \
'virtio-net.napi_tx=1"' \
"-device virtio-net-pci,netdev=hostnet0,x-txburst=16384"\
"-netdev socket,fd=5,id=hostnet0"
pane_run GUEST_2 './qrap 5 kvm -m '${VMEM}' -cpu host -smp '${VCPUS} \
'-kernel' "/boot/vmlinuz-$(uname -r)" \
'-initrd mbuto_2.img -nographic -serial stdio' \
'-nodefaults ' \
'-append "console=ttyS0 mitigations=off apparmor=0 ' \
'virtio-net.napi_tx=1"' \
"-device virtio-net-pci,netdev=hostnet0,x-txburst=16384"\
"-netdev socket,fd=5,id=hostnet0"
pane_wait GUEST_1
pane_wait GUEST_2
}
# teardown_passt() - Kill qemu and passt
teardown_passt() {
tmux send-keys -t ${PANE_PASST} "C-c"
pane_wait PASST
tmux send-keys -t ${PANE_GUEST} "C-c"
pane_wait GUEST
}
# teardown_passt() - Exit namespace, kill pasta process
teardown_pasta() {
tmux send-keys -t ${PANE_PASST} "C-c"
pane_wait PASST
tmux send-keys -t ${PANE_NS} "C-d"
pane_wait NS
}
# teardown_passt_in_ns() - Exit namespace, kill qemu, passt and pasta
teardown_passt_in_ns() {
tmux send-keys -t ${PANE_GUEST} "C-c"
pane_wait GUEST
tmux send-keys -t ${PANE_GUEST} "C-d"
tmux send-keys -t ${PANE_PASST} "C-c"
pane_wait PASST
tmux send-keys -t ${PANE_PASST} "C-d"
tmux send-keys -t ${PANE_NS} "C-d"
pane_wait GUEST
pane_wait NS
pane_wait PASST
}
# teardown_two_guests() - Exit namespaces, kill qemu processes, passt and pasta
teardown_two_guests() {
tmux send-keys -t ${PANE_GUEST_1} "C-c"
pane_wait GUEST_1
tmux send-keys -t ${PANE_GUEST_1} "C-d"
tmux send-keys -t ${PANE_GUEST_2} "C-c"
pane_wait GUEST_2
tmux send-keys -t ${PANE_GUEST_2} "C-d"
tmux send-keys -t ${PANE_PASST_1} "C-c"
pane_wait PASST_1
tmux send-keys -t ${PANE_PASST_1} "C-d"
tmux send-keys -t ${PANE_PASST_2} "C-c"
pane_wait PASST_2
tmux send-keys -t ${PANE_PASST_2} "C-d"
tmux send-keys -t ${PANE_NS_1} "C-d"
tmux send-keys -t ${PANE_NS_2} "C-d"
pane_wait GUEST_1
pane_wait GUEST_2
ns_1_wait
ns_2_wait
pane_wait PASST_1
pane_wait PASST_2
}
# setup() - Run setup_*() functions
# $*: Suffix list of setup_*() functions to be called
setup() {
for arg do
eval setup_${arg}
done
}
# teardown() - Run teardown_*() functions
# $*: Suffix list of teardown_*() functions to be called
teardown() {
for arg do
eval teardown_${arg}
done
}

610
test/lib/term Executable file
View file

@ -0,0 +1,610 @@
#!/bin/sh
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/lib/term - Set up tmux sessions and panes, handle terminals and logs
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
# Commands of X terminals for "CI" and "demo" runs
DEMO_XTERM="cool-retro-term --verbose --workdir"
CI_XTERM="mate-terminal --hide-menubar --profile=passt_ci --working-directory"
STATUS_FILE=
STATUS_FILE_NTESTS=
STATUS_FILE_INDEX=0
STATUS_COLS=
STATUS_PASS=0
STATUS_FAIL=0
PR_RED='\033[1;31m'
PR_GREEN='\033[1;32m'
PR_YELLOW='\033[1;33m'
PR_BLUE='\033[1;34m'
PR_NC='\033[0m'
PR_DELAY_INIT=100 # ms
# info() - Highlight test log pane, print message to it and to log file
# $@: Message to print
info() {
tmux select-pane -t ${PANE_INFO}
echo "${@}" >> /tmp/.passt_test_log_pipe
echo "${@}" >> "${LOGFILE}"
}
# info_n() - Highlight, print message to pane and to log file without newline
# $@: Message to print
info_n() {
tmux select-pane -t ${PANE_INFO}
printf "${@}" >> /tmp/.passt_test_log_pipe
printf "${@}" >> "${LOGFILE}"
}
# info_nolog() - Highlight test log pane, print message to it
# $@: Message to print
info_nolog() {
tmux select-pane -t ${PANE_INFO}
echo "${@}" >> /tmp/.passt_test_log_pipe
}
# info_nolog() - Print message to log file
# $@: Message to print
log() {
echo "${@}" >> "${LOGFILE}"
}
# info_nolog_n() - Send message to pane without highlighting it, without newline
# $@: Message to print
info_nolog_n() {
tmux send-keys -l -t ${PANE_INFO} "${@}"
}
# info_sep() - Print given separator, horizontally filling test log pane
# $1: Separator character
info_sep() {
tmux send-keys -l -N ${STATUS_COLS} -t ${PANE_INFO} "${1}"
tmux send-keys -t ${PANE_INFO} C-m
}
# sleep_char() - Sleep for typed characted resembling interactive input
# $1: Character typed to pane
sleep_char() {
[ ${FAST} -eq 1 ] && return
if [ "${1}" = " " ]; then
PR_DELAY=$((PR_DELAY + 40))
elif [ -n "$(printf '%s' "${1}" | tr -d [:alnum:])" ]; then
PR_DELAY=$((PR_DELAY + 30))
elif [ ${PR_DELAY} -ge 30 ]; then
PR_DELAY=$((PR_DELAY / 3 * 2))
fi
sleep "$(printf 0.%03i ${PR_DELAY})" || sleep 1
}
# display_delay() - Simple delay, omitted if $FAST is set
display_delay() {
[ ${FAST} -eq 1 ] && return
sleep "${1}" || sleep 1
}
# switch_pane() - Highlight given pane and reset character delay
# $1: Pane number
switch_pane() {
tmux select-pane -t ${1}
PR_DELAY=${PR_DELAY_INIT}
display_delay "0.2"
}
# cmd_write() - Write a command to a pane, letter by letter, and execute it
# $1: Pane number
# $@: Command to issue
cmd_write() {
__pane_no=${1}
shift
switch_pane ${__pane_no}
__str="${@}"
while [ -n "${__str}" ]; do
__rem="${__str#?}"
__first="${__str%"$__rem"}"
if [ "${__first}" = ";" ]; then
tmux send-keys -t ${__pane_no} -l '\;'
else
tmux send-keys -t ${__pane_no} -l "${__first}"
fi
sleep_char "${__first}"
__str="${__rem}"
done
tmux send-keys -t ${__pane_no} "C-m"
}
# text_write() - Write text to info pane, letter by letter
# $1: Pane number
# $@: Command to issue
text_write() {
__str="${@}"
while [ -n "${__str}" ]; do
__rem="${__str#?}"
__first="${__str%"$__rem"}"
if [ "${__first}" = ";" ]; then
tmux send-keys -t ${PANE_INFO} -l '\;'
else
tmux send-keys -t ${PANE_INFO} -l "${__first}"
fi
sleep_char "${__first}"
__str="${__rem}"
done
}
# text_backspace() - Slow backspace motion for demo
# $1: Number of backspace characters
text_backspace() {
for __count in $(seq 0 ${1}); do
tmux send-keys -t ${PANE_INFO} Bspace
sleep 0.1
done
}
# em_write() - Write to log pane in red, for demo
# $@: Text
em_write() {
info_n "${PR_RED}${@}${PR_NC}"
}
# pane_kill() - Kill a single pane given its name
# $1: Pane name
pane_kill() {
__pane_number=$(eval echo \$PANE_${1})
tmux kill-pane -t ${__pane_number}
}
# pane_highlight() - Highlight a single pane given its name
# $1: Pane name
pane_highlight() {
__pane_number=$(eval echo \$PANE_${1})
switch_pane ${__pane_number}
sleep 3
}
# pane_run() - Issue a command in given pane name
# $1: Pane name
# $@: Command to issue
pane_run() {
__pane_name="${1}"
shift
__pane_number=$(eval echo \$PANE_${__pane_name})
eval ${__pane_name}_LAST_CMD=\"\${@}\"
cmd_write ${__pane_number} "${@}"
}
# pane_wait() - Wait for command to be done in given pane name
# $1: Pane name
pane_wait() {
__pane_lc="$(echo "${1}" | tr [A-Z] [a-z])"
while [ "$(tail -n1 ${LOGDIR}/pane_${__pane_lc}.log)" != '$ ' ] && \
[ "$(tail -n1 ${LOGDIR}/pane_${__pane_lc}.log)" != '# ' ] && \
[ "$(tail -n1 ${LOGDIR}/pane_${__pane_lc}.log)" != '# # ' ]; do
sleep 0.1 || sleep 1
done
}
# pane_parse() - Print last line, @EMPTY@ if command had no output
# $1: Pane name
pane_parse() {
__pane_lc="$(echo "${1}" | tr [A-Z] [a-z])"
__buf="$(tail -n2 ${LOGDIR}/pane_${__pane_lc}.log | head -n1 | tr -d -c [:print:])"
[ "# $(eval printf '%s' \"\$${1}_LAST_CMD\")" != "${__buf}" ] && \
[ "$ $(eval printf '%s' \"\$${1}_LAST_CMD\")" != "${__buf}" ] &&
printf '%s' "${__buf}" || printf '@EMPTY@'
}
# status_file_end() - Display and log messages when tests from one file are done
status_file_end() {
[ -z "${STATUS_FILE}" ] && return
info_sep "="
log
tmux select-pane -t ${PANE_INFO} -T ""
STATUS_FILE=
}
# status_file_start() - Display and log messages when tests from one file start
status_file_start() {
switch_pane ${PANE_INFO}
status_file_end
info_nolog "Starting tests in file: ${1}\n"
log "=== ${1}"
tmux select-pane -t ${PANE_INFO} -T "${1}"
STATUS_FILE="${1}"
STATUS_FILE_NTESTS="${2}"
STATUS_FILE_INDEX=0
}
# status_file_start() - Display and log messages when a single test starts
status_test_start() {
switch_pane ${PANE_INFO}
info_nolog "Starting test: ${1}"
log "> ${1}"
STATUS_FILE_INDEX=$((STATUS_FILE_INDEX + 1))
tmux select-pane -t ${PANE_INFO} -T "${STATUS_FILE} [${STATUS_FILE_INDEX}/${STATUS_FILE_NTESTS}] - ${1}"
}
# info_check() - Display and log messages for a single test condition check
info_check() {
switch_pane ${PANE_INFO}
printf "${PR_YELLOW}?${PR_NC} ${@}" >> /tmp/.passt_test_log_pipe
printf "? ${@}" >> "${LOGFILE}"
}
# info_check_passed() - Display and log a new line when a check passes
info_check_passed() {
switch_pane ${PANE_INFO}
printf "\n" >> /tmp/.passt_test_log_pipe
printf "\n" >> ${LOGFILE}
}
# info_check_failed() - Display and log messages when a check fails
info_check_failed() {
switch_pane ${PANE_INFO}
printf " ${PR_RED}!${PR_NC}\n" >> /tmp/.passt_test_log_pipe
printf " < failed.\n" >> "${LOGFILE}"
}
# info_passed() - Display, log, and make status bar blink when a test passes
info_passed() {
switch_pane ${PANE_INFO}
info_nolog "...${PR_GREEN}passed${PR_NC}.\n"
log "...passed."
log
for i in `seq 1 3`; do
tmux set status-right-style 'bg=colour1 fg=colour2 bold'
sleep "0.1"
tmux set status-right-style 'bg=colour1 fg=colour233 bold'
sleep "0.1"
done
}
# info_failed() - Display, log, and make status bar blink when a test passes
info_failed() {
switch_pane ${PANE_INFO}
info_nolog "...${PR_RED}failed${PR_NC}.\n"
log "...failed."
log
for i in `seq 1 3`; do
tmux set status-right-style 'bg=colour1 fg=colour196 bold'
sleep "0.1"
tmux set status-right-style 'bg=colour1 fg=colour233 bold'
sleep "0.1"
done
pause_continue \
"Press any key to pause test session" \
"Resuming in " \
"Paused, press any key to continue" \
5
}
# info_skipped() - Display and log skipped test
info_skipped() {
switch_pane ${PANE_INFO}
info_nolog "...${PR_YELLOW}skipped${PR_NC}.\n"
log "...skipped."
log
}
# info_layout() - Display string for new test layout
info_layout() {
switch_pane ${PANE_INFO}
info_nolog "Test layout: ${PR_BLUE}${@}${PR_NC}.\n"
}
# status_test_ok() - Update counter of passed tests, log and display message
status_test_ok() {
STATUS_PASS=$((STATUS_PASS + 1))
tmux set status-right "PASS: ${STATUS_PASS} | FAIL: ${STATUS_FAIL} | #(TZ="UTC" date -Iseconds)"
info_passed
}
# status_test_fail() - Update counter of failed tests, log and display message
status_test_fail() {
STATUS_FAIL=$((STATUS_FAIL + 1))
tmux set status-right "PASS: ${STATUS_PASS} | FAIL: ${STATUS_FAIL} | #(TZ="UTC" date -Iseconds)"
info_failed
}
# status_test_fail() - Update counter of failed tests, log and display message
status_test_skip() {
info_skipped
}
# table_header() - Print table header to log pane
# $1: Header description
# $@: Column headers
table_header() {
perf_th ${@}
__ifs="${IFS}"
IFS=" "
__desc="${1}"
shift
__max_len=4
__count=0
for __h in ${@}; do
[ ${#__h} -gt ${__max_len} ] && __max_len=${#__h}
__count=$((__count + 1))
done
# > xxxx |<
__outer_len=$((__max_len + 3))
__width_fields=$((__outer_len * __count + 1))
TABLE_HEADER_LEFT=$((STATUS_COLS - __width_fields))
TABLE_CELL_SIZE=$((__max_len + 2))
TABLE_COLS=${__count}
__pad_left=$((TABLE_HEADER_LEFT - ${#__desc} - 2))
__buf="$(printf %-${__pad_left}s%s "" "${__desc}: ")"
for __h in ${@}; do
__pad_left=$(( (TABLE_CELL_SIZE - ${#__h} + 1) / 2))
__pad_right=$(( (TABLE_CELL_SIZE - ${#__h}) / 2))
__buf="${__buf}$(printf "|%-${__pad_left}s%s%-${__pad_right}s" "" ${__h} "")"
done
info_n "${__buf}|"
IFS="${__ifs}"
}
# table_row() - Print main table row to log pane
# $@: Column headers
table_row() {
perf_tr ${@}
__line="${@}"
__buf="$(printf %-${TABLE_HEADER_LEFT}s "")"
for __i in $(seq 1 ${TABLE_COLS}); do
__buf="${__buf}|"
for __j in $(seq 1 ${TABLE_CELL_SIZE}); do
__buf="${__buf}-"
done
done
info_n "\n${__buf}|\n"
__pad_left=$(( (TABLE_HEADER_LEFT - ${#__line} + 1) / 2))
__pad_right=$(( (TABLE_HEADER_LEFT - ${#__line}) / 2))
info_n "$(printf "%-${__pad_left}s%s%-${__pad_right}s|" "" "${__line}" "")"
}
# table_line() - Print simple line to log pane
# $@: Column headers
table_line() {
perf_tr ${@}
__line="${@}"
info_n "\n"
__pad_left=$(( (TABLE_HEADER_LEFT - ${#__line} + 1) / 2))
__pad_right=$(( (TABLE_HEADER_LEFT - ${#__line}) / 2))
info_n "$(printf "%-${__pad_left}s%s%-${__pad_right}s|" "" "${__line}" "")"
}
table_cell() {
__len="${1}"
shift
__content="${@}"
__pad_left=$((TABLE_CELL_SIZE - __len - 1))
info_n "$(printf "%-${__pad_left}s%s |" "" "${__content}")"
}
table_end() {
__buf="$(printf %-${TABLE_HEADER_LEFT}s "")"
for __i in $(seq 1 ${TABLE_COLS}); do
__buf="${__buf}'"
for __j in $(seq 1 ${TABLE_CELL_SIZE}); do
__buf="${__buf}-"
done
done
info_n "\n${__buf}'\n"
}
table_value_throughput() {
[ "${1}" = "-" ] && table_cell 1 "-" && perf_td 0 "" && return 0
__v="$(echo "scale=1; x=( ${1} + 10^8 / 2 ) / 10^9; if ( x < 1 && x > 0 ) print 0; x" | bc -l)"
perf_td 31 "${__v}"
__red="${2}"
__yellow="${3}"
if [ "$(echo "${__v} < ${__red}" | bc -l)" = "1" ]; then
table_cell ${#__v} "${PR_RED}${__v}${PR_NC}"
return 1
elif [ "$(echo "${__v} < ${__yellow}" | bc -l)" = "1" ]; then
table_cell ${#__v} "${PR_YELLOW}${__v}${PR_NC}"
return 1
else
table_cell ${#__v} "${PR_GREEN}${__v}${PR_NC}"
return 0
fi
}
table_value_latency() {
[ "${1}" = "-" ] && table_cell 1 "-" && perf_td 0 "" && return 0
__v="$(echo "scale=6; 1 / ${1} * 10^6" | bc -l)"
__v="${__v%.*}"
perf_td 11 "${__v}"
__red="${2}"
__yellow="${3}"
if [ "$(echo "${__v} > ${__red}" | bc -l)" = "1" ]; then
table_cell ${#__v} "${PR_RED}${__v}${PR_NC}"
return 1
elif [ "$(echo "${__v} > ${__yellow}" | bc -l)" = "1" ]; then
table_cell ${#__v} "${PR_YELLOW}${__v}${PR_NC}"
return 1
else
table_cell ${#__v} "${PR_GREEN}${__v}${PR_NC}"
return 0
fi
}
# pause_continue() - Pause for a while, wait for keystroke, resume on second one
pause_continue() {
tmux select-pane -t ${PANE_INFO}
info_nolog "${1}"
info_nolog_n "${2}"
__pause_tmp="$(mktemp)"
echo >> "${__pause_tmp}"
tmux pipe-pane -O -t ${PANE_INFO} "cat >> ${__pause_tmp}"
__pane_buf=
__wait=0
sleep 1
for __i in $(seq ${4} -1 0); do
if [ "$(tail -n1 ${__pause_tmp} | tr -d -c [:print:])" != "${__pane_buf}" ]; then
__wait=1
break
fi
if [ ${__i} -ne ${4} ]; then
tmux send-keys -t ${PANE_INFO} Bspace
tmux send-keys -t ${PANE_INFO} Bspace
__pane_buf="${__pane_buf} "
fi
info_nolog_n "${__i} "
__pane_buf="${__pane_buf}${__i} "
sleep 1
done
if [ ${__wait} -eq 1 ]; then
tmux send-keys -t ${PANE_INFO} Bspace
tmux send-keys -t ${PANE_INFO} Bspace
info_nolog ""
info_nolog "${3}"
__pane_buf="$(tail -n1 ${__pause_tmp})"
while true; do
[ "$(tail -n1 ${__pause_tmp})" != "${__pane_buf}" ] && break
sleep 1
done
fi
tmux pipe-pane -O -t ${PANE_INFO} ""
rm "${__pause_tmp}"
info_nolog ""
}
# run_term() - Start tmux session, X terminal if requested, running entry point
run_term() {
export SHELL="/bin/sh"
if [ ${CI} -eq 1 ]; then
__xterm_done="$(mktemp)"
${CI_XTERM} "$(pwd)" -e "sh -c \"printf '\e[8;50;240t'; tmux new-session -s passt_test ./ci from_term; echo >${__xterm_done}\""
while ! [ -s "${__xterm_done}" ]; do sleep 1; done
rm "${__xterm_done}"
elif [ ${DEMO} -eq 1 ]; then
while true; do
${DEMO_XTERM} "$(pwd)" -e sh -c 'tmux new-session -s passt_test ./run_demo from_term'
[ $? -ne 0 ] && { tmux kill-session -t passt_test; continue; }
break
done
else
tmux new-session -s passt_test ./run from_term
fi
}
# term() - Set up terminal window and panes for regular tests or CI
term() {
tmux set status-interval 1
tmux rename-window ''
tmux set window-status-format '#W'
tmux set window-status-current-format '#W'
tmux set status-left ''
tmux set window-status-separator ''
tmux set window-status-style 'bg=colour1 fg=colour233 bold'
tmux set status-style 'bg=colour1 fg=colour233 bold'
tmux set status-right-style 'bg=colour1 fg=colour233 bold'
tmux new-window -n "Testing commit: ${COMMIT}"
tmux set window-status-format '#W'
tmux set window-status-current-format '#W'
tmux set status-left ''
tmux set window-status-separator ''
tmux set window-status-current-style 'bg=colour1 fg=colour233 bold'
tmux set status-right '#(TZ="UTC" date -Iseconds)'
tmux set status-right-length 50
tmux set status-right-style 'bg=colour1 fg=colour233 bold'
tmux set history-limit 500000
tmux select-pane -t 0 -T ''
tmux set pane-border-format '#T'
tmux set pane-border-style 'fg=colour2 bg=colour233'
tmux set pane-active-border-style 'fg=colour233 bg=colour4 bold'
tmux set pane-border-status bottom
}
# term_demo() - Set up terminal window and panes for demo
term_demo() {
tmux set status-interval 1
tmux rename-window ''
tmux set window-status-format '#W'
tmux set window-status-current-format '#W'
tmux set status-left ''
tmux set window-status-separator ''
tmux set window-status-style 'bg=colour1 fg=colour15 bold'
tmux set status-right ''
tmux set status-style 'bg=colour1 fg=colour15 bold'
tmux set status-right-style 'bg=colour1 fg=colour15 bold'
tmux new-window -n "Demo at commit: ${COMMIT}"
tmux set window-status-format '#W'
tmux set window-status-current-format '#W'
tmux set status-left ''
tmux set window-status-separator ''
tmux select-pane -t 0 -T ''
tmux set pane-border-format '#T'
tmux set pane-border-style 'fg=colour2 bg=colour233'
tmux set pane-active-border-style 'fg=colour15 bg=colour4 bold'
tmux set pane-border-status bottom
}

378
test/lib/test Executable file
View file

@ -0,0 +1,378 @@
#!/bin/sh
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/lib/test - List tests and run them, evaluating directives from files
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
# Empty, 'passt' or 'pasta', to match against 'onlyfor' directive
MODE=
# test_iperf3() - Ugly helper for iperf3c/iperf3s directives
# $1: Role: client or server
# $2: Pane name, can be lowercase
# $3: Destination name or address for client
# $4: Port number, ${i} is translated to process index
# $5: Number of processes to run in parallel
# $@: Options
test_iperf3() {
__role="${1}"; shift
__pane="$(echo "${1}" | tr [a-z] [A-Z])"; shift
[ "${__role}" = "client" ] && __dest="${1}" && shift || __dest=""
__port="${1}"; shift
__procs="$((${1} - 1))"; shift
[ "${__role}" = "server" ] && __role_opt="-c" || __role_opt="-s1J"
if [ ${__role} = "client" ]; then
UDP_CLIENT=0
for __opt in ${@}; do
[ "${__opt}" = "-u" ] && UDP_CLIENT=1
done
(
sleep 2
pane_run "${__pane}" 'for i in $(seq 0 '${__procs}');' \
'do ( iperf3 -c '"${__dest}"' -p '"${__port}" \
"${@}" ' -T s${i} & echo $! > c${i}.pid & ); done'
sleep 36
pane_run "${__pane}" 'for i in $(seq 0 '${__procs}'); do'\
'kill -INT $(cat c${i}.pid) 2>/dev/null; done'
) &
return
fi
pane_run "${__pane}" 'for i in $(seq 0 '${__procs}'); do' \
':> s${i}.bw; done'
pane_wait "${__pane}"
if [ ${UDP_CLIENT} -eq 0 ]; then
pane_run "${__pane}" 'for i in $(seq 0 '${__procs}');' \
'do ( ( iperf3 -s1J -p '"${__port} ${@}" \
'& echo $! > s${i}.pid ) 2>/dev/null' \
'| jq -rM ".end.sum_received.bits_per_second"' \
'> s${i}.bw & );' \
'done'
else
pane_run "${__pane}" 'for i in $(seq 0 '${__procs}');' \
'do ( ( iperf3 -s1J -i 30 -p '"${__port} ${@}" \
'& echo $! > s${i}.pid ) 2>/dev/null' \
'| jq -rM ".intervals[0].sum.bits_per_second"' \
'> s${i}.bw & );' \
'done'
fi
pane_wait "${__pane}"
sleep 38
pane_run "${__pane}" 'for i in $(seq 0 '${__procs}'); do' \
'kill -INT $(cat s${i}.pid) 2>/dev/null; done'
sleep 1
pane_wait "${__pane}"
pane_run "${__pane}" '(cat s*.bw |' \
'sed '"'"'s/\(.*\)/\1\+/g'"'"' |' \
'tr -d "\n"; echo 0) | bc -l'
pane_wait "${__pane}"
pane_parse "${__pane}"
pane_run "${__pane}" 'for i in $(seq 0 '${__procs}'); do' \
'rm -f s${i}.bw; done'
pane_wait "${__pane}"
}
# test_one() - Run a single test file evaluating directives
# $1: Name of test file, relative to test/ directory
test_one() {
__dirclean=
__test_file="test/${1}"
__type="$(file -b --mime-type ${__test_file})"
if [ "${__type}" = "text/x-shellscript" ]; then
status_file_start "${1}" 1
"${__test_file}" && status_test_ok || status_test_fail
return
fi
__ntests="$(grep -c "^test$(printf '\t')" "${__test_file}")"
[ ${DEMO} -eq 0 ] && status_file_start "${1}" "${__ntests}"
[ ${CI} -eq 1 ] && video_link "${1}"
__subs=
__nok=-1
__perf_nok=0
__skip=0
while IFS= read -r __line; do
# Strip comments
__line="${__line%%#*}"
# tab-split command and arguments, apply variable substitutions
__cmd="${__line%%$(printf '\t')*}"
__arg="${__line#*$(printf '\t')*}"
__arg="$(subs_apply "${__subs}" "${__arg}")"
[ ${__nok} -eq 1 ] && [ "${__cmd}" != "test" ] && continue
case ${__cmd} in
"tempdir")
__tmpdir="$(mktemp -d)"
__subs="$(list_add_pair "${__subs}" "__${__arg}__" "${__tmpdir}")"
__dirclean="$(list_add "${__dirclean}" "${__tmpdir}")"
;;
"temp")
__tmpfile="$(mktemp)"
__subs="$(list_add_pair "${__subs}" "__${__arg}__" "${__tmpfile}")"
__dirclean="$(list_add "${__dirclean}" "${__tmpfile}")"
;;
"test")
[ ${__perf_nok} -eq 0 ] || __nok=1
[ ${__nok} -eq 1 ] && status_test_fail
[ ${__nok} -eq 0 ] && status_test_ok
status_test_start "${__arg}"
__nok=0
__perf_nok=0
;;
"host")
pane_run HOST "${__arg}"
pane_wait HOST
;;
"hostb")
pane_run HOST "${__arg}"
;;
"hostw")
pane_wait HOST
;;
"htools")
pane_run HOST 'which '"${__arg}"' >/dev/null || echo skip'
pane_wait HOST
[ "$(pane_parse HOST)" = "skip" ] && { __skip=1; break; }
;;
"passt")
pane_run PASST "${__arg}"
pane_wait PASST
;;
"passtb")
pane_run PASST "${__arg}"
;;
"passtw")
pane_wait PASST
;;
"pout")
__varname="${__arg%% *}"
pane_run PASST "${__arg#* }"
pane_wait PASST
__subs="$(list_add_pair "${__subs}" "__${__varname}__" "$(pane_parse PASST)")"
;;
"guest")
pane_run GUEST "${__arg}"
pane_wait GUEST
;;
"guestb")
pane_run GUEST "${__arg}"
;;
"guestw")
pane_wait GUEST
;;
"guest1")
pane_run GUEST_1 "${__arg}"
pane_wait GUEST_1
;;
"guest1b")
pane_run GUEST_1 "${__arg}"
;;
"guest1w")
pane_wait GUEST_1
;;
"gtools")
pane_run GUEST 'which '"${__arg}"' >/dev/null || echo skip'
pane_wait GUEST
[ "$(pane_parse GUEST)" = "skip" ] && { __skip=1; break; }
;;
"g1tools")
pane_run GUEST_1 'which '"${__arg}"' >/dev/null || echo skip'
pane_wait GUEST_1
[ "$(pane_parse GUEST_1)" = "skip" ] && { __skip=1; break; }
;;
"g2tools")
pane_run GUEST_2 'which '"${__arg}"' >/dev/null || echo skip'
pane_wait GUEST_2
[ "$(pane_parse GUEST_2)" = "skip" ] && { __skip=1; break; }
;;
"guest2")
pane_run GUEST_2 "${__arg}"
pane_wait GUEST_2
;;
"guest2b")
pane_run GUEST_2 "${__arg}"
;;
"guest2w")
pane_wait GUEST_2
;;
"ns")
pane_run NS "${__arg}"
pane_wait NS
;;
"nsb")
pane_run NS "${__arg}"
;;
"nsw")
pane_wait NS
;;
"nstools")
pane_run NS 'which '"${__arg}"' >/dev/null || echo skip'
pane_wait NS
[ "$(pane_parse NS)" = "skip" ] && { __skip=1; break; }
;;
"gout")
__varname="${__arg%% *}"
pane_run GUEST "${__arg#* }"
pane_wait GUEST
__subs="$(list_add_pair "${__subs}" "__${__varname}__" "$(pane_parse GUEST)")"
;;
"g1out")
__varname="${__arg%% *}"
pane_run GUEST_1 "${__arg#* }"
pane_wait GUEST_1
__subs="$(list_add_pair "${__subs}" "__${__varname}__" "$(pane_parse GUEST_1)")"
;;
"g2out")
__varname="${__arg%% *}"
pane_run GUEST_2 "${__arg#* }"
pane_wait GUEST_2
__subs="$(list_add_pair "${__subs}" "__${__varname}__" "$(pane_parse GUEST_2)")"
;;
"hout")
__varname="${__arg%% *}"
pane_run HOST "${__arg#* }"
pane_wait HOST
__subs="$(list_add_pair "${__subs}" "__${__varname}__" "$(pane_parse HOST)")"
;;
"nsout")
__varname="${__arg%% *}"
pane_run NS "${__arg#* }"
pane_wait NS
__subs="$(list_add_pair "${__subs}" "__${__varname}__" "$(pane_parse NS)")"
;;
"check")
info_check "${__arg}"
eval "${__arg} || __nok=1"
if [ ${__nok} -eq 1 ]; then
info_check_failed
else
info_check_passed
fi
;;
"sleep")
sleep "${__arg}"
;;
"info")
info "${__arg}"
;;
"report")
perf_report ${__arg}
;;
"th")
table_header ${__arg}
;;
"tr")
table_row "${__arg}"
;;
"tl")
table_line "${__arg}"
;;
"te")
table_end
;;
"bw")
table_value_throughput ${__arg} || __perf_nok=1
;;
"lat")
table_value_latency ${__arg} || __perf_nok=1
;;
"iperf3c")
set -x
test_iperf3 client ${__arg}
set +x
;;
"iperf3s")
set -x
__subs="$(list_add_pair "${__subs}" "__${__arg%% *}__" "$(test_iperf3 server ${__arg#* })" )"
set +x
;;
"set")
__subs="$(list_add_pair "${__subs}" "__${__arg%% *}__" "${__arg#* }")"
;;
# Demo commands
"say")
text_write "${__arg}"
;;
"em")
em_write "${__arg}"
;;
"nl")
info_nolog ""
;;
"hl")
pane_highlight "${__arg}"
;;
"bsp")
text_backspace "${__arg}"
;;
"killp")
pane_kill "${__arg}"
;;
esac
done < "${__test_file}"
for __d in ${__dirclean}; do
rm -rf ${__d}
done
[ ${DEMO} -eq 1 ] && return
[ ${__skip} -eq 1 ] && status_test_skip && return
[ ${__perf_nok} -eq 0 ] || __nok=1
[ ${__nok} -eq 0 ] && status_test_ok || status_test_fail
}
# test() - Build list of tests to run, in order, then issue test_one()
# $1: Name of directory containing set of test files, relative to test/
test() {
__list=
__rem=1
cd test
while [ ${__rem} -eq 1 ]; do
__rem=0
for __f in "${1}"/*; do
__type="$(file -b --mime-type ${__f})"
if [ "${__type}" = "text/x-shellscript" ]; then
__list="$(list_add "${__list}" "${__f}")"
continue
fi
if [ -n "$(file_def "${__f}" onlyfor)" ] && \
! list_has "$(file_def "${__f}" onlyfor)" "${MODE}"; then
continue
fi
if list_has_all "${__list}" "$(file_def "${__f}" req)"; then
__list="$(list_add "${__list}" "${__f}")"
else
__rem=1
fi
done
done
cd ..
for __f in ${__list}; do
test_one "${__f}"
done
}

142
test/lib/util Executable file
View file

@ -0,0 +1,142 @@
#!/bin/sh
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/lib/util - Convenience functions
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
# list_has() - Check whether a tab-separated list contains a given token
# $1: List
# $2: Token
# Return: 0 if token was found or is empty, 1 otherwise
list_has() {
[ -z "${2}" ] && return 0
__ifs="${IFS}"
IFS=' '
for __t in ${1}; do
[ "${__t}" = "${2}" ] && IFS="${__ifs}" && return 0
done
IFS="${__ifs}"
return 1
}
# list_add() - Add token to tab-separated list, unless it's already present
# $1: List
# $2: Token
list_add() {
list_has "${1}" "${2}" && return
[ -n "${1}" ] && printf '%s\t%s\n' "${1}" "${2}" || printf '%s\n' "${2}"
}
# list_remove_pair() - Drop pair with given key if present
# $1: List
# $2: Key
list_remove_pair()
{
__ifs="${IFS}"
IFS=' '
__skip_next=0
for __t in ${1}; do
[ ${__skip_next} -eq 1 ] && __skip_next=0 && continue
[ "${__t}" = "${2}" ] && __skip_next=1 && continue
printf '%s\t' "${__t}"
done
printf "\n"
IFS="${__ifs}"
}
# list_add_pair() - Add token pair to list, replace if the first one is present
# $1: List
# $2: First token
# $3: Second token
list_add_pair() {
[ -z "${3}" ] && return
if [ -n "${1}" ]; then
__new_list="$(list_remove_pair "${1}" "${2}")"
printf '%s\t%s\t%s' "${__new_list}" "${2}" "${3}"
else
printf '%s\t%s' "${2}" "${3}"
fi
printf "\n"
}
# list_has_all() - Check whether a list contains all given IFS-separated tokens
# $1: List
# $2: List of tokens
# Return: 0 if list of tokens was found or is empty, 1 otherwise
list_has_all() {
[ -z "${2}" ] && return 0
for __i in ${2}; do
list_has "${1}" "${__i}" || return 1
done
return 0
}
# file_def() - List of tokens tab-separated line from file, starting with key
# $1: Filename
# $2: Token
file_def() {
sed -n 's/^'"${2}"'\t\(.*\)/\1/p' "${1}" | tr ' ' '\t'
}
# subs_apply() - Apply substitutions using a list of token pairs
# $1: List of substitutions
# $2: String where substitutions have to be applied
subs_apply() {
echo "in subs_apply" >> /tmp/subs_apply
__ifs="${IFS}"
IFS=' '
__newarg="${2}"
__s=
for __t in ${1}; do
[ -z "${__s}" ] && __s="${__t}" && continue
echo "t: --${__t}--, --${__s}--" >> /tmp/subs_apply
__et="$(printf '%s\n' "$__t" | sed -e 's/[\/&]/\\&/g')"
__es="$(printf '%s\n' "$__s" | sed -e 's/[]\/$*.^[]/\\&/g')"
__newarg="$(printf '%s' "${__newarg}" | sed "s/${__es}/${__et}/g")"
__s=
done
printf '%s' "${__newarg}"
IFS="${__ifs}"
}
# set_mode() - Set 'passt' or 'pasta' mode for terminal control, renaming panes
# $1: Mode to be set
set_mode() {
MODE="${1}"
if [ "${1}" = "pasta" ]; then
tmux select-pane -t ${PANE_GUEST} -T "namespace"
tmux select-pane -t ${PANE_PASST} -T "pasta"
else
tmux select-pane -t ${PANE_GUEST} -T "guest"
tmux select-pane -t ${PANE_PASST} -T "passt"
fi
}
# get_info_cols() - Get number of columns for info pane
get_info_cols() {
__log_pane_cols=
__j=0
for __i in $(tmux list-panes -t passt_test:1.0 -F "#{pane_width}"); do
[ ${__j} -eq ${PANE_INFO} ] && STATUS_COLS=${__i} && break
__j=$((__j + 1))
done
}

119
test/lib/video Executable file
View file

@ -0,0 +1,119 @@
#!/bin/sh
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/lib/video - Video grabbing, JavaScript fragments with links
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
FFMPEG_PID_FILE="$(mktemp)"
VIDEO_START_SECONDS=
VIDEO_NAME=
VIDEO_LINKS_TEMPLATE="document.write('"'
Skip to:
'
VIDEO_LINKS_TEMPLATE_JS="
');
var video___VIDEO_NAME__links = [
"
VIDEO_LINKS_TEMPLATE_POST='];
for (var i = 0; i < video___VIDEO_NAME__links.length; i++) {
var obj = document.getElementById(video___VIDEO_NAME__links[i][0]);
obj.addEventListener("click", function(event) {
var __VIDEO_NAME___video = document.getElementById("__VIDEO_NAME___video");
var top = __VIDEO_NAME___video.offsetTop - 5;
event.preventDefault();
__VIDEO_NAME___video.play();
__VIDEO_NAME___video.pause();
for (var i = 0; i < video___VIDEO_NAME__links.length; i++) {
if (this.id == video___VIDEO_NAME__links[i][0]) {
__VIDEO_NAME___video.currentTime = video___VIDEO_NAME__links[i][1];
}
}
window.scrollTo({ top: top, behavior: "smooth" })
__VIDEO_NAME___video.play();
}, false);
}
'
VIDEO_LINKS_BUF=
VIDEO_LINKS_COUNT=0
# video_append_links() - Append generic string to JavaScript links file
video_append_links()
{
printf "${@}" >> "${BASEPATH}/${VIDEO_NAME}.js"
}
# video_append_links() - Append generic string to buffer for links
video_append_links_js()
{
VIDEO_LINKS_BUF="${VIDEO_LINKS_BUF}${@}"
}
# video_grab() - Fetch window geometry, start grabbing video
video_grab() {
VIDEO_NAME="${1}"
rm -f "${BASEPATH}/${VIDEO_NAME}.mp4" "${BASEPATH}/${VIDEO_NAME}.webm" "${BASEPATH}/${VIDEO_NAME}.js"
echo "${VIDEO_LINKS_TEMPLATE}" > "${BASEPATH}/${VIDEO_NAME}.js"
__x=$(xwininfo -id $(xdotool getactivewindow) | sed -n 's/[ ]*Absolute upper-left X:[ ]*\([0-9]*\)$/\1/p')
__y=$(xwininfo -id $(xdotool getactivewindow) | sed -n 's/[ ]*Absolute upper-left Y:[ ]*\([0-9]*\)$/\1/p')
__width=$(xwininfo -id $(xdotool getactivewindow) | sed -n 's/[ ]*Width:[ ]*\([0-9]*\)$/\1/p')
__height=$(xwininfo -id $(xdotool getactivewindow) | sed -n 's/[ ]*Height:[ ]*\([0-9]*\)$/\1/p')
[ $((__width % 2)) ] && __width=$((__width - 1))
[ $((__height % 2)) ] && __height=$((__height - 1))
sleep 3
VIDEO_START_SECONDS=$(sed -n 's/\([0-9]*\).[0-9]* [0-9]*.[0-9]*/\1/p' /proc/uptime)
ffmpeg -f x11grab -framerate 15 -video_size "${__width}x${__height}" -i "+${__x},${__y}" -vcodec libx264 -preset ultrafast -qp 0 -pix_fmt yuv444p -draw_mouse 0 "${BASEPATH}/${VIDEO_NAME}.mp4" & echo $! > "${FFMPEG_PID_FILE}"
}
# video_time_now() - Print current video timestamp, in seconds
video_time_now() {
__now=$(sed -n 's/\([0-9]*\).[0-9]* [0-9]*.[0-9]*/\1/p' /proc/uptime)
echo $((__now - VIDEO_START_SECONDS))
}
# video_stop() - Stop grabbing, finalise JavaScript templates, convert to webm
video_stop() {
sed -i 's/^.*$/&\\/g' "${BASEPATH}/${VIDEO_NAME}.js"
echo "${VIDEO_LINKS_TEMPLATE_JS}" | sed "s/__VIDEO_NAME__/${VIDEO_NAME}/g" >> "${BASEPATH}/${VIDEO_NAME}.js"
echo "${VIDEO_LINKS_BUF}" >> "${BASEPATH}/${VIDEO_NAME}.js"
echo "${VIDEO_LINKS_TEMPLATE_POST}" | sed "s/__VIDEO_NAME__/${VIDEO_NAME}/g" >> "${BASEPATH}/${VIDEO_NAME}.js"
kill -INT $(cat "${FFMPEG_PID_FILE}")
while ps -p $(cat "${FFMPEG_PID_FILE}") >/dev/null; do sleep 1; done
rm "${FFMPEG_PID_FILE}"
[ ${1} -ne 0 ] && return
ffmpeg -an -fflags +genpts -i "${BASEPATH}/${VIDEO_NAME}.mp4" -c:v libvpx-vp9 -row-mt 1 -minrate 10k -maxrate 200k -b:v 200k "${BASEPATH}/${VIDEO_NAME}.webm"
}
# video_link() - Append single link to given video chapter
video_link() {
[ ${VIDEO_LINKS_COUNT} -eq 0 ] && __sep="" || __sep=" |"
__id="video_link_${VIDEO_LINKS_COUNT}"
video_append_links "${__sep} <a id=\"${__id}\">${1}</a>"
video_append_links_js "[ '${__id}', $(($(video_time_now) - 1)) ],"
VIDEO_LINKS_COUNT=$((VIDEO_LINKS_COUNT + 1))
}

34
test/ndp/passt Normal file
View file

@ -0,0 +1,34 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/ndp/passt - Check NDP functionality in passt mode
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
onlyfor passt passt_in_ns
gtools ip jq sipcalc grep
htools ip jq sipcalc grep cut
test Interface name
gout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
guest ip link set dev __IFNAME__ up && sleep 2
hout HOST_IFNAME ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").dev'
check [ -n "__IFNAME__" ]
test SLAAC: prefix
gout ADDR6 ip -j -6 ad sh|jq -rM '.[] | select(.ifname == "__IFNAME__").addr_info[] | select(.scope == "global" and .prefixlen == 64).local'
gout PREFIX6 sipcalc __ADDR6__/64 | grep prefix | cut -d' ' -f4
hout HOST_ADDR6 ip -j -6 ad sh|jq -rM '.[] | select(.ifname == "__HOST_IFNAME__").addr_info[] | select(.scope == "global").local'
hout HOST_PREFIX6 sipcalc __HOST_ADDR6__/64 | grep prefix | cut -d' ' -f4
check [ "__PREFIX6__" = "__HOST_PREFIX6__" ]
test SLAAC: route
gout GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
hout HOST_GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
check [ __GW6__ = __HOST_GW6__ ]

35
test/ndp/pasta Normal file
View file

@ -0,0 +1,35 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/ndp/pasta - Check DHCP and DHCPv6 functionality in pasta mode
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
onlyfor pasta
nstools ip jq sipcalc grep cut
htools ip jq sipcalc grep cut
test Interface name
nsout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
ns ip link set dev __IFNAME__ up
sleep 2
hout HOST_IFNAME ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").dev'
check [ -n "__IFNAME__" ]
test SLAAC: prefix
nsout ADDR6 ip -j -6 ad sh|jq -rM '.[] | select(.ifname == "__IFNAME__").addr_info[] | select(.scope == "global" and .prefixlen == 64).local'
nsout PREFIX6 sipcalc __ADDR6__/64 | grep prefix | cut -d' ' -f4
hout HOST_ADDR6 ip -j -6 ad sh|jq -rM '.[] | select(.ifname == "__HOST_IFNAME__").addr_info[] | select(.scope == "global").local'
hout HOST_PREFIX6 sipcalc __HOST_ADDR6__/64 | grep prefix | cut -d' ' -f4
check [ "__PREFIX6__" = "__HOST_PREFIX6__" ]
test SLAAC: route
nsout GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
hout HOST_GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
check [ __GW6__ = __HOST_GW6__ ]

228
test/perf/passt_tcp Normal file
View file

@ -0,0 +1,228 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/perf/passt_tcp - Check TCP performance in passt mode
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
onlyfor passt_in_ns
gtools sysctl ip jq nproc seq sleep bc iperf3 tcp_rr tcp_crr # From neper
nstools sysctl ip jq nproc seq sleep bc iperf3 tcp_rr tcp_crr
htools cpupower sed seq
test passt: throughput and latency
guest /sbin/sysctl -w net.core.rmem_max=536870912
guest /sbin/sysctl -w net.core.wmem_max=536870912
guest /sbin/sysctl -w net.core.rmem_default=33554432
guest /sbin/sysctl -w net.core.wmem_default=33554432
guest /sbin/sysctl -w net.ipv4.tcp_rmem="4096 131072 268435456"
guest /sbin/sysctl -w net.ipv4.tcp_wmem="4096 131072 268435456"
guest /sbin/sysctl -w net.ipv4.tcp_timestamps=0
ns sysctl -w net.ipv4.tcp_rmem="4096 524288 134217728"
ns sysctl -w net.ipv4.tcp_wmem="4096 524288 134217728"
ns sysctl -w net.ipv4.tcp_timestamps=0
gout GW ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
gout GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
gout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
hout FREQ cpupower frequency-info -lm | sed -n 's/.*- \(.*\) GHz$/\1/p'
set THREADS 1
set STREAMS 8
set OPTS -Z -P __STREAMS__ -l 1M -i1 -t30 -O5 --pacing-timer 1000000
info Throughput in Gbps, latency in µs, one thread at __FREQ__ GHz, __STREAMS__ streams
report passt tcp __THREADS__ __FREQ__
th MTU 256B 576B 1280B 1500B 9000B 65520B
tr TCP throughput over IPv6: guest to host
bw -
bw -
guest ip link set dev __IFNAME__ mtu 1280
iperf3c guest __GW6__%__IFNAME__ 100${i}2 __THREADS__ __OPTS__ -w 4M
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 1.2 1.5
guest ip link set dev __IFNAME__ mtu 1500
iperf3c guest __GW6__%__IFNAME__ 100${i}2 __THREADS__ __OPTS__ -w 4M
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 1.6 1.8
guest ip link set dev __IFNAME__ mtu 9000
iperf3c guest __GW6__%__IFNAME__ 100${i}2 __THREADS__ __OPTS__ -w 32M
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 4.0 5.0
guest ip link set dev __IFNAME__ mtu 65520
iperf3c guest __GW6__%__IFNAME__ 100${i}2 __THREADS__ __OPTS__ -w 128M
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 7.0 8.0
tl TCP RR latency over IPv6: guest to host
lat -
lat -
lat -
lat -
lat -
nsb tcp_rr --nolog -6
gout LAT tcp_rr --nolog -6 -c -H __GW6__%__IFNAME__ | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 200 150
tl TCP CRR latency over IPv6: guest to host
lat -
lat -
lat -
lat -
lat -
nsb tcp_crr --nolog -6
gout LAT tcp_crr --nolog -6 -c -H __GW6__%__IFNAME__ | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 500 400
tr TCP throughput over IPv4: guest to host
guest ip link set dev __IFNAME__ mtu 256
iperf3c guest __GW__ 100${i}2 __THREADS__ __OPTS__ -w 1M
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 0.2 0.3
guest ip link set dev __IFNAME__ mtu 576
iperf3c guest __GW__ 100${i}2 __THREADS__ __OPTS__ -w 1M
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 0.5 0.8
guest ip link set dev __IFNAME__ mtu 1280
iperf3c guest __GW__ 100${i}2 __THREADS__ __OPTS__ -w 4M
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 1.2 1.5
guest ip link set dev __IFNAME__ mtu 1500
iperf3c guest __GW__ 100${i}2 __THREADS__ __OPTS__ -w 4M
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 1.6 1.8
guest ip link set dev __IFNAME__ mtu 9000
iperf3c guest __GW__ 100${i}2 __THREADS__ __OPTS__ -w 32M
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 4.0 5.0
guest ip link set dev __IFNAME__ mtu 65520
iperf3c guest __GW__ 100${i}2 __THREADS__ __OPTS__ -w 128M
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 7.0 8.0
tl TCP RR latency over IPv4: guest to host
lat -
lat -
lat -
lat -
lat -
nsb tcp_rr --nolog -4
gout LAT tcp_rr --nolog -4 -c -H __GW__ | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 200 150
tl TCP CRR latency over IPv4: guest to host
lat -
lat -
lat -
lat -
lat -
nsb tcp_crr --nolog -4
gout LAT tcp_crr --nolog -4 -c -H __GW__ | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 500 400
tr TCP throughput over IPv6: host to guest
bw -
bw -
ns ip link set dev lo mtu 1280
iperf3c ns ::1 100${i}1 __THREADS__ __OPTS__ -w 4M
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 1.0 1.2
ns ip link set dev lo mtu 1500
iperf3c ns ::1 100${i}1 __THREADS__ __OPTS__ -w 4M
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 2.0 3.0
ns ip link set dev lo mtu 9000
iperf3c ns ::1 100${i}1 __THREADS__ __OPTS__ -w 32M
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 5.0 6.0
ns ip link set dev lo mtu 65520
iperf3c ns ::1 100${i}1 __THREADS__ __OPTS__ -w 64M
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 6.0 6.8
ns ip link set dev lo mtu 65535
tl TCP RR latency over IPv6: host to guest
lat -
lat -
lat -
lat -
lat -
guestb tcp_rr --nolog -P 10001 -C 10011 -6
nsout LAT tcp_rr --nolog -P 10001 -C 10011 -6 -c -H ::1 | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 200 150
tl TCP CRR latency over IPv6: host to guest
lat -
lat -
lat -
lat -
lat -
guestb tcp_crr --nolog -P 10001 -C 10011 -6
nsout LAT tcp_crr --nolog -P 10001 -C 10011 -6 -c -H ::1 | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 500 350
tr TCP throughput over IPv4: host to guest
ns ip link set dev lo mtu 256
iperf3c ns 127.0.0.1 100${i}1 __THREADS__ __OPTS__ -w 1M
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 0.3 0.5
ns ip link set dev lo mtu 576
iperf3c ns 127.0.0.1 100${i}1 __THREADS__ __OPTS__ -w 1M
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 0.5 1.0
ns ip link set dev lo mtu 1280
ns ip addr add ::1 dev lo
iperf3c ns 127.0.0.1 100${i}1 __THREADS__ __OPTS__ -w 4M
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 2.0 3.0
ns ip link set dev lo mtu 1500
iperf3c ns 127.0.0.1 100${i}1 __THREADS__ __OPTS__ -w 4M
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 2.0 3.0
ns ip link set dev lo mtu 9000
iperf3c ns 127.0.0.1 100${i}1 __THREADS__ __OPTS__ -w 32M
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 5.0 6.0
ns ip link set dev lo mtu 65520
iperf3c ns 127.0.0.1 100${i}1 __THREADS__ __OPTS__ -w 64M
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 6.0 6.8
ns ip link set dev lo mtu 65535
tl TCP RR latency over IPv4: host to guest
lat -
lat -
lat -
lat -
lat -
guestb tcp_rr --nolog -P 10001 -C 10011 -4
nsout LAT tcp_rr --nolog -P 10001 -C 10011 -4 -c -H 127.0.0.1 | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 200 150
tl TCP CRR latency over IPv6: host to guest
lat -
lat -
lat -
lat -
lat -
guestb tcp_crr --nolog -P 10001 -C 10011 -4
nsout LAT tcp_crr --nolog -P 10001 -C 10011 -4 -c -H 127.0.0.1 | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 500 300
te

180
test/perf/passt_udp Normal file
View file

@ -0,0 +1,180 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/perf/passt_udp - Check UDP performance in passt mode
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
onlyfor passt_in_ns
gtools sysctl ip jq nproc sleep iperf3 udp_rr # From neper
nstools ip jq sleep iperf3 udp_rr
htools cpupower sed
test passt: throughput and latency
guest /sbin/sysctl -w net.core.rmem_max=16777216
guest /sbin/sysctl -w net.core.wmem_max=16777216
guest /sbin/sysctl -w net.core.rmem_default=16777216
guest /sbin/sysctl -w net.core.wmem_default=16777216
gout GW ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
gout GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
gout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
hout FREQ cpupower frequency-info -lm | sed -n 's/.*- \(.*\) GHz$/\1/p'
set THREADS 2
set STREAMS 1
set OPTS -u -i1 -t30 -P __STREAMS__ --pacing-timer 10000
info Throughput in Gbps, latency in µs, __THREADS__ threads at __FREQ__ GHz, one stream each
report passt udp __THREADS__ __FREQ__
th MTU 256B 576B 1280B 1500B 9000B 65520B
tr UDP throughput over IPv6: guest to host
bw -
bw -
guest ip link set dev __IFNAME__ mtu 1280
iperf3c guest __GW6__%__IFNAME__ 100${i}2 __THREADS__ __OPTS__ -b 2G
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 0.8 1.2
guest ip link set dev __IFNAME__ mtu 1500
iperf3c guest __GW6__%__IFNAME__ 100${i}2 __THREADS__ __OPTS__ -b 2G
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 1.0 1.5
guest ip link set dev __IFNAME__ mtu 9000
iperf3c guest __GW6__%__IFNAME__ 100${i}2 __THREADS__ __OPTS__ -b 4G
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 4.0 5.0
guest ip link set dev __IFNAME__ mtu 65520
iperf3c guest __GW6__%__IFNAME__ 100${i}2 __THREADS__ __OPTS__ -b 5G
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 4.0 5.0
tl UDP RR latency over IPv6: guest to host
lat -
lat -
lat -
lat -
lat -
nsb udp_rr --nolog -6
gout LAT udp_rr --nolog -6 -c -H __GW6__%__IFNAME__ | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 200 150
tr UDP throughput over IPv4: guest to host
guest ip link set dev __IFNAME__ mtu 256
iperf3c guest __GW__ 100${i}2 __THREADS__ __OPTS__ -b 300M
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 0.1 0.2
guest ip link set dev __IFNAME__ mtu 576
iperf3c guest __GW__ 100${i}2 __THREADS__ __OPTS__ -b 500M
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 0.4 0.6
guest ip link set dev __IFNAME__ mtu 1280
iperf3c guest __GW__ 100${i}2 __THREADS__ __OPTS__ -b 2G
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 0.8 1.2
guest ip link set dev __IFNAME__ mtu 1500
iperf3c guest __GW__ 100${i}2 __THREADS__ __OPTS__ -b 2G
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 1.0 1.5
guest ip link set dev __IFNAME__ mtu 9000
iperf3c guest __GW__ 100${i}2 __THREADS__ __OPTS__ -b 4G
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 4.0 5.0
guest ip link set dev __IFNAME__ mtu 65520
iperf3c guest __GW__ 100${i}2 __THREADS__ __OPTS__ -b 5G
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 4.0 5.0
tl UDP RR latency over IPv4: guest to host
lat -
lat -
lat -
lat -
lat -
nsb udp_rr --nolog -4
gout LAT udp_rr --nolog -4 -c -H __GW__ | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 200 150
tr UDP throughput over IPv6: host to guest
bw -
bw -
ns ip link set dev lo mtu 1280
iperf3c ns ::1 100${i}1 __THREADS__ __OPTS__ -b 2G
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 0.8 1.2
ns ip link set dev lo mtu 1500
iperf3c ns ::1 100${i}1 __THREADS__ __OPTS__ -b 2G
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 1.0 1.5
ns ip link set dev lo mtu 9000
iperf3c ns ::1 100${i}1 __THREADS__ __OPTS__ -b 4G
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 4.0 5.0
ns ip link set dev lo mtu 65520
iperf3c ns ::1 100${i}1 __THREADS__ __OPTS__ -b 6G
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 5.0 5.5
tl UDP RR latency over IPv6: host to guest
lat -
lat -
lat -
lat -
lat -
guestb udp_rr --nolog -P 10001 -C 10011 -6
nsout LAT udp_rr --nolog -P 10001 -C 10011 -6 -c -H ::1 | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 200 150
ns ip link set dev lo mtu 65535
tr UDP throughput over IPv4: host to guest
ns ip link set dev lo mtu 256
iperf3c ns 127.0.0.1 100${i}1 __THREADS__ __OPTS__ -b 300M
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 0.1 0.2
ns ip link set dev lo mtu 576
iperf3c ns 127.0.0.1 100${i}1 __THREADS__ __OPTS__ -b 500M
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 0.4 0.6
ns ip link set dev lo mtu 1280
ns ip addr add ::1 dev lo
iperf3c ns 127.0.0.1 100${i}1 __THREADS__ __OPTS__ -b 2G
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 0.8 1.2
ns ip link set dev lo mtu 1500
iperf3c ns 127.0.0.1 100${i}1 __THREADS__ __OPTS__ -b 2G
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 1.0 1.5
ns ip link set dev lo mtu 9000
iperf3c ns 127.0.0.1 100${i}1 __THREADS__ __OPTS__ -b 4G
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 4.0 5.0
ns ip link set dev lo mtu 65520
iperf3c ns 127.0.0.1 100${i}1 __THREADS__ __OPTS__ -b 6G
iperf3s BW guest 100${i}1 __THREADS__
bw __BW__ 5.0 5.5
tl UDP RR latency over IPv4: host to guest
lat -
lat -
lat -
lat -
lat -
guestb udp_rr --nolog -P 10001 -C 10011 -4
nsout LAT udp_rr --nolog -P 10001 -C 10011 -4 -c -H 127.0.0.1 | sed -n 's/^throughput=\(.*\)/\1/p'
lat __LAT__ 200 150
ns ip link set dev lo mtu 65535
te

256
test/perf/pasta_tcp Normal file
View file

@ -0,0 +1,256 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/perf/pasta_tcp - Check TCP performance in pasta mode
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
onlyfor passt_in_ns
htools cpupower ip seq bc sleep iperf3 tcp_rr tcp_crr jq sed
nstools sysctl nproc ip seq bc sleep iperf3 tcp_rr tcp_crr jq sed
test pasta: throughput and latency (local connections)
ns sysctl -w net.ipv4.tcp_rmem="131072 524288 134217728"
ns sysctl -w net.ipv4.tcp_wmem="131072 524288 134217728"
ns sysctl -w net.ipv4.tcp_timestamps=0
set THREADS 2
set STREAMS 2
set OPTS -Z -w 4M -l 1M -P __STREAMS__ -i1 -t30 -O5 --pacing-timer 10000
hout FREQ cpupower frequency-info -lm | sed -n 's/.*- \(.*\) GHz$/\1/p'
info Throughput in Gbps, latency in µs, __THREADS__ threads at __FREQ__ GHz, __STREAMS__ streams each
report pasta lo_tcp __THREADS__ __FREQ__
th MTU 1500B 4000B 16384B 65535B
tr TCP throughput over IPv6: ns to host
ns ip link set dev lo mtu 1500
iperf3c ns ::1 100${i}3 __THREADS__ __OPTS__
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 15.0 20.0
ns ip link set dev lo mtu 4000
iperf3c ns ::1 100${i}3 __THREADS__ __OPTS__
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 15.0 20.0
ns ip link set dev lo mtu 16384
iperf3c ns ::1 100${i}3 __THREADS__ __OPTS__
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 15.0 20.0
ns ip link set dev lo mtu 65535
iperf3c ns ::1 100${i}3 __THREADS__ __OPTS__
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 15.0 20.0
tl TCP RR latency over IPv6: ns to host
lat -
lat -
lat -
hostb tcp_rr --nolog -P 10003 -C 10013 -6
nsout LAT tcp_rr --nolog -P 10003 -C 10013 -6 -c -H ::1 | sed -n 's/^throughput=\(.*\)/\1/p'
hostw
lat __LAT__ 150 100
tl TCP CRR latency over IPv6: ns to host
lat -
lat -
lat -
hostb tcp_crr --nolog -P 10003 -C 10013 -6
nsout LAT tcp_crr --nolog -P 10003 -C 10013 -6 -c -H ::1 | sed -n 's/^throughput=\(.*\)/\1/p'
hostw
lat __LAT__ 500 350
tr TCP throughput over IPv4: ns to host
ns ip link set dev lo mtu 1500
iperf3c ns 127.0.0.1 100${i}3 __THREADS__ __OPTS__
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 15.0 20.0
ns ip link set dev lo mtu 4000
iperf3c ns 127.0.0.1 100${i}3 __THREADS__ __OPTS__
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 15.0 20.0
ns ip link set dev lo mtu 16384
iperf3c ns 127.0.0.1 100${i}3 __THREADS__ __OPTS__
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 15.0 20.0
ns ip link set dev lo mtu 65535
iperf3c ns 127.0.0.1 100${i}3 __THREADS__ __OPTS__
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 15.0 20.0
tl TCP RR latency over IPv4: ns to host
lat -
lat -
lat -
hostb tcp_rr --nolog -P 10003 -C 10013 -4
nsout LAT tcp_rr --nolog -P 10003 -C 10013 -4 -c -H 127.0.0.1 | sed -n 's/^throughput=\(.*\)/\1/p'
hostw
lat __LAT__ 150 100
tl TCP CRR latency over IPv4: ns to host
lat -
lat -
lat -
hostb tcp_crr --nolog -P 10003 -C 10013 -4
nsout LAT tcp_crr --nolog -P 10003 -C 10013 -4 -c -H 127.0.0.1 | sed -n 's/^throughput=\(.*\)/\1/p'
hostw
lat __LAT__ 500 350
tr TCP throughput over IPv6: host to ns
bw -
bw -
bw -
iperf3c host ::1 100${i}2 __THREADS__ __OPTS__
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 15.0 20.0
tl TCP RR latency over IPv6: host to ns
lat -
lat -
lat -
nsb tcp_rr --nolog -P 10002 -C 10012 -6
hout LAT tcp_rr --nolog -P 10002 -C 10012 -6 -c -H ::1 | sed -n 's/^throughput=\(.*\)/\1/p'
nsw
lat __LAT__ 150 100
tl TCP CRR latency over IPv6: host to ns
lat -
lat -
lat -
nsb tcp_crr --nolog -P 10002 -C 10012 -6
hout LAT tcp_crr --nolog -P 10002 -C 10012 -6 -c -H ::1 | sed -n 's/^throughput=\(.*\)/\1/p'
nsw
lat __LAT__ 1000 700
tr TCP throughput over IPv4: host to ns
bw -
bw -
bw -
iperf3c host 127.0.0.1 100${i}2 __THREADS__ __OPTS__
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 15.0 20.0
tl TCP RR latency over IPv4: host to ns
lat -
lat -
lat -
nsb tcp_rr --nolog -P 10002 -C 10012 -4
hout LAT tcp_rr --nolog -P 10002 -C 10012 -4 -c -H 127.0.0.1 | sed -n 's/^throughput=\(.*\)/\1/p'
nsw
lat __LAT__ 150 100
tl TCP CRR latency over IPv4: host to ns
lat -
lat -
lat -
sleep 1
nsb tcp_crr --nolog -P 10002 -C 10012 -4
hout LAT tcp_crr --nolog -P 10002 -C 10012 -4 -c -H 127.0.0.1 | sed -n 's/^throughput=\(.*\)/\1/p'
nsw
lat __LAT__ 1000 700
te
test pasta: throughput and latency (connections via tap)
nsout GW ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
nsout GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
nsout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
set THREADS 1
set STREAMS 2
set OPTS -Z -P __STREAMS__ -i1 -t30 -O5 --pacing-timer 100000
info Throughput in Gbps, latency in µs, one thread at __FREQ__ GHz, __STREAMS__ streams
report pasta tap_tcp __THREADS__ __FREQ__
th MTU 1500B 4000B 16384B 65520B
tr TCP throughput over IPv6: ns to host
ns ip link set dev __IFNAME__ mtu 1500
iperf3c ns __GW6__%__IFNAME__ 100${i}3 __THREADS__ __OPTS__ -w 512k
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 0.2 0.4
ns ip link set dev __IFNAME__ mtu 4000
iperf3c ns __GW6__%__IFNAME__ 100${i}3 __THREADS__ __OPTS__ -w 1M
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 0.3 0.5
ns ip link set dev __IFNAME__ mtu 16384
iperf3c ns __GW6__%__IFNAME__ 100${i}3 __THREADS__ __OPTS__ -w 8M
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 1.5 2.0
ns ip link set dev __IFNAME__ mtu 65520
iperf3c ns __GW6__%__IFNAME__ 100${i}3 __THREADS__ __OPTS__ -w 8M
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 2.0 2.5
tl TCP RR latency over IPv6: ns to host
lat -
lat -
lat -
hostb tcp_rr --nolog -P 10003 -C 10013 -6
nsout LAT tcp_rr --nolog -P 10003 -C 10013 -6 -c -H __GW6__%__IFNAME__ | sed -n 's/^throughput=\(.*\)/\1/p'
hostw
lat __LAT__ 150 100
tl TCP CRR latency over IPv6: ns to host
lat -
lat -
lat -
hostb tcp_crr --nolog -P 10003 -C 10013 -6
nsout LAT tcp_crr --nolog -P 10003 -C 10013 -6 -c -H __GW6__%__IFNAME__ | sed -n 's/^throughput=\(.*\)/\1/p'
hostw
lat __LAT__ 1500 500
tr TCP throughput over IPv4: ns to host
ns ip link set dev __IFNAME__ mtu 1500
iperf3c ns __GW__ 100${i}3 __THREADS__ __OPTS__ -w 512k
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 0.2 0.4
ns ip link set dev __IFNAME__ mtu 4000
iperf3c ns __GW__ 100${i}3 __THREADS__ __OPTS__ -w 1M
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 0.3 0.5
ns ip link set dev __IFNAME__ mtu 16384
iperf3c ns __GW__ 100${i}3 __THREADS__ __OPTS__ -w 8M
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 1.5 2.0
ns ip link set dev __IFNAME__ mtu 65520
iperf3c ns __GW__ 100${i}3 __THREADS__ __OPTS__ -w 8M
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 2.0 2.5
tl TCP RR latency over IPv4: ns to host
lat -
lat -
lat -
hostb tcp_rr --nolog -P 10003 -C 10013 -4
nsout LAT tcp_rr --nolog -P 10003 -C 10013 -4 -c -H __GW__ | sed -n 's/^throughput=\(.*\)/\1/p'
hostw
lat __LAT__ 150 100
tl TCP CRR latency over IPv4: ns to host
lat -
lat -
lat -
hostb tcp_crr --nolog -P 10003 -C 10013 -4
nsout LAT tcp_crr --nolog -P 10003 -C 10013 -4 -c -H __GW__ | sed -n 's/^throughput=\(.*\)/\1/p'
hostw
lat __LAT__ 1500 500
te

195
test/perf/pasta_udp Normal file
View file

@ -0,0 +1,195 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/perf/pasta_udp - Check UDP performance in pasta mode
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
onlyfor passt_in_ns
htools cpupower ip sleep iperf3 udp_rr jq sed
nstools ip sleep iperf3 udp_rr jq sed
test pasta: throughput and latency (local traffic)
hout FREQ cpupower frequency-info -lm | sed -n 's/.*- \(.*\) GHz$/\1/p'
set THREADS 1
set STREAMS 4
set OPTS -u -i1 -t30 -P __STREAMS__
info Throughput in Gbps, latency in µs, one thread at __FREQ__ GHz, __STREAMS__ streams
report pasta lo_udp 1 __FREQ__
th MTU 1500B 4000B 16384B 65535B
tr UDP throughput over IPv6: ns to host
ns ip link set dev lo mtu 1500
iperf3c ns ::1 100${i}3 __THREADS__ __OPTS__ -b 3G
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 1.0 1.5
ns ip link set dev lo mtu 4000
iperf3c ns ::1 100${i}3 __THREADS__ __OPTS__ -b 3G
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 1.2 1.8
ns ip link set dev lo mtu 16384
iperf3c ns ::1 100${i}3 __THREADS__ __OPTS__ -b 10G
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 5.0 6.0
ns ip link set dev lo mtu 65535
iperf3c ns ::1 100${i}3 __THREADS__ __OPTS__ -b 15G
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 7.0 9.0
tl UDP RR latency over IPv6: ns to host
lat -
lat -
lat -
hostb udp_rr --nolog -P 10003 -C 10013 -6
nsout LAT udp_rr --nolog -P 10003 -C 10013 -6 -c -H ::1 | sed -n 's/^throughput=\(.*\)/\1/p'
hostw
lat __LAT__ 200 150
tr UDP throughput over IPv4: ns to host
ns ip link set dev lo mtu 1500
ns ip addr add ::1 dev lo
iperf3c ns 127.0.0.1 100${i}3 __THREADS__ __OPTS__ -b 3G
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 1.0 1.5
ns ip link set dev lo mtu 4000
iperf3c ns 127.0.0.1 100${i}3 __THREADS__ __OPTS__ -b 3G
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 1.2 1.8
ns ip link set dev lo mtu 16384
iperf3c ns 127.0.0.1 100${i}3 __THREADS__ __OPTS__ -b 10G
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 5.0 6.0
ns ip link set dev lo mtu 65535
iperf3c ns 127.0.0.1 100${i}3 __THREADS__ __OPTS__ -b 15G
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 7.0 9.0
tl UDP RR latency over IPv4: ns to host
lat -
lat -
lat -
hostb udp_rr --nolog -P 10003 -C 10013 -4
nsout LAT udp_rr --nolog -P 10003 -C 10013 -4 -c -H 127.0.0.1 | sed -n 's/^throughput=\(.*\)/\1/p'
hostw
lat __LAT__ 200 150
tr UDP throughput over IPv6: host to ns
bw -
bw -
bw -
iperf3c host ::1 100${i}2 __THREADS__ __OPTS__ -b 15G
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 7.0 9.0
tl UDP RR latency over IPv6: host to ns
lat -
lat -
lat -
nsb udp_rr --nolog -P 10002 -C 10012 -6
hout LAT udp_rr --nolog -P 10002 -C 10012 -6 -c -H ::1 | sed -n 's/^throughput=\(.*\)/\1/p'
nsw
lat __LAT__ 200 150
tr UDP throughput over IPv4: host to ns
bw -
bw -
bw -
iperf3c host 127.0.0.1 100${i}2 __THREADS__ __OPTS__ -b 15G
iperf3s BW ns 100${i}2 __THREADS__
bw __BW__ 7.0 9.0
tl UDP RR latency over IPv4: host to ns
lat -
lat -
lat -
nsb udp_rr --nolog -P 10002 -C 10012 -4
hout LAT udp_rr --nolog -P 10002 -C 10012 -4 -c -H 127.0.0.1 | sed -n 's/^throughput=\(.*\)/\1/p'
nsw
lat __LAT__ 200 150
te
test pasta: throughput and latency (traffic via tap)
nsout GW ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
nsout GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
nsout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
info Throughput in Gbps, latency in µs, one thread at __FREQ__ GHz, __STREAMS__ streams
report pasta tap_udp 1 __FREQ__
th MTU 1500B 4000B 16384B 65520B
tr UDP throughput over IPv6: ns to host
ns ip link set dev __IFNAME__ mtu 1500
iperf3c ns __GW6__%__IFNAME__ 100${i}3 __THREADS__ __OPTS__ -b 1G
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 0.3 0.5
ns ip link set dev __IFNAME__ mtu 4000
iperf3c ns __GW6__%__IFNAME__ 100${i}3 __THREADS__ __OPTS__ -b 2G
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 0.5 0.8
ns ip link set dev __IFNAME__ mtu 16384
iperf3c ns __GW6__%__IFNAME__ 100${i}3 __THREADS__ __OPTS__ -b 3G
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 3.0 4.0
ns ip link set dev __IFNAME__ mtu 65520
iperf3c ns __GW6__%__IFNAME__ 100${i}3 __THREADS__ __OPTS__ -b 3G
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 6.0 7.0
tl UDP RR latency over IPv6: ns to host
lat -
lat -
lat -
hostb udp_rr --nolog -P 10003 -C 10013 -6
nsout LAT udp_rr --nolog -P 10003 -C 10013 -6 -c -H __GW6__%__IFNAME__ | sed -n 's/^throughput=\(.*\)/\1/p'
hostw
lat __LAT__ 200 150
tr UDP throughput over IPv4: ns to host
ns ip link set dev __IFNAME__ mtu 1500
iperf3c ns __GW__ 100${i}3 __THREADS__ __OPTS__ -b 1G
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 0.3 0.5
ns ip link set dev __IFNAME__ mtu 4000
iperf3c ns __GW__ 100${i}3 __THREADS__ __OPTS__ -b 2G
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 0.5 0.8
ns ip link set dev __IFNAME__ mtu 16384
iperf3c ns __GW__ 100${i}3 __THREADS__ __OPTS__ -b 3G
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 3.0 4.0
ns ip link set dev __IFNAME__ mtu 65520
iperf3c ns __GW__ 100${i}3 __THREADS__ __OPTS__ -b 3G
iperf3s BW host 100${i}3 __THREADS__
bw __BW__ 6.0 7.0
tl UDP RR latency over IPv4: ns to host
lat -
lat -
lat -
hostb udp_rr --nolog -P 10003 -C 10013 -4
nsout LAT udp_rr --nolog -P 10003 -C 10013 -4 -c -H __GW__ | sed -n 's/^throughput=\(.*\)/\1/p'
hostw
lat __LAT__ 200 150
te

154
test/run Executable file
View file

@ -0,0 +1,154 @@
#!/bin/sh
#
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/run - Entry point to run test cases and demo
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
# Start an X terminal and capture a video of the test run (also set for ./ci)
CI=${CI:-0}
# Start an X terminal and show the demo (also set for ./demo)
DEMO=${DEMO:-0}
# Base path for output files
BASEPATH=${BASEPATH:-"$(pwd)"}
# Location of log files for test run
LOGDIR=${LOGDIR:-"${BASEPATH}/test_logs"}
LOGFILE=${LOGFILE:-"${LOGDIR}/test.log"}
# If set, skip typing delays while issuing commands in panes
FAST=${FAST:-1}
# If set, run passt and pasta with debug options
DEBUG=${DEBUG:-0}
# If set, tell passt and pasta to take packet captures
PCAP=${PCAP:-0}
COMMIT="$(git log --oneline --no-decorate -1)"
. lib/util
. lib/setup
. lib/term
. lib/perf_report
. lib/layout
. lib/test
. lib/video
# cleanup() - Remove temporary files
cleanup() {
rm -f /tmp/.passt_test_log_pipe
}
# run() - Call setup functions, run tests, handle exit from test session
run() {
rm -f /tmp/.passt_test_log_pipe
mkfifo /tmp/.passt_test_log_pipe
term
perf_init
[ ${CI} -eq 1 ] && video_grab ci
setup build
test build
setup pasta
test ndp
test dhcp
test tcp
test udp
teardown pasta
setup passt
test ndp
test dhcp
test tcp
test udp
teardown passt
setup passt_in_ns
test ndp
test dhcp
test icmp
test tcp
test udp
test perf
teardown passt_in_ns
setup two_guests
test two_guests
teardown two_guests
perf_finish
[ ${CI} -eq 1 ] && video_stop ${STATUS_FAIL}
log "PASS: ${STATUS_PASS}, FAIL: ${STATUS_FAIL}"
pause_continue \
"Press any key to keep test session open" \
"Closing in " \
"Interrupted, press any key to quit" \
9
return ${STATUS_FAIL}
}
# demo() - Simpler path for demo purposes
demo() {
rm -f /tmp/.passt_test_log_pipe
mkfifo /tmp/.passt_test_log_pipe
FAST=0
term_demo
layout_demo_passt
video_grab demo_passt
MODE=passt
test demo
video_stop 0
tmux send-keys -t ${PANE_GUEST} "C-c"
layout_demo_pasta
video_grab demo_pasta
MODE=pasta
test demo
video_stop 0
return 0
}
[ "$(basename "${0}")" = "ci" ] && CI=1
[ "$(basename "${0}")" = "run_demo" ] && DEMO=1
if [ "${1}" = "from_term" ]; then
cd ..
if [ ${DEMO} -eq 1 ]; then
demo
else
run
fi
tmux kill-session -t passt_test
exit
else
rm -rf "${LOGDIR}"
mkdir -p "${LOGDIR}"
:> "${LOGFILE}"
trap "cleanup" EXIT
run_term
trap "" EXIT
fi
tail -n1 ${LOGFILE}
echo "Log at ${LOGFILE}"
exit $(tail -n1 ${LOGFILE} | sed -n 's/.*FAIL: \(.*\)$/\1/p')

1
test/run_demo Symbolic link
View file

@ -0,0 +1 @@
run

86
test/tcp/passt Normal file
View file

@ -0,0 +1,86 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/tcp/passt - Check TCP functionality in passt mode
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
onlyfor passt
gtools nc ip jq cat md5sum cut
htools dd nc ip jq cat md5sum cut
test TCP/IPv4: host to guest: big transfer
temp TEMP_BIG
guestb nc -4 -l 10001 > test_big.bin
host dd if=/dev/urandom bs=1M count=10 > __TEMP_BIG__
host cat __TEMP_BIG__ | nc -N 127.0.0.1 10001
guestw
hout HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
gout GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1
check [ "__GUEST_MD5_BIG__" = "__HOST_MD5_BIG__" ]
test TCP/IPv4: guest to host: big transfer
hostb nc -4 -l 10003 > __TEMP_BIG__
gout GW ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
guest cat test_big.bin | nc -N __GW__ 10003
hostw
hout HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
check [ "__GUEST_MD5_BIG__" = "__HOST_MD5_BIG__" ]
test TCP/IPv4: host to guest: small transfer
temp TEMP_SMALL
guestb nc -4 -l 10001 > test_small.bin
host dd if=/dev/urandom bs=2k count=1 > __TEMP_SMALL__
host cat __TEMP_SMALL__ | nc -N 127.0.0.1 10001
guestw
hout HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
check [ "__GUEST_MD5_SMALL__" = "__HOST_MD5_SMALL__" ]
test TCP/IPv4: guest to host: small transfer
hostb nc -4 -l 10003 > __TEMP_SMALL__
sleep 1
guest cat test_small.bin | nc -N __GW__ 10003
hostw
hout HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
check [ "__GUEST_MD5_SMALL__" = "__HOST_MD5_SMALL__" ]
test TCP/IPv6: host to guest: big transfer
guestb nc -6 -l 10001 > test_big.bin
sleep 1
host cat __TEMP_BIG__ | nc -N ::1 10001
guestw
gout GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1
check [ "__GUEST_MD5_BIG__" = "__HOST_MD5_BIG__" ]
test TCP/IPv6: guest to host: big transfer
hostb nc -6 -l 10003 > __TEMP_BIG__
gout GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
gout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
guest cat test_big.bin | nc -N __GW6__%__IFNAME__ 10003
hostw
hout HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
check [ "__GUEST_MD5_BIG__" = "__HOST_MD5_BIG__" ]
test TCP/IPv6: host to guest: small transfer
guestb nc -6 -l 10001 > test_small.bin
sleep 1
host cat __TEMP_SMALL__ | nc -N ::1 10001
guestw
gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
check [ "__GUEST_MD5_SMALL__" = "__HOST_MD5_SMALL__" ]
test TCP/IPv6: guest to host: small transfer
hostb nc -6 -l 10003 > __TEMP_SMALL__
sleep 1
guest cat test_small.bin | nc -N __GW6__%__IFNAME__ 10003
hostw
hout HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
check [ "__GUEST_MD5_SMALL__" = "__HOST_MD5_SMALL__" ]

262
test/tcp/passt_in_ns Normal file
View file

@ -0,0 +1,262 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/tcp/passt_in_ns - Check TCP functionality for passt in ns with pasta
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
onlyfor passt_in_ns
gtools nc ip jq cat md5sum cut
htools dd nc ip jq cat md5sum cut
nstools nc ip jq cat md5sum cut
test TCP/IPv4: host to guest: big transfer
temp TEMP_BIG
guestb nc -4 -l 10001 > test_big.bin
host dd if=/dev/urandom bs=1M count=10 > __TEMP_BIG__
host cat __TEMP_BIG__ | nc -N 127.0.0.1 10001
guestw
hout MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
gout GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1
check [ "__GUEST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv4: host to ns: big transfer
temp TEMP_NS_BIG
nsb nc -4 -l 10002 > __TEMP_NS_BIG__
host cat __TEMP_BIG__ | nc -N 127.0.0.1 10002
nsw
nsout NS_MD5_BIG md5sum __TEMP_NS_BIG__ | cut -d' ' -f1
check [ "__NS_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv4: guest to host: big transfer
hostb nc -4 -l 10003 > __TEMP_BIG__
gout GW ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
guest cat test_big.bin | nc -N __GW__ 10003
hostw
hout HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv4: guest to ns: big transfer
nsb nc -4 -l 10002 > __TEMP_BIG__
guest cat test_big.bin | nc -N __GW__ 10002
hostw
hout HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv4: ns to host (spliced): big transfer
sleep 1
hostb nc -4 -l 10003 > __TEMP_BIG__
ns cat __TEMP_NS_BIG__ | nc -N 127.0.0.1 10003
hostw
hout HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv4: ns to host (via tap): big transfer
hostb nc -4 -l 10003 > __TEMP_BIG__
ns cat __TEMP_NS_BIG__ | nc -N __GW__ 10003
hostw
hout HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv4: ns to guest (using loopback address): big transfer
guestb nc -4 -l 10001 > test_big.bin
ns cat __TEMP_NS_BIG__ | nc -N 127.0.0.1 10001
guestw
gout GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1
check [ "__GUEST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv4: ns to guest (using namespace address): big transfer
guestb nc -4 -l 10001 > test_big.bin
nsout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
nsout ADDR ip -j -4 ad sh|jq -rM '.[] | select(.ifname == "__IFNAME__").addr_info[0].local'
ns cat __TEMP_NS_BIG__ | nc -N __ADDR__ 10001
guestw
gout GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1
check [ "__GUEST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv4: host to guest: small transfer
temp TEMP_SMALL
guestb nc -4 -l 10001 > test_small.bin
host dd if=/dev/urandom bs=2k count=100 > __TEMP_SMALL__
host cat __TEMP_SMALL__ | nc -N 127.0.0.1 10001
guestw
hout MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
check [ "__GUEST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv4: host to ns: small transfer
temp TEMP_NS_SMALL
nsb nc -4 -l 10002 > __TEMP_NS_SMALL__
host cat __TEMP_SMALL__ | nc -N 127.0.0.1 10002
nsw
nsout NS_MD5_SMALL md5sum __TEMP_NS_SMALL__ | cut -d' ' -f1
check [ "__NS_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv4: guest to host: small transfer
hostb nc -4 -l 10003 > __TEMP_SMALL__
gout GW ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
guest cat test_small.bin | nc -N __GW__ 10003
hostw
hout HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv4: guest to ns: small transfer
nsb nc -4 -l 10002 > __TEMP_SMALL__
guest cat test_small.bin | nc -N __GW__ 10002
hostw
hout HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv4: ns to host (spliced): small transfer
sleep 1
hostb nc -4 -l 10003 > __TEMP_SMALL__
ns cat __TEMP_NS_SMALL__ | nc -N 127.0.0.1 10003
hostw
hout HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv4: ns to host (via tap): small transfer
hostb nc -4 -l 10003 > __TEMP_SMALL__
ns cat __TEMP_NS_SMALL__ | nc -N __GW__ 10003
hostw
hout HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv4: ns to guest (using loopback address): small transfer
guestb nc -4 -l 10001 > test_small.bin
ns cat __TEMP_NS_SMALL__ | nc -N 127.0.0.1 10001
guestw
gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
check [ "__GUEST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv4: ns to guest (using namespace address): small transfer
guestb nc -4 -l 10001 > test_small.bin
ns cat __TEMP_NS_SMALL__ | nc -N __ADDR__ 10001
guestw
gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
check [ "__GUEST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv6: host to guest: big transfer
guestb nc -6 -l 10001 > test_big.bin
host cat __TEMP_BIG__ | nc -N ::1 10001
guestw
gout GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1
check [ "__GUEST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv6: host to ns: big transfer
nsb nc -6 -l 10002 > __TEMP_NS_BIG__
host cat __TEMP_BIG__ | nc -N ::1 10002
nsw
nsout NS_MD5_BIG md5sum __TEMP_NS_BIG__ | cut -d' ' -f1
check [ "__NS_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv6: guest to host: big transfer
hostb nc -6 -l 10003 > __TEMP_BIG__
gout GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
gout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
guest cat test_big.bin | nc -N __GW6__%__IFNAME__ 10003
hostw
hout HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv6: guest to ns: big transfer
nsb nc -6 -l 10002 > __TEMP_BIG__
guest cat test_big.bin | nc -N __GW6__%__IFNAME__ 10002
hostw
hout HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv6: ns to host (spliced): big transfer
hostb nc -6 -l 10003 > __TEMP_BIG__
ns cat __TEMP_NS_BIG__ | nc -N ::1 10003
hostw
hout HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv6: ns to host (via tap): big transfer
hostb nc -6 -l 10003 > __TEMP_BIG__
nsout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
ns cat __TEMP_NS_BIG__ | nc -N __GW6__%__IFNAME__ 10003
hostw
hout HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv6: ns to guest (using loopback address): big transfer
guestb nc -6 -l 10001 > test_big.bin
ns cat __TEMP_NS_BIG__ | nc -N ::1 10001
guestw
gout GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1
check [ "__GUEST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv6: ns to guest (using namespace address): big transfer
guestb nc -6 -l 10001 > test_big.bin
nsout ADDR6 ip -j -6 ad sh|jq -rM '.[] | select(.ifname == "__IFNAME__").addr_info[0].local'
ns cat __TEMP_NS_BIG__ | nc -N __ADDR6__ 10001
guestw
gout GUEST_MD5_BIG md5sum test_big.bin | cut -d' ' -f1
check [ "__GUEST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv6: host to guest: small transfer
guestb nc -6 -l 10001 > test_small.bin
host cat __TEMP_SMALL__ | nc -N ::1 10001
guestw
gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
check [ "__GUEST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv6: host to ns: small transfer
nsb nc -6 -l 10002 > __TEMP_NS_SMALL__
host cat __TEMP_SMALL__ | nc -N ::1 10002
nsw
nsout NS_MD5_SMALL md5sum __TEMP_NS_SMALL__ | cut -d' ' -f1
check [ "__NS_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv6: guest to host: small transfer
hostb nc -6 -l 10003 > __TEMP_SMALL__
gout GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
gout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
guest cat test_small.bin | nc -N __GW6__%__IFNAME__ 10003
hostw
hout HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv6: guest to ns: small transfer
nsb nc -6 -l 10002 > __TEMP_SMALL__
guest cat test_small.bin | nc -N __GW6__%__IFNAME__ 10002
hostw
hout HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv6: ns to host (spliced): small transfer
hostb nc -6 -l 10003 > __TEMP_SMALL__
ns cat __TEMP_NS_SMALL__ | nc -N ::1 10003
hostw
hout HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv6: ns to host (via tap): small transfer
hostb nc -6 -l 10003 > __TEMP_SMALL__
nsout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
ns cat __TEMP_NS_SMALL__ | nc -N __GW6__%__IFNAME__ 10003
hostw
hout HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv6: ns to guest (using loopback address): small transfer
guestb nc -6 -l 10001 > test_small.bin
ns cat __TEMP_NS_SMALL__ | nc -N ::1 10001
guestw
gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
check [ "__GUEST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv6: ns to guest (using namespace address): small transfer
guestb nc -6 -l 10001 > test_small.bin
ns cat __TEMP_NS_SMALL__ | nc -N __ADDR6__ 10001
guestw
gout GUEST_MD5_SMALL md5sum test_small.bin | cut -d' ' -f1
check [ "__GUEST_MD5_SMALL__" = "__MD5_SMALL__" ]

118
test/tcp/pasta Normal file
View file

@ -0,0 +1,118 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/tcp/pasta - Check TCP functionality for pasta
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
onlyfor pasta
htools dd nc ip jq cat md5sum cut
nstools nc ip jq cat md5sum cut
test TCP/IPv4: host to ns: big transfer
temp TEMP_BIG
temp TEMP_NS_BIG
nsb nc -4 -l 10002 > __TEMP_NS_BIG__
host dd if=/dev/urandom bs=1M count=10 > __TEMP_BIG__
host cat __TEMP_BIG__ | nc -N 127.0.0.1 10002
nsw
hout MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
nsout NS_MD5_BIG md5sum __TEMP_NS_BIG__ | cut -d' ' -f1
check [ "__NS_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv4: ns to host (spliced): big transfer
hostb nc -4 -l 10003 > __TEMP_BIG__
ns cat __TEMP_NS_BIG__ | nc -N 127.0.0.1 10003
hostw
hout HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv4: ns to host (via tap): big transfer
hostb nc -4 -l 10003 > __TEMP_BIG__
nsout GW ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
ns cat __TEMP_NS_BIG__ | nc -N __GW__ 10003
hostw
hout HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv4: host to ns: small transfer
temp TEMP_SMALL
temp TEMP_NS_SMALL
nsb nc -4 -l 10002 > __TEMP_NS_SMALL__
host dd if=/dev/urandom bs=2k count=1 > __TEMP_SMALL__
host cat __TEMP_SMALL__ | nc -N 127.0.0.1 10002
nsw
hout MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
nsout NS_MD5_SMALL md5sum __TEMP_NS_SMALL__ | cut -d' ' -f1
check [ "__NS_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv4: ns to host (spliced): small transfer
hostb nc -4 -l 10003 > __TEMP_SMALL__
ns cat __TEMP_NS_SMALL__ | nc -N 127.0.0.1 10003
hostw
hout HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv4: ns to host (via tap): small transfer
hostb nc -4 -l 10003 > __TEMP_SMALL__
nsout GW ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
ns cat __TEMP_NS_SMALL__ | nc -N __GW__ 10003
hostw
hout HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv6: host to ns: big transfer
nsb nc -6 -l 10002 > __TEMP_NS_BIG__
host cat __TEMP_BIG__ | nc -N ::1 10002
nsw
hout MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
nsout NS_MD5_BIG md5sum __TEMP_NS_BIG__ | cut -d' ' -f1
check [ "__NS_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv6: ns to host (spliced): big transfer
hostb nc -6 -l 10003 > __TEMP_BIG__
ns cat __TEMP_NS_BIG__ | nc -N ::1 10003
hostw
hout HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
nsw
test TCP/IPv6: ns to host (via tap): big transfer
hostb nc -6 -l 10003 > __TEMP_BIG__
nsout GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
nsout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
ns cat __TEMP_NS_BIG__ | nc -N __GW6__%__IFNAME__ 10003
hostw
hout HOST_MD5_BIG md5sum __TEMP_BIG__ | cut -d' ' -f1
check [ "__HOST_MD5_BIG__" = "__MD5_BIG__" ]
test TCP/IPv6: host to ns: small transfer
temp TEMP_SMALL
temp TEMP_NS_SMALL
nsb nc -6 -l 10002 > __TEMP_NS_SMALL__
host dd if=/dev/urandom bs=2k count=1 > __TEMP_SMALL__
host cat __TEMP_SMALL__ | nc -N ::1 10002
nsw
hout MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
nsout NS_MD5_SMALL md5sum __TEMP_NS_SMALL__ | cut -d' ' -f1
check [ "__NS_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv6: ns to host (spliced): small transfer
hostb nc -6 -l 10003 > __TEMP_SMALL__
ns cat __TEMP_NS_SMALL__ | nc -N ::1 10003
hostw
hout HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]
test TCP/IPv6: ns to host (via tap): small transfer
hostb nc -6 -l 10003 > __TEMP_SMALL__
ns cat __TEMP_NS_SMALL__ | nc -N __GW6__%__IFNAME__ 10003
hostw
hout HOST_MD5_SMALL md5sum __TEMP_SMALL__ | cut -d' ' -f1
check [ "__HOST_MD5_SMALL__" = "__MD5_SMALL__" ]

75
test/two_guests/basic Normal file
View file

@ -0,0 +1,75 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/two_guests/basic - Check basic functionality with two guests
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
g1tools ip jq dhclient nc cat
g2tools ip jq dhclient nc cat
htools ip jq cat md5sum cut
test Interface names
g1out IFNAME1 ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
g2out IFNAME2 ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
hout HOST_IFNAME ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").dev'
check [ -n "__IFNAME1__" ]
check [ -n "__IFNAME2__" ]
test DHCP: addresses
guest1 /sbin/dhclient __IFNAME1__
guest2 /sbin/dhclient __IFNAME1__
g1out ADDR1 ip -j -4 ad sh|jq -rM '.[] | select(.ifname == "__IFNAME1__").addr_info[0].local'
g2out ADDR2 ip -j -4 ad sh|jq -rM '.[] | select(.ifname == "__IFNAME2__").addr_info[0].local'
hout HOST_ADDR ip -j -4 ad sh|jq -rM '.[] | select(.ifname == "__HOST_IFNAME__").addr_info[0].local'
check [ "__ADDR1__" = "__HOST_ADDR__" ]
check [ "__ADDR2__" = "__HOST_ADDR__" ]
test DHCPv6: addresses
guest1 /sbin/dhclient -6 __IFNAME1__
guest2 /sbin/dhclient -6 __IFNAME1__
g1out ADDR1_6 ip -j -6 ad sh|jq -rM '.[] | select(.ifname == "__IFNAME1__").addr_info[] | select(.prefixlen == 128).local'
g2out ADDR2_6 ip -j -6 ad sh|jq -rM '.[] | select(.ifname == "__IFNAME2__").addr_info[] | select(.prefixlen == 128).local'
hout HOST_ADDR6 ip -j -6 ad sh|jq -rM '.[] | select(.ifname == "__HOST_IFNAME__").addr_info[] | select(.scope == "global").local'
check [ "__ADDR1_6__" = "__HOST_ADDR6__" ]
check [ "__ADDR2_6__" = "__HOST_ADDR6__" ]
test TCP/IPv4: guest 1 > guest 2
g1out GW1 ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
guest2b nc -4 -l 10004 > msg
guest1 echo "Hello_from_guest_1" | nc -N __GW1__ 10004
guest2w
sleep 1
g2out MSG2 cat msg
check [ "__MSG2__" = "Hello_from_guest_1" ]
test TCP/IPv6: guest 2 > guest 1
g2out GW2_6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
guest1b nc -6 -l 10001 > msg
guest2 echo "Hello_from_guest_2" | nc -N __GW2_6__%__IFNAME2__ 10001
guest1w
sleep 1
g1out MSG1 cat msg
check [ "__MSG1__" = "Hello_from_guest_2" ]
test UDP/IPv4: guest 1 > guest 2
guest2b nc -u -W1 -4 -l 10004 > msg
guest1 echo "Hello_from_guest_1" | nc -u -q1 __GW1__ 10004
guest2w
sleep 1
g2out MSG2 cat msg
check [ "__MSG2__" = "Hello_from_guest_1" ]
test UDP/IPv6: guest 2 > guest 1
guest1b nc -u -W1 -6 -l 10001 > msg
guest2 echo "Hello_from_guest_2" | nc -u -q1 -N __GW2_6__%__IFNAME2__ 10001
guest1w
sleep 1
g1out MSG1 cat msg
check [ "__MSG1__" = "Hello_from_guest_2" ]

54
test/udp/passt Normal file
View file

@ -0,0 +1,54 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/udp/passt - Check UDP functionality in passt mode
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
onlyfor passt
gtools nc tee grep cat ip jq md5sum cut
htools printf dd nc tee grep cat ip jq md5sum cut
test UDP/IPv4: host to guest
temp TEMP
temp NC_PID
guestb (nc -u -q1 -4 -l 10001 & echo $! > __NC_PID__) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
host dd if=/dev/urandom bs=1k count=5 > __TEMP_BIG__ && printf "\nEND_OF_TEST\n" >> __TEMP__
host cat __TEMP__ | nc -u -q1 -N 127.0.0.1 10001
guestw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
gout GUEST_MD5 md5sum test.bin | cut -d' ' -f1
check [ "__GUEST_MD5__" = "__HOST_MD5__" ]
test UDP/IPv4: guest to host
host :> __TEMP__
hostb (nc -u -q1 -4 -l 10003 & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
gout GW ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
guest cat test.bin | nc -u -q1 -N __GW__ 10003
hostw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
check [ "__GUEST_MD5__" = "__HOST_MD5__" ]
test UDP/IPv6: host to guest
guestb (nc -u -q1 -6 -l 10001 & echo $! > nc.pid) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat nc.pid))
sleep 1
host cat __TEMP__ | nc -u -q1 -N ::1 10001
guestw
gout GUEST_MD5 md5sum test.bin | cut -d' ' -f1
check [ "__GUEST_MD5__" = "__HOST_MD5__" ]
test UDP/IPv6: guest to host
host :> __TEMP__
hostb (nc -u -q1 -6 -l 10003 & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
gout GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
gout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
guest cat test.bin | nc -u -q1 -N __GW6__%__IFNAME__ 10003
hostw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
check [ "__GUEST_MD5__" = "__HOST_MD5__" ]

152
test/udp/passt_in_ns Normal file
View file

@ -0,0 +1,152 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/udp/passt_in_ns - Check UDP functionality for passt in ns and pasta
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
onlyfor passt_in_ns
gtools nc tee grep cat ip jq md5sum cut
nstools nc tee grep cat ip jq md5sum cut
htools printf dd nc tee grep cat ip jq md5sum cut
test UDP/IPv4: host to guest
temp TEMP
temp NC_PID
guestb (nc -u -q1 -4 -l 10001 & echo $! > nc.pic) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat nc.pic))
host dd if=/dev/urandom bs=1k count=5 > __TEMP__ && printf "\nEND_OF_TEST\n" >> __TEMP__
host cat __TEMP__ | nc -u -q1 -N 127.0.0.1 10001
guestw
hout MD5 md5sum __TEMP__ | cut -d' ' -f1
gout GUEST_MD5 md5sum test.bin | cut -d' ' -f1
check [ "__GUEST_MD5__" = "__MD5__" ]
test UDP/IPv4: host to ns
temp TEMP_NS
ns :> __TEMP_NS__
nsb (nc -u -q1 -4 -l 10002 & echo $! > __NC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
host cat __TEMP__ | nc -u -q1 -N 127.0.0.1 10002
nsw
nsout NS_MD5 md5sum __TEMP_NS__ | cut -d' ' -f1
check [ "__NS_MD5__" = "__MD5__" ]
test UDP/IPv4: guest to host
host :> __TEMP__
hostb (nc -u -q1 -4 -l 10003 & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
gout GW ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
guest cat test.bin | nc -u -q1 -N __GW__ 10003
hostw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
check [ "__HOST_MD5__" = "__MD5__" ]
test UDP/IPv4: guest to ns
ns :> __TEMP_NS__
nsb (nc -u -q1 -4 -l 10002 & echo $! > __NC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
guest cat test.bin | nc -u -q1 -N __GW__ 10002
hostw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
check [ "__HOST_MD5__" = "__MD5__" ]
test UDP/IPv4: ns to host (recvmmsg/sendmmsg)
sleep 1
host :> __TEMP__
hostb (nc -u -q1 -4 -l 10003 & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
ns cat __TEMP_NS__ | nc -u -q1 -N 127.0.0.1 10003
hostw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
check [ "__HOST_MD5__" = "__MD5__" ]
test UDP/IPv4: ns to host (via tap)
host :> __TEMP__
hostb (nc -u -q1 -4 -l 10003 & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
ns cat __TEMP_NS__ | nc -u -q1 -N __GW__ 10003
hostw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
check [ "__HOST_MD5__" = "__MD5__" ]
test UDP/IPv4: ns to guest (using loopback address)
guestb (nc -u -q1 -4 -l 10001 & echo $! > nc.pid) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat nc.pid))
ns cat __TEMP_NS__ | nc -u -q1 -N 127.0.0.1 10001
guestw
gout GUEST_MD5 md5sum test.bin | cut -d' ' -f1
check [ "__GUEST_MD5__" = "__MD5__" ]
test UDP/IPv4: ns to guest (using namespace address)
guestb (nc -u -q1 -4 -l 10001 & echo $! > nc.pid) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat nc.pid))
nsout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
nsout ADDR ip -j -4 ad sh|jq -rM '.[] | select(.ifname == "__IFNAME__").addr_info[0].local'
ns cat __TEMP_NS__ | nc -u -q1 -N __ADDR__ 10001
guestw
gout GUEST_MD5 md5sum test.bin | cut -d' ' -f1
check [ "__GUEST_MD5__" = "__MD5__" ]
test UDP/IPv6: host to guest
guestb (nc -u -q1 -6 -l 10001 & echo $! > nc.pid) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat nc.pid))
host cat __TEMP__ | nc -u -q1 -N ::1 10001
guestw
gout GUEST_MD5 md5sum test.bin | cut -d' ' -f1
check [ "__GUEST_MD5__" = "__MD5__" ]
test UDP/IPv6: host to ns
ns :> __TEMP_NS__
nsb (nc -u -q1 -6 -l 10002 & echo $! > __NC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
host cat __TEMP__ | nc -u -q1 -N ::1 10002
nsw
nsout NS_MD5 md5sum __TEMP_NS__ | cut -d' ' -f1
check [ "__NS_MD5__" = "__MD5__" ]
test UDP/IPv6: guest to host
host :> __TEMP__
hostb (nc -u -q1 -6 -l 10003 & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
gout GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
gout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
guest cat test.bin | nc -u -q1 -N __GW6__%__IFNAME__ 10003
hostw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
check [ "__HOST_MD5__" = "__MD5__" ]
test UDP/IPv6: guest to ns
ns :> __TEMP_NS__
nsb (nc -u -q1 -6 -l 10002 & echo $! > __NC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
guest cat test.bin | nc -u -q1 -N __GW6__%__IFNAME__ 10002
hostw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
check [ "__HOST_MD5__" = "__MD5__" ]
test UDP/IPv6: ns to host (recvmmsg/sendmmsg)
host :> __TEMP__
hostb (nc -u -q1 -6 -l 10003 & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
ns cat __TEMP_NS__ | nc -u -q1 -N ::1 10003
hostw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
check [ "__HOST_MD5__" = "__MD5__" ]
test UDP/IPv6: ns to host (via tap)
host :> __TEMP__
hostb (nc -u -q1 -6 -l 10003 & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
nsout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
ns cat __TEMP_NS__ | nc -u -q1 -N __GW6__%__IFNAME__ 10003
hostw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
check [ "__HOST_MD5__" = "__MD5__" ]
test UDP/IPv6: ns to guest (using loopback address)
guestb (nc -u -q1 -6 -l 10001 & echo $! > nc.pid) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat nc.pid))
ns cat __TEMP_NS__ | nc -u -q1 -N ::1 10001
guestw
gout GUEST_MD5 md5sum test.bin | cut -d' ' -f1
check [ "__GUEST_MD5__" = "__MD5__" ]
test UDP/IPv6: ns to guest (using namespace address)
guestb (nc -u -q1 -6 -l 10001 & echo $! > nc.pid) | tee test.bin | (grep -qm1 "END_OF_TEST" && kill $(cat nc.pid))
nsout ADDR6 ip -j -6 ad sh|jq -rM '.[] | select(.ifname == "__IFNAME__").addr_info[0].local'
ns cat __TEMP_NS__ | nc -u -q1 -N __ADDR6__ 10001
guestw
gout GUEST_MD5 md5sum test.bin | cut -d' ' -f1
check [ "__GUEST_MD5__" = "__MD5__" ]

76
test/udp/pasta Normal file
View file

@ -0,0 +1,76 @@
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# PASST - Plug A Simple Socket Transport
# for qemu/UNIX domain socket mode
#
# PASTA - Pack A Subtle Tap Abstraction
# for network namespace/tap device mode
#
# test/udp/pasta - Check UDP functionality for pasta
#
# Copyright (c) 2021 Red Hat GmbH
# Author: Stefano Brivio <sbrivio@redhat.com>
onlyfor pasta
nstools nc tee grep cat ip jq md5sum cut
htools printf dd nc tee grep cat ip jq md5sum cut
test UDP/IPv4: host to ns
temp TEMP
temp TEMP_NS
temp NC_PID
ns :> __TEMP_NS__
nsb (nc -u -q1 -4 -l 10002 & echo $! > __NC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
host dd if=/dev/urandom bs=1k count=5 > __TEMP__ && printf "\nEND_OF_TEST\n" >> __TEMP__
host cat __TEMP__ | nc -u -q1 -N 127.0.0.1 10002
nsw
hout MD5 md5sum __TEMP__ | cut -d' ' -f1
nsout NS_MD5 md5sum __TEMP_NS__ | cut -d' ' -f1
check [ "__NS_MD5__" = "__MD5__" ]
test UDP/IPv4: ns to host (recvmmsg/sendmmsg)
host :> __TEMP__
hostb (nc -u -q1 -4 -l 10003 & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
sleep 1
ns cat __TEMP_NS__ | nc -u -q1 -N 127.0.0.1 10003
hostw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
check [ "__HOST_MD5__" = "__MD5__" ]
test UDP/IPv4: ns to host (via tap)
host :> __TEMP__
hostb (nc -u -q1 -4 -l 10003 & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
nsout GW ip -j -4 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
ns cat __TEMP_NS__ | nc -u -q1 -N __GW__ 10003
hostw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
check [ "__HOST_MD5__" = "__MD5__" ]
test UDP/IPv6: host to ns
ns :> __TEMP_NS__
nsb (nc -u -q1 -6 -l 10002 & echo $! > __NC_PID__) | tee __TEMP_NS__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
host cat __TEMP__ | nc -u -q1 -N ::1 10002
nsw
hout MD5 md5sum __TEMP__ | cut -d' ' -f1
nsout NS_MD5 md5sum __TEMP_NS__ | cut -d' ' -f1
check [ "__NS_MD5__" = "__MD5__" ]
test UDP/IPv6: ns to host (recvmmsg/sendmmsg)
host :> __TEMP__
hostb (nc -u -q1 -6 -l 10003 & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
sleep 1
ns cat __TEMP_NS__ | nc -u -q1 -N ::1 10003
hostw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
check [ "__HOST_MD5__" = "__MD5__" ]
nsw
test UDP/IPv6: ns to host (via tap)
host :> __TEMP__
hostb (nc -u -q1 -6 -l 10003 & echo $! > __NC_PID__) | tee __TEMP__ | (grep -qm1 "END_OF_TEST" && kill $(cat __NC_PID__))
nsout GW6 ip -j -6 ro sh|jq -rM '.[] | select(.dst == "default").gateway'
nsout IFNAME ip -j li sh | jq -rM '.[] | select(.link_type == "ether").ifname'
ns cat __TEMP_NS__ | nc -u -q1 -N __GW6__%__IFNAME__ 10003
hostw
hout HOST_MD5 md5sum __TEMP__ | cut -d' ' -f1
check [ "__HOST_MD5__" = "__MD5__" ]