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