xref: /linux/tools/testing/selftests/drivers/net/netdevsim/devlink.sh (revision 2a8e91235254862aa1d99434c6105aec65cd8e42)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3
4lib_dir=$(dirname $0)/../../../net/forwarding
5
6ALL_TESTS="fw_flash_test params_test  \
7	   params_default_test regions_test reload_test \
8	   netns_reload_test resource_test resource_dump_test \
9	   port_resource_doit_test dev_info_test \
10	   empty_reporter_test dummy_reporter_test rate_test"
11NUM_NETIFS=0
12source $lib_dir/lib.sh
13
14BUS_ADDR=10
15PORT_COUNT=4
16VF_COUNT=4
17DEV_NAME=netdevsim$BUS_ADDR
18SYSFS_NET_DIR=/sys/bus/netdevsim/devices/$DEV_NAME/net/
19DEBUGFS_DIR=/sys/kernel/debug/netdevsim/$DEV_NAME/
20DL_HANDLE=netdevsim/$DEV_NAME
21
22wait_for_devlink()
23{
24	"$@" | grep -q $DL_HANDLE
25}
26
27devlink_wait()
28{
29	local timeout=$1
30
31	busywait "$timeout" wait_for_devlink devlink dev
32}
33
34fw_flash_test()
35{
36	DUMMYFILE=$(find /lib/firmware -type f -printf '%P\n' | head -1)
37	RET=0
38
39	if [ -z "$DUMMYFILE" ]
40	then
41		echo "SKIP: unable to find suitable dummy firmware file"
42		return
43	fi
44
45	echo "10"> $DEBUGFS_DIR/fw_update_flash_chunk_time_ms
46
47	devlink dev flash $DL_HANDLE file $DUMMYFILE
48	check_err $? "Failed to flash with status updates on"
49
50	devlink dev flash $DL_HANDLE file $DUMMYFILE component fw.mgmt
51	check_err $? "Failed to flash with component attribute"
52
53	devlink dev flash $DL_HANDLE file $DUMMYFILE overwrite settings
54	check_fail $? "Flash with overwrite settings should be rejected"
55
56	echo "1"> $DEBUGFS_DIR/fw_update_overwrite_mask
57	check_err $? "Failed to change allowed overwrite mask"
58
59	devlink dev flash $DL_HANDLE file $DUMMYFILE overwrite settings
60	check_err $? "Failed to flash with settings overwrite enabled"
61
62	devlink dev flash $DL_HANDLE file $DUMMYFILE overwrite identifiers
63	check_fail $? "Flash with overwrite settings should be identifiers"
64
65	echo "3"> $DEBUGFS_DIR/fw_update_overwrite_mask
66	check_err $? "Failed to change allowed overwrite mask"
67
68	devlink dev flash $DL_HANDLE file $DUMMYFILE overwrite identifiers overwrite settings
69	check_err $? "Failed to flash with settings and identifiers overwrite enabled"
70
71	echo "n"> $DEBUGFS_DIR/fw_update_status
72	check_err $? "Failed to disable status updates"
73
74	devlink dev flash $DL_HANDLE file $DUMMYFILE
75	check_err $? "Failed to flash with status updates off"
76
77	log_test "fw flash test"
78}
79
80param_get()
81{
82	local name=$1
83	local attr=${2:-value}
84	local cmode=${3:-driverinit}
85
86	cmd_jq "devlink dev param show $DL_HANDLE name $name -j" \
87	       '.[][][].values[] | select(.cmode == "'"$cmode"'").'"$attr"
88}
89
90param_set()
91{
92	local name=$1
93	local value=$2
94	local cmode=${3:-driverinit}
95
96	devlink dev param set $DL_HANDLE name $name cmode $cmode value $value
97}
98
99param_set_default()
100{
101	local name=$1
102	local cmode=${2:-driverinit}
103
104	devlink dev param set $DL_HANDLE name $name default cmode $cmode
105}
106
107check_value()
108{
109	local name=$1
110	local phase_name=$2
111	local expected_param_value=$3
112	local expected_debugfs_value=$4
113	local cmode=${5:-driverinit}
114	local value
115	local attr="value"
116
117	if [[ "$phase_name" == *"default"* ]]; then
118		attr="default"
119	fi
120
121	value=$(param_get $name $attr $cmode)
122	check_err $? "Failed to get $name param $attr"
123	[ "$value" == "$expected_param_value" ]
124	check_err $? "Unexpected $phase_name $name param $attr"
125	value=$(<$DEBUGFS_DIR/$name)
126	check_err $? "Failed to get $name debugfs value"
127	[ "$value" == "$expected_debugfs_value" ]
128	check_err $? "Unexpected $phase_name $name debugfs value"
129}
130
131params_test()
132{
133	RET=0
134
135	local max_macs
136	local test1
137
138	check_value max_macs initial 32 32
139	check_value test1 initial true Y
140
141	param_set max_macs 16
142	check_err $? "Failed to set max_macs param value"
143	param_set test1 false
144	check_err $? "Failed to set test1 param value"
145
146	check_value max_macs post-set 16 32
147	check_value test1 post-set false Y
148
149	devlink dev reload $DL_HANDLE
150
151	check_value max_macs post-reload 16 16
152	check_value test1 post-reload false N
153
154	log_test "params test"
155}
156
157value_to_debugfs()
158{
159	local value=$1
160
161	case "$value" in
162		true)
163			echo "Y"
164			;;
165		false)
166			echo "N"
167			;;
168		*)
169			echo "$value"
170			;;
171	esac
172}
173
174test_default()
175{
176	local param_name=$1
177	local new_value=$2
178	local expected_default=$3
179	local cmode=${4:-driverinit}
180	local default_debugfs
181	local new_debugfs
182	local expected_debugfs
183
184	default_debugfs=$(value_to_debugfs $expected_default)
185	new_debugfs=$(value_to_debugfs $new_value)
186
187	expected_debugfs=$default_debugfs
188	check_value $param_name initial-default $expected_default $expected_debugfs $cmode
189
190	param_set $param_name $new_value $cmode
191	check_err $? "Failed to set $param_name to $new_value"
192
193	expected_debugfs=$([ "$cmode" == "runtime" ] && echo "$new_debugfs" || echo "$default_debugfs")
194	check_value $param_name post-set $new_value $expected_debugfs $cmode
195
196	devlink dev reload $DL_HANDLE
197	check_err $? "Failed to reload device"
198
199	expected_debugfs=$new_debugfs
200	check_value $param_name post-reload-new-value $new_value $expected_debugfs $cmode
201
202	param_set_default $param_name $cmode
203	check_err $? "Failed to set $param_name to default"
204
205	expected_debugfs=$([ "$cmode" == "runtime" ] && echo "$default_debugfs" || echo "$new_debugfs")
206	check_value $param_name post-set-default $expected_default $expected_debugfs $cmode
207
208	devlink dev reload $DL_HANDLE
209	check_err $? "Failed to reload device"
210
211	expected_debugfs=$default_debugfs
212	check_value $param_name post-reload-default $expected_default $expected_debugfs $cmode
213}
214
215params_default_test()
216{
217	RET=0
218
219	if ! devlink dev param help 2>&1 | grep -q "value VALUE | default"; then
220		echo "SKIP: devlink cli missing default feature"
221		return
222	fi
223
224	# Remove side effects of previous tests. Use plain param_set, because
225	# param_set_default is a feature under test here.
226	param_set max_macs 32 driverinit
227	check_err $? "Failed to reset max_macs to default value"
228	param_set test1 true driverinit
229	check_err $? "Failed to reset test1 to default value"
230	param_set test2 1234 runtime
231	check_err $? "Failed to reset test2 to default value"
232
233	devlink dev reload $DL_HANDLE
234	check_err $? "Failed to reload device for clean state"
235
236	test_default max_macs 16 32 driverinit
237	test_default test1 false true driverinit
238	test_default test2 100 1234 runtime
239
240	log_test "params default test"
241}
242
243check_region_size()
244{
245	local name=$1
246	local size
247
248	size=$(devlink region show $DL_HANDLE/$name -j | jq -e -r '.[][].size')
249	check_err $? "Failed to get $name region size"
250	[ $size -eq 32768 ]
251	check_err $? "Invalid $name region size"
252}
253
254check_region_snapshot_count()
255{
256	local name=$1
257	local phase_name=$2
258	local expected_count=$3
259	local count
260
261	count=$(devlink region show $DL_HANDLE/$name -j | jq -e -r '.[][].snapshot | length')
262	[ $count -eq $expected_count ]
263	check_err $? "Unexpected $phase_name snapshot count"
264}
265
266regions_test()
267{
268	RET=0
269
270	local count
271
272	check_region_size dummy
273	check_region_snapshot_count dummy initial 0
274
275	echo ""> $DEBUGFS_DIR/take_snapshot
276	check_err $? "Failed to take first dummy region snapshot"
277	check_region_snapshot_count dummy post-first-snapshot 1
278
279	echo ""> $DEBUGFS_DIR/take_snapshot
280	check_err $? "Failed to take second dummy region snapshot"
281	check_region_snapshot_count dummy post-second-snapshot 2
282
283	echo ""> $DEBUGFS_DIR/take_snapshot
284	check_err $? "Failed to take third dummy region snapshot"
285	check_region_snapshot_count dummy post-third-snapshot 3
286
287	devlink region del $DL_HANDLE/dummy snapshot 1
288	check_err $? "Failed to delete first dummy region snapshot"
289
290	check_region_snapshot_count dummy post-first-delete 2
291
292	devlink region new $DL_HANDLE/dummy snapshot 25
293	check_err $? "Failed to create a new snapshot with id 25"
294
295	check_region_snapshot_count dummy post-first-request 3
296
297	devlink region dump $DL_HANDLE/dummy snapshot 25 >> /dev/null
298	check_err $? "Failed to dump snapshot with id 25"
299
300	devlink region read $DL_HANDLE/dummy snapshot 25 addr 0 len 1 >> /dev/null
301	check_err $? "Failed to read snapshot with id 25 (1 byte)"
302
303	devlink region read $DL_HANDLE/dummy snapshot 25 addr 128 len 128 >> /dev/null
304	check_err $? "Failed to read snapshot with id 25 (128 bytes)"
305
306	devlink region read $DL_HANDLE/dummy snapshot 25 addr 128 len $((1<<32)) >> /dev/null
307	check_err $? "Failed to read snapshot with id 25 (oversized)"
308
309	devlink region read $DL_HANDLE/dummy snapshot 25 addr $((1<<32)) len 128 >> /dev/null 2>&1
310	check_fail $? "Bad read of snapshot with id 25 did not fail"
311
312	devlink region del $DL_HANDLE/dummy snapshot 25
313	check_err $? "Failed to delete snapshot with id 25"
314
315	check_region_snapshot_count dummy post-second-delete 2
316
317	sid=$(devlink -j region new $DL_HANDLE/dummy | jq '.[][][][]')
318	check_err $? "Failed to create a new snapshot with id allocated by the kernel"
319
320	check_region_snapshot_count dummy post-first-request 3
321
322	devlink region dump $DL_HANDLE/dummy snapshot $sid >> /dev/null
323	check_err $? "Failed to dump a snapshot with id allocated by the kernel"
324
325	devlink region del $DL_HANDLE/dummy snapshot $sid
326	check_err $? "Failed to delete snapshot with id allocated by the kernel"
327
328	check_region_snapshot_count dummy post-first-request 2
329
330	log_test "regions test"
331}
332
333reload_test()
334{
335	RET=0
336
337	devlink dev reload $DL_HANDLE
338	check_err $? "Failed to reload"
339
340	echo "y"> $DEBUGFS_DIR/fail_reload
341	check_err $? "Failed to setup devlink reload to fail"
342
343	devlink dev reload $DL_HANDLE
344	check_fail $? "Unexpected success of devlink reload"
345
346	echo "n"> $DEBUGFS_DIR/fail_reload
347	check_err $? "Failed to setup devlink reload not to fail"
348
349	devlink dev reload $DL_HANDLE
350	check_err $? "Failed to reload after set not to fail"
351
352	echo "y"> $DEBUGFS_DIR/dont_allow_reload
353	check_err $? "Failed to forbid devlink reload"
354
355	devlink dev reload $DL_HANDLE
356	check_fail $? "Unexpected success of devlink reload"
357
358	echo "n"> $DEBUGFS_DIR/dont_allow_reload
359	check_err $? "Failed to re-enable devlink reload"
360
361	devlink dev reload $DL_HANDLE
362	check_err $? "Failed to reload after re-enable"
363
364	log_test "reload test"
365}
366
367netns_reload_test()
368{
369	RET=0
370
371	ip netns add testns1
372	check_err $? "Failed add netns \"testns1\""
373	ip netns add testns2
374	check_err $? "Failed add netns \"testns2\""
375
376	devlink dev reload $DL_HANDLE netns testns1
377	check_err $? "Failed to reload into netns \"testns1\""
378
379	devlink -N testns1 dev reload $DL_HANDLE netns testns2
380	check_err $? "Failed to reload from netns \"testns1\" into netns \"testns2\""
381
382	ip netns del testns2
383	ip netns del testns1
384
385	# Wait until netns async cleanup is done.
386	devlink_wait 2000
387
388	log_test "netns reload test"
389}
390
391DUMMYDEV="dummytest"
392
393res_val_get()
394{
395	local netns=$1
396	local parentname=$2
397	local name=$3
398	local type=$4
399
400	cmd_jq "devlink -N $netns resource show $DL_HANDLE -j" \
401	       ".[][][] | select(.name == \"$parentname\").resources[] \
402	        | select(.name == \"$name\").$type"
403}
404
405resource_test()
406{
407	RET=0
408
409	ip netns add testns1
410	check_err $? "Failed add netns \"testns1\""
411	ip netns add testns2
412	check_err $? "Failed add netns \"testns2\""
413
414	devlink dev reload $DL_HANDLE netns testns1
415	check_err $? "Failed to reload into netns \"testns1\""
416
417	# Create dummy dev to add the address and routes on.
418
419	ip -n testns1 link add name $DUMMYDEV type dummy
420	check_err $? "Failed create dummy device"
421	ip -n testns1 link set $DUMMYDEV up
422	check_err $? "Failed bring up dummy device"
423	ip -n testns1 a a 192.0.1.1/24 dev $DUMMYDEV
424	check_err $? "Failed add an IP address to dummy device"
425
426	local occ=$(res_val_get testns1 IPv4 fib occ)
427	local limit=$((occ+1))
428
429	# Set fib size limit to handle one another route only.
430
431	devlink -N testns1 resource set $DL_HANDLE path IPv4/fib size $limit
432	check_err $? "Failed to set IPv4/fib resource size"
433	local size_new=$(res_val_get testns1 IPv4 fib size_new)
434	[ "$size_new" -eq "$limit" ]
435	check_err $? "Unexpected \"size_new\" value (got $size_new, expected $limit)"
436
437	devlink -N testns1 dev reload $DL_HANDLE
438	check_err $? "Failed to reload"
439	local size=$(res_val_get testns1 IPv4 fib size)
440	[ "$size" -eq "$limit" ]
441	check_err $? "Unexpected \"size\" value (got $size, expected $limit)"
442
443	# Insert 2 routes, the first is going to be inserted,
444	# the second is expected to fail to be inserted.
445
446	ip -n testns1 r a 192.0.2.0/24 via 192.0.1.2
447	check_err $? "Failed to add route"
448
449	ip -n testns1 r a 192.0.3.0/24 via 192.0.1.2
450	check_fail $? "Unexpected successful route add over limit"
451
452	# Now create another dummy in second network namespace and
453	# insert two routes. That is over the limit of the netdevsim
454	# instance in the first namespace. Move the netdevsim instance
455	# into the second namespace and expect it to fail.
456
457	ip -n testns2 link add name $DUMMYDEV type dummy
458	check_err $? "Failed create dummy device"
459	ip -n testns2 link set $DUMMYDEV up
460	check_err $? "Failed bring up dummy device"
461	ip -n testns2 a a 192.0.1.1/24 dev $DUMMYDEV
462	check_err $? "Failed add an IP address to dummy device"
463	ip -n testns2 r a 192.0.2.0/24 via 192.0.1.2
464	check_err $? "Failed to add route"
465	ip -n testns2 r a 192.0.3.0/24 via 192.0.1.2
466	check_err $? "Failed to add route"
467
468	devlink -N testns1 dev reload $DL_HANDLE netns testns2
469	check_fail $? "Unexpected successful reload from netns \"testns1\" into netns \"testns2\""
470
471	devlink -N testns2 resource set $DL_HANDLE path IPv4/fib size ' -1'
472	check_err $? "Failed to reset IPv4/fib resource size"
473
474	devlink -N testns2 dev reload $DL_HANDLE netns 1
475	check_err $? "Failed to reload devlink back"
476
477	ip netns del testns2
478	ip netns del testns1
479
480	# Wait until netns async cleanup is done.
481	devlink_wait 2000
482
483	log_test "resource test"
484}
485
486resource_dump_test()
487{
488	RET=0
489
490	local port_jq
491	local dev_jq
492	local dl_jq
493	local count
494
495	dl_jq="with_entries(select(.key | startswith(\"$DL_HANDLE\")))"
496	port_jq="[.[] | $dl_jq | keys |"
497	port_jq+=" map(select(test(\"/.+/\"))) | length] | add"
498	dev_jq="[.[] | $dl_jq | keys |"
499	dev_jq+=" map(select(test(\"/.+/\")|not)) | length] | add"
500
501	if ! devlink resource help 2>&1 | grep -q "scope"; then
502		echo "SKIP: devlink resource show not supported"
503		return
504	fi
505
506	devlink resource show > /dev/null 2>&1
507	check_err $? "Failed to dump all resources"
508
509	count=$(cmd_jq "devlink resource show -j" "$port_jq")
510	[ "$count" -gt "0" ]
511	check_err $? "missing port resources in resource dump"
512
513	count=$(cmd_jq "devlink resource show -j" "$dev_jq")
514	[ "$count" -gt "0" ]
515	check_err $? "missing device resources in resource dump"
516
517	count=$(cmd_jq "devlink resource show scope dev -j" "$dev_jq")
518	[ "$count" -gt "0" ]
519	check_err $? "dev scope missing device resources"
520
521	count=$(cmd_jq "devlink resource show scope dev -j" "$port_jq")
522	[ "$count" -eq "0" ]
523	check_err $? "dev scope returned port resources"
524
525	count=$(cmd_jq "devlink resource show scope port -j" "$port_jq")
526	[ "$count" -gt "0" ]
527	check_err $? "port scope missing port resources"
528
529	count=$(cmd_jq "devlink resource show scope port -j" "$dev_jq")
530	[ "$count" -eq "0" ]
531	check_err $? "port scope returned device resources"
532
533	log_test "resource dump test"
534}
535
536info_get()
537{
538	local name=$1
539
540	cmd_jq "devlink dev info $DL_HANDLE -j" ".[][][\"$name\"]" "-e"
541}
542
543dev_info_test()
544{
545	RET=0
546
547	driver=$(info_get "driver")
548	check_err $? "Failed to get driver name"
549	[ "$driver" == "netdevsim" ]
550	check_err $? "Unexpected driver name $driver"
551
552	log_test "dev_info test"
553}
554
555empty_reporter_test()
556{
557	RET=0
558
559	devlink health show $DL_HANDLE reporter empty >/dev/null
560	check_err $? "Failed show empty reporter"
561
562	devlink health dump show $DL_HANDLE reporter empty >/dev/null
563	check_err $? "Failed show dump of empty reporter"
564
565	devlink health diagnose $DL_HANDLE reporter empty >/dev/null
566	check_err $? "Failed diagnose empty reporter"
567
568	devlink health recover $DL_HANDLE reporter empty
569	check_err $? "Failed recover empty reporter"
570
571	log_test "empty reporter test"
572}
573
574check_reporter_info()
575{
576	local name=$1
577	local expected_state=$2
578	local expected_error=$3
579	local expected_recover=$4
580	local expected_grace_period=$5
581	local expected_auto_recover=$6
582
583	local show=$(devlink health show $DL_HANDLE reporter $name -j | jq -e -r ".[][][]")
584	check_err $? "Failed show $name reporter"
585
586	local state=$(echo $show | jq -r ".state")
587	[ "$state" == "$expected_state" ]
588	check_err $? "Unexpected \"state\" value (got $state, expected $expected_state)"
589
590	local error=$(echo $show | jq -r ".error")
591	[ "$error" == "$expected_error" ]
592	check_err $? "Unexpected \"error\" value (got $error, expected $expected_error)"
593
594	local recover=`echo $show | jq -r ".recover"`
595	[ "$recover" == "$expected_recover" ]
596	check_err $? "Unexpected \"recover\" value (got $recover, expected $expected_recover)"
597
598	local grace_period=$(echo $show | jq -r ".grace_period")
599	check_err $? "Failed get $name reporter grace_period"
600	[ "$grace_period" == "$expected_grace_period" ]
601	check_err $? "Unexpected \"grace_period\" value (got $grace_period, expected $expected_grace_period)"
602
603	local auto_recover=$(echo $show | jq -r ".auto_recover")
604	[ "$auto_recover" == "$expected_auto_recover" ]
605	check_err $? "Unexpected \"auto_recover\" value (got $auto_recover, expected $expected_auto_recover)"
606}
607
608dummy_reporter_test()
609{
610	RET=0
611
612	check_reporter_info dummy healthy 0 0 0 true
613
614	devlink health set $DL_HANDLE reporter dummy auto_recover false
615	check_err $? "Failed to dummy reporter auto_recover option"
616
617	check_reporter_info dummy healthy 0 0 0 false
618
619	local BREAK_MSG="foo bar"
620	echo "$BREAK_MSG"> $DEBUGFS_DIR/health/break_health
621	check_err $? "Failed to break dummy reporter"
622
623	check_reporter_info dummy error 1 0 0 false
624
625	local dump=$(devlink health dump show $DL_HANDLE reporter dummy -j)
626	check_err $? "Failed show dump of dummy reporter"
627
628	local dump_break_msg=$(echo $dump | jq -r ".break_message")
629	[ "$dump_break_msg" == "$BREAK_MSG" ]
630	check_err $? "Unexpected dump break message value (got $dump_break_msg, expected $BREAK_MSG)"
631
632	devlink health dump clear $DL_HANDLE reporter dummy
633	check_err $? "Failed clear dump of dummy reporter"
634
635	devlink health recover $DL_HANDLE reporter dummy
636	check_err $? "Failed recover dummy reporter"
637
638	check_reporter_info dummy healthy 1 1 0 false
639
640	devlink health set $DL_HANDLE reporter dummy auto_recover true
641	check_err $? "Failed to dummy reporter auto_recover option"
642
643	check_reporter_info dummy healthy 1 1 0 true
644
645	echo "$BREAK_MSG"> $DEBUGFS_DIR/health/break_health
646	check_err $? "Failed to break dummy reporter"
647
648	check_reporter_info dummy healthy 2 2 0 true
649
650	local diagnose=$(devlink health diagnose $DL_HANDLE reporter dummy -j -p)
651	check_err $? "Failed show diagnose of dummy reporter"
652
653	local rcvrd_break_msg=$(echo $diagnose | jq -r ".recovered_break_message")
654	[ "$rcvrd_break_msg" == "$BREAK_MSG" ]
655	check_err $? "Unexpected recovered break message value (got $rcvrd_break_msg, expected $BREAK_MSG)"
656
657	devlink health set $DL_HANDLE reporter dummy grace_period 10
658	check_err $? "Failed to dummy reporter grace_period option"
659
660	check_reporter_info dummy healthy 2 2 10 true
661
662	echo "Y"> $DEBUGFS_DIR/health/fail_recover
663	check_err $? "Failed set dummy reporter recovery to fail"
664
665	echo "$BREAK_MSG"> $DEBUGFS_DIR/health/break_health
666	check_fail $? "Unexpected success of dummy reporter break"
667
668	check_reporter_info dummy error 3 2 10 true
669
670	devlink health recover $DL_HANDLE reporter dummy
671	check_fail $? "Unexpected success of dummy reporter recover"
672
673	echo "N"> $DEBUGFS_DIR/health/fail_recover
674	check_err $? "Failed set dummy reporter recovery to be successful"
675
676	devlink health recover $DL_HANDLE reporter dummy
677	check_err $? "Failed recover dummy reporter"
678
679	check_reporter_info dummy healthy 3 3 10 true
680
681	echo 8192 > $DEBUGFS_DIR/health/binary_len
682	check_err $? "Failed set dummy reporter binary len to 8192"
683
684	local dump=$(devlink health dump show $DL_HANDLE reporter dummy -j)
685	check_err $? "Failed show dump of dummy reporter"
686
687	devlink health dump clear $DL_HANDLE reporter dummy
688	check_err $? "Failed clear dump of dummy reporter"
689
690	log_test "dummy reporter test"
691}
692
693rate_leafs_get()
694{
695	local handle=$1
696
697	cmd_jq "devlink port function rate show -j" \
698	       '.[] | to_entries | .[] | select(.value.type == "leaf") | .key | select(contains("'$handle'"))'
699}
700
701rate_nodes_get()
702{
703	local handle=$1
704
705	cmd_jq "devlink port function rate show -j" \
706		'.[] | to_entries | .[] | select(.value.type == "node") | .key | select(contains("'$handle'"))'
707}
708
709rate_attr_set()
710{
711	local handle=$1
712	local name=$2
713	local value=$3
714	local units=$4
715
716	devlink port function rate set $handle $name $value$units
717}
718
719rate_attr_get()
720{
721	local handle=$1
722	local name=$2
723
724	cmd_jq "devlink port function rate show $handle -j" '.[][].'$name
725}
726
727rate_attr_tx_rate_check()
728{
729	local handle=$1
730	local name=$2
731	local rate=$3
732	local debug_file=$4
733
734	rate_attr_set $handle $name $rate mbit
735	check_err $? "Failed to set $name value"
736
737	local debug_value=$(cat $debug_file)
738	check_err $? "Failed to read $name value from debugfs"
739	[ "$debug_value" == "$rate" ]
740	check_err $? "Unexpected $name debug value $debug_value != $rate"
741
742	local api_value=$(( $(rate_attr_get $handle $name) * 8 / 1000000 ))
743	check_err $? "Failed to get $name attr value"
744	[ "$api_value" == "$rate" ]
745	check_err $? "Unexpected $name attr value $api_value != $rate"
746}
747
748rate_attr_parent_check()
749{
750	local handle=$1
751	local parent=$2
752	local debug_file=$3
753
754	rate_attr_set $handle parent $parent
755	check_err $? "Failed to set parent"
756
757	debug_value=$(cat $debug_file)
758	check_err $? "Failed to get parent debugfs value"
759	[ "$debug_value" == "$parent" ]
760	check_err $? "Unexpected parent debug value $debug_value != $parent"
761
762	api_value=$(rate_attr_get $r_obj parent)
763	check_err $? "Failed to get parent attr value"
764	[ "$api_value" == "$parent" ]
765	check_err $? "Unexpected parent attr value $api_value != $parent"
766}
767
768rate_attr_tc_bw_check()
769{
770	local handle=$1
771	local tc_bw=$2
772	local debug_file=$3
773
774	local tc_bw_str=""
775	for bw in $tc_bw; do
776		local tc=${bw%%:*}
777		local value=${bw##*:}
778		tc_bw_str="$tc_bw_str $tc:$value"
779	done
780	tc_bw_str=${tc_bw_str# }
781
782	rate_attr_set "$handle" tc-bw "$tc_bw_str"
783	check_err $? "Failed to set tc-bw values"
784
785	for bw in $tc_bw; do
786		local tc=${bw%%:*}
787		local value=${bw##*:}
788		local debug_value
789		debug_value=$(cat "$debug_file"/tc"${tc}"_bw)
790		check_err $? "Failed to read tc-bw value from debugfs for tc$tc"
791		[ "$debug_value" == "$value" ]
792		check_err $? "Unexpected tc-bw debug value for tc$tc: $debug_value != $value"
793	done
794
795	for bw in $tc_bw; do
796		local tc=${bw%%:*}
797		local expected_value=${bw##*:}
798		local api_value
799		api_value=$(rate_attr_get "$handle" tc_"$tc")
800		if [ "$api_value" = "null" ]; then
801			api_value=0
802		fi
803		[ "$api_value" == "$expected_value" ]
804		check_err $? "Unexpected tc-bw value for tc$tc: $api_value != $expected_value"
805	done
806}
807
808rate_node_add()
809{
810	local handle=$1
811
812	devlink port function rate add $handle
813}
814
815rate_node_del()
816{
817	local handle=$1
818
819	devlink port function rate del $handle
820}
821
822port_resource_doit_test()
823{
824	RET=0
825
826	local port_handle="${DL_HANDLE}/0"
827	local name
828	local size
829
830	if ! devlink resource help 2>&1 | grep -q "PORT_INDEX"; then
831		echo "SKIP: devlink resource show with port not supported"
832		return
833	fi
834
835	name=$(cmd_jq "devlink resource show $port_handle -j" \
836		      '.[][][].name')
837	[ "$name" == "test_resource" ]
838	check_err $? "wrong port resource name (got $name)"
839
840	size=$(cmd_jq "devlink resource show $port_handle -j" \
841		      '.[][][].size')
842	[ "$size" == "20" ]
843	check_err $? "wrong port resource size (got $size)"
844
845	log_test "port resource doit test"
846}
847
848rate_test()
849{
850	RET=0
851
852	echo $VF_COUNT > /sys/bus/netdevsim/devices/$DEV_NAME/sriov_numvfs
853	devlink dev eswitch set $DL_HANDLE mode switchdev
854	local leafs=`rate_leafs_get $DL_HANDLE`
855	local num_leafs=`echo $leafs | wc -w`
856	[ "$num_leafs" == "$VF_COUNT" ]
857	check_err $? "Expected $VF_COUNT rate leafs but got $num_leafs"
858
859	rate=10
860	for r_obj in $leafs
861	do
862		rate_attr_tx_rate_check $r_obj tx_share $rate \
863			$DEBUGFS_DIR/ports/${r_obj##*/}/tx_share
864		rate=$(($rate+10))
865	done
866
867	rate=100
868	for r_obj in $leafs
869	do
870		rate_attr_tx_rate_check $r_obj tx_max $rate \
871			$DEBUGFS_DIR/ports/${r_obj##*/}/tx_max
872		rate=$(($rate+100))
873	done
874
875	local tc_bw="0:0 1:40 2:0 3:0 4:0 5:0 6:60 7:0"
876	for r_obj in $leafs
877	do
878		rate_attr_tc_bw_check "$r_obj" "$tc_bw" \
879			"$DEBUGFS_DIR"/ports/"${r_obj##*/}"
880	done
881
882	local node1_name='group1'
883	local node1="$DL_HANDLE/$node1_name"
884	rate_node_add "$node1"
885	check_err $? "Failed to add node $node1"
886
887	local num_nodes=`rate_nodes_get $DL_HANDLE | wc -w`
888	[ $num_nodes == 1 ]
889	check_err $? "Expected 1 rate node in output but got $num_nodes"
890
891	local node_tx_share=10
892	rate_attr_tx_rate_check $node1 tx_share $node_tx_share \
893		$DEBUGFS_DIR/rate_nodes/${node1##*/}/tx_share
894
895	local node_tx_max=100
896	rate_attr_tx_rate_check $node1 tx_max $node_tx_max \
897		$DEBUGFS_DIR/rate_nodes/${node1##*/}/tx_max
898
899
900	local tc_bw="0:20 1:0 2:0 3:0 4:0 5:20 6:60 7:0"
901	rate_attr_tc_bw_check $node1 "$tc_bw" \
902		"$DEBUGFS_DIR"/rate_nodes/"${node1##*/}"
903
904
905	rate_node_del "$node1"
906	check_err $? "Failed to delete node $node1"
907	local num_nodes=`rate_nodes_get $DL_HANDLE | wc -w`
908	[ $num_nodes == 0 ]
909	check_err $? "Expected 0 rate node but got $num_nodes"
910
911	local node1_name='group1'
912	local node1="$DL_HANDLE/$node1_name"
913	rate_node_add "$node1"
914	check_err $? "Failed to add node $node1"
915
916	rate_attr_parent_check $r_obj $node1_name \
917		$DEBUGFS_DIR/ports/${r_obj##*/}/rate_parent
918
919	local node2_name='group2'
920	local node2="$DL_HANDLE/$node2_name"
921	rate_node_add "$node2"
922	check_err $? "Failed to add node $node2"
923
924	rate_attr_parent_check $node2 $node1_name \
925		$DEBUGFS_DIR/rate_nodes/$node2_name/rate_parent
926	rate_node_del "$node2"
927	check_err $? "Failed to delete node $node2"
928	rate_attr_set "$r_obj" noparent
929	check_err $? "Failed to unset $r_obj parent node"
930	rate_node_del "$node1"
931	check_err $? "Failed to delete node $node1"
932
933	log_test "rate test"
934}
935
936setup_prepare()
937{
938	modprobe netdevsim
939	echo "$BUS_ADDR $PORT_COUNT" > /sys/bus/netdevsim/new_device
940	while [ ! -d $SYSFS_NET_DIR ] ; do :; done
941}
942
943cleanup()
944{
945	pre_cleanup
946	echo "$BUS_ADDR" > /sys/bus/netdevsim/del_device
947	modprobe -r netdevsim
948}
949
950trap cleanup EXIT
951
952setup_prepare
953
954tests_run
955
956exit $EXIT_STATUS
957