xref: /spdk/test/nvme/nvme_reset_stuck_adm_cmd.sh (revision a5f87f39127c7e0da8d9c4fcd042a27e350be84e)
1#!/usr/bin/env bash
2#  SPDX-License-Identifier: BSD-3-Clause
3# (C) Copyright 2023 Hewlett Packard Enterprise Development LP
4#  All rights reserved.
5#
6testdir=$(readlink -f $(dirname $0))
7rootdir=$(readlink -f $testdir/../..)
8source $rootdir/test/common/autotest_common.sh
9
10function base64_decode_bits() {
11	local bin_array status
12
13	bin_array=($(base64 -d <(printf '%s' "$1") | hexdump -ve '/1 "0x%02x\n"'))
14	status=$((bin_array[-1] << 8 | bin_array[-2]))
15	printf '0x%x' $(((status >> $2) & $3))
16}
17
18ctrlr_name="nvme0"
19# Error injection timeout - 15 sec (in usec)
20err_injection_timeout=15000000
21# Test timeout - 5 sec
22test_timeout=5
23
24# SCT_GENERIC
25err_injection_sct=0
26# SC_INVALID_OPCODE
27err_injection_sc=1
28
29bdf=$(get_first_nvme_bdf)
30if [ -z "${bdf}" ]; then
31	echo "No NVMe drive found but test requires it. Failing the test."
32	exit 1
33fi
34
35"$SPDK_BIN_DIR/spdk_tgt" -m 0xF &
36spdk_target_pid=$!
37trap 'killprocess "$spdk_target_pid"; exit 1' SIGINT SIGTERM EXIT
38waitforlisten "$spdk_target_pid"
39
40$rpc_py bdev_nvme_attach_controller -b $ctrlr_name -t PCIe -a ${bdf}
41tmp_file=$(mktemp "/tmp/err_inj_XXXXX.txt")
42
43# Set error injection for SPDK_NVME_OPC_GET_FEATURES admin call
44$rpc_py bdev_nvme_add_error_injection -n $ctrlr_name --cmd-type admin --opc 10 --timeout-in-us $err_injection_timeout --err-count 1 --sct $err_injection_sct --sc $err_injection_sc --do_not_submit
45start_time=$(date +%s)
46
47# The following RPC call generated based on C code taken from 'get_feature_test(...)'
48#	cmd.opc = SPDK_NVME_OPC_GET_FEATURES;
49#	cmd.cdw10_bits.get_features.fid = SPDK_NVME_FEAT_NUMBER_OF_QUEUES;
50$rootdir/scripts/rpc.py bdev_nvme_send_cmd -n $ctrlr_name -t admin -r c2h -c "CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" > $tmp_file &
51get_feat_pid=$!
52trap 'killprocess "$get_feat_pid"; exit 1' SIGINT SIGTERM EXIT
53
54# Making sure that 'get feat' process working for at least 1 sec
55sleep 2
56
57$rpc_py bdev_nvme_reset_controller $ctrlr_name
58
59echo "Waiting for RPC error injection (bdev_nvme_send_cmd) process PID:" $get_feat_pid
60wait $get_feat_pid
61diff_time=$(($(date +%s) - start_time))
62$rpc_py bdev_nvme_detach_controller $ctrlr_name
63
64trap - SIGINT SIGTERM EXIT
65
66# extracting 'sc' and 'sct' values from 'struct spdk_nvme_status'
67spdk_nvme_status=$(jq -r '.cpl' $tmp_file)
68nvme_status_sc=$(base64_decode_bits $spdk_nvme_status 1 255)
69nvme_status_sct=$(base64_decode_bits $spdk_nvme_status 9 3)
70
71rm -f $tmp_file
72
73killprocess "$spdk_target_pid"
74
75if ((err_injection_sc != nvme_status_sc || err_injection_sct != nvme_status_sct)); then
76	echo "Error NVMe completion status. SC: $nvme_status_sc, SCT: $nvme_status_sct"
77	echo " - expected status: SC: $err_injection_sc, SCT: $err_injection_sct"
78	exit 1
79elif ((diff_time > test_timeout)); then
80	echo "Test failed. Error injection timeout $diff_time sec exceeded expected timeout $test_timeout sec."
81	exit 1
82fi
83