linux/tools/testing/selftests/net/forwarding/sch_ets_tests.sh
Petr Machata ddd3fd750f selftests: forwarding: sch_ets: Add test coverage for ETS Qdisc
This tests the newly-added ETS Qdisc. It runs two to three streams of
traffic, each with a different priority. ETS Qdisc is supposed to allocate
bandwidth according to the DRR algorithm and given weights. After running
the traffic for a while, counters are compared for each stream to check
that the expected ratio is in fact observed.

In order for the DRR process to kick in, a traffic bottleneck must exist in
the first place. In slow path, such bottleneck can be implemented by
wrapping the ETS Qdisc inside a TBF or other shaper. This might however
make the configuration unoffloadable. Instead, on HW datapath, the
bottleneck would be set up by lowering port speed and configuring shared
buffer suitably.

Therefore the test is structured as a core component that implements the
testing, with two wrapper scripts that implement the details of slow path
resp. fast path configuration.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-12-18 13:32:30 -08:00

228 lines
4.0 KiB
Bash

# SPDX-License-Identifier: GPL-2.0
# Global interface:
# $put -- port under test (e.g. $swp2)
# get_stats($band) -- A function to collect stats for band
# ets_start_traffic($band) -- Start traffic for this band
# ets_change_qdisc($op, $dev, $nstrict, $quanta...) -- Add or change qdisc
# WS describes the Qdisc configuration. It has one value per band (so the
# number of array elements indicates the number of bands). If the value is
# 0, it is a strict band, otherwise the it's a DRR band and the value is
# that band's quantum.
declare -a WS
qdisc_describe()
{
local nbands=${#WS[@]}
local nstrict=0
local i
for ((i = 0; i < nbands; i++)); do
if ((!${WS[$i]})); then
: $((nstrict++))
fi
done
echo -n "ets bands $nbands"
if ((nstrict)); then
echo -n " strict $nstrict"
fi
if ((nstrict < nbands)); then
echo -n " quanta"
for ((i = nstrict; i < nbands; i++)); do
echo -n " ${WS[$i]}"
done
fi
}
__strict_eval()
{
local desc=$1; shift
local d=$1; shift
local total=$1; shift
local above=$1; shift
RET=0
if ((! total)); then
check_err 1 "No traffic observed"
log_test "$desc"
return
fi
local ratio=$(echo "scale=2; 100 * $d / $total" | bc -l)
if ((above)); then
test $(echo "$ratio > 95.0" | bc -l) -eq 1
check_err $? "Not enough traffic"
log_test "$desc"
log_info "Expected ratio >95% Measured ratio $ratio"
else
test $(echo "$ratio < 5" | bc -l) -eq 1
check_err $? "Too much traffic"
log_test "$desc"
log_info "Expected ratio <5% Measured ratio $ratio"
fi
}
strict_eval()
{
__strict_eval "$@" 1
}
notraf_eval()
{
__strict_eval "$@" 0
}
__ets_dwrr_test()
{
local -a streams=("$@")
local low_stream=${streams[0]}
local seen_strict=0
local -a t0 t1 d
local stream
local total
local i
echo "Testing $(qdisc_describe), streams ${streams[@]}"
for stream in ${streams[@]}; do
ets_start_traffic $stream
done
sleep 10
t0=($(for stream in ${streams[@]}; do
get_stats $stream
done))
sleep 10
t1=($(for stream in ${streams[@]}; do
get_stats $stream
done))
d=($(for ((i = 0; i < ${#streams[@]}; i++)); do
echo $((${t1[$i]} - ${t0[$i]}))
done))
total=$(echo ${d[@]} | sed 's/ /+/g' | bc)
for ((i = 0; i < ${#streams[@]}; i++)); do
local stream=${streams[$i]}
if ((seen_strict)); then
notraf_eval "band $stream" ${d[$i]} $total
elif ((${WS[$stream]} == 0)); then
strict_eval "band $stream" ${d[$i]} $total
seen_strict=1
elif ((stream == low_stream)); then
# Low stream is used as DWRR evaluation reference.
continue
else
multipath_eval "bands $low_stream:$stream" \
${WS[$low_stream]} ${WS[$stream]} \
${d[0]} ${d[$i]}
fi
done
for stream in ${streams[@]}; do
stop_traffic
done
}
ets_dwrr_test_012()
{
__ets_dwrr_test 0 1 2
}
ets_dwrr_test_01()
{
__ets_dwrr_test 0 1
}
ets_dwrr_test_12()
{
__ets_dwrr_test 1 2
}
ets_qdisc_setup()
{
local dev=$1; shift
local nstrict=$1; shift
local -a quanta=("$@")
local ndwrr=${#quanta[@]}
local nbands=$((nstrict + ndwrr))
local nstreams=$(if ((nbands > 3)); then echo 3; else echo $nbands; fi)
local priomap=$(seq 0 $((nstreams - 1)))
local i
WS=($(
for ((i = 0; i < nstrict; i++)); do
echo 0
done
for ((i = 0; i < ndwrr; i++)); do
echo ${quanta[$i]}
done
))
ets_change_qdisc $dev $nstrict "$priomap" ${quanta[@]}
}
ets_set_dwrr_uniform()
{
ets_qdisc_setup $put 0 3300 3300 3300
}
ets_set_dwrr_varying()
{
ets_qdisc_setup $put 0 5000 3500 1500
}
ets_set_strict()
{
ets_qdisc_setup $put 3
}
ets_set_mixed()
{
ets_qdisc_setup $put 1 5000 2500 1500
}
ets_change_quantum()
{
tc class change dev $put classid 10:2 ets quantum 8000
WS[1]=8000
}
ets_set_dwrr_two_bands()
{
ets_qdisc_setup $put 0 5000 2500
}
ets_test_strict()
{
ets_set_strict
ets_dwrr_test_01
ets_dwrr_test_12
}
ets_test_mixed()
{
ets_set_mixed
ets_dwrr_test_01
ets_dwrr_test_12
}
ets_test_dwrr()
{
ets_set_dwrr_uniform
ets_dwrr_test_012
ets_set_dwrr_varying
ets_dwrr_test_012
ets_change_quantum
ets_dwrr_test_012
ets_set_dwrr_two_bands
ets_dwrr_test_01
}