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