xref: /spdk/test/nvmf/host/digest.sh (revision a5f87f39127c7e0da8d9c4fcd042a27e350be84e)
1#!/usr/bin/env bash
2# SPDX-License-Identifier: BSD-3-Clause
3# Copyright (C) 2023 Intel Corporation.  All rights reserved.
4#
5
6testdir=$(readlink -f "$(dirname "$0")")
7rootdir=$(readlink -f "$testdir/../../../")
8
9set -- "--transport=tcp" "$@"
10
11source "$rootdir/test/common/autotest_common.sh"
12source "$rootdir/test/nvmf/common.sh"
13
14nqn=nqn.2016-06.io.spdk:cnode1
15bperfsock=/var/tmp/bperf.sock
16runtime=2
17
18bperf_rpc() { "$rootdir/scripts/rpc.py" -s "$bperfsock" "$@"; }
19bperf_py() { "$rootdir/examples/bdev/bdevperf/bdevperf.py" -s "$bperfsock" "$@"; }
20
21cleanup() {
22	[[ -n "$bperfpid" ]] && killprocess $bperfpid || :
23	nvmftestfini
24}
25
26get_transient_errcount() {
27	bperf_rpc bdev_get_iostat -b "$1" \
28		| jq -r '.bdevs[0]
29			| .driver_specific
30			| .nvme_error
31			| .status_code
32			| .command_transient_transport_error'
33}
34
35get_accel_stats() {
36	bperf_rpc accel_get_stats \
37		| jq -rc '.operations[]
38			| select(.opcode=="crc32c")
39			| "\(.module_name) \(.executed)"'
40}
41
42common_target_config() {
43	rpc_cmd <<- CONFIG
44		framework_start_init
45		bdev_null_create null0 100 4096
46		nvmf_create_transport $NVMF_TRANSPORT_OPTS --in-capsule-data-size 4096
47		nvmf_create_subsystem $nqn -a
48		nvmf_subsystem_add_ns $nqn null0
49		nvmf_subsystem_add_listener -t tcp -a $NVMF_FIRST_TARGET_IP -s $NVMF_PORT $nqn
50	CONFIG
51}
52
53run_bperf_err() {
54	local rw bs qd
55
56	rw=$1 bs=$2 qd=$3
57	"$rootdir/build/examples/bdevperf" -m 2 -r "$bperfsock" -w $rw -o $bs -t $runtime -q $qd -z &
58	bperfpid=$!
59
60	waitforlisten "$bperfpid" "$bperfsock"
61	bperf_rpc bdev_nvme_set_options --nvme-error-stat --bdev-retry-count -1
62	# Make sure error injection is disabled when the controller is being attached
63	rpc_cmd accel_error_inject_error -o crc32c -t disable
64	bperf_rpc bdev_nvme_attach_controller --ddgst -t tcp -a "$NVMF_FIRST_TARGET_IP" \
65		-s "$NVMF_PORT" -f ipv4 -n "$nqn" -b nvme0
66	# Inject digest errors
67	rpc_cmd accel_error_inject_error -o crc32c -t corrupt -i $((qd * 2))
68
69	bperf_py "perform_tests"
70	# Make sure that the digest errors were actually caught
71	(($(get_transient_errcount nvme0n1) > 0))
72
73	killprocess $bperfpid
74}
75
76run_bperf() {
77	local rw bs qd
78	local acc_module acc_executed exp_module
79
80	rw=$1 bs=$2 qd=$3
81	"$rootdir/build/examples/bdevperf" -m 2 -r "$bperfsock" -w $rw -o $bs -t $runtime -q $qd -z --wait-for-rpc &
82	bperfpid=$!
83	waitforlisten "$bperfpid" "$bperfsock"
84
85	[[ $SPDK_TEST_ACCEL_DSA -eq 1 ]] && bperf_rpc dsa_scan_accel_module
86	bperf_rpc framework_start_init
87
88	bperf_rpc bdev_nvme_attach_controller --ddgst -t tcp -a "$NVMF_FIRST_TARGET_IP" \
89		-s "$NVMF_PORT" -f ipv4 -n "$nqn" -b nvme0
90
91	bperf_py "perform_tests"
92	read -r acc_module acc_executed < <(get_accel_stats)
93	[[ $SPDK_TEST_ACCEL_DSA -eq 1 ]] && exp_module="dsa" || exp_module="software"
94	((acc_executed > 0))
95	[[ "$acc_module" == "$exp_module" ]]
96
97	killprocess $bperfpid
98}
99
100run_digest_error() {
101	nvmfappstart --wait-for-rpc
102
103	rpc_cmd accel_assign_opc -o crc32c -m error
104	common_target_config
105
106	# Test the reads - the host should detect digest errors and retry the requests until successful.
107	run_bperf_err randread 4096 128
108	run_bperf_err randread $((128 * 1024)) 16
109
110	# Test the writes - the target should detect digest errors, complete the commands with a transient
111	# transport error and the host should retry them until successful.  Test both small writes fitting
112	# within a CapsuleCmd as well as large ones requiring H2CData PDUs.
113	run_bperf_err randwrite 4096 128
114	run_bperf_err randwrite $((128 * 1024)) 16
115	killprocess $nvmfpid
116}
117
118run_digest() {
119	nvmfappstart --wait-for-rpc
120	common_target_config
121
122	run_bperf randread 4096 128
123	run_bperf randread $((128 * 1024)) 16
124	run_bperf randwrite 4096 128
125	run_bperf randwrite $((128 * 1024)) 16
126	killprocess $nvmfpid
127}
128
129# This test only makes sense for the TCP transport
130[[ "$TEST_TRANSPORT" != "tcp" ]] && exit 1
131
132nvmftestinit
133
134trap cleanup SIGINT SIGTERM EXIT
135run_test "nvmf_digest_clean" run_digest
136run_test "nvmf_digest_error" run_digest_error
137
138trap - SIGINT SIGTERM EXIT
139nvmftestfini
140