Back to home page

OSCL-LXR

 
 

    


0001 #!/bin/bash
0002 # SPDX-License-Identifier: GPL-2.0
0003 #
0004 # Test devlink-trap L3 exceptions functionality over mlxsw.
0005 # Check all exception traps to make sure they are triggered under the right
0006 # conditions.
0007 
0008 # +---------------------------------+
0009 # | H1 (vrf)                        |
0010 # |    + $h1                        |
0011 # |    | 192.0.2.1/24               |
0012 # |    | 2001:db8:1::1/64           |
0013 # |    |                            |
0014 # |    |  default via 192.0.2.2     |
0015 # |    |  default via 2001:db8:1::2 |
0016 # +----|----------------------------+
0017 #      |
0018 # +----|----------------------------------------------------------------------+
0019 # | SW |                                                                      |
0020 # |    + $rp1                                                                 |
0021 # |        192.0.2.2/24                                                       |
0022 # |        2001:db8:1::2/64                                                   |
0023 # |                                                                           |
0024 # |        2001:db8:2::2/64                                                   |
0025 # |        198.51.100.2/24                                                    |
0026 # |    + $rp2                                                                 |
0027 # |    |                                                                      |
0028 # +----|----------------------------------------------------------------------+
0029 #      |
0030 # +----|----------------------------+
0031 # |    |  default via 198.51.100.2  |
0032 # |    |  default via 2001:db8:2::2 |
0033 # |    |                            |
0034 # |    | 2001:db8:2::1/64           |
0035 # |    | 198.51.100.1/24            |
0036 # |    + $h2                        |
0037 # | H2 (vrf)                        |
0038 # +---------------------------------+
0039 
0040 lib_dir=$(dirname $0)/../../../net/forwarding
0041 
0042 ALL_TESTS="
0043         mtu_value_is_too_small_test
0044         ttl_value_is_too_small_test
0045         mc_reverse_path_forwarding_test
0046         reject_route_test
0047         unresolved_neigh_test
0048         ipv4_lpm_miss_test
0049         ipv6_lpm_miss_test
0050 "
0051 
0052 NUM_NETIFS=4
0053 source $lib_dir/lib.sh
0054 source $lib_dir/tc_common.sh
0055 source $lib_dir/devlink_lib.sh
0056 
0057 require_command $MCD
0058 require_command $MC_CLI
0059 table_name=selftests
0060 
0061 h1_create()
0062 {
0063         simple_if_init $h1 192.0.2.1/24 2001:db8:1::1/64
0064 
0065         ip -4 route add default vrf v$h1 nexthop via 192.0.2.2
0066         ip -6 route add default vrf v$h1 nexthop via 2001:db8:1::2
0067 
0068         tc qdisc add dev $h1 clsact
0069 }
0070 
0071 h1_destroy()
0072 {
0073         tc qdisc del dev $h1 clsact
0074 
0075         ip -6 route del default vrf v$h1 nexthop via 2001:db8:1::2
0076         ip -4 route del default vrf v$h1 nexthop via 192.0.2.2
0077 
0078         simple_if_fini $h1 192.0.2.1/24 2001:db8:1::1/64
0079 }
0080 
0081 h2_create()
0082 {
0083         simple_if_init $h2 198.51.100.1/24 2001:db8:2::1/64
0084 
0085         ip -4 route add default vrf v$h2 nexthop via 198.51.100.2
0086         ip -6 route add default vrf v$h2 nexthop via 2001:db8:2::2
0087 }
0088 
0089 h2_destroy()
0090 {
0091         ip -6 route del default vrf v$h2 nexthop via 2001:db8:2::2
0092         ip -4 route del default vrf v$h2 nexthop via 198.51.100.2
0093 
0094         simple_if_fini $h2 198.51.100.1/24 2001:db8:2::1/64
0095 }
0096 
0097 router_create()
0098 {
0099         ip link set dev $rp1 up
0100         ip link set dev $rp2 up
0101 
0102         tc qdisc add dev $rp2 clsact
0103 
0104         __addr_add_del $rp1 add 192.0.2.2/24 2001:db8:1::2/64
0105         __addr_add_del $rp2 add 198.51.100.2/24 2001:db8:2::2/64
0106 }
0107 
0108 router_destroy()
0109 {
0110         __addr_add_del $rp2 del 198.51.100.2/24 2001:db8:2::2/64
0111         __addr_add_del $rp1 del 192.0.2.2/24 2001:db8:1::2/64
0112 
0113         tc qdisc del dev $rp2 clsact
0114 
0115         ip link set dev $rp2 down
0116         ip link set dev $rp1 down
0117 }
0118 
0119 setup_prepare()
0120 {
0121         h1=${NETIFS[p1]}
0122         rp1=${NETIFS[p2]}
0123 
0124         rp2=${NETIFS[p3]}
0125         h2=${NETIFS[p4]}
0126 
0127         rp1mac=$(mac_get $rp1)
0128 
0129         start_mcd
0130 
0131         vrf_prepare
0132         forwarding_enable
0133 
0134         h1_create
0135         h2_create
0136 
0137         router_create
0138 }
0139 
0140 cleanup()
0141 {
0142         pre_cleanup
0143 
0144         router_destroy
0145 
0146         h2_destroy
0147         h1_destroy
0148 
0149         forwarding_restore
0150         vrf_cleanup
0151 
0152         kill_mcd
0153 }
0154 
0155 ping_check()
0156 {
0157         ping_do $h1 198.51.100.1
0158         check_err $? "Packets that should not be trapped were trapped"
0159 }
0160 
0161 trap_action_check()
0162 {
0163         local trap_name=$1; shift
0164         local expected_action=$1; shift
0165 
0166         action=$(devlink_trap_action_get $trap_name)
0167         if [ "$action" != $expected_action ]; then
0168                 check_err 1 "Trap $trap_name has wrong action: $action"
0169         fi
0170 }
0171 
0172 mtu_value_is_too_small_test()
0173 {
0174         local trap_name="mtu_value_is_too_small"
0175         local expected_action="trap"
0176         local mz_pid
0177 
0178         RET=0
0179 
0180         ping_check $trap_name
0181         trap_action_check $trap_name $expected_action
0182 
0183         # type - Destination Unreachable
0184         # code - Fragmentation Needed and Don't Fragment was Set
0185         tc filter add dev $h1 ingress protocol ip pref 1 handle 101 \
0186                 flower skip_hw ip_proto icmp type 3 code 4 action pass
0187 
0188         mtu_set $rp2 1300
0189 
0190         # Generate IP packets bigger than router's MTU with don't fragment
0191         # flag on.
0192         $MZ $h1 -t udp "sp=54321,dp=12345,df" -p 1400 -c 0 -d 1msec -b $rp1mac \
0193                 -B 198.51.100.1 -q &
0194         mz_pid=$!
0195 
0196         devlink_trap_exception_test $trap_name
0197 
0198         tc_check_packets_hitting "dev $h1 ingress" 101
0199         check_err $? "Packets were not received to h1"
0200 
0201         log_test "MTU value is too small"
0202 
0203         mtu_restore $rp2
0204 
0205         kill $mz_pid && wait $mz_pid &> /dev/null
0206         tc filter del dev $h1 ingress protocol ip pref 1 handle 101 flower
0207 }
0208 
0209 __ttl_value_is_too_small_test()
0210 {
0211         local ttl_val=$1; shift
0212         local trap_name="ttl_value_is_too_small"
0213         local expected_action="trap"
0214         local mz_pid
0215 
0216         RET=0
0217 
0218         ping_check $trap_name
0219         trap_action_check $trap_name $expected_action
0220 
0221         # type - Time Exceeded
0222         # code - Time to Live exceeded in Transit
0223         tc filter add dev $h1 ingress protocol ip pref 1 handle 101 \
0224                  flower skip_hw ip_proto icmp type 11 code 0 action pass
0225 
0226         # Generate IP packets with small TTL
0227         $MZ $h1 -t udp "ttl=$ttl_val,sp=54321,dp=12345" -c 0 -d 1msec \
0228                 -b $rp1mac -B 198.51.100.1 -q &
0229         mz_pid=$!
0230 
0231         devlink_trap_exception_test $trap_name
0232 
0233         tc_check_packets_hitting "dev $h1 ingress" 101
0234         check_err $? "Packets were not received to h1"
0235 
0236         log_test "TTL value is too small: TTL=$ttl_val"
0237 
0238         kill $mz_pid && wait $mz_pid &> /dev/null
0239         tc filter del dev $h1 ingress protocol ip pref 1 handle 101 flower
0240 }
0241 
0242 ttl_value_is_too_small_test()
0243 {
0244         __ttl_value_is_too_small_test 0
0245         __ttl_value_is_too_small_test 1
0246 }
0247 
0248 start_mcd()
0249 {
0250         SMCROUTEDIR="$(mktemp -d)"
0251         for ((i = 1; i <= $NUM_NETIFS; ++i)); do
0252                  echo "phyint ${NETIFS[p$i]} enable" >> \
0253                          $SMCROUTEDIR/$table_name.conf
0254         done
0255 
0256         $MCD -N -I $table_name -f $SMCROUTEDIR/$table_name.conf \
0257                 -P $SMCROUTEDIR/$table_name.pid
0258 }
0259 
0260 kill_mcd()
0261 {
0262         pkill $MCD
0263         rm -rf $SMCROUTEDIR
0264 }
0265 
0266 __mc_reverse_path_forwarding_test()
0267 {
0268         local desc=$1; shift
0269         local src_ip=$1; shift
0270         local dst_ip=$1; shift
0271         local dst_mac=$1; shift
0272         local proto=$1; shift
0273         local flags=${1:-""}; shift
0274         local trap_name="mc_reverse_path_forwarding"
0275         local expected_action="trap"
0276         local mz_pid
0277 
0278         RET=0
0279 
0280         ping_check $trap_name
0281         trap_action_check $trap_name $expected_action
0282 
0283         tc filter add dev $rp2 egress protocol $proto pref 1 handle 101 \
0284                 flower dst_ip $dst_ip ip_proto udp action drop
0285 
0286         $MC_CLI -I $table_name add $rp1 $src_ip $dst_ip $rp2
0287 
0288         # Generate packets to multicast address.
0289         $MZ $h2 $flags -t udp "sp=54321,dp=12345" -c 0 -p 128 \
0290                 -a 00:11:22:33:44:55 -b $dst_mac \
0291                 -A $src_ip -B $dst_ip -q &
0292 
0293         mz_pid=$!
0294 
0295         devlink_trap_exception_test $trap_name
0296 
0297         tc_check_packets "dev $rp2 egress" 101 0
0298         check_err $? "Packets were not dropped"
0299 
0300         log_test "Multicast reverse path forwarding: $desc"
0301 
0302         kill $mz_pid && wait $mz_pid &> /dev/null
0303         tc filter del dev $rp2 egress protocol $proto pref 1 handle 101 flower
0304 }
0305 
0306 mc_reverse_path_forwarding_test()
0307 {
0308         __mc_reverse_path_forwarding_test "IPv4" "192.0.2.1" "225.1.2.3" \
0309                 "01:00:5e:01:02:03" "ip"
0310         __mc_reverse_path_forwarding_test "IPv6" "2001:db8:1::1" "ff0e::3" \
0311                 "33:33:00:00:00:03" "ipv6" "-6"
0312 }
0313 
0314 __reject_route_test()
0315 {
0316         local desc=$1; shift
0317         local dst_ip=$1; shift
0318         local proto=$1; shift
0319         local ip_proto=$1; shift
0320         local type=$1; shift
0321         local code=$1; shift
0322         local unreachable=$1; shift
0323         local flags=${1:-""}; shift
0324         local trap_name="reject_route"
0325         local expected_action="trap"
0326         local mz_pid
0327 
0328         RET=0
0329 
0330         ping_check $trap_name
0331         trap_action_check $trap_name $expected_action
0332 
0333         tc filter add dev $h1 ingress protocol $proto pref 1 handle 101 flower \
0334                 skip_hw ip_proto $ip_proto type $type code $code action pass
0335 
0336         ip route add unreachable $unreachable
0337 
0338         # Generate pacekts to h2. The destination IP is unreachable.
0339         $MZ $flags $h1 -t udp "sp=54321,dp=12345" -c 0 -d 1msec -b $rp1mac \
0340                 -B $dst_ip -q &
0341         mz_pid=$!
0342 
0343         devlink_trap_exception_test $trap_name
0344 
0345         tc_check_packets_hitting "dev $h1 ingress" 101
0346         check_err $? "ICMP packet was not received to h1"
0347 
0348         log_test "Reject route: $desc"
0349 
0350         kill $mz_pid && wait $mz_pid &> /dev/null
0351         ip route del unreachable $unreachable
0352         tc filter del dev $h1 ingress protocol $proto pref 1 handle 101 flower
0353 }
0354 
0355 reject_route_test()
0356 {
0357         # type - Destination Unreachable
0358         # code - Host Unreachable
0359         __reject_route_test "IPv4" 198.51.100.1 "ip" "icmp" 3 1 \
0360                 "198.51.100.0/26"
0361         # type - Destination Unreachable
0362         # code - No Route
0363         __reject_route_test "IPv6" 2001:db8:2::1 "ipv6" "icmpv6" 1 0 \
0364                 "2001:db8:2::0/66" "-6"
0365 }
0366 
0367 __host_miss_test()
0368 {
0369         local desc=$1; shift
0370         local dip=$1; shift
0371         local trap_name="unresolved_neigh"
0372         local expected_action="trap"
0373         local mz_pid
0374 
0375         RET=0
0376 
0377         ping_check $trap_name
0378         trap_action_check $trap_name $expected_action
0379 
0380         ip neigh flush dev $rp2
0381 
0382         t0_packets=$(devlink_trap_rx_packets_get $trap_name)
0383 
0384         # Generate packets to h2 (will incur a unresolved neighbor).
0385         # The ping should pass and devlink counters should be increased.
0386         ping_do $h1 $dip
0387         check_err $? "ping failed: $desc"
0388 
0389         t1_packets=$(devlink_trap_rx_packets_get $trap_name)
0390 
0391         if [[ $t0_packets -eq $t1_packets ]]; then
0392                 check_err 1 "Trap counter did not increase"
0393         fi
0394 
0395         log_test "Unresolved neigh: host miss: $desc"
0396 }
0397 
0398 __invalid_nexthop_test()
0399 {
0400         local desc=$1; shift
0401         local dip=$1; shift
0402         local extra_add=$1; shift
0403         local subnet=$1; shift
0404         local via_add=$1; shift
0405         local trap_name="unresolved_neigh"
0406         local expected_action="trap"
0407         local mz_pid
0408 
0409         RET=0
0410 
0411         ping_check $trap_name
0412         trap_action_check $trap_name $expected_action
0413 
0414         ip address add $extra_add/$subnet dev $h2
0415 
0416         # Check that correct route does not trigger unresolved_neigh
0417         ip $flags route add $dip via $extra_add dev $rp2
0418 
0419         # Generate packets in order to discover all neighbours.
0420         # Without it, counters of unresolved_neigh will be increased
0421         # during neighbours discovery and the check below will fail
0422         # for a wrong reason
0423         ping_do $h1 $dip
0424 
0425         t0_packets=$(devlink_trap_rx_packets_get $trap_name)
0426         ping_do $h1 $dip
0427         t1_packets=$(devlink_trap_rx_packets_get $trap_name)
0428 
0429         if [[ $t0_packets -ne $t1_packets ]]; then
0430                 check_err 1 "Trap counter increased when it should not"
0431         fi
0432 
0433         ip $flags route del $dip via $extra_add dev $rp2
0434 
0435         # Check that route to nexthop that does not exist trigger
0436         # unresolved_neigh
0437         ip $flags route add $dip via $via_add dev $h2
0438 
0439         t0_packets=$(devlink_trap_rx_packets_get $trap_name)
0440         ping_do $h1 $dip
0441         t1_packets=$(devlink_trap_rx_packets_get $trap_name)
0442 
0443         if [[ $t0_packets -eq $t1_packets ]]; then
0444                 check_err 1 "Trap counter did not increase"
0445         fi
0446 
0447         ip $flags route del $dip via $via_add dev $h2
0448         ip address del $extra_add/$subnet dev $h2
0449         log_test "Unresolved neigh: nexthop does not exist: $desc"
0450 }
0451 
0452 __invalid_nexthop_bucket_test()
0453 {
0454         local desc=$1; shift
0455         local dip=$1; shift
0456         local via_add=$1; shift
0457         local trap_name="unresolved_neigh"
0458 
0459         RET=0
0460 
0461         # Check that route to nexthop that does not exist triggers
0462         # unresolved_neigh
0463         ip nexthop add id 1 via $via_add dev $rp2
0464         ip nexthop add id 10 group 1 type resilient buckets 32
0465         ip route add $dip nhid 10
0466 
0467         t0_packets=$(devlink_trap_rx_packets_get $trap_name)
0468         ping_do $h1 $dip
0469         t1_packets=$(devlink_trap_rx_packets_get $trap_name)
0470 
0471         if [[ $t0_packets -eq $t1_packets ]]; then
0472                 check_err 1 "Trap counter did not increase"
0473         fi
0474 
0475         ip route del $dip nhid 10
0476         ip nexthop del id 10
0477         ip nexthop del id 1
0478         log_test "Unresolved neigh: nexthop bucket does not exist: $desc"
0479 }
0480 
0481 unresolved_neigh_test()
0482 {
0483         __host_miss_test "IPv4" 198.51.100.1
0484         __host_miss_test "IPv6" 2001:db8:2::1
0485         __invalid_nexthop_test "IPv4" 198.51.100.1 198.51.100.3 24 198.51.100.4
0486         __invalid_nexthop_test "IPv6" 2001:db8:2::1 2001:db8:2::3 64 \
0487                 2001:db8:2::4
0488         __invalid_nexthop_bucket_test "IPv4" 198.51.100.1 198.51.100.4
0489         __invalid_nexthop_bucket_test "IPv6" 2001:db8:2::1 2001:db8:2::4
0490 }
0491 
0492 vrf_without_routes_create()
0493 {
0494         # VRF creating makes the links to be down and then up again.
0495         # By default, IPv6 address is not saved after link becomes down.
0496         # Save IPv6 address using sysctl configuration.
0497         sysctl_set net.ipv6.conf.$rp1.keep_addr_on_down 1
0498         sysctl_set net.ipv6.conf.$rp2.keep_addr_on_down 1
0499 
0500         ip link add dev vrf1 type vrf table 101
0501         ip link set dev $rp1 master vrf1
0502         ip link set dev $rp2 master vrf1
0503         ip link set dev vrf1 up
0504 
0505         # Wait for rp1 and rp2 to be up
0506         setup_wait
0507 }
0508 
0509 vrf_without_routes_destroy()
0510 {
0511         ip link set dev $rp1 nomaster
0512         ip link set dev $rp2 nomaster
0513         ip link del dev vrf1
0514 
0515         sysctl_restore net.ipv6.conf.$rp2.keep_addr_on_down
0516         sysctl_restore net.ipv6.conf.$rp1.keep_addr_on_down
0517 
0518         # Wait for interfaces to be up
0519         setup_wait
0520 }
0521 
0522 ipv4_lpm_miss_test()
0523 {
0524         local trap_name="ipv4_lpm_miss"
0525         local expected_action="trap"
0526         local mz_pid
0527 
0528         RET=0
0529 
0530         ping_check $trap_name
0531         trap_action_check $trap_name $expected_action
0532 
0533         # Create a VRF without a default route
0534         vrf_without_routes_create
0535 
0536         # Generate packets through a VRF without a matching route.
0537         $MZ $h1 -t udp "sp=54321,dp=12345" -c 0 -d 1msec -b $rp1mac \
0538                 -B 203.0.113.1 -q &
0539         mz_pid=$!
0540 
0541         devlink_trap_exception_test $trap_name
0542 
0543         log_test "LPM miss: IPv4"
0544 
0545         kill $mz_pid && wait $mz_pid &> /dev/null
0546         vrf_without_routes_destroy
0547 }
0548 
0549 ipv6_lpm_miss_test()
0550 {
0551         local trap_name="ipv6_lpm_miss"
0552         local expected_action="trap"
0553         local mz_pid
0554 
0555         RET=0
0556 
0557         ping_check $trap_name
0558         trap_action_check $trap_name $expected_action
0559 
0560         # Create a VRF without a default route
0561         vrf_without_routes_create
0562 
0563         # Generate packets through a VRF without a matching route.
0564         $MZ -6 $h1 -t udp "sp=54321,dp=12345" -c 0 -d 1msec -b $rp1mac \
0565                 -B 2001:db8::1 -q &
0566         mz_pid=$!
0567 
0568         devlink_trap_exception_test $trap_name
0569 
0570         log_test "LPM miss: IPv6"
0571 
0572         kill $mz_pid && wait $mz_pid &> /dev/null
0573         vrf_without_routes_destroy
0574 }
0575 
0576 trap cleanup EXIT
0577 
0578 setup_prepare
0579 setup_wait
0580 
0581 tests_run
0582 
0583 exit $EXIT_STATUS