# SPDX-License-Identifier: GPL-2.0
# This is a template for ETS Qdisc test.
#
# This test sends from H1 several traffic streams with 802.1p-tagged packets.
# The tags are used at $swp1 to prioritize the traffic. Each stream is then
# queued at a different ETS band according to the assigned priority. After
# runnig for a while, counters at H2 are consulted to determine whether the
# traffic scheduling was according to the ETS configuration.
#
# This template is supposed to be embedded by a test driver, which implements
# statistics collection, any HW-specific stuff, and prominently configures the
# system to assure that there is overcommitment at $swp2. That is necessary so
# that the ETS traffic selection algorithm kicks in and has to schedule some
# traffic at the expense of other.
#
# A driver for veth-based testing is in sch_ets.sh, an example of a driver for
# an offloaded data path is in selftests/drivers/net/mlxsw/sch_ets.sh.
#
# +---------------------------------------------------------------------+
# | H1 |
# | + $h1.10 + $h1.11 + $h1.12 |
# | | 192.0.2.1/28 | 192.0.2.17/28 | 192.0.2.33/28 |
# | | egress-qos-map | egress-qos-map | egress-qos-map |
# | | 0:0 | 0:1 | 0:2 |
# | \____________________ | ____________________/ |
# | \|/ |
# | + $h1 |
# +---------------------------|-----------------------------------------+
# |
# +---------------------------|-----------------------------------------+
# | SW + $swp1 |
# | | >1Gbps |
# | ____________________/|\____________________ |
# | / | \ |
# | +--|----------------+ +--|----------------+ +--|----------------+ |
# | | + $swp1.10 | | + $swp1.11 | | + $swp1.12 | |
# | | ingress-qos-map| | ingress-qos-map| | ingress-qos-map| |
# | | 0:0 1:1 2:2 | | 0:0 1:1 2:2 | | 0:0 1:1 2:2 | |
# | | | | | | | |
# | | BR10 | | BR11 | | BR12 | |
# | | | | | | | |
# | | + $swp2.10 | | + $swp2.11 | | + $swp2.12 | |
# | +--|----------------+ +--|----------------+ +--|----------------+ |
# | \____________________ | ____________________/ |
# | \|/ |
# | + $swp2 |
# | | 1Gbps (ethtool or HTB qdisc) |
# | | qdisc ets quanta $W0 $W1 $W2 |
# | | priomap 0 1 2 |
# +---------------------------|-----------------------------------------+
# |
# +---------------------------|-----------------------------------------+
# | H2 + $h2 |
# | ____________________/|\____________________ |
# | / | \ |
# | + $h2.10 + $h2.11 + $h2.12 |
# | 192.0.2.2/28 192.0.2.18/28 192.0.2.34/28 |
# +---------------------------------------------------------------------+
NUM_NETIFS=4
CHECK_TC=yes
source $lib_dir/lib.sh
source $lib_dir/sch_ets_tests.sh
PARENT=root
QDISC_DEV=
sip()
{
echo 192.0.2.$((16 * $1 + 1))
}
dip()
{
echo 192.0.2.$((16 * $1 + 2))
}
# Callback from sch_ets_tests.sh
ets_start_traffic()
{
local dst_mac=$(mac_get $h2)
local i=$1; shift
start_traffic $h1.1$i $(sip $i) $(dip $i) $dst_mac
}
ETS_CHANGE_QDISC=
priomap_mode()
{
echo "Running in priomap mode"
ets_delete_qdisc
ETS_CHANGE_QDISC=ets_change_qdisc_priomap
}
classifier_mode()
{
echo "Running in classifier mode"
ets_delete_qdisc
ETS_CHANGE_QDISC=ets_change_qdisc_classifier
}
ets_change_qdisc_priomap()
{
local dev=$1; shift
local nstrict=$1; shift
local priomap=$1; shift
local quanta=("${@}")
local op=$(if [[ -n $QDISC_DEV ]]; then echo change; else echo add; fi)
tc qdisc $op dev $dev $PARENT handle 10: ets \
$(if ((nstrict)); then echo strict $nstrict; fi) \
$(if ((${#quanta[@]})); then echo quanta ${quanta[@]}; fi) \
priomap $priomap
QDISC_DEV=$dev
}
ets_change_qdisc_classifier()
{
local dev=$1; shift
local nstrict=$1; shift
local priomap=$1; shift
local quanta=("${@}")
local op=$(if [[ -n $QDISC_DEV ]]; then echo change; else echo add; fi)
tc qdisc $op dev $dev $PARENT handle 10: ets \
$(if ((nstrict)); then echo strict $nstrict; fi) \
$(if ((${#quanta[@]})); then echo quanta ${quanta[@]}; fi)
if [[ $op == add ]]; then
local prio=0
local band
for band in $priomap; do
tc filter add dev $dev parent 10: basic \
match "meta(priority eq $prio)" \
flowid 10:$((band + 1))
((prio++))
done
fi
QDISC_DEV=$dev
}
# Callback from sch_ets_tests.sh
ets_change_qdisc()
{
if [[ -z "$ETS_CHANGE_QDISC" ]]; then
exit 1
fi
$ETS_CHANGE_QDISC "$@"
}
ets_delete_qdisc()
{
if [[ -n $QDISC_DEV ]]; then
tc qdisc del dev $QDISC_DEV $PARENT
QDISC_DEV=
fi
}
h1_create()
{
local i;
simple_if_init $h1
mtu_set $h1 9900
for i in {0..2}; do
vlan_create $h1 1$i v$h1 $(sip $i)/28
ip link set dev $h1.1$i type vlan egress 0:$i
done
}
h1_destroy()
{
local i
for i in {0..2}; do
vlan_destroy $h1 1$i
done
mtu_restore $h1
simple_if_fini $h1
}
h2_create()
{
local i
simple_if_init $h2
mtu_set $h2 9900
for i in {0..2}; do
vlan_create $h2 1$i v$h2 $(dip $i)/28
done
}
h2_destroy()
{
local i
for i in {0..2}; do
vlan_destroy $h2 1$i
done
mtu_restore $h2
simple_if_fini $h2
}
ets_switch_create()
{
local i
ip link set dev $swp1 up
mtu_set $swp1 9900
ip link set dev $swp2 up
mtu_set $swp2 9900
for i in {0..2}; do
vlan_create $swp1 1$i
ip link set dev $swp1.1$i type vlan ingress 0:0 1:1 2:2
vlan_create $swp2 1$i
ip link add dev br1$i type bridge
ip link set dev $swp1.1$i master br1$i
ip link set dev $swp2.1$i master br1$i
ip link set dev br1$i up
ip link set dev $swp1.1$i up
ip link set dev $swp2.1$i up
done
}
ets_switch_destroy()
{
local i
ets_delete_qdisc
for i in {0..2}; do
ip link del dev br1$i
vlan_destroy $swp2 1$i
vlan_destroy $swp1 1$i
done
mtu_restore $swp2
ip link set dev $swp2 down
mtu_restore $swp1
ip link set dev $swp1 down
}
setup_prepare()
{
h1=${NETIFS[p1]}
swp1=${NETIFS[p2]}
swp2=${NETIFS[p3]}
h2=${NETIFS[p4]}
put=$swp2
hut=$h2
vrf_prepare
h1_create
h2_create
switch_create
}
cleanup()
{
pre_cleanup
switch_destroy
h2_destroy
h1_destroy
vrf_cleanup
}
ping_ipv4()
{
ping_test $h1.10 $(dip 0) " vlan 10"
ping_test $h1.11 $(dip 1) " vlan 11"
ping_test $h1.12 $(dip 2) " vlan 12"
}
ets_run()
{
trap cleanup EXIT
setup_prepare
setup_wait
tests_run
exit $EXIT_STATUS
}