2021-04-09 14:04:40 +03:00
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
readonly STATS = " $( mktemp -p /tmp ns-XXXXXX) "
readonly BASE = ` basename $STATS `
readonly SRC = 2
readonly DST = 1
readonly DST_NAT = 100
readonly NS_SRC = $BASE $SRC
readonly NS_DST = $BASE $DST
# "baremetal" network used for raw UDP traffic
readonly BM_NET_V4 = 192.168.1.
readonly BM_NET_V6 = 2001:db8::
2021-07-20 11:41:52 +03:00
readonly CPUS = ` nproc`
2021-04-09 14:04:40 +03:00
ret = 0
cleanup( ) {
local ns
2021-06-16 17:03:21 +03:00
local jobs
readonly jobs = " $( jobs -p) "
2021-04-09 14:04:40 +03:00
[ -n " ${ jobs } " ] && kill -1 ${ jobs } 2>/dev/null
rm -f $STATS
for ns in $NS_SRC $NS_DST ; do
ip netns del $ns 2>/dev/null
done
}
trap cleanup EXIT
create_ns( ) {
local ns
for ns in $NS_SRC $NS_DST ; do
ip netns add $ns
ip -n $ns link set dev lo up
done
ip link add name veth$SRC type veth peer name veth$DST
for ns in $SRC $DST ; do
ip link set dev veth$ns netns $BASE $ns up
ip -n $BASE $ns addr add dev veth$ns $BM_NET_V4 $ns /24
ip -n $BASE $ns addr add dev veth$ns $BM_NET_V6 $ns /64 nodad
done
echo "#kernel" > $BASE
chmod go-rw $BASE
}
__chk_flag( ) {
local msg = " $1 "
local target = $2
local expected = $3
local flagname = $4
local flag = ` ip netns exec $BASE $target ethtool -k veth$target | \
grep $flagname | awk '{print $2}' `
printf "%-60s" " $msg "
if [ " $flag " = " $expected " ] ; then
echo " ok "
else
echo " fail - expected $expected found $flag "
ret = 1
fi
}
chk_gro_flag( ) {
__chk_flag " $1 " $2 $3 generic-receive-offload
}
chk_tso_flag( ) {
__chk_flag " $1 " $2 $3 tcp-segmentation-offload
}
2021-07-20 11:41:52 +03:00
chk_channels( ) {
local msg = " $1 "
local target = $2
local rx = $3
local tx = $4
local dev = veth$target
local cur_rx = ` ip netns exec $BASE $target ethtool -l $dev | \
grep RX: | tail -n 1 | awk '{print $2}' `
local cur_tx = ` ip netns exec $BASE $target ethtool -l $dev | \
grep TX: | tail -n 1 | awk '{print $2}' `
local cur_combined = ` ip netns exec $BASE $target ethtool -l $dev | \
grep Combined: | tail -n 1 | awk '{print $2}' `
printf "%-60s" " $msg "
if [ " $cur_rx " = " $rx " -a " $cur_tx " = " $tx " -a " $cur_combined " = "n/a" ] ; then
echo " ok "
else
echo " fail rx: $rx : $cur_rx tx: $tx : $cur_tx combined:n/a: $cur_combined "
fi
}
2021-04-09 14:04:40 +03:00
chk_gro( ) {
local msg = " $1 "
local expected = $2
ip netns exec $BASE $SRC ping -qc 1 $BM_NET_V4 $DST >/dev/null
NSTAT_HISTORY = $STATS ip netns exec $NS_DST nstat -n
printf "%-60s" " $msg "
ip netns exec $BASE $DST ./udpgso_bench_rx -C 1000 -R 10 &
local spid = $!
sleep 0.1
ip netns exec $NS_SRC ./udpgso_bench_tx -4 -s 13000 -S 1300 -M 1 -D $BM_NET_V4 $DST
local retc = $?
wait $spid
local rets = $?
if [ ${ rets } -ne 0 ] || [ ${ retc } -ne 0 ] ; then
echo " fail client exit code $retc , server $rets "
ret = 1
return
fi
local pkts = ` NSTAT_HISTORY = $STATS ip netns exec $NS_DST nstat IpInReceives | \
awk '{print $2}' | tail -n 1`
if [ " $pkts " = " $expected " ] ; then
echo " ok "
else
echo " fail - got $pkts packets, expected $expected "
ret = 1
fi
}
2021-07-20 11:41:52 +03:00
__change_channels( )
{
local cur_cpu
local end = $1
local cur
local i
while true; do
printf -v cur '%(%s)T'
[ $cur -le $end ] || break
for i in ` seq 1 $CPUS ` ; do
ip netns exec $NS_SRC ethtool -L veth$SRC rx $i tx $i
ip netns exec $NS_DST ethtool -L veth$DST rx $i tx $i
done
for i in ` seq 1 $(( CPUS - 1 )) ` ; do
cur_cpu = $(( CPUS - $i ))
ip netns exec $NS_SRC ethtool -L veth$SRC rx $cur_cpu tx $cur_cpu
ip netns exec $NS_DST ethtool -L veth$DST rx $cur_cpu tx $cur_cpu
done
done
}
__send_data( ) {
local end = $1
while true; do
printf -v cur '%(%s)T'
[ $cur -le $end ] || break
ip netns exec $NS_SRC ./udpgso_bench_tx -4 -s 1000 -M 300 -D $BM_NET_V4 $DST
done
}
do_stress( ) {
local end
printf -v end '%(%s)T'
end = $(( end + $STRESS ))
ip netns exec $NS_SRC ethtool -L veth$SRC rx 3 tx 3
ip netns exec $NS_DST ethtool -L veth$DST rx 3 tx 3
ip netns exec $NS_DST ./udpgso_bench_rx &
local rx_pid = $!
echo " Running stress test for $STRESS seconds... "
__change_channels $end &
local ch_pid = $!
__send_data $end &
local data_pid_1 = $!
__send_data $end &
local data_pid_2 = $!
__send_data $end &
local data_pid_3 = $!
__send_data $end &
local data_pid_4 = $!
wait $ch_pid $data_pid_1 $data_pid_2 $data_pid_3 $data_pid_4
kill -9 $rx_pid
echo "done"
# restore previous setting
ip netns exec $NS_SRC ethtool -L veth$SRC rx 2 tx 2
ip netns exec $NS_DST ethtool -L veth$DST rx 2 tx 1
}
usage( ) {
echo " Usage: $0 [-h] [-s <seconds>] "
echo -e "\t-h: show this help"
echo -e "\t-s: run optional stress tests for the given amount of seconds"
}
STRESS = 0
while getopts "hs:" option; do
case " $option " in
"h" )
usage $0
exit 0
; ;
"s" )
STRESS = $OPTARG
; ;
esac
done
2021-04-09 14:04:40 +03:00
if [ ! -f ../bpf/xdp_dummy.o ] ; then
echo "Missing xdp_dummy helper. Build bpf selftest first"
2021-06-16 17:03:21 +03:00
exit 1
2021-04-09 14:04:40 +03:00
fi
2021-07-20 11:41:52 +03:00
[ $CPUS -lt 2 ] && echo "Only one CPU available, some tests will be skipped"
[ $STRESS -gt 0 -a $CPUS -lt 3 ] && echo " stress test will be skipped, too"
2021-04-09 14:04:40 +03:00
create_ns
chk_gro_flag "default - gro flag" $SRC off
chk_gro_flag " - peer gro flag" $DST off
chk_tso_flag " - tso flag" $SRC on
chk_tso_flag " - peer tso flag" $DST on
chk_gro " - aggregation" 1
ip netns exec $NS_SRC ethtool -K veth$SRC tx-udp-segmentation off
chk_gro " - aggregation with TSO off" 10
cleanup
create_ns
ip netns exec $NS_DST ethtool -K veth$DST gro on
chk_gro_flag "with gro on - gro flag" $DST on
chk_gro_flag " - peer gro flag" $SRC off
chk_tso_flag " - tso flag" $SRC on
chk_tso_flag " - peer tso flag" $DST on
ip netns exec $NS_SRC ethtool -K veth$SRC tx-udp-segmentation off
ip netns exec $NS_DST ethtool -K veth$DST rx-udp-gro-forwarding on
chk_gro " - aggregation with TSO off" 1
cleanup
create_ns
2021-07-20 11:41:52 +03:00
chk_channels "default channels" $DST 1 1
2021-04-09 14:04:40 +03:00
ip -n $NS_DST link set dev veth$DST down
ip netns exec $NS_DST ethtool -K veth$DST gro on
chk_gro_flag "with gro enabled on link down - gro flag" $DST on
chk_gro_flag " - peer gro flag" $SRC off
chk_tso_flag " - tso flag" $SRC on
chk_tso_flag " - peer tso flag" $DST on
ip -n $NS_DST link set dev veth$DST up
ip netns exec $NS_SRC ethtool -K veth$SRC tx-udp-segmentation off
ip netns exec $NS_DST ethtool -K veth$DST rx-udp-gro-forwarding on
chk_gro " - aggregation with TSO off" 1
cleanup
create_ns
2021-07-20 11:41:52 +03:00
CUR_TX = 1
CUR_RX = 1
if [ $CPUS -gt 1 ] ; then
ip netns exec $NS_DST ethtool -L veth$DST tx 2
chk_channels "setting tx channels" $DST 1 2
CUR_TX = 2
fi
if [ $CPUS -gt 2 ] ; then
ip netns exec $NS_DST ethtool -L veth$DST rx 3 tx 3
chk_channels "setting both rx and tx channels" $DST 3 3
CUR_RX = 3
CUR_TX = 3
fi
ip netns exec $NS_DST ethtool -L veth$DST combined 2 2>/dev/null
chk_channels "bad setting: combined channels" $DST $CUR_RX $CUR_TX
ip netns exec $NS_DST ethtool -L veth$DST tx $(( CPUS + 1 )) 2>/dev/null
chk_channels "setting invalid channels nr" $DST $CUR_RX $CUR_TX
if [ $CPUS -gt 1 ] ; then
# this also tests queues nr reduction
ip netns exec $NS_DST ethtool -L veth$DST rx 1 tx 2 2>/dev/null
ip netns exec $NS_SRC ethtool -L veth$SRC rx 1 tx 2 2>/dev/null
printf "%-60s" "bad setting: XDP with RX nr less than TX"
ip -n $NS_DST link set dev veth$DST xdp object ../bpf/xdp_dummy.o \
2022-06-30 09:22:28 +03:00
section xdp 2>/dev/null && \
2021-07-20 11:41:52 +03:00
echo "fail - set operation successful ?!?" || echo " ok "
# the following tests will run with multiple channels active
ip netns exec $NS_SRC ethtool -L veth$SRC rx 2
ip netns exec $NS_DST ethtool -L veth$DST rx 2
ip -n $NS_DST link set dev veth$DST xdp object ../bpf/xdp_dummy.o \
2022-06-30 09:22:28 +03:00
section xdp 2>/dev/null
2021-07-20 11:41:52 +03:00
printf "%-60s" "bad setting: reducing RX nr below peer TX with XDP set"
ip netns exec $NS_DST ethtool -L veth$DST rx 1 2>/dev/null && \
echo "fail - set operation successful ?!?" || echo " ok "
CUR_RX = 2
CUR_TX = 2
fi
if [ $CPUS -gt 2 ] ; then
printf "%-60s" "bad setting: increasing peer TX nr above RX with XDP set"
ip netns exec $NS_SRC ethtool -L veth$SRC tx 3 2>/dev/null && \
echo "fail - set operation successful ?!?" || echo " ok "
chk_channels "setting invalid channels nr" $DST 2 2
fi
2022-06-30 09:22:28 +03:00
ip -n $NS_DST link set dev veth$DST xdp object ../bpf/xdp_dummy.o section xdp 2>/dev/null
2021-04-09 14:04:40 +03:00
chk_gro_flag "with xdp attached - gro flag" $DST on
chk_gro_flag " - peer gro flag" $SRC off
chk_tso_flag " - tso flag" $SRC off
chk_tso_flag " - peer tso flag" $DST on
ip netns exec $NS_DST ethtool -K veth$DST rx-udp-gro-forwarding on
chk_gro " - aggregation" 1
ip -n $NS_DST link set dev veth$DST down
ip -n $NS_SRC link set dev veth$SRC down
chk_gro_flag " - after dev off, flag" $DST on
chk_gro_flag " - peer flag" $SRC off
ip netns exec $NS_DST ethtool -K veth$DST gro on
ip -n $NS_DST link set dev veth$DST xdp off
chk_gro_flag " - after gro on xdp off, gro flag" $DST on
chk_gro_flag " - peer gro flag" $SRC off
chk_tso_flag " - tso flag" $SRC on
chk_tso_flag " - peer tso flag" $DST on
2021-07-20 11:41:52 +03:00
if [ $CPUS -gt 1 ] ; then
ip netns exec $NS_DST ethtool -L veth$DST tx 1
chk_channels "decreasing tx channels with device down" $DST 2 1
fi
2021-04-09 14:04:40 +03:00
ip -n $NS_DST link set dev veth$DST up
ip -n $NS_SRC link set dev veth$SRC up
chk_gro " - aggregation" 1
2021-07-20 11:41:52 +03:00
if [ $CPUS -gt 1 ] ; then
[ $STRESS -gt 0 -a $CPUS -gt 2 ] && do_stress
ip -n $NS_DST link set dev veth$DST down
ip -n $NS_SRC link set dev veth$SRC down
ip netns exec $NS_DST ethtool -L veth$DST tx 2
chk_channels "increasing tx channels with device down" $DST 2 2
ip -n $NS_DST link set dev veth$DST up
ip -n $NS_SRC link set dev veth$SRC up
fi
2021-04-09 14:04:40 +03:00
ip netns exec $NS_DST ethtool -K veth$DST gro off
ip netns exec $NS_SRC ethtool -K veth$SRC tx-udp-segmentation off
chk_gro "aggregation again with default and TSO off" 10
exit $ret