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"
7NUM_NETIFS=4
8source tc_common.sh
9source lib.sh
10
11tcflags="skip_hw"
12
13h1_create()
14{
15	simple_if_init $h1 192.0.2.1/24
16	tc qdisc add dev $h1 clsact
17}
18
19h1_destroy()
20{
21	tc qdisc del dev $h1 clsact
22	simple_if_fini $h1 192.0.2.1/24
23}
24
25h2_create()
26{
27	simple_if_init $h2 192.0.2.2/24
28	tc qdisc add dev $h2 clsact
29}
30
31h2_destroy()
32{
33	tc qdisc del dev $h2 clsact
34	simple_if_fini $h2 192.0.2.2/24
35}
36
37switch_create()
38{
39	simple_if_init $swp1 192.0.2.2/24
40	tc qdisc add dev $swp1 clsact
41
42	simple_if_init $swp2 192.0.2.1/24
43}
44
45switch_destroy()
46{
47	simple_if_fini $swp2 192.0.2.1/24
48
49	tc qdisc del dev $swp1 clsact
50	simple_if_fini $swp1 192.0.2.2/24
51}
52
53mirred_egress_test()
54{
55	local action=$1
56	local protocol=$2
57	local classifier=$3
58	local classifier_args=$4
59
60	RET=0
61
62	tc filter add dev $h2 ingress protocol ip pref 1 handle 101 flower \
63		$tcflags dst_ip 192.0.2.2 action drop
64
65	$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
66		-t ip -q
67
68	tc_check_packets "dev $h2 ingress" 101 1
69	check_fail $? "Matched without redirect rule inserted"
70
71	tc filter add dev $swp1 ingress protocol $protocol pref 1 handle 101 \
72		$classifier $tcflags $classifier_args \
73		action mirred egress $action dev $swp2
74
75	$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
76		-t ip -q
77
78	tc_check_packets "dev $h2 ingress" 101 1
79	check_err $? "Did not match incoming $action packet"
80
81	tc filter del dev $swp1 ingress protocol $protocol pref 1 handle 101 \
82		$classifier
83	tc filter del dev $h2 ingress protocol ip pref 1 handle 101 flower
84
85	log_test "mirred egress $classifier $action ($tcflags)"
86}
87
88gact_drop_and_ok_test()
89{
90	RET=0
91
92	tc filter add dev $swp1 ingress protocol ip pref 2 handle 102 flower \
93		$tcflags dst_ip 192.0.2.2 action drop
94
95	$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
96		-t ip -q
97
98	tc_check_packets "dev $swp1 ingress" 102 1
99	check_err $? "Packet was not dropped"
100
101	tc filter add dev $swp1 ingress protocol ip pref 1 handle 101 flower \
102		$tcflags dst_ip 192.0.2.2 action ok
103
104	$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
105		-t ip -q
106
107	tc_check_packets "dev $swp1 ingress" 101 1
108	check_err $? "Did not see passed packet"
109
110	tc_check_packets "dev $swp1 ingress" 102 2
111	check_fail $? "Packet was dropped and it should not reach here"
112
113	tc filter del dev $swp1 ingress protocol ip pref 2 handle 102 flower
114	tc filter del dev $swp1 ingress protocol ip pref 1 handle 101 flower
115
116	log_test "gact drop and ok ($tcflags)"
117}
118
119gact_trap_test()
120{
121	RET=0
122
123	if [[ "$tcflags" != "skip_sw" ]]; then
124		return 0;
125	fi
126
127	tc filter add dev $swp1 ingress protocol ip pref 1 handle 101 flower \
128		skip_hw dst_ip 192.0.2.2 action drop
129	tc filter add dev $swp1 ingress protocol ip pref 3 handle 103 flower \
130		$tcflags dst_ip 192.0.2.2 action mirred egress redirect \
131		dev $swp2
132
133	$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
134		-t ip -q
135
136	tc_check_packets "dev $swp1 ingress" 101 1
137	check_fail $? "Saw packet without trap rule inserted"
138
139	tc filter add dev $swp1 ingress protocol ip pref 2 handle 102 flower \
140		$tcflags dst_ip 192.0.2.2 action trap
141
142	$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
143		-t ip -q
144
145	tc_check_packets "dev $swp1 ingress" 102 1
146	check_err $? "Packet was not trapped"
147
148	tc_check_packets "dev $swp1 ingress" 101 1
149	check_err $? "Did not see trapped packet"
150
151	tc filter del dev $swp1 ingress protocol ip pref 3 handle 103 flower
152	tc filter del dev $swp1 ingress protocol ip pref 2 handle 102 flower
153	tc filter del dev $swp1 ingress protocol ip pref 1 handle 101 flower
154
155	log_test "trap ($tcflags)"
156}
157
158mirred_egress_to_ingress_test()
159{
160	RET=0
161
162	tc filter add dev $h1 protocol ip pref 100 handle 100 egress flower \
163		ip_proto icmp src_ip 192.0.2.1 dst_ip 192.0.2.2 type 8 action \
164			ct commit nat src addr 192.0.2.2 pipe \
165			ct clear pipe \
166			ct commit nat dst addr 192.0.2.1 pipe \
167			mirred ingress redirect dev $h1
168
169	tc filter add dev $swp1 protocol ip pref 11 handle 111 ingress flower \
170		ip_proto icmp src_ip 192.0.2.1 dst_ip 192.0.2.2 type 8 action drop
171	tc filter add dev $swp1 protocol ip pref 12 handle 112 ingress flower \
172		ip_proto icmp src_ip 192.0.2.1 dst_ip 192.0.2.2 type 0 action pass
173
174	$MZ $h1 -c 1 -p 64 -a $h1mac -b $h2mac -A 192.0.2.1 -B 192.0.2.2 \
175		-t icmp "ping,id=42,seq=10" -q
176
177	tc_check_packets "dev $h1 egress" 100 1
178	check_err $? "didn't mirror first packet"
179
180	tc_check_packets "dev $swp1 ingress" 111 1
181	check_fail $? "didn't redirect first packet"
182	tc_check_packets "dev $swp1 ingress" 112 1
183	check_err $? "didn't receive reply to first packet"
184
185	ping 192.0.2.2 -I$h1 -c1 -w1 -q 1>/dev/null 2>&1
186
187	tc_check_packets "dev $h1 egress" 100 2
188	check_err $? "didn't mirror second packet"
189	tc_check_packets "dev $swp1 ingress" 111 1
190	check_fail $? "didn't redirect second packet"
191	tc_check_packets "dev $swp1 ingress" 112 2
192	check_err $? "didn't receive reply to second packet"
193
194	tc filter del dev $h1 egress protocol ip pref 100 handle 100 flower
195	tc filter del dev $swp1 ingress protocol ip pref 11 handle 111 flower
196	tc filter del dev $swp1 ingress protocol ip pref 12 handle 112 flower
197
198	log_test "mirred_egress_to_ingress ($tcflags)"
199}
200
201setup_prepare()
202{
203	h1=${NETIFS[p1]}
204	swp1=${NETIFS[p2]}
205
206	swp2=${NETIFS[p3]}
207	h2=${NETIFS[p4]}
208
209	h1mac=$(mac_get $h1)
210	h2mac=$(mac_get $h2)
211
212	swp1origmac=$(mac_get $swp1)
213	swp2origmac=$(mac_get $swp2)
214	ip link set $swp1 address $h2mac
215	ip link set $swp2 address $h1mac
216
217	vrf_prepare
218
219	h1_create
220	h2_create
221	switch_create
222}
223
224cleanup()
225{
226	pre_cleanup
227
228	switch_destroy
229	h2_destroy
230	h1_destroy
231
232	vrf_cleanup
233
234	ip link set $swp2 address $swp2origmac
235	ip link set $swp1 address $swp1origmac
236}
237
238mirred_egress_redirect_test()
239{
240	mirred_egress_test "redirect" "ip" "flower" "dst_ip 192.0.2.2"
241}
242
243mirred_egress_mirror_test()
244{
245	mirred_egress_test "mirror" "ip" "flower" "dst_ip 192.0.2.2"
246}
247
248matchall_mirred_egress_mirror_test()
249{
250	mirred_egress_test "mirror" "all" "matchall" ""
251}
252
253trap cleanup EXIT
254
255setup_prepare
256setup_wait
257
258tests_run
259
260tc_offload_check
261if [[ $? -ne 0 ]]; then
262	log_info "Could not test offloaded functionality"
263else
264	tcflags="skip_sw"
265	tests_run
266fi
267
268exit $EXIT_STATUS
269