xref: /linux/tools/testing/selftests/net/forwarding/tc_actions.sh (revision f8fdda9e4f988c210b1e4519a28ddbf7d29b0038)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4ALL_TESTS="gact_drop_and_ok_test mirred_egress_redirect_test \
5	mirred_egress_mirror_test matchall_mirred_egress_mirror_test \
6	gact_trap_test mirred_egress_to_ingress_test \
7	mirred_egress_to_ingress_tcp_test \
8	ingress_2nd_vlan_push egress_2nd_vlan_push"
9NUM_NETIFS=4
10source tc_common.sh
11source lib.sh
12
13require_command ncat
14
15tcflags="skip_hw"
16
17h1_create()
18{
19	simple_if_init $h1 192.0.2.1/24
20	tc qdisc add dev $h1 clsact
21}
22
23h1_destroy()
24{
25	tc qdisc del dev $h1 clsact
26	simple_if_fini $h1 192.0.2.1/24
27}
28
29h2_create()
30{
31	simple_if_init $h2 192.0.2.2/24
32	tc qdisc add dev $h2 clsact
33}
34
35h2_destroy()
36{
37	tc qdisc del dev $h2 clsact
38	simple_if_fini $h2 192.0.2.2/24
39}
40
41switch_create()
42{
43	simple_if_init $swp1 192.0.2.2/24
44	tc qdisc add dev $swp1 clsact
45
46	simple_if_init $swp2 192.0.2.1/24
47}
48
49switch_destroy()
50{
51	simple_if_fini $swp2 192.0.2.1/24
52
53	tc qdisc del dev $swp1 clsact
54	simple_if_fini $swp1 192.0.2.2/24
55}
56
57mirred_egress_test()
58{
59	local action=$1
60	local protocol=$2
61	local classifier=$3
62	local classifier_args=$4
63
64	RET=0
65
66	tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \
67		dst_ip 192.0.2.2 action drop
68
69	$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
70		-t ip -q
71
72	tc_check_packets "dev $h2 ingress" 101 1
73	check_fail $? "Matched without redirect rule inserted"
74
75	tc filter add dev $swp1 ingress protocol $protocol pref 1 handle 101 \
76		$classifier $tcflags $classifier_args \
77		action mirred egress $action dev $swp2
78
79	$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
80		-t ip -q
81
82	tc_check_packets "dev $h2 ingress" 101 1
83	check_err $? "Did not match incoming $action packet"
84
85	tc filter del dev $swp1 ingress protocol $protocol pref 1 handle 101 \
86		$classifier
87	tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
88
89	log_test "mirred egress $classifier $action ($tcflags)"
90}
91
92gact_drop_and_ok_test()
93{
94	RET=0
95
96	tc filter add dev $swp1 ingress protocol ip pref 2 handle 102 flower \
97		$tcflags dst_ip 192.0.2.2 action drop
98
99	$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
100		-t ip -q
101
102	tc_check_packets "dev $swp1 ingress" 102 1
103	check_err $? "Packet was not dropped"
104
105	tc filter add dev $swp1 ingress protocol ip pref 1 handle 101 flower \
106		$tcflags dst_ip 192.0.2.2 action ok
107
108	$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
109		-t ip -q
110
111	tc_check_packets "dev $swp1 ingress" 101 1
112	check_err $? "Did not see passed packet"
113
114	tc_check_packets "dev $swp1 ingress" 102 2
115	check_fail $? "Packet was dropped and it should not reach here"
116
117	tc filter del dev $swp1 ingress protocol ip pref 2 handle 102 flower
118	tc filter del dev $swp1 ingress protocol ip pref 1 handle 101 flower
119
120	log_test "gact drop and ok ($tcflags)"
121}
122
123gact_trap_test()
124{
125	RET=0
126
127	if [[ "$tcflags" != "skip_sw" ]]; then
128		return 0;
129	fi
130
131	tc filter add dev $swp1 ingress protocol ip pref 1 handle 101 flower \
132		skip_hw dst_ip 192.0.2.2 action drop
133	tc filter add dev $swp1 ingress protocol ip pref 3 handle 103 flower \
134		$tcflags dst_ip 192.0.2.2 action mirred egress redirect \
135		dev $swp2
136
137	$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
138		-t ip -q
139
140	tc_check_packets "dev $swp1 ingress" 101 1
141	check_fail $? "Saw packet without trap rule inserted"
142
143	tc filter add dev $swp1 ingress protocol ip pref 2 handle 102 flower \
144		$tcflags dst_ip 192.0.2.2 action trap
145
146	$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
147		-t ip -q
148
149	tc_check_packets "dev $swp1 ingress" 102 1
150	check_err $? "Packet was not trapped"
151
152	tc_check_packets "dev $swp1 ingress" 101 1
153	check_err $? "Did not see trapped packet"
154
155	tc filter del dev $swp1 ingress protocol ip pref 3 handle 103 flower
156	tc filter del dev $swp1 ingress protocol ip pref 2 handle 102 flower
157	tc filter del dev $swp1 ingress protocol ip pref 1 handle 101 flower
158
159	log_test "trap ($tcflags)"
160}
161
162mirred_egress_to_ingress_test()
163{
164	RET=0
165
166	tc filter add dev $h1 protocol ip pref 100 handle 100 egress flower \
167		ip_proto icmp src_ip 192.0.2.1 dst_ip 192.0.2.2 type 8 action \
168			ct commit nat src addr 192.0.2.2 pipe \
169			ct clear pipe \
170			ct commit nat dst addr 192.0.2.1 pipe \
171			mirred ingress redirect dev $h1
172
173	tc filter add dev $swp1 protocol ip pref 11 handle 111 ingress flower \
174		ip_proto icmp src_ip 192.0.2.1 dst_ip 192.0.2.2 type 8 action drop
175	tc filter add dev $swp1 protocol ip pref 12 handle 112 ingress flower \
176		ip_proto icmp src_ip 192.0.2.1 dst_ip 192.0.2.2 type 0 action pass
177
178	$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
179		-t icmp "ping,id=42,seq=10" -q
180
181	tc_check_packets "dev $h1 egress" 100 1
182	check_err $? "didn't mirror first packet"
183
184	tc_check_packets "dev $swp1 ingress" 111 1
185	check_fail $? "didn't redirect first packet"
186	tc_check_packets "dev $swp1 ingress" 112 1
187	check_err $? "didn't receive reply to first packet"
188
189	ping 192.0.2.2 -I$h1 -c1 -w1 -q 1>/dev/null 2>&1
190
191	tc_check_packets "dev $h1 egress" 100 2
192	check_err $? "didn't mirror second packet"
193	tc_check_packets "dev $swp1 ingress" 111 1
194	check_fail $? "didn't redirect second packet"
195	tc_check_packets "dev $swp1 ingress" 112 2
196	check_err $? "didn't receive reply to second packet"
197
198	tc filter del dev $h1 egress protocol ip pref 100 handle 100 flower
199	tc filter del dev $swp1 ingress protocol ip pref 11 handle 111 flower
200	tc filter del dev $swp1 ingress protocol ip pref 12 handle 112 flower
201
202	log_test "mirred_egress_to_ingress ($tcflags)"
203}
204
205mirred_egress_to_ingress_tcp_test()
206{
207	mirred_e2i_tf1=$(mktemp) mirred_e2i_tf2=$(mktemp)
208
209	RET=0
210	dd conv=sparse status=none if=/dev/zero bs=1M count=2 of=$mirred_e2i_tf1
211	tc filter add dev $h1 protocol ip pref 100 handle 100 egress flower \
212		$tcflags ip_proto tcp src_ip 192.0.2.1 dst_ip 192.0.2.2 \
213			action ct commit nat src addr 192.0.2.2 pipe \
214			action ct clear pipe \
215			action ct commit nat dst addr 192.0.2.1 pipe \
216			action ct clear pipe \
217			action skbedit ptype host pipe \
218			action mirred ingress redirect dev $h1
219	tc filter add dev $h1 protocol ip pref 101 handle 101 egress flower \
220		$tcflags ip_proto icmp \
221			action mirred ingress redirect dev $h1
222	tc filter add dev $h1 protocol ip pref 102 handle 102 ingress flower \
223		ip_proto icmp \
224			action drop
225
226	ip vrf exec v$h1 ncat --recv-only -w10 -l -p 12345 -o $mirred_e2i_tf2 &
227	local rpid=$!
228	ip vrf exec v$h1 ncat -w1 --send-only 192.0.2.2 12345 <$mirred_e2i_tf1
229	wait -n $rpid
230	cmp -s $mirred_e2i_tf1 $mirred_e2i_tf2
231	check_err $? "server output check failed"
232
233	$MZ $h1 -c 10 -p 64 -a $h1mac -b $h1mac -A 192.0.2.1 -B 192.0.2.1 \
234		-t icmp "ping,id=42,seq=5" -q
235	tc_check_packets "dev $h1 egress" 101 10
236	check_err $? "didn't mirred redirect ICMP"
237	tc_check_packets "dev $h1 ingress" 102 10
238	check_err $? "didn't drop mirred ICMP"
239
240	tc filter del dev $h1 egress protocol ip pref 100 handle 100 flower
241	tc filter del dev $h1 egress protocol ip pref 101 handle 101 flower
242	tc filter del dev $h1 ingress protocol ip pref 102 handle 102 flower
243
244	rm -f $mirred_e2i_tf1 $mirred_e2i_tf2
245	log_test "mirred_egress_to_ingress_tcp ($tcflags)"
246}
247
248ingress_2nd_vlan_push()
249{
250	tc filter add dev $swp1 ingress pref 20 chain 0 handle 20 flower \
251		$tcflags num_of_vlans 1 \
252		action vlan push id 100 protocol 0x8100 action goto chain 5
253	tc filter add dev $swp1 ingress pref 30 chain 5 handle 30 flower \
254		$tcflags num_of_vlans 2 \
255		cvlan_ethtype 0x800 action pass
256
257	$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
258		-t ip -Q 10 -q
259
260	tc_check_packets "dev $swp1 ingress" 30 1
261	check_err $? "No double-vlan packets received"
262
263	tc filter del dev $swp1 ingress pref 20 chain 0 handle 20 flower
264	tc filter del dev $swp1 ingress pref 30 chain 5 handle 30 flower
265
266	log_test "ingress_2nd_vlan_push ($tcflags)"
267}
268
269egress_2nd_vlan_push()
270{
271	tc filter add dev $h1 egress pref 20 chain 0 handle 20 flower \
272		$tcflags num_of_vlans 0 \
273		action vlan push id 10 protocol 0x8100 \
274		pipe action vlan push id 100 protocol 0x8100 action goto chain 5
275	tc filter add dev $h1 egress pref 30 chain 5 handle 30 flower \
276		$tcflags num_of_vlans 2 \
277		cvlan_ethtype 0x800 action pass
278
279	$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
280		-t ip -q
281
282	tc_check_packets "dev $h1 egress" 30 1
283	check_err $? "No double-vlan packets received"
284
285	tc filter del dev $h1 egress pref 20 chain 0 handle 20 flower
286	tc filter del dev $h1 egress pref 30 chain 5 handle 30 flower
287
288	log_test "egress_2nd_vlan_push ($tcflags)"
289}
290
291setup_prepare()
292{
293	h1=${NETIFS[p1]}
294	swp1=${NETIFS[p2]}
295
296	swp2=${NETIFS[p3]}
297	h2=${NETIFS[p4]}
298
299	h1mac=$(mac_get $h1)
300	h2mac=$(mac_get $h2)
301
302	swp1origmac=$(mac_get $swp1)
303	swp2origmac=$(mac_get $swp2)
304	ip link set $swp1 address $h2mac
305	ip link set $swp2 address $h1mac
306
307	vrf_prepare
308
309	h1_create
310	h2_create
311	switch_create
312}
313
314cleanup()
315{
316	local tf
317
318	pre_cleanup
319
320	switch_destroy
321	h2_destroy
322	h1_destroy
323
324	vrf_cleanup
325
326	ip link set $swp2 address $swp2origmac
327	ip link set $swp1 address $swp1origmac
328
329	for tf in $mirred_e2i_tf1 $mirred_e2i_tf2; do rm -f $tf; done
330}
331
332mirred_egress_redirect_test()
333{
334	mirred_egress_test "redirect" "ip" "flower" "dst_ip 192.0.2.2"
335}
336
337mirred_egress_mirror_test()
338{
339	mirred_egress_test "mirror" "ip" "flower" "dst_ip 192.0.2.2"
340}
341
342matchall_mirred_egress_mirror_test()
343{
344	mirred_egress_test "mirror" "all" "matchall" ""
345}
346
347trap cleanup EXIT
348
349setup_prepare
350setup_wait
351
352tests_run
353
354tc_offload_check
355if [[ $? -ne 0 ]]; then
356	log_info "Could not test offloaded functionality"
357else
358	tcflags="skip_sw"
359	tests_run
360fi
361
362exit $EXIT_STATUS
363