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 RET=0 268 269 if [ $(devlink_trap_policers_num_get) -eq 0 ]; then 270 check_err 1 "Failed to dump policers" 271 fi 272 273 devlink trap policer set $DEVLINK_DEV policer 1337 &> /dev/null 274 check_fail $? "Did not get an error for setting a non-existing policer" 275 devlink trap policer show $DEVLINK_DEV policer 1337 &> /dev/null 276 check_fail $? "Did not get an error for getting a non-existing policer" 277 278 devlink trap policer set $DEVLINK_DEV policer 1 rate 2000 burst 16 279 check_err $? "Failed to set valid parameters for a valid policer" 280 if [ $(devlink_trap_policer_rate_get 1) -ne 2000 ]; then 281 check_err 1 "Policer rate was not changed" 282 fi 283 if [ $(devlink_trap_policer_burst_get 1) -ne 16 ]; then 284 check_err 1 "Policer burst size was not changed" 285 fi 286 287 devlink trap policer set $DEVLINK_DEV policer 1 rate 0 &> /dev/null 288 check_fail $? "Policer rate was changed to rate lower than limit" 289 devlink trap policer set $DEVLINK_DEV policer 1 rate 9000 &> /dev/null 290 check_fail $? "Policer rate was changed to rate higher than limit" 291 devlink trap policer set $DEVLINK_DEV policer 1 burst 2 &> /dev/null 292 check_fail $? "Policer burst size was changed to burst size lower than limit" 293 devlink trap policer set $DEVLINK_DEV policer 1 rate 65537 &> /dev/null 294 check_fail $? "Policer burst size was changed to burst size higher than limit" 295 echo "y" > $DEBUGFS_DIR/fail_trap_policer_set 296 devlink trap policer set $DEVLINK_DEV policer 1 rate 3000 &> /dev/null 297 check_fail $? "Managed to set policer rate when should not" 298 echo "n" > $DEBUGFS_DIR/fail_trap_policer_set 299 if [ $(devlink_trap_policer_rate_get 1) -ne 2000 ]; then 300 check_err 1 "Policer rate was changed to an invalid value" 301 fi 302 if [ $(devlink_trap_policer_burst_get 1) -ne 16 ]; then 303 check_err 1 "Policer burst size was changed to an invalid value" 304 fi 305 306 packets_t0=$(devlink_trap_policer_rx_dropped_get 1) 307 sleep .5 308 packets_t1=$(devlink_trap_policer_rx_dropped_get 1) 309 if [ ! $packets_t1 -gt $packets_t0 ]; then 310 check_err 1 "Policer drop counter was not incremented" 311 fi 312 313 echo "y"> $DEBUGFS_DIR/fail_trap_policer_counter_get 314 devlink -s trap policer show $DEVLINK_DEV policer 1 &> /dev/null 315 check_fail $? "Managed to read policer drop counter when should not" 316 echo "n"> $DEBUGFS_DIR/fail_trap_policer_counter_get 317 devlink -s trap policer show $DEVLINK_DEV policer 1 &> /dev/null 318 check_err $? "Did not manage to read policer drop counter when should" 319 320 log_test "Trap policer" 321} 322 323trap_group_check_policer() 324{ 325 local group_name=$1; shift 326 327 devlink -j -p trap group show $DEVLINK_DEV group $group_name \ 328 | jq -e '.[][][]["policer"]' &> /dev/null 329} 330 331trap_policer_bind_test() 332{ 333 RET=0 334 335 devlink trap group set $DEVLINK_DEV group l2_drops policer 1 336 check_err $? "Failed to bind a valid policer" 337 if [ $(devlink_trap_group_policer_get "l2_drops") -ne 1 ]; then 338 check_err 1 "Bound policer was not changed" 339 fi 340 341 devlink trap group set $DEVLINK_DEV group l2_drops policer 1337 \ 342 &> /dev/null 343 check_fail $? "Did not get an error for binding a non-existing policer" 344 if [ $(devlink_trap_group_policer_get "l2_drops") -ne 1 ]; then 345 check_err 1 "Bound policer was changed when should not" 346 fi 347 348 devlink trap group set $DEVLINK_DEV group l2_drops policer 0 349 check_err $? "Failed to unbind a policer when using ID 0" 350 trap_group_check_policer "l2_drops" 351 check_fail $? "Trap group has a policer after unbinding with ID 0" 352 353 devlink trap group set $DEVLINK_DEV group l2_drops policer 1 354 check_err $? "Failed to bind a valid policer" 355 356 devlink trap group set $DEVLINK_DEV group l2_drops nopolicer 357 check_err $? "Failed to unbind a policer when using 'nopolicer' keyword" 358 trap_group_check_policer "l2_drops" 359 check_fail $? "Trap group has a policer after unbinding with 'nopolicer' keyword" 360 361 devlink trap group set $DEVLINK_DEV group l2_drops policer 1 362 check_err $? "Failed to bind a valid policer" 363 364 echo "y"> $DEBUGFS_DIR/fail_trap_group_set 365 devlink trap group set $DEVLINK_DEV group l2_drops policer 2 \ 366 &> /dev/null 367 check_fail $? "Managed to bind a policer when should not" 368 echo "n"> $DEBUGFS_DIR/fail_trap_group_set 369 devlink trap group set $DEVLINK_DEV group l2_drops policer 2 370 check_err $? "Did not manage to bind a policer when should" 371 372 devlink trap group set $DEVLINK_DEV group l2_drops action drop \ 373 policer 1337 &> /dev/null 374 check_fail $? "Did not get an error for partially modified trap group" 375 376 log_test "Trap policer binding" 377} 378 379port_del_test() 380{ 381 local group_name 382 local i 383 384 # The test never fails. It is meant to exercise different code paths 385 # and make sure we properly dismantle a port while packets are 386 # in-flight. 387 RET=0 388 389 devlink_traps_enable_all 390 391 for i in $(seq 1 10); do 392 ip link set dev $NETDEV up 393 394 sleep $SLEEP_TIME 395 396 netdevsim_port_destroy 397 netdevsim_port_create 398 udevadm settle 399 done 400 401 devlink_traps_disable_all 402 403 log_test "Port delete" 404} 405 406dev_del_test() 407{ 408 local group_name 409 local i 410 411 # The test never fails. It is meant to exercise different code paths 412 # and make sure we properly unregister traps while packets are 413 # in-flight. 414 RET=0 415 416 devlink_traps_enable_all 417 418 for i in $(seq 1 10); do 419 ip link set dev $NETDEV up 420 421 sleep $SLEEP_TIME 422 423 cleanup 424 setup_prepare 425 done 426 427 devlink_traps_disable_all 428 429 log_test "Device delete" 430} 431 432netdevsim_dev_create() 433{ 434 echo "$DEV_ADDR 0" > ${NETDEVSIM_PATH}/new_device 435} 436 437netdevsim_dev_destroy() 438{ 439 echo "$DEV_ADDR" > ${NETDEVSIM_PATH}/del_device 440} 441 442netdevsim_port_create() 443{ 444 echo 1 > ${NETDEVSIM_PATH}/devices/${DEV}/new_port 445} 446 447netdevsim_port_destroy() 448{ 449 echo 1 > ${NETDEVSIM_PATH}/devices/${DEV}/del_port 450} 451 452setup_prepare() 453{ 454 local netdev 455 456 netdevsim_dev_create 457 458 if [ ! -d "${NETDEVSIM_PATH}/devices/${DEV}" ]; then 459 echo "Failed to create netdevsim device" 460 exit 1 461 fi 462 463 netdevsim_port_create 464 465 if [ ! -d "${NETDEVSIM_PATH}/devices/${DEV}/net/" ]; then 466 echo "Failed to create netdevsim port" 467 exit 1 468 fi 469 470 # Wait for udev to rename newly created netdev. 471 udevadm settle 472 473 NETDEV=$(ls ${NETDEVSIM_PATH}/devices/${DEV}/net/) 474} 475 476cleanup() 477{ 478 pre_cleanup 479 netdevsim_port_destroy 480 netdevsim_dev_destroy 481} 482 483trap cleanup EXIT 484 485setup_prepare 486 487tests_run 488 489exit $EXIT_STATUS 490