1# SPDX-License-Identifier: GPL-2.0
2
3# Global interface:
4#  $put -- port under test (e.g. $swp2)
5#  collect_stats($streams...) -- A function to get stats for individual streams
6#  ets_start_traffic($band) -- Start traffic for this band
7#  ets_change_qdisc($op, $dev, $nstrict, $quanta...) -- Add or change qdisc
8
9# WS describes the Qdisc configuration. It has one value per band (so the
10# number of array elements indicates the number of bands). If the value is
11# 0, it is a strict band, otherwise the it's a DRR band and the value is
12# that band's quantum.
13declare -a WS
14
15qdisc_describe()
16{
17	local nbands=${#WS[@]}
18	local nstrict=0
19	local i
20
21	for ((i = 0; i < nbands; i++)); do
22		if ((!${WS[$i]})); then
23			: $((nstrict++))
24		fi
25	done
26
27	echo -n "ets bands $nbands"
28	if ((nstrict)); then
29		echo -n " strict $nstrict"
30	fi
31	if ((nstrict < nbands)); then
32		echo -n " quanta"
33		for ((i = nstrict; i < nbands; i++)); do
34			echo -n " ${WS[$i]}"
35		done
36	fi
37}
38
39__strict_eval()
40{
41	local desc=$1; shift
42	local d=$1; shift
43	local total=$1; shift
44	local above=$1; shift
45
46	RET=0
47
48	if ((! total)); then
49		check_err 1 "No traffic observed"
50		log_test "$desc"
51		return
52	fi
53
54	local ratio=$(echo "scale=2; 100 * $d / $total" | bc -l)
55	if ((above)); then
56		test $(echo "$ratio > 95.0" | bc -l) -eq 1
57		check_err $? "Not enough traffic"
58		log_test "$desc"
59		log_info "Expected ratio >95% Measured ratio $ratio"
60	else
61		test $(echo "$ratio < 5" | bc -l) -eq 1
62		check_err $? "Too much traffic"
63		log_test "$desc"
64		log_info "Expected ratio <5% Measured ratio $ratio"
65	fi
66}
67
68strict_eval()
69{
70	__strict_eval "$@" 1
71}
72
73notraf_eval()
74{
75	__strict_eval "$@" 0
76}
77
78__ets_dwrr_test()
79{
80	local -a streams=("$@")
81
82	local low_stream=${streams[0]}
83	local seen_strict=0
84	local -a t0 t1 d
85	local stream
86	local total
87	local i
88
89	echo "Testing $(qdisc_describe), streams ${streams[@]}"
90
91	for stream in ${streams[@]}; do
92		ets_start_traffic $stream
93	done
94
95	sleep 10
96
97	t0=($(collect_stats "${streams[@]}"))
98
99	sleep 10
100
101	t1=($(collect_stats "${streams[@]}"))
102	d=($(for ((i = 0; i < ${#streams[@]}; i++)); do
103		 echo $((${t1[$i]} - ${t0[$i]}))
104	     done))
105	total=$(echo ${d[@]} | sed 's/ /+/g' | bc)
106
107	for ((i = 0; i < ${#streams[@]}; i++)); do
108		local stream=${streams[$i]}
109		if ((seen_strict)); then
110			notraf_eval "band $stream" ${d[$i]} $total
111		elif ((${WS[$stream]} == 0)); then
112			strict_eval "band $stream" ${d[$i]} $total
113			seen_strict=1
114		elif ((stream == low_stream)); then
115			# Low stream is used as DWRR evaluation reference.
116			continue
117		else
118			multipath_eval "bands $low_stream:$stream" \
119				       ${WS[$low_stream]} ${WS[$stream]} \
120				       ${d[0]} ${d[$i]}
121		fi
122	done
123
124	for stream in ${streams[@]}; do
125		stop_traffic
126	done
127}
128
129ets_dwrr_test_012()
130{
131	__ets_dwrr_test 0 1 2
132}
133
134ets_dwrr_test_01()
135{
136	__ets_dwrr_test 0 1
137}
138
139ets_dwrr_test_12()
140{
141	__ets_dwrr_test 1 2
142}
143
144ets_qdisc_setup()
145{
146	local dev=$1; shift
147	local nstrict=$1; shift
148	local -a quanta=("$@")
149
150	local ndwrr=${#quanta[@]}
151	local nbands=$((nstrict + ndwrr))
152	local nstreams=$(if ((nbands > 3)); then echo 3; else echo $nbands; fi)
153	local priomap=$(seq 0 $((nstreams - 1)))
154	local i
155
156	WS=($(
157		for ((i = 0; i < nstrict; i++)); do
158			echo 0
159		done
160		for ((i = 0; i < ndwrr; i++)); do
161			echo ${quanta[$i]}
162		done
163	))
164
165	ets_change_qdisc $dev $nstrict "$priomap" ${quanta[@]}
166}
167
168ets_set_dwrr_uniform()
169{
170	ets_qdisc_setup $put 0 3300 3300 3300
171}
172
173ets_set_dwrr_varying()
174{
175	ets_qdisc_setup $put 0 5000 3500 1500
176}
177
178ets_set_strict()
179{
180	ets_qdisc_setup $put 3
181}
182
183ets_set_mixed()
184{
185	ets_qdisc_setup $put 1 5000 2500 1500
186}
187
188ets_change_quantum()
189{
190	tc class change dev $put classid 10:2 ets quantum 8000
191	WS[1]=8000
192}
193
194ets_set_dwrr_two_bands()
195{
196	ets_qdisc_setup $put 0 5000 2500
197}
198
199ets_test_strict()
200{
201	ets_set_strict
202	ets_dwrr_test_01
203	ets_dwrr_test_12
204}
205
206ets_test_mixed()
207{
208	ets_set_mixed
209	ets_dwrr_test_01
210	ets_dwrr_test_12
211}
212
213ets_test_dwrr()
214{
215	ets_set_dwrr_uniform
216	ets_dwrr_test_012
217	ets_set_dwrr_varying
218	ets_dwrr_test_012
219	ets_change_quantum
220	ets_dwrr_test_012
221	ets_set_dwrr_two_bands
222	ets_dwrr_test_01
223}
224