1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0 3# 4# This test is for checking devlink-trap functionality. It makes use of 5# netdevsim which implements the required callbacks. 6 7lib_dir=$(dirname $0)/../../../net/forwarding 8 9ALL_TESTS=" 10 init_test 11 trap_action_test 12 trap_metadata_test 13 bad_trap_test 14 bad_trap_action_test 15 trap_stats_test 16 trap_group_action_test 17 bad_trap_group_test 18 trap_group_stats_test 19 trap_policer_test 20 trap_policer_bind_test 21 port_del_test 22 dev_del_test 23" 24NETDEVSIM_PATH=/sys/bus/netdevsim/ 25DEV_ADDR=1337 26DEV=netdevsim${DEV_ADDR} 27DEVLINK_DEV=netdevsim/${DEV} 28DEBUGFS_DIR=/sys/kernel/debug/netdevsim/$DEV/ 29SLEEP_TIME=1 30NETDEV="" 31NUM_NETIFS=0 32source $lib_dir/lib.sh 33source $lib_dir/devlink_lib.sh 34 35require_command udevadm 36 37modprobe netdevsim &> /dev/null 38if [ ! -d "$NETDEVSIM_PATH" ]; then 39 echo "SKIP: No netdevsim support" 40 exit 1 41fi 42 43if [ -d "${NETDEVSIM_PATH}/devices/netdevsim${DEV_ADDR}" ]; then 44 echo "SKIP: Device netdevsim${DEV_ADDR} already exists" 45 exit 1 46fi 47 48init_test() 49{ 50 RET=0 51 52 test $(devlink_traps_num_get) -ne 0 53 check_err $? "No traps were registered" 54 55 log_test "Initialization" 56} 57 58trap_action_test() 59{ 60 local orig_action 61 local trap_name 62 local action 63 64 RET=0 65 66 for trap_name in $(devlink_traps_get); do 67 # The action of non-drop traps cannot be changed. 68 if [ $(devlink_trap_type_get $trap_name) = "drop" ]; then 69 devlink_trap_action_set $trap_name "trap" 70 action=$(devlink_trap_action_get $trap_name) 71 if [ $action != "trap" ]; then 72 check_err 1 "Trap $trap_name did not change action to trap" 73 fi 74 75 devlink_trap_action_set $trap_name "drop" 76 action=$(devlink_trap_action_get $trap_name) 77 if [ $action != "drop" ]; then 78 check_err 1 "Trap $trap_name did not change action to drop" 79 fi 80 else 81 orig_action=$(devlink_trap_action_get $trap_name) 82 83 devlink_trap_action_set $trap_name "trap" 84 action=$(devlink_trap_action_get $trap_name) 85 if [ $action != $orig_action ]; then 86 check_err 1 "Trap $trap_name changed action when should not" 87 fi 88 89 devlink_trap_action_set $trap_name "drop" 90 action=$(devlink_trap_action_get $trap_name) 91 if [ $action != $orig_action ]; then 92 check_err 1 "Trap $trap_name changed action when should not" 93 fi 94 fi 95 done 96 97 log_test "Trap action" 98} 99 100trap_metadata_test() 101{ 102 local trap_name 103 104 RET=0 105 106 for trap_name in $(devlink_traps_get); do 107 devlink_trap_metadata_test $trap_name "input_port" 108 check_err $? "Input port not reported as metadata of trap $trap_name" 109 if [ $trap_name == "ingress_flow_action_drop" ] || 110 [ $trap_name == "egress_flow_action_drop" ]; then 111 devlink_trap_metadata_test $trap_name "flow_action_cookie" 112 check_err $? "Flow action cookie not reported as metadata of trap $trap_name" 113 fi 114 done 115 116 log_test "Trap metadata" 117} 118 119bad_trap_test() 120{ 121 RET=0 122 123 devlink_trap_action_set "made_up_trap" "drop" 124 check_fail $? "Did not get an error for non-existing trap" 125 126 log_test "Non-existing trap" 127} 128 129bad_trap_action_test() 130{ 131 local traps_arr 132 local trap_name 133 134 RET=0 135 136 # Pick first trap. 137 traps_arr=($(devlink_traps_get)) 138 trap_name=${traps_arr[0]} 139 140 devlink_trap_action_set $trap_name "made_up_action" 141 check_fail $? "Did not get an error for non-existing trap action" 142 143 log_test "Non-existing trap action" 144} 145 146trap_stats_test() 147{ 148 local trap_name 149 150 RET=0 151 152 for trap_name in $(devlink_traps_get); do 153 devlink_trap_stats_idle_test $trap_name 154 check_err $? "Stats of trap $trap_name not idle when netdev down" 155 156 ip link set dev $NETDEV up 157 158 if [ $(devlink_trap_type_get $trap_name) = "drop" ]; then 159 devlink_trap_action_set $trap_name "trap" 160 devlink_trap_stats_idle_test $trap_name 161 check_fail $? "Stats of trap $trap_name idle when action is trap" 162 163 devlink_trap_action_set $trap_name "drop" 164 devlink_trap_stats_idle_test $trap_name 165 check_err $? "Stats of trap $trap_name not idle when action is drop" 166 else 167 devlink_trap_stats_idle_test $trap_name 168 check_fail $? "Stats of non-drop trap $trap_name idle when should not" 169 fi 170 171 ip link set dev $NETDEV down 172 done 173 174 log_test "Trap statistics" 175} 176 177trap_group_action_test() 178{ 179 local curr_group group_name 180 local trap_name 181 local trap_type 182 local action 183 184 RET=0 185 186 for group_name in $(devlink_trap_groups_get); do 187 devlink_trap_group_action_set $group_name "trap" 188 189 for trap_name in $(devlink_traps_get); do 190 curr_group=$(devlink_trap_group_get $trap_name) 191 if [ $curr_group != $group_name ]; then 192 continue 193 fi 194 195 trap_type=$(devlink_trap_type_get $trap_name) 196 if [ $trap_type != "drop" ]; then 197 continue 198 fi 199 200 action=$(devlink_trap_action_get $trap_name) 201 if [ $action != "trap" ]; then 202 check_err 1 "Trap $trap_name did not change action to trap" 203 fi 204 done 205 206 devlink_trap_group_action_set $group_name "drop" 207 208 for trap_name in $(devlink_traps_get); do 209 curr_group=$(devlink_trap_group_get $trap_name) 210 if [ $curr_group != $group_name ]; then 211 continue 212 fi 213 214 trap_type=$(devlink_trap_type_get $trap_name) 215 if [ $trap_type != "drop" ]; then 216 continue 217 fi 218 219 action=$(devlink_trap_action_get $trap_name) 220 if [ $action != "drop" ]; then 221 check_err 1 "Trap $trap_name did not change action to drop" 222 fi 223 done 224 done 225 226 log_test "Trap group action" 227} 228 229bad_trap_group_test() 230{ 231 RET=0 232 233 devlink_trap_group_action_set "made_up_trap_group" "drop" 234 check_fail $? "Did not get an error for non-existing trap group" 235 236 log_test "Non-existing trap group" 237} 238 239trap_group_stats_test() 240{ 241 local group_name 242 243 RET=0 244 245 for group_name in $(devlink_trap_groups_get); do 246 devlink_trap_group_stats_idle_test $group_name 247 check_err $? "Stats of trap group $group_name not idle when netdev down" 248 249 ip link set dev $NETDEV up 250 251 devlink_trap_group_action_set $group_name "trap" 252 devlink_trap_group_stats_idle_test $group_name 253 check_fail $? "Stats of trap group $group_name idle when action is trap" 254 255 devlink_trap_group_action_set $group_name "drop" 256 ip link set dev $NETDEV down 257 done 258 259 log_test "Trap group statistics" 260} 261 262trap_policer_test() 263{ 264 local packets_t0 265 local packets_t1 266 267 if [ $(devlink_trap_policers_num_get) -eq 0 ]; then 268 check_err 1 "Failed to dump policers" 269 fi 270 271 devlink trap policer set $DEVLINK_DEV policer 1337 &> /dev/null 272 check_fail $? "Did not get an error for setting a non-existing policer" 273 devlink trap policer show $DEVLINK_DEV policer 1337 &> /dev/null 274 check_fail $? "Did not get an error for getting a non-existing policer" 275 276 devlink trap policer set $DEVLINK_DEV policer 1 rate 2000 burst 16 277 check_err $? "Failed to set valid parameters for a valid policer" 278 if [ $(devlink_trap_policer_rate_get 1) -ne 2000 ]; then 279 check_err 1 "Policer rate was not changed" 280 fi 281 if [ $(devlink_trap_policer_burst_get 1) -ne 16 ]; then 282 check_err 1 "Policer burst size was not changed" 283 fi 284 285 devlink trap policer set $DEVLINK_DEV policer 1 rate 0 &> /dev/null 286 check_fail $? "Policer rate was changed to rate lower than limit" 287 devlink trap policer set $DEVLINK_DEV policer 1 rate 9000 &> /dev/null 288 check_fail $? "Policer rate was changed to rate higher than limit" 289 devlink trap policer set $DEVLINK_DEV policer 1 burst 2 &> /dev/null 290 check_fail $? "Policer burst size was changed to burst size lower than limit" 291 devlink trap policer set $DEVLINK_DEV policer 1 rate 65537 &> /dev/null 292 check_fail $? "Policer burst size was changed to burst size higher than limit" 293 echo "y" > $DEBUGFS_DIR/fail_trap_policer_set 294 devlink trap policer set $DEVLINK_DEV policer 1 rate 3000 &> /dev/null 295 check_fail $? "Managed to set policer rate when should not" 296 echo "n" > $DEBUGFS_DIR/fail_trap_policer_set 297 if [ $(devlink_trap_policer_rate_get 1) -ne 2000 ]; then 298 check_err 1 "Policer rate was changed to an invalid value" 299 fi 300 if [ $(devlink_trap_policer_burst_get 1) -ne 16 ]; then 301 check_err 1 "Policer burst size was changed to an invalid value" 302 fi 303 304 packets_t0=$(devlink_trap_policer_rx_dropped_get 1) 305 sleep .5 306 packets_t1=$(devlink_trap_policer_rx_dropped_get 1) 307 if [ ! $packets_t1 -gt $packets_t0 ]; then 308 check_err 1 "Policer drop counter was not incremented" 309 fi 310 311 echo "y"> $DEBUGFS_DIR/fail_trap_policer_counter_get 312 devlink -s trap policer show $DEVLINK_DEV policer 1 &> /dev/null 313 check_fail $? "Managed to read policer drop counter when should not" 314 echo "n"> $DEBUGFS_DIR/fail_trap_policer_counter_get 315 devlink -s trap policer show $DEVLINK_DEV policer 1 &> /dev/null 316 check_err $? "Did not manage to read policer drop counter when should" 317 318 log_test "Trap policer" 319} 320 321trap_group_check_policer() 322{ 323 local group_name=$1; shift 324 325 devlink -j -p trap group show $DEVLINK_DEV group $group_name \ 326 | jq -e '.[][][]["policer"]' &> /dev/null 327} 328 329trap_policer_bind_test() 330{ 331 devlink trap group set $DEVLINK_DEV group l2_drops policer 1 332 check_err $? "Failed to bind a valid policer" 333 if [ $(devlink_trap_group_policer_get "l2_drops") -ne 1 ]; then 334 check_err 1 "Bound policer was not changed" 335 fi 336 337 devlink trap group set $DEVLINK_DEV group l2_drops policer 1337 \ 338 &> /dev/null 339 check_fail $? "Did not get an error for binding a non-existing policer" 340 if [ $(devlink_trap_group_policer_get "l2_drops") -ne 1 ]; then 341 check_err 1 "Bound policer was changed when should not" 342 fi 343 344 devlink trap group set $DEVLINK_DEV group l2_drops policer 0 345 check_err $? "Failed to unbind a policer when using ID 0" 346 trap_group_check_policer "l2_drops" 347 check_fail $? "Trap group has a policer after unbinding with ID 0" 348 349 devlink trap group set $DEVLINK_DEV group l2_drops policer 1 350 check_err $? "Failed to bind a valid policer" 351 352 devlink trap group set $DEVLINK_DEV group l2_drops nopolicer 353 check_err $? "Failed to unbind a policer when using 'nopolicer' keyword" 354 trap_group_check_policer "l2_drops" 355 check_fail $? "Trap group has a policer after unbinding with 'nopolicer' keyword" 356 357 devlink trap group set $DEVLINK_DEV group l2_drops policer 1 358 check_err $? "Failed to bind a valid policer" 359 360 echo "y"> $DEBUGFS_DIR/fail_trap_group_set 361 devlink trap group set $DEVLINK_DEV group l2_drops policer 2 \ 362 &> /dev/null 363 check_fail $? "Managed to bind a policer when should not" 364 echo "n"> $DEBUGFS_DIR/fail_trap_group_set 365 devlink trap group set $DEVLINK_DEV group l2_drops policer 2 366 check_err $? "Did not manage to bind a policer when should" 367 368 devlink trap group set $DEVLINK_DEV group l2_drops action drop \ 369 policer 1337 &> /dev/null 370 check_fail $? "Did not get an error for partially modified trap group" 371 372 log_test "Trap policer binding" 373} 374 375port_del_test() 376{ 377 local group_name 378 local i 379 380 # The test never fails. It is meant to exercise different code paths 381 # and make sure we properly dismantle a port while packets are 382 # in-flight. 383 RET=0 384 385 devlink_traps_enable_all 386 387 for i in $(seq 1 10); do 388 ip link set dev $NETDEV up 389 390 sleep $SLEEP_TIME 391 392 netdevsim_port_destroy 393 netdevsim_port_create 394 udevadm settle 395 done 396 397 devlink_traps_disable_all 398 399 log_test "Port delete" 400} 401 402dev_del_test() 403{ 404 local group_name 405 local i 406 407 # The test never fails. It is meant to exercise different code paths 408 # and make sure we properly unregister traps while packets are 409 # in-flight. 410 RET=0 411 412 devlink_traps_enable_all 413 414 for i in $(seq 1 10); do 415 ip link set dev $NETDEV up 416 417 sleep $SLEEP_TIME 418 419 cleanup 420 setup_prepare 421 done 422 423 devlink_traps_disable_all 424 425 log_test "Device delete" 426} 427 428netdevsim_dev_create() 429{ 430 echo "$DEV_ADDR 0" > ${NETDEVSIM_PATH}/new_device 431} 432 433netdevsim_dev_destroy() 434{ 435 echo "$DEV_ADDR" > ${NETDEVSIM_PATH}/del_device 436} 437 438netdevsim_port_create() 439{ 440 echo 1 > ${NETDEVSIM_PATH}/devices/${DEV}/new_port 441} 442 443netdevsim_port_destroy() 444{ 445 echo 1 > ${NETDEVSIM_PATH}/devices/${DEV}/del_port 446} 447 448setup_prepare() 449{ 450 local netdev 451 452 netdevsim_dev_create 453 454 if [ ! -d "${NETDEVSIM_PATH}/devices/${DEV}" ]; then 455 echo "Failed to create netdevsim device" 456 exit 1 457 fi 458 459 netdevsim_port_create 460 461 if [ ! -d "${NETDEVSIM_PATH}/devices/${DEV}/net/" ]; then 462 echo "Failed to create netdevsim port" 463 exit 1 464 fi 465 466 # Wait for udev to rename newly created netdev. 467 udevadm settle 468 469 NETDEV=$(ls ${NETDEVSIM_PATH}/devices/${DEV}/net/) 470} 471 472cleanup() 473{ 474 pre_cleanup 475 netdevsim_port_destroy 476 netdevsim_dev_destroy 477} 478 479trap cleanup EXIT 480 481setup_prepare 482 483tests_run 484 485exit $EXIT_STATUS 486