| #!/bin/bash |
| # SPDX-License-Identifier: GPL-2.0 |
| # |
| # This test is for checking devlink-trap functionality. It makes use of |
| # netdevsim which implements the required callbacks. |
| |
| lib_dir=$(dirname $0)/../../../net/forwarding |
| |
| ALL_TESTS=" |
| init_test |
| trap_action_test |
| trap_metadata_test |
| bad_trap_test |
| bad_trap_action_test |
| trap_stats_test |
| trap_group_action_test |
| bad_trap_group_test |
| trap_group_stats_test |
| port_del_test |
| dev_del_test |
| " |
| NETDEVSIM_PATH=/sys/bus/netdevsim/ |
| DEV_ADDR=1337 |
| DEV=netdevsim${DEV_ADDR} |
| DEVLINK_DEV=netdevsim/${DEV} |
| SLEEP_TIME=1 |
| NETDEV="" |
| NUM_NETIFS=0 |
| source $lib_dir/lib.sh |
| source $lib_dir/devlink_lib.sh |
| |
| require_command udevadm |
| |
| modprobe netdevsim &> /dev/null |
| if [ ! -d "$NETDEVSIM_PATH" ]; then |
| echo "SKIP: No netdevsim support" |
| exit 1 |
| fi |
| |
| if [ -d "${NETDEVSIM_PATH}/devices/netdevsim${DEV_ADDR}" ]; then |
| echo "SKIP: Device netdevsim${DEV_ADDR} already exists" |
| exit 1 |
| fi |
| |
| init_test() |
| { |
| RET=0 |
| |
| test $(devlink_traps_num_get) -ne 0 |
| check_err $? "No traps were registered" |
| |
| log_test "Initialization" |
| } |
| |
| trap_action_test() |
| { |
| local orig_action |
| local trap_name |
| local action |
| |
| RET=0 |
| |
| for trap_name in $(devlink_traps_get); do |
| # The action of non-drop traps cannot be changed. |
| if [ $(devlink_trap_type_get $trap_name) = "drop" ]; then |
| devlink_trap_action_set $trap_name "trap" |
| action=$(devlink_trap_action_get $trap_name) |
| if [ $action != "trap" ]; then |
| check_err 1 "Trap $trap_name did not change action to trap" |
| fi |
| |
| devlink_trap_action_set $trap_name "drop" |
| action=$(devlink_trap_action_get $trap_name) |
| if [ $action != "drop" ]; then |
| check_err 1 "Trap $trap_name did not change action to drop" |
| fi |
| else |
| orig_action=$(devlink_trap_action_get $trap_name) |
| |
| devlink_trap_action_set $trap_name "trap" |
| action=$(devlink_trap_action_get $trap_name) |
| if [ $action != $orig_action ]; then |
| check_err 1 "Trap $trap_name changed action when should not" |
| fi |
| |
| devlink_trap_action_set $trap_name "drop" |
| action=$(devlink_trap_action_get $trap_name) |
| if [ $action != $orig_action ]; then |
| check_err 1 "Trap $trap_name changed action when should not" |
| fi |
| fi |
| done |
| |
| log_test "Trap action" |
| } |
| |
| trap_metadata_test() |
| { |
| local trap_name |
| |
| RET=0 |
| |
| for trap_name in $(devlink_traps_get); do |
| devlink_trap_metadata_test $trap_name "input_port" |
| check_err $? "Input port not reported as metadata of trap $trap_name" |
| done |
| |
| log_test "Trap metadata" |
| } |
| |
| bad_trap_test() |
| { |
| RET=0 |
| |
| devlink_trap_action_set "made_up_trap" "drop" |
| check_fail $? "Did not get an error for non-existing trap" |
| |
| log_test "Non-existing trap" |
| } |
| |
| bad_trap_action_test() |
| { |
| local traps_arr |
| local trap_name |
| |
| RET=0 |
| |
| # Pick first trap. |
| traps_arr=($(devlink_traps_get)) |
| trap_name=${traps_arr[0]} |
| |
| devlink_trap_action_set $trap_name "made_up_action" |
| check_fail $? "Did not get an error for non-existing trap action" |
| |
| log_test "Non-existing trap action" |
| } |
| |
| trap_stats_test() |
| { |
| local trap_name |
| |
| RET=0 |
| |
| for trap_name in $(devlink_traps_get); do |
| devlink_trap_stats_idle_test $trap_name |
| check_err $? "Stats of trap $trap_name not idle when netdev down" |
| |
| ip link set dev $NETDEV up |
| |
| if [ $(devlink_trap_type_get $trap_name) = "drop" ]; then |
| devlink_trap_action_set $trap_name "trap" |
| devlink_trap_stats_idle_test $trap_name |
| check_fail $? "Stats of trap $trap_name idle when action is trap" |
| |
| devlink_trap_action_set $trap_name "drop" |
| devlink_trap_stats_idle_test $trap_name |
| check_err $? "Stats of trap $trap_name not idle when action is drop" |
| else |
| devlink_trap_stats_idle_test $trap_name |
| check_fail $? "Stats of non-drop trap $trap_name idle when should not" |
| fi |
| |
| ip link set dev $NETDEV down |
| done |
| |
| log_test "Trap statistics" |
| } |
| |
| trap_group_action_test() |
| { |
| local curr_group group_name |
| local trap_name |
| local trap_type |
| local action |
| |
| RET=0 |
| |
| for group_name in $(devlink_trap_groups_get); do |
| devlink_trap_group_action_set $group_name "trap" |
| |
| for trap_name in $(devlink_traps_get); do |
| curr_group=$(devlink_trap_group_get $trap_name) |
| if [ $curr_group != $group_name ]; then |
| continue |
| fi |
| |
| trap_type=$(devlink_trap_type_get $trap_name) |
| if [ $trap_type != "drop" ]; then |
| continue |
| fi |
| |
| action=$(devlink_trap_action_get $trap_name) |
| if [ $action != "trap" ]; then |
| check_err 1 "Trap $trap_name did not change action to trap" |
| fi |
| done |
| |
| devlink_trap_group_action_set $group_name "drop" |
| |
| for trap_name in $(devlink_traps_get); do |
| curr_group=$(devlink_trap_group_get $trap_name) |
| if [ $curr_group != $group_name ]; then |
| continue |
| fi |
| |
| trap_type=$(devlink_trap_type_get $trap_name) |
| if [ $trap_type != "drop" ]; then |
| continue |
| fi |
| |
| action=$(devlink_trap_action_get $trap_name) |
| if [ $action != "drop" ]; then |
| check_err 1 "Trap $trap_name did not change action to drop" |
| fi |
| done |
| done |
| |
| log_test "Trap group action" |
| } |
| |
| bad_trap_group_test() |
| { |
| RET=0 |
| |
| devlink_trap_group_action_set "made_up_trap_group" "drop" |
| check_fail $? "Did not get an error for non-existing trap group" |
| |
| log_test "Non-existing trap group" |
| } |
| |
| trap_group_stats_test() |
| { |
| local group_name |
| |
| RET=0 |
| |
| for group_name in $(devlink_trap_groups_get); do |
| devlink_trap_group_stats_idle_test $group_name |
| check_err $? "Stats of trap group $group_name not idle when netdev down" |
| |
| ip link set dev $NETDEV up |
| |
| devlink_trap_group_action_set $group_name "trap" |
| devlink_trap_group_stats_idle_test $group_name |
| check_fail $? "Stats of trap group $group_name idle when action is trap" |
| |
| devlink_trap_group_action_set $group_name "drop" |
| ip link set dev $NETDEV down |
| done |
| |
| log_test "Trap group statistics" |
| } |
| |
| port_del_test() |
| { |
| local group_name |
| local i |
| |
| # The test never fails. It is meant to exercise different code paths |
| # and make sure we properly dismantle a port while packets are |
| # in-flight. |
| RET=0 |
| |
| devlink_traps_enable_all |
| |
| for i in $(seq 1 10); do |
| ip link set dev $NETDEV up |
| |
| sleep $SLEEP_TIME |
| |
| netdevsim_port_destroy |
| netdevsim_port_create |
| udevadm settle |
| done |
| |
| devlink_traps_disable_all |
| |
| log_test "Port delete" |
| } |
| |
| dev_del_test() |
| { |
| local group_name |
| local i |
| |
| # The test never fails. It is meant to exercise different code paths |
| # and make sure we properly unregister traps while packets are |
| # in-flight. |
| RET=0 |
| |
| devlink_traps_enable_all |
| |
| for i in $(seq 1 10); do |
| ip link set dev $NETDEV up |
| |
| sleep $SLEEP_TIME |
| |
| cleanup |
| setup_prepare |
| done |
| |
| devlink_traps_disable_all |
| |
| log_test "Device delete" |
| } |
| |
| netdevsim_dev_create() |
| { |
| echo "$DEV_ADDR 0" > ${NETDEVSIM_PATH}/new_device |
| } |
| |
| netdevsim_dev_destroy() |
| { |
| echo "$DEV_ADDR" > ${NETDEVSIM_PATH}/del_device |
| } |
| |
| netdevsim_port_create() |
| { |
| echo 1 > ${NETDEVSIM_PATH}/devices/${DEV}/new_port |
| } |
| |
| netdevsim_port_destroy() |
| { |
| echo 1 > ${NETDEVSIM_PATH}/devices/${DEV}/del_port |
| } |
| |
| setup_prepare() |
| { |
| local netdev |
| |
| netdevsim_dev_create |
| |
| if [ ! -d "${NETDEVSIM_PATH}/devices/${DEV}" ]; then |
| echo "Failed to create netdevsim device" |
| exit 1 |
| fi |
| |
| netdevsim_port_create |
| |
| if [ ! -d "${NETDEVSIM_PATH}/devices/${DEV}/net/" ]; then |
| echo "Failed to create netdevsim port" |
| exit 1 |
| fi |
| |
| # Wait for udev to rename newly created netdev. |
| udevadm settle |
| |
| NETDEV=$(ls ${NETDEVSIM_PATH}/devices/${DEV}/net/) |
| } |
| |
| cleanup() |
| { |
| pre_cleanup |
| netdevsim_port_destroy |
| netdevsim_dev_destroy |
| } |
| |
| trap cleanup EXIT |
| |
| setup_prepare |
| |
| tests_run |
| |
| exit $EXIT_STATUS |