Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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