#!/bin/bash # SPDX-License-Identifier: GPL-2.0 # # Test devlink-trap L2 drops functionality over mlxsw. Each registered L2 drop # packet trap is tested to make sure it is triggered under the right # conditions. lib_dir=$(dirname $0)/../../../net/forwarding ALL_TESTS=" source_mac_is_multicast_test vlan_tag_mismatch_test ingress_vlan_filter_test ingress_stp_filter_test port_list_is_empty_test port_loopback_filter_test " NUM_NETIFS=4 source $lib_dir/tc_common.sh source $lib_dir/lib.sh source $lib_dir/devlink_lib.sh h1_create() { simple_if_init $h1 } h1_destroy() { simple_if_fini $h1 } h2_create() { simple_if_init $h2 } h2_destroy() { simple_if_fini $h2 } switch_create() { ip link add dev br0 type bridge vlan_filtering 1 mcast_snooping 0 ip link set dev $swp1 master br0 ip link set dev $swp2 master br0 ip link set dev br0 up ip link set dev $swp1 up ip link set dev $swp2 up tc qdisc add dev $swp2 clsact } switch_destroy() { tc qdisc del dev $swp2 clsact ip link set dev $swp2 down ip link set dev $swp1 down ip link del dev br0 } setup_prepare() { h1=${NETIFS[p1]} swp1=${NETIFS[p2]} swp2=${NETIFS[p3]} h2=${NETIFS[p4]} vrf_prepare h1_create h2_create switch_create } cleanup() { pre_cleanup switch_destroy h2_destroy h1_destroy vrf_cleanup } source_mac_is_multicast_test() { local trap_name="source_mac_is_multicast" local smac=01:02:03:04:05:06 local mz_pid tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \ flower src_mac $smac action drop $MZ $h1 -c 0 -p 100 -a $smac -b bcast -t ip -d 1msec -q & mz_pid=$! RET=0 devlink_trap_drop_test $trap_name $swp2 101 log_test "Source MAC is multicast" devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101 } __vlan_tag_mismatch_test() { local trap_name="vlan_tag_mismatch" local dmac=de:ad:be:ef:13:37 local opt=$1; shift local mz_pid # Remove PVID flag. This should prevent untagged and prio-tagged # packets from entering the bridge. bridge vlan add vid 1 dev $swp1 untagged master tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \ flower dst_mac $dmac action drop $MZ $h1 "$opt" -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q & mz_pid=$! devlink_trap_drop_test $trap_name $swp2 101 # Add PVID and make sure packets are no longer dropped. bridge vlan add vid 1 dev $swp1 pvid untagged master devlink_trap_action_set $trap_name "trap" devlink_trap_stats_idle_test $trap_name check_err $? "Trap stats not idle when packets should not be dropped" devlink_trap_group_stats_idle_test $(devlink_trap_group_get $trap_name) check_err $? "Trap group stats not idle with when packets should not be dropped" tc_check_packets "dev $swp2 egress" 101 0 check_fail $? "Packets not forwarded when should" devlink_trap_action_set $trap_name "drop" devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101 } vlan_tag_mismatch_untagged_test() { RET=0 __vlan_tag_mismatch_test log_test "VLAN tag mismatch - untagged packets" } vlan_tag_mismatch_vid_0_test() { RET=0 __vlan_tag_mismatch_test "-Q 0" log_test "VLAN tag mismatch - prio-tagged packets" } vlan_tag_mismatch_test() { vlan_tag_mismatch_untagged_test vlan_tag_mismatch_vid_0_test } ingress_vlan_filter_test() { local trap_name="ingress_vlan_filter" local dmac=de:ad:be:ef:13:37 local mz_pid local vid=10 bridge vlan add vid $vid dev $swp2 master RET=0 tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \ flower dst_mac $dmac action drop $MZ $h1 -Q $vid -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q & mz_pid=$! devlink_trap_drop_test $trap_name $swp2 101 # Add the VLAN on the bridge port and make sure packets are no longer # dropped. bridge vlan add vid $vid dev $swp1 master devlink_trap_action_set $trap_name "trap" devlink_trap_stats_idle_test $trap_name check_err $? "Trap stats not idle when packets should not be dropped" devlink_trap_group_stats_idle_test $(devlink_trap_group_get $trap_name) check_err $? "Trap group stats not idle with when packets should not be dropped" tc_check_packets "dev $swp2 egress" 101 0 check_fail $? "Packets not forwarded when should" devlink_trap_action_set $trap_name "drop" log_test "Ingress VLAN filter" devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101 bridge vlan del vid $vid dev $swp1 master bridge vlan del vid $vid dev $swp2 master } __ingress_stp_filter_test() { local trap_name="ingress_spanning_tree_filter" local dmac=de:ad:be:ef:13:37 local state=$1; shift local mz_pid local vid=20 bridge vlan add vid $vid dev $swp2 master bridge vlan add vid $vid dev $swp1 master ip link set dev $swp1 type bridge_slave state $state tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \ flower dst_mac $dmac action drop $MZ $h1 -Q $vid -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q & mz_pid=$! devlink_trap_drop_test $trap_name $swp2 101 # Change STP state to forwarding and make sure packets are no longer # dropped. ip link set dev $swp1 type bridge_slave state 3 devlink_trap_action_set $trap_name "trap" devlink_trap_stats_idle_test $trap_name check_err $? "Trap stats not idle when packets should not be dropped" devlink_trap_group_stats_idle_test $(devlink_trap_group_get $trap_name) check_err $? "Trap group stats not idle with when packets should not be dropped" tc_check_packets "dev $swp2 egress" 101 0 check_fail $? "Packets not forwarded when should" devlink_trap_action_set $trap_name "drop" devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101 bridge vlan del vid $vid dev $swp1 master bridge vlan del vid $vid dev $swp2 master } ingress_stp_filter_listening_test() { local state=$1; shift RET=0 __ingress_stp_filter_test $state log_test "Ingress STP filter - listening state" } ingress_stp_filter_learning_test() { local state=$1; shift RET=0 __ingress_stp_filter_test $state log_test "Ingress STP filter - learning state" } ingress_stp_filter_test() { ingress_stp_filter_listening_test 1 ingress_stp_filter_learning_test 2 } port_list_is_empty_uc_test() { local trap_name="port_list_is_empty" local dmac=de:ad:be:ef:13:37 local mz_pid # Disable unicast flooding on both ports, so that packets cannot egress # any port. ip link set dev $swp1 type bridge_slave flood off ip link set dev $swp2 type bridge_slave flood off RET=0 tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \ flower dst_mac $dmac action drop $MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q & mz_pid=$! devlink_trap_drop_test $trap_name $swp2 101 # Allow packets to be flooded to one port. ip link set dev $swp2 type bridge_slave flood on devlink_trap_action_set $trap_name "trap" devlink_trap_stats_idle_test $trap_name check_err $? "Trap stats not idle when packets should not be dropped" devlink_trap_group_stats_idle_test $(devlink_trap_group_get $trap_name) check_err $? "Trap group stats not idle with when packets should not be dropped" tc_check_packets "dev $swp2 egress" 101 0 check_fail $? "Packets not forwarded when should" devlink_trap_action_set $trap_name "drop" log_test "Port list is empty - unicast" devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101 ip link set dev $swp1 type bridge_slave flood on } port_list_is_empty_mc_test() { local trap_name="port_list_is_empty" local dmac=01:00:5e:00:00:01 local dip=239.0.0.1 local mz_pid # Disable multicast flooding on both ports, so that packets cannot # egress any port. We also need to flush IP addresses from the bridge # in order to prevent packets from being flooded to the router port. ip link set dev $swp1 type bridge_slave mcast_flood off ip link set dev $swp2 type bridge_slave mcast_flood off ip address flush dev br0 RET=0 tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \ flower dst_mac $dmac action drop $MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -B $dip -d 1msec -q & mz_pid=$! devlink_trap_drop_test $trap_name $swp2 101 # Allow packets to be flooded to one port. ip link set dev $swp2 type bridge_slave mcast_flood on devlink_trap_action_set $trap_name "trap" devlink_trap_stats_idle_test $trap_name check_err $? "Trap stats not idle when packets should not be dropped" devlink_trap_group_stats_idle_test $(devlink_trap_group_get $trap_name) check_err $? "Trap group stats not idle with when packets should not be dropped" tc_check_packets "dev $swp2 egress" 101 0 check_fail $? "Packets not forwarded when should" devlink_trap_action_set $trap_name "drop" log_test "Port list is empty - multicast" devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101 ip link set dev $swp1 type bridge_slave mcast_flood on } port_list_is_empty_test() { port_list_is_empty_uc_test port_list_is_empty_mc_test } port_loopback_filter_uc_test() { local trap_name="port_loopback_filter" local dmac=de:ad:be:ef:13:37 local mz_pid # Make sure packets can only egress the input port. ip link set dev $swp2 type bridge_slave flood off RET=0 tc filter add dev $swp2 egress protocol ip pref 1 handle 101 \ flower dst_mac $dmac action drop $MZ $h1 -c 0 -p 100 -a own -b $dmac -t ip -d 1msec -q & mz_pid=$! devlink_trap_drop_test $trap_name $swp2 101 # Allow packets to be flooded. ip link set dev $swp2 type bridge_slave flood on devlink_trap_action_set $trap_name "trap" devlink_trap_stats_idle_test $trap_name check_err $? "Trap stats not idle when packets should not be dropped" devlink_trap_group_stats_idle_test $(devlink_trap_group_get $trap_name) check_err $? "Trap group stats not idle with when packets should not be dropped" tc_check_packets "dev $swp2 egress" 101 0 check_fail $? "Packets not forwarded when should" devlink_trap_action_set $trap_name "drop" log_test "Port loopback filter - unicast" devlink_trap_drop_cleanup $mz_pid $swp2 ip 1 101 } port_loopback_filter_test() { port_loopback_filter_uc_test } trap cleanup EXIT setup_prepare setup_wait tests_run exit $EXIT_STATUS