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