1# SPDX-License-Identifier: GPL-2.0
2
3# Global interface:
4#  $put -- port under test (e.g. $swp2)
5#  get_stats($band) -- A function to collect stats for band
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=($(for stream in ${streams[@]}; do
98		  get_stats $stream
99	      done))
100
101	sleep 10
102
103	t1=($(for stream in ${streams[@]}; do
104		  get_stats $stream
105	      done))
106	d=($(for ((i = 0; i < ${#streams[@]}; i++)); do
107		 echo $((${t1[$i]} - ${t0[$i]}))
108	     done))
109	total=$(echo ${d[@]} | sed 's/ /+/g' | bc)
110
111	for ((i = 0; i < ${#streams[@]}; i++)); do
112		local stream=${streams[$i]}
113		if ((seen_strict)); then
114			notraf_eval "band $stream" ${d[$i]} $total
115		elif ((${WS[$stream]} == 0)); then
116			strict_eval "band $stream" ${d[$i]} $total
117			seen_strict=1
118		elif ((stream == low_stream)); then
119			# Low stream is used as DWRR evaluation reference.
120			continue
121		else
122			multipath_eval "bands $low_stream:$stream" \
123				       ${WS[$low_stream]} ${WS[$stream]} \
124				       ${d[0]} ${d[$i]}
125		fi
126	done
127
128	for stream in ${streams[@]}; do
129		stop_traffic
130	done
131}
132
133ets_dwrr_test_012()
134{
135	__ets_dwrr_test 0 1 2
136}
137
138ets_dwrr_test_01()
139{
140	__ets_dwrr_test 0 1
141}
142
143ets_dwrr_test_12()
144{
145	__ets_dwrr_test 1 2
146}
147
148ets_qdisc_setup()
149{
150	local dev=$1; shift
151	local nstrict=$1; shift
152	local -a quanta=("$@")
153
154	local ndwrr=${#quanta[@]}
155	local nbands=$((nstrict + ndwrr))
156	local nstreams=$(if ((nbands > 3)); then echo 3; else echo $nbands; fi)
157	local priomap=$(seq 0 $((nstreams - 1)))
158	local i
159
160	WS=($(
161		for ((i = 0; i < nstrict; i++)); do
162			echo 0
163		done
164		for ((i = 0; i < ndwrr; i++)); do
165			echo ${quanta[$i]}
166		done
167	))
168
169	ets_change_qdisc $dev $nstrict "$priomap" ${quanta[@]}
170}
171
172ets_set_dwrr_uniform()
173{
174	ets_qdisc_setup $put 0 3300 3300 3300
175}
176
177ets_set_dwrr_varying()
178{
179	ets_qdisc_setup $put 0 5000 3500 1500
180}
181
182ets_set_strict()
183{
184	ets_qdisc_setup $put 3
185}
186
187ets_set_mixed()
188{
189	ets_qdisc_setup $put 1 5000 2500 1500
190}
191
192ets_change_quantum()
193{
194	tc class change dev $put classid 10:2 ets quantum 8000
195	WS[1]=8000
196}
197
198ets_set_dwrr_two_bands()
199{
200	ets_qdisc_setup $put 0 5000 2500
201}
202
203ets_test_strict()
204{
205	ets_set_strict
206	ets_dwrr_test_01
207	ets_dwrr_test_12
208}
209
210ets_test_mixed()
211{
212	ets_set_mixed
213	ets_dwrr_test_01
214	ets_dwrr_test_12
215}
216
217ets_test_dwrr()
218{
219	ets_set_dwrr_uniform
220	ets_dwrr_test_012
221	ets_set_dwrr_varying
222	ets_dwrr_test_012
223	ets_change_quantum
224	ets_dwrr_test_012
225	ets_set_dwrr_two_bands
226	ets_dwrr_test_01
227}
228