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