• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# Test devlink-trap L3 drops functionality over mlxsw. Each registered L3 drop
5# packet trap is tested to make sure it is triggered under the right
6# conditions.
7
8# +---------------------------------+
9# | H1 (vrf)                        |
10# |    + $h1                        |
11# |    | 192.0.2.1/24               |
12# |    | 2001:db8:1::1/64           |
13# |    |                            |
14# |    |  default via 192.0.2.2     |
15# |    |  default via 2001:db8:1::2 |
16# +----|----------------------------+
17#      |
18# +----|----------------------------------------------------------------------+
19# | SW |                                                                      |
20# |    + $rp1                                                                 |
21# |        192.0.2.2/24                                                       |
22# |        2001:db8:1::2/64                                                   |
23# |                                                                           |
24# |        2001:db8:2::2/64                                                   |
25# |        198.51.100.2/24                                                    |
26# |    + $rp2                                                                 |
27# |    |                                                                      |
28# +----|----------------------------------------------------------------------+
29#      |
30# +----|----------------------------+
31# |    |  default via 198.51.100.2  |
32# |    |  default via 2001:db8:2::2 |
33# |    |                            |
34# |    | 2001:db8:2::1/64           |
35# |    | 198.51.100.1/24            |
36# |    + $h2                        |
37# | H2 (vrf)                        |
38# +---------------------------------+
39
40lib_dir=$(dirname $0)/../../../net/forwarding
41
42ALL_TESTS="
43	non_ip_test
44	uc_dip_over_mc_dmac_test
45	dip_is_loopback_test
46	sip_is_mc_test
47	sip_is_loopback_test
48	ip_header_corrupted_test
49	ipv4_sip_is_limited_bc_test
50	ipv6_mc_dip_reserved_scope_test
51	ipv6_mc_dip_interface_local_scope_test
52	blackhole_route_test
53	irif_disabled_test
54	erif_disabled_test
55"
56
57NUM_NETIFS=4
58source $lib_dir/lib.sh
59source $lib_dir/tc_common.sh
60source $lib_dir/devlink_lib.sh
61
62h1_create()
63{
64	simple_if_init $h1 192.0.2.1/24 2001:db8:1::1/64
65
66	ip -4 route add default vrf v$h1 nexthop via 192.0.2.2
67	ip -6 route add default vrf v$h1 nexthop via 2001:db8:1::2
68}
69
70h1_destroy()
71{
72	ip -6 route del default vrf v$h1 nexthop via 2001:db8:1::2
73	ip -4 route del default vrf v$h1 nexthop via 192.0.2.2
74
75	simple_if_fini $h1 192.0.2.1/24 2001:db8:1::1/64
76}
77
78h2_create()
79{
80	simple_if_init $h2 $h2_ipv4/24 $h2_ipv6/64
81
82	ip -4 route add default vrf v$h2 nexthop via 198.51.100.2
83	ip -6 route add default vrf v$h2 nexthop via 2001:db8:2::2
84}
85
86h2_destroy()
87{
88	ip -6 route del default vrf v$h2 nexthop via 2001:db8:2::2
89	ip -4 route del default vrf v$h2 nexthop via 198.51.100.2
90
91	simple_if_fini $h2 $h2_ipv4/24 $h2_ipv6/64
92}
93
94router_create()
95{
96	ip link set dev $rp1 up
97	ip link set dev $rp2 up
98
99	tc qdisc add dev $rp2 clsact
100
101	__addr_add_del $rp1 add 192.0.2.2/24 2001:db8:1::2/64
102	__addr_add_del $rp2 add 198.51.100.2/24 2001:db8:2::2/64
103}
104
105router_destroy()
106{
107	__addr_add_del $rp2 del 198.51.100.2/24 2001:db8:2::2/64
108	__addr_add_del $rp1 del 192.0.2.2/24 2001:db8:1::2/64
109
110	tc qdisc del dev $rp2 clsact
111
112	ip link set dev $rp2 down
113	ip link set dev $rp1 down
114}
115
116setup_prepare()
117{
118	h1=${NETIFS[p1]}
119	rp1=${NETIFS[p2]}
120
121	rp2=${NETIFS[p3]}
122	h2=${NETIFS[p4]}
123
124	h1mac=$(mac_get $h1)
125	rp1mac=$(mac_get $rp1)
126
127	h1_ipv4=192.0.2.1
128	h2_ipv4=198.51.100.1
129	h1_ipv6=2001:db8:1::1
130	h2_ipv6=2001:db8:2::1
131
132	vrf_prepare
133	forwarding_enable
134
135	h1_create
136	h2_create
137
138	router_create
139}
140
141cleanup()
142{
143	pre_cleanup
144
145	router_destroy
146
147	h2_destroy
148	h1_destroy
149
150	forwarding_restore
151	vrf_cleanup
152}
153
154ping_check()
155{
156	trap_name=$1; shift
157
158	devlink_trap_action_set $trap_name "trap"
159	ping_do $h1 $h2_ipv4
160	check_err $? "Packets that should not be trapped were trapped"
161	devlink_trap_action_set $trap_name "drop"
162}
163
164non_ip_test()
165{
166	local trap_name="non_ip"
167	local mz_pid
168
169	RET=0
170
171	ping_check $trap_name
172
173	tc filter add dev $rp2 egress protocol ip pref 1 handle 101 \
174		flower dst_ip $h2_ipv4 action drop
175
176	# Generate non-IP packets to the router
177	$MZ $h1 -c 0 -p 100 -d 1msec -B $h2_ipv4 -q "$rp1mac $h1mac \
178		00:00 de:ad:be:ef" &
179	mz_pid=$!
180
181	devlink_trap_drop_test $trap_name $rp2 101
182
183	log_test "Non IP"
184
185	devlink_trap_drop_cleanup $mz_pid $rp2 "ip" 1 101
186}
187
188__uc_dip_over_mc_dmac_test()
189{
190	local desc=$1; shift
191	local proto=$1; shift
192	local dip=$1; shift
193	local flags=${1:-""}; shift
194	local trap_name="uc_dip_over_mc_dmac"
195	local dmac=01:02:03:04:05:06
196	local mz_pid
197
198	RET=0
199
200	ping_check $trap_name
201
202	tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \
203		flower ip_proto udp src_port 54321 dst_port 12345 action drop
204
205	# Generate IP packets with a unicast IP and a multicast destination MAC
206	$MZ $h1 $flags -t udp "sp=54321,dp=12345" -c 0 -p 100 -b $dmac \
207		-B $dip -d 1msec -q &
208	mz_pid=$!
209
210	devlink_trap_drop_test $trap_name $rp2 101
211
212	log_test "Unicast destination IP over multicast destination MAC: $desc"
213
214	devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101
215}
216
217uc_dip_over_mc_dmac_test()
218{
219	__uc_dip_over_mc_dmac_test "IPv4" "ip" $h2_ipv4
220	__uc_dip_over_mc_dmac_test "IPv6" "ipv6" $h2_ipv6 "-6"
221}
222
223__sip_is_loopback_test()
224{
225	local desc=$1; shift
226	local proto=$1; shift
227	local sip=$1; shift
228	local dip=$1; shift
229	local flags=${1:-""}; shift
230	local trap_name="sip_is_loopback_address"
231	local mz_pid
232
233	RET=0
234
235	ping_check $trap_name
236
237	tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \
238		flower src_ip $sip action drop
239
240	# Generate packets with loopback source IP
241	$MZ $h1 $flags -t udp "sp=54321,dp=12345" -c 0 -p 100 -A $sip \
242		-b $rp1mac -B $dip -d 1msec -q &
243	mz_pid=$!
244
245	devlink_trap_drop_test $trap_name $rp2 101
246
247	log_test "Source IP is loopback address: $desc"
248
249	devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101
250}
251
252sip_is_loopback_test()
253{
254	__sip_is_loopback_test "IPv4" "ip" "127.0.0.0/8" $h2_ipv4
255	__sip_is_loopback_test "IPv6" "ipv6" "::1" $h2_ipv6 "-6"
256}
257
258__dip_is_loopback_test()
259{
260	local desc=$1; shift
261	local proto=$1; shift
262	local dip=$1; shift
263	local flags=${1:-""}; shift
264	local trap_name="dip_is_loopback_address"
265	local mz_pid
266
267	RET=0
268
269	ping_check $trap_name
270
271	tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \
272		flower dst_ip $dip action drop
273
274	# Generate packets with loopback destination IP
275	$MZ $h1 $flags -t udp "sp=54321,dp=12345" -c 0 -p 100 -b $rp1mac \
276		-B $dip -d 1msec -q &
277	mz_pid=$!
278
279	devlink_trap_drop_test $trap_name $rp2 101
280
281	log_test "Destination IP is loopback address: $desc"
282
283	devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101
284}
285
286dip_is_loopback_test()
287{
288	__dip_is_loopback_test "IPv4" "ip" "127.0.0.0/8"
289	__dip_is_loopback_test "IPv6" "ipv6" "::1" "-6"
290}
291
292__sip_is_mc_test()
293{
294	local desc=$1; shift
295	local proto=$1; shift
296	local sip=$1; shift
297	local dip=$1; shift
298	local flags=${1:-""}; shift
299	local trap_name="sip_is_mc"
300	local mz_pid
301
302	RET=0
303
304	ping_check $trap_name
305
306	tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \
307		flower src_ip $sip action drop
308
309	# Generate packets with multicast source IP
310	$MZ $h1 $flags -t udp "sp=54321,dp=12345" -c 0 -p 100 -A $sip \
311		-b $rp1mac -B $dip -d 1msec -q &
312	mz_pid=$!
313
314	devlink_trap_drop_test $trap_name $rp2 101
315
316	log_test "Source IP is multicast: $desc"
317
318	devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101
319}
320
321sip_is_mc_test()
322{
323	__sip_is_mc_test "IPv4" "ip" "239.1.1.1" $h2_ipv4
324	__sip_is_mc_test "IPv6" "ipv6" "FF02::2" $h2_ipv6 "-6"
325}
326
327ipv4_sip_is_limited_bc_test()
328{
329	local trap_name="ipv4_sip_is_limited_bc"
330	local sip=255.255.255.255
331	local mz_pid
332
333	RET=0
334
335	ping_check $trap_name
336
337	tc filter add dev $rp2 egress protocol ip pref 1 handle 101 \
338		flower src_ip $sip action drop
339
340	# Generate packets with limited broadcast source IP
341	$MZ $h1 -t udp "sp=54321,dp=12345" -c 0 -p 100 -A $sip -b $rp1mac \
342		-B $h2_ipv4 -d 1msec -q &
343	mz_pid=$!
344
345	devlink_trap_drop_test $trap_name $rp2 101
346
347	log_test "IPv4 source IP is limited broadcast"
348
349	devlink_trap_drop_cleanup $mz_pid $rp2 "ip" 1 101
350}
351
352ipv4_payload_get()
353{
354	local ipver=$1; shift
355	local ihl=$1; shift
356	local checksum=$1; shift
357
358	p=$(:
359		)"08:00:"$(                   : ETH type
360		)"$ipver"$(                   : IP version
361		)"$ihl:"$(                    : IHL
362		)"00:"$(		      : IP TOS
363		)"00:F4:"$(                   : IP total length
364		)"00:00:"$(                   : IP identification
365		)"20:00:"$(                   : IP flags + frag off
366		)"30:"$(                      : IP TTL
367		)"01:"$(                      : IP proto
368		)"$checksum:"$(               : IP header csum
369		)"$h1_ipv4:"$(                : IP saddr
370	        )"$h2_ipv4:"$(                : IP daddr
371		)
372	echo $p
373}
374
375__ipv4_header_corrupted_test()
376{
377	local desc=$1; shift
378	local ipver=$1; shift
379	local ihl=$1; shift
380	local checksum=$1; shift
381	local trap_name="ip_header_corrupted"
382	local payload
383	local mz_pid
384
385	RET=0
386
387	ping_check $trap_name
388
389	tc filter add dev $rp2 egress protocol ip pref 1 handle 101 \
390		flower dst_ip $h2_ipv4 action drop
391
392	payload=$(ipv4_payload_get $ipver $ihl $checksum)
393
394	# Generate packets with corrupted IP header
395	$MZ $h1 -c 0 -d 1msec -a $h1mac -b $rp1mac -q p=$payload &
396	mz_pid=$!
397
398	devlink_trap_drop_test $trap_name $rp2 101
399
400	log_test "IP header corrupted: $desc: IPv4"
401
402	devlink_trap_drop_cleanup $mz_pid $rp2 "ip" 1 101
403}
404
405ipv6_payload_get()
406{
407	local ipver=$1; shift
408
409	p=$(:
410		)"86:DD:"$(                  : ETH type
411		)"$ipver"$(                  : IP version
412		)"0:0:"$(                    : Traffic class
413		)"0:00:00:"$(		     : Flow label
414		)"00:00:"$(                  : Payload length
415		)"01:"$(                     : Next header
416		)"04:"$(                     : Hop limit
417		)"$h1_ipv6:"$(      	     : IP saddr
418		)"$h2_ipv6:"$(               : IP daddr
419		)
420	echo $p
421}
422
423__ipv6_header_corrupted_test()
424{
425	local desc=$1; shift
426	local ipver=$1; shift
427	local trap_name="ip_header_corrupted"
428	local payload
429	local mz_pid
430
431	RET=0
432
433	ping_check $trap_name
434
435	tc filter add dev $rp2 egress protocol ip pref 1 handle 101 \
436		flower dst_ip $h2_ipv4 action drop
437
438	payload=$(ipv6_payload_get $ipver)
439
440	# Generate packets with corrupted IP header
441	$MZ $h1 -c 0 -d 1msec -a $h1mac -b $rp1mac -q p=$payload &
442	mz_pid=$!
443
444	devlink_trap_drop_test $trap_name $rp2 101
445
446	log_test "IP header corrupted: $desc: IPv6"
447
448	devlink_trap_drop_cleanup $mz_pid $rp2 "ip" 1 101
449}
450
451ip_header_corrupted_test()
452{
453	# Each test uses one wrong value. The three values below are correct.
454	local ipv="4"
455	local ihl="5"
456	local checksum="00:F4"
457
458	__ipv4_header_corrupted_test "wrong IP version" 5 $ihl $checksum
459	__ipv4_header_corrupted_test "wrong IHL" $ipv 4 $checksum
460	__ipv4_header_corrupted_test "wrong checksum" $ipv $ihl "00:00"
461	__ipv6_header_corrupted_test "wrong IP version" 5
462}
463
464ipv6_mc_dip_reserved_scope_test()
465{
466	local trap_name="ipv6_mc_dip_reserved_scope"
467	local dip=FF00::
468	local mz_pid
469
470	RET=0
471
472	ping_check $trap_name
473
474	tc filter add dev $rp2 egress protocol ipv6 pref 1 handle 101 \
475		flower dst_ip $dip action drop
476
477	# Generate packets with reserved scope destination IP
478	$MZ $h1 -6 -t udp "sp=54321,dp=12345" -c 0 -p 100 -b \
479		"33:33:00:00:00:00" -B $dip -d 1msec -q &
480	mz_pid=$!
481
482	devlink_trap_drop_test $trap_name $rp2 101
483
484	log_test "IPv6 multicast destination IP reserved scope"
485
486	devlink_trap_drop_cleanup $mz_pid $rp2 "ipv6" 1 101
487}
488
489ipv6_mc_dip_interface_local_scope_test()
490{
491	local trap_name="ipv6_mc_dip_interface_local_scope"
492	local dip=FF01::
493	local mz_pid
494
495	RET=0
496
497	ping_check $trap_name
498
499	tc filter add dev $rp2 egress protocol ipv6 pref 1 handle 101 \
500		flower dst_ip $dip action drop
501
502	# Generate packets with interface local scope destination IP
503	$MZ $h1 -6 -t udp "sp=54321,dp=12345" -c 0 -p 100 -b \
504		"33:33:00:00:00:00" -B $dip -d 1msec -q &
505	mz_pid=$!
506
507	devlink_trap_drop_test $trap_name $rp2 101
508
509	log_test "IPv6 multicast destination IP interface-local scope"
510
511	devlink_trap_drop_cleanup $mz_pid $rp2 "ipv6" 1 101
512}
513
514__blackhole_route_test()
515{
516	local flags=$1; shift
517	local subnet=$1; shift
518	local proto=$1; shift
519	local dip=$1; shift
520	local ip_proto=${1:-"icmp"}; shift
521	local trap_name="blackhole_route"
522	local mz_pid
523
524	RET=0
525
526	ping_check $trap_name
527
528	ip -$flags route add blackhole $subnet
529	tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \
530		flower skip_hw dst_ip $dip ip_proto $ip_proto action drop
531
532	# Generate packets to the blackhole route
533	$MZ $h1 -$flags -t udp "sp=54321,dp=12345" -c 0 -p 100 -b $rp1mac \
534		-B $dip -d 1msec -q &
535	mz_pid=$!
536
537	devlink_trap_drop_test $trap_name $rp2 101
538	log_test "Blackhole route: IPv$flags"
539
540	devlink_trap_drop_cleanup $mz_pid $rp2 $proto 1 101
541	ip -$flags route del blackhole $subnet
542}
543
544blackhole_route_test()
545{
546	__blackhole_route_test "4" "198.51.100.0/30" "ip" $h2_ipv4
547	__blackhole_route_test "6" "2001:db8:2::/120" "ipv6" $h2_ipv6 "icmpv6"
548}
549
550irif_disabled_test()
551{
552	local trap_name="irif_disabled"
553	local t0_packets t0_bytes
554	local t1_packets t1_bytes
555	local mz_pid
556
557	RET=0
558
559	ping_check $trap_name
560
561	devlink_trap_action_set $trap_name "trap"
562
563	# When RIF of a physical port ("Sub-port RIF") is destroyed, we first
564	# block the STP of the {Port, VLAN} so packets cannot get into the RIF.
565	# Using bridge enables us to see this trap because when bridge is
566	# destroyed, there is a small time window that packets can go into the
567	# RIF, while it is disabled.
568	ip link add dev br0 type bridge
569	ip link set dev $rp1 master br0
570	ip address flush dev $rp1
571	__addr_add_del br0 add 192.0.2.2/24
572	ip li set dev br0 up
573
574	t0_packets=$(devlink_trap_rx_packets_get $trap_name)
575	t0_bytes=$(devlink_trap_rx_bytes_get $trap_name)
576
577	# Generate packets to h2 through br0 RIF that will be removed later
578	$MZ $h1 -t udp "sp=54321,dp=12345" -c 0 -p 100 -a own -b $rp1mac \
579		-B $h2_ipv4 -q &
580	mz_pid=$!
581
582	# Wait before removing br0 RIF to allow packets to go into the bridge.
583	sleep 1
584
585	# Flushing address will dismantle the RIF
586	ip address flush dev br0
587
588	t1_packets=$(devlink_trap_rx_packets_get $trap_name)
589	t1_bytes=$(devlink_trap_rx_bytes_get $trap_name)
590
591	if [[ $t0_packets -eq $t1_packets && $t0_bytes -eq $t1_bytes ]]; then
592		check_err 1 "Trap stats idle when packets should be trapped"
593	fi
594
595	log_test "Ingress RIF disabled"
596
597	kill $mz_pid && wait $mz_pid &> /dev/null
598	ip link set dev $rp1 nomaster
599	__addr_add_del $rp1 add 192.0.2.2/24 2001:db8:1::2/64
600	ip link del dev br0 type bridge
601	devlink_trap_action_set $trap_name "drop"
602}
603
604erif_disabled_test()
605{
606	local trap_name="erif_disabled"
607	local t0_packets t0_bytes
608	local t1_packets t1_bytes
609	local mz_pid
610
611	RET=0
612
613	ping_check $trap_name
614
615	devlink_trap_action_set $trap_name "trap"
616	ip link add dev br0 type bridge
617	ip add flush dev $rp1
618	ip link set dev $rp1 master br0
619	__addr_add_del br0 add 192.0.2.2/24
620	ip link set dev br0 up
621
622	t0_packets=$(devlink_trap_rx_packets_get $trap_name)
623	t0_bytes=$(devlink_trap_rx_bytes_get $trap_name)
624
625	rp2mac=$(mac_get $rp2)
626
627	# Generate packets that should go out through br0 RIF that will be
628	# removed later
629	$MZ $h2 -t udp "sp=54321,dp=12345" -c 0 -p 100 -a own -b $rp2mac \
630		-B 192.0.2.1 -q &
631	mz_pid=$!
632
633	sleep 5
634	# Unlinking the port from the bridge will disable the RIF associated
635	# with br0 as it is no longer an upper of any mlxsw port.
636	ip link set dev $rp1 nomaster
637
638	t1_packets=$(devlink_trap_rx_packets_get $trap_name)
639	t1_bytes=$(devlink_trap_rx_bytes_get $trap_name)
640
641	if [[ $t0_packets -eq $t1_packets && $t0_bytes -eq $t1_bytes ]]; then
642		check_err 1 "Trap stats idle when packets should be trapped"
643	fi
644
645	log_test "Egress RIF disabled"
646
647	kill $mz_pid && wait $mz_pid &> /dev/null
648	__addr_add_del $rp1 add 192.0.2.2/24 2001:db8:1::2/64
649	ip link del dev br0 type bridge
650	devlink_trap_action_set $trap_name "drop"
651}
652
653trap cleanup EXIT
654
655setup_prepare
656setup_wait
657
658tests_run
659
660exit $EXIT_STATUS
661