Linux Audio

Check our new training course

Embedded Linux Audio

Check our new training course
with Creative Commons CC-BY-SA
lecture materials

Bootlin logo

Elixir Cross Referencer

Loading...
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0

lib_dir=$(dirname $0)/../../../net/forwarding

ALL_TESTS="
	l3_reporting_test
	l3_fail_next_test
	l3_counter_test
	l3_rollback_test
	l3_monitor_test
"

NETDEVSIM_PATH=/sys/bus/netdevsim/
DEV_ADDR_1=1337
DEV_ADDR_2=1057
DEV_ADDR_3=5417
NUM_NETIFS=0
source $lib_dir/lib.sh

DUMMY_IFINDEX=

DEV_ADDR()
{
	local n=$1; shift
	local var=DEV_ADDR_$n

	echo ${!var}
}

DEV()
{
	echo netdevsim$(DEV_ADDR $1)
}

DEVLINK_DEV()
{
	echo netdevsim/$(DEV $1)
}

SYSFS_NET_DIR()
{
	echo /sys/bus/netdevsim/devices/$(DEV $1)/net/
}

DEBUGFS_DIR()
{
	echo /sys/kernel/debug/netdevsim/$(DEV $1)/
}

nsim_add()
{
	local n=$1; shift

	echo "$(DEV_ADDR $n) 1" > ${NETDEVSIM_PATH}/new_device
	while [ ! -d $(SYSFS_NET_DIR $n) ] ; do :; done
}

nsim_reload()
{
	local n=$1; shift
	local ns=$1; shift

	devlink dev reload $(DEVLINK_DEV $n) netns $ns

	if [ $? -ne 0 ]; then
		echo "Failed to reload $(DEV $n) into netns \"testns1\""
		exit 1
	fi

}

nsim_del()
{
	local n=$1; shift

	echo "$(DEV_ADDR $n)" > ${NETDEVSIM_PATH}/del_device
}

nsim_hwstats_toggle()
{
	local action=$1; shift
	local instance=$1; shift
	local netdev=$1; shift
	local type=$1; shift

	local ifindex=$($IP -j link show dev $netdev | jq '.[].ifindex')

	echo $ifindex > $(DEBUGFS_DIR $instance)/hwstats/$type/$action
}

nsim_hwstats_enable()
{
	nsim_hwstats_toggle enable_ifindex "$@"
}

nsim_hwstats_disable()
{
	nsim_hwstats_toggle disable_ifindex "$@"
}

nsim_hwstats_fail_next_enable()
{
	nsim_hwstats_toggle fail_next_enable "$@"
}

setup_prepare()
{
	modprobe netdevsim &> /dev/null
	nsim_add 1
	nsim_add 2
	nsim_add 3

	ip netns add testns1

	if [ $? -ne 0 ]; then
		echo "Failed to add netns \"testns1\""
		exit 1
	fi

	nsim_reload 1 testns1
	nsim_reload 2 testns1
	nsim_reload 3 testns1

	IP="ip -n testns1"

	$IP link add name dummy1 type dummy
	$IP link set dev dummy1 up
	DUMMY_IFINDEX=$($IP -j link show dev dummy1 | jq '.[].ifindex')
}

cleanup()
{
	pre_cleanup

	$IP link del name dummy1
	ip netns del testns1
	nsim_del 3
	nsim_del 2
	nsim_del 1
	modprobe -r netdevsim &> /dev/null
}

netdev_hwstats_used()
{
	local netdev=$1; shift
	local type=$1; shift

	$IP -j stats show dev "$netdev" group offload subgroup hw_stats_info |
	    jq '.[].info.l3_stats.used'
}

netdev_check_used()
{
	local netdev=$1; shift
	local type=$1; shift

	[[ $(netdev_hwstats_used $netdev $type) == "true" ]]
}

netdev_check_unused()
{
	local netdev=$1; shift
	local type=$1; shift

	[[ $(netdev_hwstats_used $netdev $type) == "false" ]]
}

netdev_hwstats_request()
{
	local netdev=$1; shift
	local type=$1; shift

	$IP -j stats show dev "$netdev" group offload subgroup hw_stats_info |
	    jq ".[].info.${type}_stats.request"
}

netdev_check_requested()
{
	local netdev=$1; shift
	local type=$1; shift

	[[ $(netdev_hwstats_request $netdev $type) == "true" ]]
}

netdev_check_unrequested()
{
	local netdev=$1; shift
	local type=$1; shift

	[[ $(netdev_hwstats_request $netdev $type) == "false" ]]
}

reporting_test()
{
	local type=$1; shift
	local instance=1

	RET=0

	[[ -n $(netdev_hwstats_used dummy1 $type) ]]
	check_err $? "$type stats not reported"

	netdev_check_unused dummy1 $type
	check_err $? "$type stats reported as used before either device or netdevsim request"

	nsim_hwstats_enable $instance dummy1 $type
	netdev_check_unused dummy1 $type
	check_err $? "$type stats reported as used before device request"
	netdev_check_unrequested dummy1 $type
	check_err $? "$type stats reported as requested before device request"

	$IP stats set dev dummy1 ${type}_stats on
	netdev_check_used dummy1 $type
	check_err $? "$type stats reported as not used after both device and netdevsim request"
	netdev_check_requested dummy1 $type
	check_err $? "$type stats reported as not requested after device request"

	nsim_hwstats_disable $instance dummy1 $type
	netdev_check_unused dummy1 $type
	check_err $? "$type stats reported as used after netdevsim request withdrawn"

	nsim_hwstats_enable $instance dummy1 $type
	netdev_check_used dummy1 $type
	check_err $? "$type stats reported as not used after netdevsim request reenabled"

	$IP stats set dev dummy1 ${type}_stats off
	netdev_check_unused dummy1 $type
	check_err $? "$type stats reported as used after device request withdrawn"
	netdev_check_unrequested dummy1 $type
	check_err $? "$type stats reported as requested after device request withdrawn"

	nsim_hwstats_disable $instance dummy1 $type
	netdev_check_unused dummy1 $type
	check_err $? "$type stats reported as used after both requests withdrawn"

	log_test "Reporting of $type stats usage"
}

l3_reporting_test()
{
	reporting_test l3
}

__fail_next_test()
{
	local instance=$1; shift
	local type=$1; shift

	RET=0

	netdev_check_unused dummy1 $type
	check_err $? "$type stats reported as used before either device or netdevsim request"

	nsim_hwstats_enable $instance dummy1 $type
	nsim_hwstats_fail_next_enable $instance dummy1 $type
	netdev_check_unused dummy1 $type
	check_err $? "$type stats reported as used before device request"
	netdev_check_unrequested dummy1 $type
	check_err $? "$type stats reported as requested before device request"

	$IP stats set dev dummy1 ${type}_stats on 2>/dev/null
	check_fail $? "$type stats request not bounced as it should have been"
	netdev_check_unused dummy1 $type
	check_err $? "$type stats reported as used after bounce"
	netdev_check_unrequested dummy1 $type
	check_err $? "$type stats reported as requested after bounce"

	$IP stats set dev dummy1 ${type}_stats on
	check_err $? "$type stats request failed when it shouldn't have"
	netdev_check_used dummy1 $type
	check_err $? "$type stats reported as not used after both device and netdevsim request"
	netdev_check_requested dummy1 $type
	check_err $? "$type stats reported as not requested after device request"

	$IP stats set dev dummy1 ${type}_stats off
	nsim_hwstats_disable $instance dummy1 $type

	log_test "Injected failure of $type stats enablement (netdevsim #$instance)"
}

fail_next_test()
{
	__fail_next_test 1 "$@"
	__fail_next_test 2 "$@"
	__fail_next_test 3 "$@"
}

l3_fail_next_test()
{
	fail_next_test l3
}

get_hwstat()
{
	local netdev=$1; shift
	local type=$1; shift
	local selector=$1; shift

	$IP -j stats show dev $netdev group offload subgroup ${type}_stats |
		  jq ".[0].stats64.${selector}"
}

counter_test()
{
	local type=$1; shift
	local instance=1

	RET=0

	nsim_hwstats_enable $instance dummy1 $type
	$IP stats set dev dummy1 ${type}_stats on
	netdev_check_used dummy1 $type
	check_err $? "$type stats reported as not used after both device and netdevsim request"

	# Netdevsim counts 10pps on ingress. We should see maybe a couple
	# packets, unless things take a reeealy long time.
	local pkts=$(get_hwstat dummy1 l3 rx.packets)
	((pkts < 10))
	check_err $? "$type stats show >= 10 packets after first enablement"

	sleep 2.5

	local pkts=$(get_hwstat dummy1 l3 rx.packets)
	((pkts >= 20))
	check_err $? "$type stats show < 20 packets after 2.5s passed"

	$IP stats set dev dummy1 ${type}_stats off

	sleep 2

	$IP stats set dev dummy1 ${type}_stats on
	local pkts=$(get_hwstat dummy1 l3 rx.packets)
	((pkts < 10))
	check_err $? "$type stats show >= 10 packets after second enablement"

	$IP stats set dev dummy1 ${type}_stats off
	nsim_hwstats_fail_next_enable $instance dummy1 $type
	$IP stats set dev dummy1 ${type}_stats on 2>/dev/null
	check_fail $? "$type stats request not bounced as it should have been"

	sleep 2

	$IP stats set dev dummy1 ${type}_stats on
	local pkts=$(get_hwstat dummy1 l3 rx.packets)
	((pkts < 10))
	check_err $? "$type stats show >= 10 packets after post-fail enablement"

	$IP stats set dev dummy1 ${type}_stats off

	log_test "Counter values in $type stats"
}

l3_counter_test()
{
	counter_test l3
}

rollback_test()
{
	local type=$1; shift

	RET=0

	nsim_hwstats_enable 1 dummy1 l3
	nsim_hwstats_enable 2 dummy1 l3
	nsim_hwstats_enable 3 dummy1 l3

	# The three netdevsim instances are registered in order of their number
	# one after another. It is reasonable to expect that whatever
	# notifications take place hit no. 2 in between hitting nos. 1 and 3,
	# whatever the actual order. This allows us to test that a fail caused
	# by no. 2 does not leave the system in a partial state, and rolls
	# everything back.

	nsim_hwstats_fail_next_enable 2 dummy1 l3
	$IP stats set dev dummy1 ${type}_stats on 2>/dev/null
	check_fail $? "$type stats request not bounced as it should have been"

	netdev_check_unused dummy1 $type
	check_err $? "$type stats reported as used after bounce"
	netdev_check_unrequested dummy1 $type
	check_err $? "$type stats reported as requested after bounce"

	sleep 2

	$IP stats set dev dummy1 ${type}_stats on
	check_err $? "$type stats request not upheld as it should have been"

	local pkts=$(get_hwstat dummy1 l3 rx.packets)
	((pkts < 10))
	check_err $? "$type stats show $pkts packets after post-fail enablement"

	$IP stats set dev dummy1 ${type}_stats off

	nsim_hwstats_disable 3 dummy1 l3
	nsim_hwstats_disable 2 dummy1 l3
	nsim_hwstats_disable 1 dummy1 l3

	log_test "Failure in $type stats enablement rolled back"
}

l3_rollback_test()
{
	rollback_test l3
}

l3_monitor_test()
{
	hw_stats_monitor_test dummy1 l3		   \
		"nsim_hwstats_enable 1 dummy1 l3"  \
		"nsim_hwstats_disable 1 dummy1 l3" \
		"$IP"
}

trap cleanup EXIT

setup_prepare
tests_run

exit $EXIT_STATUS