cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

devlink_lib.sh (12986B)


      1#!/bin/bash
      2# SPDX-License-Identifier: GPL-2.0
      3
      4# Kselftest framework requirement - SKIP code is 4.
      5ksft_skip=4
      6
      7##############################################################################
      8# Defines
      9
     10if [[ ! -v DEVLINK_DEV ]]; then
     11	DEVLINK_DEV=$(devlink port show "${NETIFS[p1]:-$NETIF_NO_CABLE}" -j \
     12			     | jq -r '.port | keys[]' | cut -d/ -f-2)
     13	if [ -z "$DEVLINK_DEV" ]; then
     14		echo "SKIP: ${NETIFS[p1]} has no devlink device registered for it"
     15		exit $ksft_skip
     16	fi
     17	if [[ "$(echo $DEVLINK_DEV | grep -c pci)" -eq 0 ]]; then
     18		echo "SKIP: devlink device's bus is not PCI"
     19		exit $ksft_skip
     20	fi
     21
     22	DEVLINK_VIDDID=$(lspci -s $(echo $DEVLINK_DEV | cut -d"/" -f2) \
     23			 -n | cut -d" " -f3)
     24elif [[ ! -z "$DEVLINK_DEV" ]]; then
     25	devlink dev show $DEVLINK_DEV &> /dev/null
     26	if [ $? -ne 0 ]; then
     27		echo "SKIP: devlink device \"$DEVLINK_DEV\" not found"
     28		exit $ksft_skip
     29	fi
     30fi
     31
     32##############################################################################
     33# Sanity checks
     34
     35devlink help 2>&1 | grep resource &> /dev/null
     36if [ $? -ne 0 ]; then
     37	echo "SKIP: iproute2 too old, missing devlink resource support"
     38	exit $ksft_skip
     39fi
     40
     41devlink help 2>&1 | grep trap &> /dev/null
     42if [ $? -ne 0 ]; then
     43	echo "SKIP: iproute2 too old, missing devlink trap support"
     44	exit $ksft_skip
     45fi
     46
     47devlink dev help 2>&1 | grep info &> /dev/null
     48if [ $? -ne 0 ]; then
     49	echo "SKIP: iproute2 too old, missing devlink dev info support"
     50	exit $ksft_skip
     51fi
     52
     53##############################################################################
     54# Devlink helpers
     55
     56devlink_resource_names_to_path()
     57{
     58	local resource
     59	local path=""
     60
     61	for resource in "${@}"; do
     62		if [ "$path" == "" ]; then
     63			path="$resource"
     64		else
     65			path="${path}/$resource"
     66		fi
     67	done
     68
     69	echo "$path"
     70}
     71
     72devlink_resource_get()
     73{
     74	local name=$1
     75	local resource_name=.[][\"$DEVLINK_DEV\"]
     76
     77	resource_name="$resource_name | .[] | select (.name == \"$name\")"
     78
     79	shift
     80	for resource in "${@}"; do
     81		resource_name="${resource_name} | .[\"resources\"][] | \
     82			       select (.name == \"$resource\")"
     83	done
     84
     85	devlink -j resource show "$DEVLINK_DEV" | jq "$resource_name"
     86}
     87
     88devlink_resource_size_get()
     89{
     90	local size=$(devlink_resource_get "$@" | jq '.["size_new"]')
     91
     92	if [ "$size" == "null" ]; then
     93		devlink_resource_get "$@" | jq '.["size"]'
     94	else
     95		echo "$size"
     96	fi
     97}
     98
     99devlink_resource_size_set()
    100{
    101	local new_size=$1
    102	local path
    103
    104	shift
    105	path=$(devlink_resource_names_to_path "$@")
    106	devlink resource set "$DEVLINK_DEV" path "$path" size "$new_size"
    107	check_err $? "Failed setting path $path to size $size"
    108}
    109
    110devlink_resource_occ_get()
    111{
    112	devlink_resource_get "$@" | jq '.["occ"]'
    113}
    114
    115devlink_reload()
    116{
    117	local still_pending
    118
    119	devlink dev reload "$DEVLINK_DEV" &> /dev/null
    120	check_err $? "Failed reload"
    121
    122	still_pending=$(devlink resource show "$DEVLINK_DEV" | \
    123			grep -c "size_new")
    124	check_err $still_pending "Failed reload - There are still unset sizes"
    125}
    126
    127declare -A DEVLINK_ORIG
    128
    129# Changing pool type from static to dynamic causes reinterpretation of threshold
    130# values. They therefore need to be saved before pool type is changed, then the
    131# pool type can be changed, and then the new values need to be set up. Therefore
    132# instead of saving the current state implicitly in the _set call, provide
    133# functions for all three primitives: save, set, and restore.
    134
    135devlink_port_pool_threshold()
    136{
    137	local port=$1; shift
    138	local pool=$1; shift
    139
    140	devlink sb port pool show $port pool $pool -j \
    141		| jq '.port_pool."'"$port"'"[].threshold'
    142}
    143
    144devlink_port_pool_th_save()
    145{
    146	local port=$1; shift
    147	local pool=$1; shift
    148	local key="port_pool($port,$pool).threshold"
    149
    150	DEVLINK_ORIG[$key]=$(devlink_port_pool_threshold $port $pool)
    151}
    152
    153devlink_port_pool_th_set()
    154{
    155	local port=$1; shift
    156	local pool=$1; shift
    157	local th=$1; shift
    158
    159	devlink sb port pool set $port pool $pool th $th
    160}
    161
    162devlink_port_pool_th_restore()
    163{
    164	local port=$1; shift
    165	local pool=$1; shift
    166	local key="port_pool($port,$pool).threshold"
    167	local -a orig=(${DEVLINK_ORIG[$key]})
    168
    169	if [[ -z $orig ]]; then
    170		echo "WARNING: Mismatched devlink_port_pool_th_restore"
    171	else
    172		devlink sb port pool set $port pool $pool th $orig
    173	fi
    174}
    175
    176devlink_pool_size_thtype()
    177{
    178	local pool=$1; shift
    179
    180	devlink sb pool show "$DEVLINK_DEV" pool $pool -j \
    181	    | jq -r '.pool[][] | (.size, .thtype)'
    182}
    183
    184devlink_pool_size_thtype_save()
    185{
    186	local pool=$1; shift
    187	local key="pool($pool).size_thtype"
    188
    189	DEVLINK_ORIG[$key]=$(devlink_pool_size_thtype $pool)
    190}
    191
    192devlink_pool_size_thtype_set()
    193{
    194	local pool=$1; shift
    195	local thtype=$1; shift
    196	local size=$1; shift
    197
    198	devlink sb pool set "$DEVLINK_DEV" pool $pool size $size thtype $thtype
    199}
    200
    201devlink_pool_size_thtype_restore()
    202{
    203	local pool=$1; shift
    204	local key="pool($pool).size_thtype"
    205	local -a orig=(${DEVLINK_ORIG[$key]})
    206
    207	if [[ -z ${orig[0]} ]]; then
    208		echo "WARNING: Mismatched devlink_pool_size_thtype_restore"
    209	else
    210		devlink sb pool set "$DEVLINK_DEV" pool $pool \
    211			size ${orig[0]} thtype ${orig[1]}
    212	fi
    213}
    214
    215devlink_tc_bind_pool_th()
    216{
    217	local port=$1; shift
    218	local tc=$1; shift
    219	local dir=$1; shift
    220
    221	devlink sb tc bind show $port tc $tc type $dir -j \
    222	    | jq -r '.tc_bind[][] | (.pool, .threshold)'
    223}
    224
    225devlink_tc_bind_pool_th_save()
    226{
    227	local port=$1; shift
    228	local tc=$1; shift
    229	local dir=$1; shift
    230	local key="tc_bind($port,$dir,$tc).pool_th"
    231
    232	DEVLINK_ORIG[$key]=$(devlink_tc_bind_pool_th $port $tc $dir)
    233}
    234
    235devlink_tc_bind_pool_th_set()
    236{
    237	local port=$1; shift
    238	local tc=$1; shift
    239	local dir=$1; shift
    240	local pool=$1; shift
    241	local th=$1; shift
    242
    243	devlink sb tc bind set $port tc $tc type $dir pool $pool th $th
    244}
    245
    246devlink_tc_bind_pool_th_restore()
    247{
    248	local port=$1; shift
    249	local tc=$1; shift
    250	local dir=$1; shift
    251	local key="tc_bind($port,$dir,$tc).pool_th"
    252	local -a orig=(${DEVLINK_ORIG[$key]})
    253
    254	if [[ -z ${orig[0]} ]]; then
    255		echo "WARNING: Mismatched devlink_tc_bind_pool_th_restore"
    256	else
    257		devlink sb tc bind set $port tc $tc type $dir \
    258			pool ${orig[0]} th ${orig[1]}
    259	fi
    260}
    261
    262devlink_traps_num_get()
    263{
    264	devlink -j trap | jq '.[]["'$DEVLINK_DEV'"] | length'
    265}
    266
    267devlink_traps_get()
    268{
    269	devlink -j trap | jq -r '.[]["'$DEVLINK_DEV'"][].name'
    270}
    271
    272devlink_trap_type_get()
    273{
    274	local trap_name=$1; shift
    275
    276	devlink -j trap show $DEVLINK_DEV trap $trap_name \
    277		| jq -r '.[][][].type'
    278}
    279
    280devlink_trap_action_set()
    281{
    282	local trap_name=$1; shift
    283	local action=$1; shift
    284
    285	# Pipe output to /dev/null to avoid expected warnings.
    286	devlink trap set $DEVLINK_DEV trap $trap_name \
    287		action $action &> /dev/null
    288}
    289
    290devlink_trap_action_get()
    291{
    292	local trap_name=$1; shift
    293
    294	devlink -j trap show $DEVLINK_DEV trap $trap_name \
    295		| jq -r '.[][][].action'
    296}
    297
    298devlink_trap_group_get()
    299{
    300	devlink -j trap show $DEVLINK_DEV trap $trap_name \
    301		| jq -r '.[][][].group'
    302}
    303
    304devlink_trap_metadata_test()
    305{
    306	local trap_name=$1; shift
    307	local metadata=$1; shift
    308
    309	devlink -jv trap show $DEVLINK_DEV trap $trap_name \
    310		| jq -e '.[][][].metadata | contains(["'$metadata'"])' \
    311		&> /dev/null
    312}
    313
    314devlink_trap_rx_packets_get()
    315{
    316	local trap_name=$1; shift
    317
    318	devlink -js trap show $DEVLINK_DEV trap $trap_name \
    319		| jq '.[][][]["stats"]["rx"]["packets"]'
    320}
    321
    322devlink_trap_rx_bytes_get()
    323{
    324	local trap_name=$1; shift
    325
    326	devlink -js trap show $DEVLINK_DEV trap $trap_name \
    327		| jq '.[][][]["stats"]["rx"]["bytes"]'
    328}
    329
    330devlink_trap_drop_packets_get()
    331{
    332	local trap_name=$1; shift
    333
    334	devlink -js trap show $DEVLINK_DEV trap $trap_name \
    335		| jq '.[][][]["stats"]["rx"]["dropped"]'
    336}
    337
    338devlink_trap_stats_idle_test()
    339{
    340	local trap_name=$1; shift
    341	local t0_packets t0_bytes
    342	local t1_packets t1_bytes
    343
    344	t0_packets=$(devlink_trap_rx_packets_get $trap_name)
    345	t0_bytes=$(devlink_trap_rx_bytes_get $trap_name)
    346
    347	sleep 1
    348
    349	t1_packets=$(devlink_trap_rx_packets_get $trap_name)
    350	t1_bytes=$(devlink_trap_rx_bytes_get $trap_name)
    351
    352	if [[ $t0_packets -eq $t1_packets && $t0_bytes -eq $t1_bytes ]]; then
    353		return 0
    354	else
    355		return 1
    356	fi
    357}
    358
    359devlink_trap_drop_stats_idle_test()
    360{
    361	local trap_name=$1; shift
    362	local t0_packets t0_bytes
    363
    364	t0_packets=$(devlink_trap_drop_packets_get $trap_name)
    365
    366	sleep 1
    367
    368	t1_packets=$(devlink_trap_drop_packets_get $trap_name)
    369
    370	if [[ $t0_packets -eq $t1_packets ]]; then
    371		return 0
    372	else
    373		return 1
    374	fi
    375}
    376
    377devlink_traps_enable_all()
    378{
    379	local trap_name
    380
    381	for trap_name in $(devlink_traps_get); do
    382		devlink_trap_action_set $trap_name "trap"
    383	done
    384}
    385
    386devlink_traps_disable_all()
    387{
    388	for trap_name in $(devlink_traps_get); do
    389		devlink_trap_action_set $trap_name "drop"
    390	done
    391}
    392
    393devlink_trap_groups_get()
    394{
    395	devlink -j trap group | jq -r '.[]["'$DEVLINK_DEV'"][].name'
    396}
    397
    398devlink_trap_group_action_set()
    399{
    400	local group_name=$1; shift
    401	local action=$1; shift
    402
    403	# Pipe output to /dev/null to avoid expected warnings.
    404	devlink trap group set $DEVLINK_DEV group $group_name action $action \
    405		&> /dev/null
    406}
    407
    408devlink_trap_group_rx_packets_get()
    409{
    410	local group_name=$1; shift
    411
    412	devlink -js trap group show $DEVLINK_DEV group $group_name \
    413		| jq '.[][][]["stats"]["rx"]["packets"]'
    414}
    415
    416devlink_trap_group_rx_bytes_get()
    417{
    418	local group_name=$1; shift
    419
    420	devlink -js trap group show $DEVLINK_DEV group $group_name \
    421		| jq '.[][][]["stats"]["rx"]["bytes"]'
    422}
    423
    424devlink_trap_group_stats_idle_test()
    425{
    426	local group_name=$1; shift
    427	local t0_packets t0_bytes
    428	local t1_packets t1_bytes
    429
    430	t0_packets=$(devlink_trap_group_rx_packets_get $group_name)
    431	t0_bytes=$(devlink_trap_group_rx_bytes_get $group_name)
    432
    433	sleep 1
    434
    435	t1_packets=$(devlink_trap_group_rx_packets_get $group_name)
    436	t1_bytes=$(devlink_trap_group_rx_bytes_get $group_name)
    437
    438	if [[ $t0_packets -eq $t1_packets && $t0_bytes -eq $t1_bytes ]]; then
    439		return 0
    440	else
    441		return 1
    442	fi
    443}
    444
    445devlink_trap_exception_test()
    446{
    447	local trap_name=$1; shift
    448	local group_name
    449
    450	group_name=$(devlink_trap_group_get $trap_name)
    451
    452	devlink_trap_stats_idle_test $trap_name
    453	check_fail $? "Trap stats idle when packets should have been trapped"
    454
    455	devlink_trap_group_stats_idle_test $group_name
    456	check_fail $? "Trap group idle when packets should have been trapped"
    457}
    458
    459devlink_trap_drop_test()
    460{
    461	local trap_name=$1; shift
    462	local dev=$1; shift
    463	local handle=$1; shift
    464	local group_name
    465
    466	group_name=$(devlink_trap_group_get $trap_name)
    467
    468	# This is the common part of all the tests. It checks that stats are
    469	# initially idle, then non-idle after changing the trap action and
    470	# finally idle again. It also makes sure the packets are dropped and
    471	# never forwarded.
    472	devlink_trap_stats_idle_test $trap_name
    473	check_err $? "Trap stats not idle with initial drop action"
    474	devlink_trap_group_stats_idle_test $group_name
    475	check_err $? "Trap group stats not idle with initial drop action"
    476
    477	devlink_trap_action_set $trap_name "trap"
    478	devlink_trap_stats_idle_test $trap_name
    479	check_fail $? "Trap stats idle after setting action to trap"
    480	devlink_trap_group_stats_idle_test $group_name
    481	check_fail $? "Trap group stats idle after setting action to trap"
    482
    483	devlink_trap_action_set $trap_name "drop"
    484
    485	devlink_trap_stats_idle_test $trap_name
    486	check_err $? "Trap stats not idle after setting action to drop"
    487	devlink_trap_group_stats_idle_test $group_name
    488	check_err $? "Trap group stats not idle after setting action to drop"
    489
    490	tc_check_packets "dev $dev egress" $handle 0
    491	check_err $? "Packets were not dropped"
    492}
    493
    494devlink_trap_drop_cleanup()
    495{
    496	local mz_pid=$1; shift
    497	local dev=$1; shift
    498	local proto=$1; shift
    499	local pref=$1; shift
    500	local handle=$1; shift
    501
    502	kill $mz_pid && wait $mz_pid &> /dev/null
    503	tc filter del dev $dev egress protocol $proto pref $pref handle $handle flower
    504}
    505
    506devlink_trap_stats_test()
    507{
    508	local test_name=$1; shift
    509	local trap_name=$1; shift
    510	local send_one="$@"
    511	local t0_packets
    512	local t1_packets
    513
    514	RET=0
    515
    516	t0_packets=$(devlink_trap_rx_packets_get $trap_name)
    517
    518	$send_one && sleep 1
    519
    520	t1_packets=$(devlink_trap_rx_packets_get $trap_name)
    521
    522	if [[ $t1_packets -eq $t0_packets ]]; then
    523		check_err 1 "Trap stats did not increase"
    524	fi
    525
    526	log_test "$test_name"
    527}
    528
    529devlink_trap_policers_num_get()
    530{
    531	devlink -j -p trap policer show | jq '.[]["'$DEVLINK_DEV'"] | length'
    532}
    533
    534devlink_trap_policer_rate_get()
    535{
    536	local policer_id=$1; shift
    537
    538	devlink -j -p trap policer show $DEVLINK_DEV policer $policer_id \
    539		| jq '.[][][]["rate"]'
    540}
    541
    542devlink_trap_policer_burst_get()
    543{
    544	local policer_id=$1; shift
    545
    546	devlink -j -p trap policer show $DEVLINK_DEV policer $policer_id \
    547		| jq '.[][][]["burst"]'
    548}
    549
    550devlink_trap_policer_rx_dropped_get()
    551{
    552	local policer_id=$1; shift
    553
    554	devlink -j -p -s trap policer show $DEVLINK_DEV policer $policer_id \
    555		| jq '.[][][]["stats"]["rx"]["dropped"]'
    556}
    557
    558devlink_trap_group_policer_get()
    559{
    560	local group_name=$1; shift
    561
    562	devlink -j -p trap group show $DEVLINK_DEV group $group_name \
    563		| jq '.[][][]["policer"]'
    564}
    565
    566devlink_port_by_netdev()
    567{
    568	local if_name=$1
    569
    570	devlink -j port show $if_name | jq -e '.[] | keys' | jq -r '.[]'
    571}
    572
    573devlink_cpu_port_get()
    574{
    575	local cpu_dl_port_num=$(devlink port list | grep "$DEVLINK_DEV" |
    576				grep cpu | cut -d/ -f3 | cut -d: -f1 |
    577				sed -n '1p')
    578
    579	echo "$DEVLINK_DEV/$cpu_dl_port_num"
    580}
    581
    582devlink_cell_size_get()
    583{
    584	devlink sb pool show "$DEVLINK_DEV" pool 0 -j \
    585	    | jq '.pool[][].cell_size'
    586}