1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# Test tc-police action.
5#
6# +---------------------------------+
7# | H1 (vrf)                        |
8# |    + $h1                        |
9# |    | 192.0.2.1/24               |
10# |    |                            |
11# |    |  default via 192.0.2.2     |
12# +----|----------------------------+
13#      |
14# +----|----------------------------------------------------------------------+
15# | SW |                                                                      |
16# |    + $rp1                                                                 |
17# |        192.0.2.2/24                                                       |
18# |                                                                           |
19# |        198.51.100.2/24                           203.0.113.2/24           |
20# |    + $rp2                                    + $rp3                       |
21# |    |                                         |                            |
22# +----|-----------------------------------------|----------------------------+
23#      |                                         |
24# +----|----------------------------+       +----|----------------------------+
25# |    |  default via 198.51.100.2  |       |    |  default via 203.0.113.2   |
26# |    |                            |       |    |                            |
27# |    | 198.51.100.1/24            |       |    | 203.0.113.1/24             |
28# |    + $h2                        |       |    + $h3                        |
29# | H2 (vrf)                        |       | H3 (vrf)                        |
30# +---------------------------------+       +---------------------------------+
31
32ALL_TESTS="
33	police_rx_test
34	police_tx_test
35	police_shared_test
36	police_rx_mirror_test
37	police_tx_mirror_test
38	police_pps_rx_test
39	police_pps_tx_test
40"
41NUM_NETIFS=6
42source tc_common.sh
43source lib.sh
44
45h1_create()
46{
47	simple_if_init $h1 192.0.2.1/24
48
49	ip -4 route add default vrf v$h1 nexthop via 192.0.2.2
50}
51
52h1_destroy()
53{
54	ip -4 route del default vrf v$h1 nexthop via 192.0.2.2
55
56	simple_if_fini $h1 192.0.2.1/24
57}
58
59h2_create()
60{
61	simple_if_init $h2 198.51.100.1/24
62
63	ip -4 route add default vrf v$h2 nexthop via 198.51.100.2
64
65	tc qdisc add dev $h2 clsact
66}
67
68h2_destroy()
69{
70	tc qdisc del dev $h2 clsact
71
72	ip -4 route del default vrf v$h2 nexthop via 198.51.100.2
73
74	simple_if_fini $h2 198.51.100.1/24
75}
76
77h3_create()
78{
79	simple_if_init $h3 203.0.113.1/24
80
81	ip -4 route add default vrf v$h3 nexthop via 203.0.113.2
82
83	tc qdisc add dev $h3 clsact
84}
85
86h3_destroy()
87{
88	tc qdisc del dev $h3 clsact
89
90	ip -4 route del default vrf v$h3 nexthop via 203.0.113.2
91
92	simple_if_fini $h3 203.0.113.1/24
93}
94
95router_create()
96{
97	ip link set dev $rp1 up
98	ip link set dev $rp2 up
99	ip link set dev $rp3 up
100
101	__addr_add_del $rp1 add 192.0.2.2/24
102	__addr_add_del $rp2 add 198.51.100.2/24
103	__addr_add_del $rp3 add 203.0.113.2/24
104
105	tc qdisc add dev $rp1 clsact
106	tc qdisc add dev $rp2 clsact
107}
108
109router_destroy()
110{
111	tc qdisc del dev $rp2 clsact
112	tc qdisc del dev $rp1 clsact
113
114	__addr_add_del $rp3 del 203.0.113.2/24
115	__addr_add_del $rp2 del 198.51.100.2/24
116	__addr_add_del $rp1 del 192.0.2.2/24
117
118	ip link set dev $rp3 down
119	ip link set dev $rp2 down
120	ip link set dev $rp1 down
121}
122
123police_common_test()
124{
125	local test_name=$1; shift
126
127	RET=0
128
129	# Rule to measure bandwidth on ingress of $h2
130	tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \
131		dst_ip 198.51.100.1 ip_proto udp dst_port 54321 \
132		action drop
133
134	mausezahn $h1 -a own -b $(mac_get $rp1) -A 192.0.2.1 -B 198.51.100.1 \
135		-t udp sp=12345,dp=54321 -p 1000 -c 0 -q &
136
137	local t0=$(tc_rule_stats_get $h2 1 ingress .bytes)
138	sleep 10
139	local t1=$(tc_rule_stats_get $h2 1 ingress .bytes)
140
141	local er=$((80 * 1000 * 1000))
142	local nr=$(rate $t0 $t1 10)
143	local nr_pct=$((100 * (nr - er) / er))
144	((-10 <= nr_pct && nr_pct <= 10))
145	check_err $? "Expected rate $(humanize $er), got $(humanize $nr), which is $nr_pct% off. Required accuracy is +-10%."
146
147	log_test "$test_name"
148
149	{ kill %% && wait %%; } 2>/dev/null
150	tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
151}
152
153police_rx_test()
154{
155	# Rule to police traffic destined to $h2 on ingress of $rp1
156	tc filter add dev $rp1 ingress protocol ip pref 1 handle 101 flower \
157		dst_ip 198.51.100.1 ip_proto udp dst_port 54321 \
158		action police rate 80mbit burst 16k conform-exceed drop/ok
159
160	police_common_test "police on rx"
161
162	tc filter del dev $rp1 ingress protocol ip pref 1 handle 101 flower
163}
164
165police_tx_test()
166{
167	# Rule to police traffic destined to $h2 on egress of $rp2
168	tc filter add dev $rp2 egress protocol ip pref 1 handle 101 flower \
169		dst_ip 198.51.100.1 ip_proto udp dst_port 54321 \
170		action police rate 80mbit burst 16k conform-exceed drop/ok
171
172	police_common_test "police on tx"
173
174	tc filter del dev $rp2 egress protocol ip pref 1 handle 101 flower
175}
176
177police_shared_common_test()
178{
179	local dport=$1; shift
180	local test_name=$1; shift
181
182	RET=0
183
184	mausezahn $h1 -a own -b $(mac_get $rp1) -A 192.0.2.1 -B 198.51.100.1 \
185		-t udp sp=12345,dp=$dport -p 1000 -c 0 -q &
186
187	local t0=$(tc_rule_stats_get $h2 1 ingress .bytes)
188	sleep 10
189	local t1=$(tc_rule_stats_get $h2 1 ingress .bytes)
190
191	local er=$((80 * 1000 * 1000))
192	local nr=$(rate $t0 $t1 10)
193	local nr_pct=$((100 * (nr - er) / er))
194	((-10 <= nr_pct && nr_pct <= 10))
195	check_err $? "Expected rate $(humanize $er), got $(humanize $nr), which is $nr_pct% off. Required accuracy is +-10%."
196
197	log_test "$test_name"
198
199	{ kill %% && wait %%; } 2>/dev/null
200}
201
202police_shared_test()
203{
204	# Rule to measure bandwidth on ingress of $h2
205	tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \
206		dst_ip 198.51.100.1 ip_proto udp src_port 12345 \
207		action drop
208
209	# Rule to police traffic destined to $h2 on ingress of $rp1
210	tc filter add dev $rp1 ingress protocol ip pref 1 handle 101 flower \
211		dst_ip 198.51.100.1 ip_proto udp dst_port 54321 \
212		action police rate 80mbit burst 16k conform-exceed drop/ok \
213		index 10
214
215	# Rule to police a different flow destined to $h2 on egress of $rp2
216	# using same policer
217	tc filter add dev $rp2 egress protocol ip pref 1 handle 101 flower \
218		dst_ip 198.51.100.1 ip_proto udp dst_port 22222 \
219		action police index 10
220
221	police_shared_common_test 54321 "police with shared policer - rx"
222
223	police_shared_common_test 22222 "police with shared policer - tx"
224
225	tc filter del dev $rp2 egress protocol ip pref 1 handle 101 flower
226	tc filter del dev $rp1 ingress protocol ip pref 1 handle 101 flower
227	tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
228}
229
230police_mirror_common_test()
231{
232	local pol_if=$1; shift
233	local dir=$1; shift
234	local test_name=$1; shift
235
236	RET=0
237
238	# Rule to measure bandwidth on ingress of $h2
239	tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \
240		dst_ip 198.51.100.1 ip_proto udp dst_port 54321 \
241		action drop
242
243	# Rule to measure bandwidth of mirrored traffic on ingress of $h3
244	tc filter add dev $h3 ingress protocol ip pref 1 handle 101 flower \
245		dst_ip 198.51.100.1 ip_proto udp dst_port 54321 \
246		action drop
247
248	# Rule to police traffic destined to $h2 and mirror to $h3
249	tc filter add dev $pol_if $dir protocol ip pref 1 handle 101 flower \
250		dst_ip 198.51.100.1 ip_proto udp dst_port 54321 \
251		action police rate 80mbit burst 16k conform-exceed drop/pipe \
252		action mirred egress mirror dev $rp3
253
254	mausezahn $h1 -a own -b $(mac_get $rp1) -A 192.0.2.1 -B 198.51.100.1 \
255		-t udp sp=12345,dp=54321 -p 1000 -c 0 -q &
256
257	local t0=$(tc_rule_stats_get $h2 1 ingress .bytes)
258	sleep 10
259	local t1=$(tc_rule_stats_get $h2 1 ingress .bytes)
260
261	local er=$((80 * 1000 * 1000))
262	local nr=$(rate $t0 $t1 10)
263	local nr_pct=$((100 * (nr - er) / er))
264	((-10 <= nr_pct && nr_pct <= 10))
265	check_err $? "Expected rate $(humanize $er), got $(humanize $nr), which is $nr_pct% off. Required accuracy is +-10%."
266
267	local t0=$(tc_rule_stats_get $h3 1 ingress .bytes)
268	sleep 10
269	local t1=$(tc_rule_stats_get $h3 1 ingress .bytes)
270
271	local er=$((80 * 1000 * 1000))
272	local nr=$(rate $t0 $t1 10)
273	local nr_pct=$((100 * (nr - er) / er))
274	((-10 <= nr_pct && nr_pct <= 10))
275	check_err $? "Expected rate $(humanize $er), got $(humanize $nr), which is $nr_pct% off. Required accuracy is +-10%."
276
277	log_test "$test_name"
278
279	{ kill %% && wait %%; } 2>/dev/null
280	tc filter del dev $pol_if $dir protocol ip pref 1 handle 101 flower
281	tc filter del dev $h3 ingress protocol ip pref 1 handle 101 flower
282	tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
283}
284
285police_rx_mirror_test()
286{
287	police_mirror_common_test $rp1 ingress "police rx and mirror"
288}
289
290police_tx_mirror_test()
291{
292	police_mirror_common_test $rp2 egress "police tx and mirror"
293}
294
295police_pps_common_test()
296{
297	local test_name=$1; shift
298
299	RET=0
300
301	# Rule to measure bandwidth on ingress of $h2
302	tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \
303		dst_ip 198.51.100.1 ip_proto udp dst_port 54321 \
304		action drop
305
306	mausezahn $h1 -a own -b $(mac_get $rp1) -A 192.0.2.1 -B 198.51.100.1 \
307		-t udp sp=12345,dp=54321 -p 1000 -c 0 -q &
308
309	local t0=$(tc_rule_stats_get $h2 1 ingress .packets)
310	sleep 10
311	local t1=$(tc_rule_stats_get $h2 1 ingress .packets)
312
313	local er=$((2000))
314	local nr=$(packets_rate $t0 $t1 10)
315	local nr_pct=$((100 * (nr - er) / er))
316	((-10 <= nr_pct && nr_pct <= 10))
317	check_err $? "Expected rate $(humanize $er), got $(humanize $nr), which is $nr_pct% off. Required accuracy is +-10%."
318
319	log_test "$test_name"
320
321	{ kill %% && wait %%; } 2>/dev/null
322	tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
323}
324
325police_pps_rx_test()
326{
327	# Rule to police traffic destined to $h2 on ingress of $rp1
328	tc filter add dev $rp1 ingress protocol ip pref 1 handle 101 flower \
329		dst_ip 198.51.100.1 ip_proto udp dst_port 54321 \
330		action police pkts_rate 2000 pkts_burst 400 conform-exceed drop/ok
331
332	police_pps_common_test "police pps on rx"
333
334	tc filter del dev $rp1 ingress protocol ip pref 1 handle 101 flower
335}
336
337police_pps_tx_test()
338{
339	# Rule to police traffic destined to $h2 on egress of $rp2
340	tc filter add dev $rp2 egress protocol ip pref 1 handle 101 flower \
341		dst_ip 198.51.100.1 ip_proto udp dst_port 54321 \
342		action police pkts_rate 2000 pkts_burst 400 conform-exceed drop/ok
343
344	police_pps_common_test "police pps on tx"
345
346	tc filter del dev $rp2 egress protocol ip pref 1 handle 101 flower
347}
348
349setup_prepare()
350{
351	h1=${NETIFS[p1]}
352	rp1=${NETIFS[p2]}
353
354	rp2=${NETIFS[p3]}
355	h2=${NETIFS[p4]}
356
357	rp3=${NETIFS[p5]}
358	h3=${NETIFS[p6]}
359
360	vrf_prepare
361	forwarding_enable
362
363	h1_create
364	h2_create
365	h3_create
366	router_create
367}
368
369cleanup()
370{
371	pre_cleanup
372
373	router_destroy
374	h3_destroy
375	h2_destroy
376	h1_destroy
377
378	forwarding_restore
379	vrf_cleanup
380}
381
382trap cleanup EXIT
383
384setup_prepare
385setup_wait
386
387tests_run
388
389exit $EXIT_STATUS
390