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