1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# Test devlink-trap tunnel drops and exceptions functionality over mlxsw.
5# Check all traps to make sure they are triggered under the right
6# conditions.
7
8# +------------------------+
9# | H1 (vrf)               |
10# |    + $h1               |
11# |    | 2001:db8:1::1/64  |
12# +----|-------------------+
13#      |
14# +----|----------------------------------------------------------------------+
15# | SW |                                                                      |
16# | +--|--------------------------------------------------------------------+ |
17# | |  + $swp1                   BR1 (802.1d)                               | |
18# | |                                                                       | |
19# | |  + vx1 (vxlan)                                                        | |
20# | |    local 2001:db8:3::1                                                | |
21# | |    id 1000 dstport $VXPORT                                            | |
22# | +-----------------------------------------------------------------------+ |
23# |                                                                           |
24# |    + $rp1                                                                 |
25# |    | 2001:db8:3::1/64                                                     |
26# +----|----------------------------------------------------------------------+
27#      |
28# +----|--------------------------------------------------------+
29# |    |                                             VRF2       |
30# |    + $rp2                                                   |
31# |      2001:db8:3::2/64                                       |
32# |                                                             |
33# +-------------------------------------------------------------+
34
35lib_dir=$(dirname $0)/../../../net/forwarding
36
37ALL_TESTS="
38	decap_error_test
39	overlay_smac_is_mc_test
40"
41
42NUM_NETIFS=4
43source $lib_dir/lib.sh
44source $lib_dir/tc_common.sh
45source $lib_dir/devlink_lib.sh
46
47: ${VXPORT:=4789}
48export VXPORT
49
50h1_create()
51{
52	simple_if_init $h1 2001:db8:1::1/64
53}
54
55h1_destroy()
56{
57	simple_if_fini $h1 2001:db8:1::1/64
58}
59
60switch_create()
61{
62	ip link add name br1 type bridge vlan_filtering 0 mcast_snooping 0
63	# Make sure the bridge uses the MAC address of the local port and not
64	# that of the VxLAN's device.
65	ip link set dev br1 address $(mac_get $swp1)
66	ip link set dev br1 up
67
68	tc qdisc add dev $swp1 clsact
69	ip link set dev $swp1 master br1
70	ip link set dev $swp1 up
71
72	ip link add name vx1 type vxlan id 1000 local 2001:db8:3::1 \
73		dstport "$VXPORT" nolearning udp6zerocsumrx udp6zerocsumtx \
74		tos inherit ttl 100
75	ip link set dev vx1 master br1
76	ip link set dev vx1 up
77
78	ip link set dev $rp1 up
79	ip address add dev $rp1 2001:db8:3::1/64
80}
81
82switch_destroy()
83{
84	ip address del dev $rp1 2001:db8:3::1/64
85	ip link set dev $rp1 down
86
87	ip link set dev vx1 down
88	ip link set dev vx1 nomaster
89	ip link del dev vx1
90
91	ip link set dev $swp1 down
92	ip link set dev $swp1 nomaster
93	tc qdisc del dev $swp1 clsact
94
95	ip link set dev br1 down
96	ip link del dev br1
97}
98
99vrf2_create()
100{
101	simple_if_init $rp2 2001:db8:3::2/64
102}
103
104vrf2_destroy()
105{
106	simple_if_fini $rp2 2001:db8:3::2/64
107}
108
109setup_prepare()
110{
111	h1=${NETIFS[p1]}
112	swp1=${NETIFS[p2]}
113
114	rp1=${NETIFS[p3]}
115	rp2=${NETIFS[p4]}
116
117	vrf_prepare
118	forwarding_enable
119	h1_create
120	switch_create
121	vrf2_create
122}
123
124cleanup()
125{
126	pre_cleanup
127
128	vrf2_destroy
129	switch_destroy
130	h1_destroy
131	forwarding_restore
132	vrf_cleanup
133}
134
135ecn_payload_get()
136{
137	local dest_mac=$(mac_get $h1)
138	local saddr="20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:03"
139	local daddr="20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:01"
140	p=$(:
141		)"08:"$(                      : VXLAN flags
142		)"00:00:00:"$(                : VXLAN reserved
143		)"00:03:e8:"$(                : VXLAN VNI : 1000
144		)"00:"$(                      : VXLAN reserved
145		)"$dest_mac:"$(               : ETH daddr
146		)"00:00:00:00:00:00:"$(       : ETH saddr
147		)"86:dd:"$(                   : ETH type
148		)"6"$(                        : IP version
149		)"0:0"$(		      : Traffic class
150		)"0:00:00:"$(                 : Flow label
151		)"00:08:"$(                   : Payload length
152		)"3a:"$(                      : Next header
153		)"04:"$(                      : Hop limit
154		)"$saddr:"$(                  : IP saddr
155		)"$daddr:"$(		      : IP daddr
156		)"80:"$(                      : ICMPv6.type
157		)"00:"$(                      : ICMPv6.code
158		)"00:"$(                      : ICMPv6.checksum
159		)
160	echo $p
161}
162
163ecn_decap_test()
164{
165	local trap_name="decap_error"
166	local desc=$1; shift
167	local ecn_desc=$1; shift
168	local outer_tos=$1; shift
169	local mz_pid
170
171	RET=0
172
173	tc filter add dev $swp1 egress protocol ipv6 pref 1 handle 101 \
174		flower src_ip 2001:db8:1::3 dst_ip 2001:db8:1::1 action pass
175
176	rp1_mac=$(mac_get $rp1)
177	payload=$(ecn_payload_get)
178
179	ip vrf exec v$rp2 $MZ -6 $rp2 -c 0 -d 1msec -b $rp1_mac \
180		-B 2001:db8:3::1 -t udp \
181		sp=12345,dp=$VXPORT,tos=$outer_tos,p=$payload -q &
182	mz_pid=$!
183
184	devlink_trap_exception_test $trap_name
185
186	tc_check_packets "dev $swp1 egress" 101 0
187	check_err $? "Packets were not dropped"
188
189	log_test "$desc: Inner ECN is not ECT and outer is $ecn_desc"
190
191	kill $mz_pid && wait $mz_pid &> /dev/null
192	tc filter del dev $swp1 egress protocol ipv6 pref 1 handle 101 flower
193}
194
195reserved_bits_payload_get()
196{
197	local dest_mac=$(mac_get $h1)
198	local saddr="20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:03"
199	local daddr="20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:01"
200	p=$(:
201		)"08:"$(                      : VXLAN flags
202		)"01:00:00:"$(                : VXLAN reserved
203		)"00:03:e8:"$(                : VXLAN VNI : 1000
204		)"00:"$(                      : VXLAN reserved
205		)"$dest_mac:"$(               : ETH daddr
206		)"00:00:00:00:00:00:"$(       : ETH saddr
207		)"86:dd:"$(                   : ETH type
208		)"6"$(                        : IP version
209		)"0:0"$(		      : Traffic class
210		)"0:00:00:"$(                 : Flow label
211		)"00:08:"$(                   : Payload length
212		)"3a:"$(                      : Next header
213		)"04:"$(                      : Hop limit
214		)"$saddr:"$(                  : IP saddr
215		)"$daddr:"$(		      : IP daddr
216		)"80:"$(                      : ICMPv6.type
217		)"00:"$(                      : ICMPv6.code
218		)"00:"$(                      : ICMPv6.checksum
219		)
220	echo $p
221}
222
223short_payload_get()
224{
225        dest_mac=$(mac_get $h1)
226        p=$(:
227		)"08:"$(                      : VXLAN flags
228		)"00:00:00:"$(                : VXLAN reserved
229		)"00:03:e8:"$(                : VXLAN VNI : 1000
230		)"00:"$(                      : VXLAN reserved
231		)"$dest_mac:"$(               : ETH daddr
232		)"00:00:00:00:00:00:"$(       : ETH saddr
233		)
234        echo $p
235}
236
237corrupted_packet_test()
238{
239	local trap_name="decap_error"
240	local desc=$1; shift
241	local payload_get=$1; shift
242	local mz_pid
243
244	RET=0
245
246	# In case of too short packet, there is no any inner packet,
247	# so the matching will always succeed
248	tc filter add dev $swp1 egress protocol ipv6 pref 1 handle 101 \
249		flower skip_hw src_ip 2001:db8:3::1 dst_ip 2001:db8:1::1 \
250		action pass
251
252	rp1_mac=$(mac_get $rp1)
253	payload=$($payload_get)
254	ip vrf exec v$rp2 $MZ -6 $rp2 -c 0 -d 1msec -b $rp1_mac \
255		-B 2001:db8:3::1 -t udp sp=12345,dp=$VXPORT,p=$payload -q &
256	mz_pid=$!
257
258	devlink_trap_exception_test $trap_name
259
260	tc_check_packets "dev $swp1 egress" 101 0
261	check_err $? "Packets were not dropped"
262
263	log_test "$desc"
264
265	kill $mz_pid && wait $mz_pid &> /dev/null
266	tc filter del dev $swp1 egress protocol ipv6 pref 1 handle 101 flower
267}
268
269decap_error_test()
270{
271	ecn_decap_test "Decap error" "ECT(1)" 01
272	ecn_decap_test "Decap error" "ECT(0)" 02
273	ecn_decap_test "Decap error" "CE" 03
274
275	corrupted_packet_test "Decap error: Reserved bits in use" \
276		"reserved_bits_payload_get"
277	corrupted_packet_test "Decap error: Too short inner packet" \
278		"short_payload_get"
279}
280
281mc_smac_payload_get()
282{
283	local dest_mac=$(mac_get $h1)
284	local source_mac="01:02:03:04:05:06"
285	local saddr="20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:03"
286	local daddr="20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:01"
287	p=$(:
288		)"08:"$(                      : VXLAN flags
289		)"00:00:00:"$(                : VXLAN reserved
290		)"00:03:e8:"$(                : VXLAN VNI : 1000
291		)"00:"$(                      : VXLAN reserved
292		)"$dest_mac:"$(               : ETH daddr
293		)"$source_mac:"$(	      : ETH saddr
294		)"86:dd:"$(                   : ETH type
295		)"6"$(                        : IP version
296		)"0:0"$(		      : Traffic class
297		)"0:00:00:"$(                 : Flow label
298		)"00:08:"$(                   : Payload length
299		)"3a:"$(                      : Next header
300		)"04:"$(                      : Hop limit
301		)"$saddr:"$(                  : IP saddr
302		)"$daddr:"$(		      : IP daddr
303		)"80:"$(                      : ICMPv6.type
304		)"00:"$(                      : ICMPv6.code
305		)"00:"$(                      : ICMPv6.checksum
306		)
307	echo $p
308}
309
310overlay_smac_is_mc_test()
311{
312	local trap_name="overlay_smac_is_mc"
313	local mz_pid
314
315	RET=0
316
317	# The matching will be checked on devlink_trap_drop_test()
318	# and the filter will be removed on devlink_trap_drop_cleanup()
319	tc filter add dev $swp1 egress protocol ipv6 pref 1 handle 101 \
320		flower src_mac 01:02:03:04:05:06 action pass
321
322	rp1_mac=$(mac_get $rp1)
323	payload=$(mc_smac_payload_get)
324
325	ip vrf exec v$rp2 $MZ -6 $rp2 -c 0 -d 1msec -b $rp1_mac \
326		-B 2001:db8:3::1 -t udp sp=12345,dp=$VXPORT,p=$payload -q &
327	mz_pid=$!
328
329	devlink_trap_drop_test $trap_name $swp1 101
330
331	log_test "Overlay source MAC is multicast"
332
333	devlink_trap_drop_cleanup $mz_pid $swp1 "ipv6" 1 101
334}
335
336trap cleanup EXIT
337
338setup_prepare
339setup_wait
340tests_run
341
342exit $EXIT_STATUS
343