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