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 else 169 devlink_trap_stats_idle_test $trap_name 170 check_fail $? "Stats of non-drop trap $trap_name idle when should not" 171 fi 172 173 ip link set dev $NETDEV down 174 done 175 176 log_test "Trap statistics" 177} 178 179trap_group_action_test() 180{ 181 local curr_group group_name 182 local trap_name 183 local trap_type 184 local action 185 186 RET=0 187 188 for group_name in $(devlink_trap_groups_get); do 189 devlink_trap_group_action_set $group_name "trap" 190 191 for trap_name in $(devlink_traps_get); do 192 curr_group=$(devlink_trap_group_get $trap_name) 193 if [ $curr_group != $group_name ]; then 194 continue 195 fi 196 197 trap_type=$(devlink_trap_type_get $trap_name) 198 if [ $trap_type != "drop" ]; then 199 continue 200 fi 201 202 action=$(devlink_trap_action_get $trap_name) 203 if [ $action != "trap" ]; then 204 check_err 1 "Trap $trap_name did not change action to trap" 205 fi 206 done 207 208 devlink_trap_group_action_set $group_name "drop" 209 210 for trap_name in $(devlink_traps_get); do 211 curr_group=$(devlink_trap_group_get $trap_name) 212 if [ $curr_group != $group_name ]; then 213 continue 214 fi 215 216 trap_type=$(devlink_trap_type_get $trap_name) 217 if [ $trap_type != "drop" ]; then 218 continue 219 fi 220 221 action=$(devlink_trap_action_get $trap_name) 222 if [ $action != "drop" ]; then 223 check_err 1 "Trap $trap_name did not change action to drop" 224 fi 225 done 226 done 227 228 log_test "Trap group action" 229} 230 231bad_trap_group_test() 232{ 233 RET=0 234 235 devlink_trap_group_action_set "made_up_trap_group" "drop" 236 check_fail $? "Did not get an error for non-existing trap group" 237 238 log_test "Non-existing trap group" 239} 240 241trap_group_stats_test() 242{ 243 local group_name 244 245 RET=0 246 247 for group_name in $(devlink_trap_groups_get); do 248 devlink_trap_group_stats_idle_test $group_name 249 check_err $? "Stats of trap group $group_name not idle when netdev down" 250 251 ip link set dev $NETDEV up 252 253 devlink_trap_group_action_set $group_name "trap" 254 devlink_trap_group_stats_idle_test $group_name 255 check_fail $? "Stats of trap group $group_name idle when action is trap" 256 257 devlink_trap_group_action_set $group_name "drop" 258 ip link set dev $NETDEV down 259 done 260 261 log_test "Trap group statistics" 262} 263 264trap_policer_test() 265{ 266 local packets_t0 267 local packets_t1 268 269 RET=0 270 271 if [ $(devlink_trap_policers_num_get) -eq 0 ]; then 272 check_err 1 "Failed to dump policers" 273 fi 274 275 devlink trap policer set $DEVLINK_DEV policer 1337 &> /dev/null 276 check_fail $? "Did not get an error for setting a non-existing policer" 277 devlink trap policer show $DEVLINK_DEV policer 1337 &> /dev/null 278 check_fail $? "Did not get an error for getting a non-existing policer" 279 280 devlink trap policer set $DEVLINK_DEV policer 1 rate 2000 burst 16 281 check_err $? "Failed to set valid parameters for a valid policer" 282 if [ $(devlink_trap_policer_rate_get 1) -ne 2000 ]; then 283 check_err 1 "Policer rate was not changed" 284 fi 285 if [ $(devlink_trap_policer_burst_get 1) -ne 16 ]; then 286 check_err 1 "Policer burst size was not changed" 287 fi 288 289 devlink trap policer set $DEVLINK_DEV policer 1 rate 0 &> /dev/null 290 check_fail $? "Policer rate was changed to rate lower than limit" 291 devlink trap policer set $DEVLINK_DEV policer 1 rate 9000 &> /dev/null 292 check_fail $? "Policer rate was changed to rate higher than limit" 293 devlink trap policer set $DEVLINK_DEV policer 1 burst 2 &> /dev/null 294 check_fail $? "Policer burst size was changed to burst size lower than limit" 295 devlink trap policer set $DEVLINK_DEV policer 1 rate 65537 &> /dev/null 296 check_fail $? "Policer burst size was changed to burst size higher than limit" 297 echo "y" > $DEBUGFS_DIR/fail_trap_policer_set 298 devlink trap policer set $DEVLINK_DEV policer 1 rate 3000 &> /dev/null 299 check_fail $? "Managed to set policer rate when should not" 300 echo "n" > $DEBUGFS_DIR/fail_trap_policer_set 301 if [ $(devlink_trap_policer_rate_get 1) -ne 2000 ]; then 302 check_err 1 "Policer rate was changed to an invalid value" 303 fi 304 if [ $(devlink_trap_policer_burst_get 1) -ne 16 ]; then 305 check_err 1 "Policer burst size was changed to an invalid value" 306 fi 307 308 packets_t0=$(devlink_trap_policer_rx_dropped_get 1) 309 sleep .5 310 packets_t1=$(devlink_trap_policer_rx_dropped_get 1) 311 if [ ! $packets_t1 -gt $packets_t0 ]; then 312 check_err 1 "Policer drop counter was not incremented" 313 fi 314 315 echo "y"> $DEBUGFS_DIR/fail_trap_policer_counter_get 316 devlink -s trap policer show $DEVLINK_DEV policer 1 &> /dev/null 317 check_fail $? "Managed to read policer drop counter when should not" 318 echo "n"> $DEBUGFS_DIR/fail_trap_policer_counter_get 319 devlink -s trap policer show $DEVLINK_DEV policer 1 &> /dev/null 320 check_err $? "Did not manage to read policer drop counter when should" 321 322 log_test "Trap policer" 323} 324 325trap_group_check_policer() 326{ 327 local group_name=$1; shift 328 329 devlink -j -p trap group show $DEVLINK_DEV group $group_name \ 330 | jq -e '.[][][]["policer"]' &> /dev/null 331} 332 333trap_policer_bind_test() 334{ 335 RET=0 336 337 devlink trap group set $DEVLINK_DEV group l2_drops policer 1 338 check_err $? "Failed to bind a valid policer" 339 if [ $(devlink_trap_group_policer_get "l2_drops") -ne 1 ]; then 340 check_err 1 "Bound policer was not changed" 341 fi 342 343 devlink trap group set $DEVLINK_DEV group l2_drops policer 1337 \ 344 &> /dev/null 345 check_fail $? "Did not get an error for binding a non-existing policer" 346 if [ $(devlink_trap_group_policer_get "l2_drops") -ne 1 ]; then 347 check_err 1 "Bound policer was changed when should not" 348 fi 349 350 devlink trap group set $DEVLINK_DEV group l2_drops policer 0 351 check_err $? "Failed to unbind a policer when using ID 0" 352 trap_group_check_policer "l2_drops" 353 check_fail $? "Trap group has a policer after unbinding with ID 0" 354 355 devlink trap group set $DEVLINK_DEV group l2_drops policer 1 356 check_err $? "Failed to bind a valid policer" 357 358 devlink trap group set $DEVLINK_DEV group l2_drops nopolicer 359 check_err $? "Failed to unbind a policer when using 'nopolicer' keyword" 360 trap_group_check_policer "l2_drops" 361 check_fail $? "Trap group has a policer after unbinding with 'nopolicer' keyword" 362 363 devlink trap group set $DEVLINK_DEV group l2_drops policer 1 364 check_err $? "Failed to bind a valid policer" 365 366 echo "y"> $DEBUGFS_DIR/fail_trap_group_set 367 devlink trap group set $DEVLINK_DEV group l2_drops policer 2 \ 368 &> /dev/null 369 check_fail $? "Managed to bind a policer when should not" 370 echo "n"> $DEBUGFS_DIR/fail_trap_group_set 371 devlink trap group set $DEVLINK_DEV group l2_drops policer 2 372 check_err $? "Did not manage to bind a policer when should" 373 374 devlink trap group set $DEVLINK_DEV group l2_drops action drop \ 375 policer 1337 &> /dev/null 376 check_fail $? "Did not get an error for partially modified trap group" 377 378 log_test "Trap policer binding" 379} 380 381port_del_test() 382{ 383 local group_name 384 local i 385 386 # The test never fails. It is meant to exercise different code paths 387 # and make sure we properly dismantle a port while packets are 388 # in-flight. 389 RET=0 390 391 devlink_traps_enable_all 392 393 for i in $(seq 1 10); do 394 ip link set dev $NETDEV up 395 396 sleep $SLEEP_TIME 397 398 netdevsim_port_destroy 399 netdevsim_port_create 400 udevadm settle 401 done 402 403 devlink_traps_disable_all 404 405 log_test "Port delete" 406} 407 408dev_del_test() 409{ 410 local group_name 411 local i 412 413 # The test never fails. It is meant to exercise different code paths 414 # and make sure we properly unregister traps while packets are 415 # in-flight. 416 RET=0 417 418 devlink_traps_enable_all 419 420 for i in $(seq 1 10); do 421 ip link set dev $NETDEV up 422 423 sleep $SLEEP_TIME 424 425 cleanup 426 setup_prepare 427 done 428 429 devlink_traps_disable_all 430 431 log_test "Device delete" 432} 433 434netdevsim_dev_create() 435{ 436 echo "$DEV_ADDR 0" > ${NETDEVSIM_PATH}/new_device 437} 438 439netdevsim_dev_destroy() 440{ 441 echo "$DEV_ADDR" > ${NETDEVSIM_PATH}/del_device 442} 443 444netdevsim_port_create() 445{ 446 echo 1 > ${NETDEVSIM_PATH}/devices/${DEV}/new_port 447} 448 449netdevsim_port_destroy() 450{ 451 echo 1 > ${NETDEVSIM_PATH}/devices/${DEV}/del_port 452} 453 454setup_prepare() 455{ 456 local netdev 457 458 netdevsim_dev_create 459 460 if [ ! -d "${NETDEVSIM_PATH}/devices/${DEV}" ]; then 461 echo "Failed to create netdevsim device" 462 exit 1 463 fi 464 465 netdevsim_port_create 466 467 if [ ! -d "${NETDEVSIM_PATH}/devices/${DEV}/net/" ]; then 468 echo "Failed to create netdevsim port" 469 exit 1 470 fi 471 472 # Wait for udev to rename newly created netdev. 473 udevadm settle 474 475 NETDEV=$(ls ${NETDEVSIM_PATH}/devices/${DEV}/net/) 476} 477 478cleanup() 479{ 480 pre_cleanup 481 netdevsim_port_destroy 482 netdevsim_dev_destroy 483} 484 485trap cleanup EXIT 486 487setup_prepare 488 489tests_run 490 491exit $EXIT_STATUS 492