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