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