1# SPDX-License-Identifier: GPL-2.0
2
3# This is a template for ETS Qdisc test.
4#
5# This test sends from H1 several traffic streams with 802.1p-tagged packets.
6# The tags are used at $swp1 to prioritize the traffic. Each stream is then
7# queued at a different ETS band according to the assigned priority. After
8# runnig for a while, counters at H2 are consulted to determine whether the
9# traffic scheduling was according to the ETS configuration.
10#
11# This template is supposed to be embedded by a test driver, which implements
12# statistics collection, any HW-specific stuff, and prominently configures the
13# system to assure that there is overcommitment at $swp2. That is necessary so
14# that the ETS traffic selection algorithm kicks in and has to schedule some
15# traffic at the expense of other.
16#
17# A driver for veth-based testing is in sch_ets.sh, an example of a driver for
18# an offloaded data path is in selftests/drivers/net/mlxsw/sch_ets.sh.
19#
20# +---------------------------------------------------------------------+
21# | H1                                                                  |
22# |     + $h1.10              + $h1.11              + $h1.12            |
23# |     | 192.0.2.1/28        | 192.0.2.17/28       | 192.0.2.33/28     |
24# |     | egress-qos-map      | egress-qos-map      | egress-qos-map    |
25# |     |  0:0                |  0:1                |  0:2              |
26# |     \____________________ | ____________________/                   |
27# |                          \|/                                        |
28# |                           + $h1                                     |
29# +---------------------------|-----------------------------------------+
30#                             |
31# +---------------------------|-----------------------------------------+
32# | SW                        + $swp1                                   |
33# |                           | >1Gbps                                  |
34# |      ____________________/|\____________________                    |
35# |     /                     |                     \                   |
36# |  +--|----------------+ +--|----------------+ +--|----------------+  |
37# |  |  + $swp1.10       | |  + $swp1.11       | |  + $swp1.12       |  |
38# |  |    ingress-qos-map| |    ingress-qos-map| |    ingress-qos-map|  |
39# |  |     0:0 1:1 2:2   | |     0:0 1:1 2:2   | |     0:0 1:1 2:2   |  |
40# |  |                   | |                   | |                   |  |
41# |  |    BR10           | |    BR11           | |    BR12           |  |
42# |  |                   | |                   | |                   |  |
43# |  |  + $swp2.10       | |  + $swp2.11       | |  + $swp2.12       |  |
44# |  +--|----------------+ +--|----------------+ +--|----------------+  |
45# |     \____________________ | ____________________/                   |
46# |                          \|/                                        |
47# |                           + $swp2                                   |
48# |                           | 1Gbps (ethtool or HTB qdisc)            |
49# |                           | qdisc ets quanta $W0 $W1 $W2            |
50# |                           |           priomap 0 1 2                 |
51# +---------------------------|-----------------------------------------+
52#                             |
53# +---------------------------|-----------------------------------------+
54# | H2                        + $h2                                     |
55# |      ____________________/|\____________________                    |
56# |     /                     |                     \                   |
57# |     + $h2.10              + $h2.11              + $h2.12            |
58# |       192.0.2.2/28          192.0.2.18/28         192.0.2.34/28     |
59# +---------------------------------------------------------------------+
60
61NUM_NETIFS=4
62CHECK_TC=yes
63source $lib_dir/lib.sh
64source $lib_dir/sch_ets_tests.sh
65
66PARENT=root
67QDISC_DEV=
68
69sip()
70{
71	echo 192.0.2.$((16 * $1 + 1))
72}
73
74dip()
75{
76	echo 192.0.2.$((16 * $1 + 2))
77}
78
79# Callback from sch_ets_tests.sh
80ets_start_traffic()
81{
82	local dst_mac=$(mac_get $h2)
83	local i=$1; shift
84
85	start_traffic $h1.1$i $(sip $i) $(dip $i) $dst_mac
86}
87
88ETS_CHANGE_QDISC=
89
90priomap_mode()
91{
92	echo "Running in priomap mode"
93	ets_delete_qdisc
94	ETS_CHANGE_QDISC=ets_change_qdisc_priomap
95}
96
97classifier_mode()
98{
99	echo "Running in classifier mode"
100	ets_delete_qdisc
101	ETS_CHANGE_QDISC=ets_change_qdisc_classifier
102}
103
104ets_change_qdisc_priomap()
105{
106	local dev=$1; shift
107	local nstrict=$1; shift
108	local priomap=$1; shift
109	local quanta=("${@}")
110
111	local op=$(if [[ -n $QDISC_DEV ]]; then echo change; else echo add; fi)
112
113	tc qdisc $op dev $dev $PARENT handle 10: ets			       \
114		$(if ((nstrict)); then echo strict $nstrict; fi)	       \
115		$(if ((${#quanta[@]})); then echo quanta ${quanta[@]}; fi)     \
116		priomap $priomap
117	QDISC_DEV=$dev
118}
119
120ets_change_qdisc_classifier()
121{
122	local dev=$1; shift
123	local nstrict=$1; shift
124	local priomap=$1; shift
125	local quanta=("${@}")
126
127	local op=$(if [[ -n $QDISC_DEV ]]; then echo change; else echo add; fi)
128
129	tc qdisc $op dev $dev $PARENT handle 10: ets			       \
130		$(if ((nstrict)); then echo strict $nstrict; fi)	       \
131		$(if ((${#quanta[@]})); then echo quanta ${quanta[@]}; fi)
132
133	if [[ $op == add ]]; then
134		local prio=0
135		local band
136
137		for band in $priomap; do
138			tc filter add dev $dev parent 10: basic \
139				match "meta(priority eq $prio)" \
140				flowid 10:$((band + 1))
141			((prio++))
142		done
143	fi
144	QDISC_DEV=$dev
145}
146
147# Callback from sch_ets_tests.sh
148ets_change_qdisc()
149{
150	if [[ -z "$ETS_CHANGE_QDISC" ]]; then
151		exit 1
152	fi
153	$ETS_CHANGE_QDISC "$@"
154}
155
156ets_delete_qdisc()
157{
158	if [[ -n $QDISC_DEV ]]; then
159		tc qdisc del dev $QDISC_DEV $PARENT
160		QDISC_DEV=
161	fi
162}
163
164h1_create()
165{
166	local i;
167
168	simple_if_init $h1
169	mtu_set $h1 9900
170	for i in {0..2}; do
171		vlan_create $h1 1$i v$h1 $(sip $i)/28
172		ip link set dev $h1.1$i type vlan egress 0:$i
173	done
174}
175
176h1_destroy()
177{
178	local i
179
180	for i in {0..2}; do
181		vlan_destroy $h1 1$i
182	done
183	mtu_restore $h1
184	simple_if_fini $h1
185}
186
187h2_create()
188{
189	local i
190
191	simple_if_init $h2
192	mtu_set $h2 9900
193	for i in {0..2}; do
194		vlan_create $h2 1$i v$h2 $(dip $i)/28
195	done
196}
197
198h2_destroy()
199{
200	local i
201
202	for i in {0..2}; do
203		vlan_destroy $h2 1$i
204	done
205	mtu_restore $h2
206	simple_if_fini $h2
207}
208
209ets_switch_create()
210{
211	local i
212
213	ip link set dev $swp1 up
214	mtu_set $swp1 9900
215
216	ip link set dev $swp2 up
217	mtu_set $swp2 9900
218
219	for i in {0..2}; do
220		vlan_create $swp1 1$i
221		ip link set dev $swp1.1$i type vlan ingress 0:0 1:1 2:2
222
223		vlan_create $swp2 1$i
224
225		ip link add dev br1$i type bridge
226		ip link set dev $swp1.1$i master br1$i
227		ip link set dev $swp2.1$i master br1$i
228
229		ip link set dev br1$i up
230		ip link set dev $swp1.1$i up
231		ip link set dev $swp2.1$i up
232	done
233}
234
235ets_switch_destroy()
236{
237	local i
238
239	ets_delete_qdisc
240
241	for i in {0..2}; do
242		ip link del dev br1$i
243		vlan_destroy $swp2 1$i
244		vlan_destroy $swp1 1$i
245	done
246
247	mtu_restore $swp2
248	ip link set dev $swp2 down
249
250	mtu_restore $swp1
251	ip link set dev $swp1 down
252}
253
254setup_prepare()
255{
256	h1=${NETIFS[p1]}
257	swp1=${NETIFS[p2]}
258
259	swp2=${NETIFS[p3]}
260	h2=${NETIFS[p4]}
261
262	put=$swp2
263	hut=$h2
264
265	vrf_prepare
266
267	h1_create
268	h2_create
269	switch_create
270}
271
272cleanup()
273{
274	pre_cleanup
275
276	switch_destroy
277	h2_destroy
278	h1_destroy
279
280	vrf_cleanup
281}
282
283ping_ipv4()
284{
285	ping_test $h1.10 $(dip 0) " vlan 10"
286	ping_test $h1.11 $(dip 1) " vlan 11"
287	ping_test $h1.12 $(dip 2) " vlan 12"
288}
289
290ets_run()
291{
292	trap cleanup EXIT
293
294	setup_prepare
295	setup_wait
296
297	tests_run
298
299	exit $EXIT_STATUS
300}
301