devlink_trap.sh 13 KB

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