xref: /spdk/test/bdev/chaining.sh (revision 6ecf0442ef0837776cebebdd988431f2420be303)
1#!/usr/bin/env bash
2# SPDX-License-Identifier: BSD-3-Clause
3# Copyright (C) 2023 Intel Corporation
4# All rights reserved.
5#
6
7testdir=$(readlink -f $(dirname $0))
8rootdir=$(readlink -f $testdir/../..)
9
10# Use TCP as the default nvmf transport
11TEST_TRANSPORT=${TEST_TRANSPORT:=tcp}
12
13source "$rootdir/test/common/autotest_common.sh"
14source "$rootdir/test/nvmf/common.sh"
15
16nqn=nqn.2016-06.io.spdk:cnode0
17key0=(00112233445566778899001122334455 11223344556677889900112233445500)
18key1=(22334455667788990011223344550011 33445566778899001122334455001122)
19bperfsock=/var/tmp/bperf.sock
20declare -A stats
21
22rpc_bperf() { "$rootdir/scripts/rpc.py" -s "$bperfsock" "$@"; }
23
24spdk_dd() {
25	local config
26
27	# Disable auto-examine to avoid seeing the examine callbacks' reads in accel stats
28	config=$("$rootdir/scripts/gen_nvme.sh" --mode=remote --json-with-subsystems \
29		--trid="$TEST_TRANSPORT:$NVMF_FIRST_TARGET_IP:$NVMF_PORT:$nqn" \
30		| jq '.subsystems[0].config[.subsystems[0].config | length] |=
31			{"method": "bdev_set_options", "params": {"bdev_auto_examine": false}}')
32
33	"$rootdir/build/bin/spdk_dd" -c <(echo "$config") "$@"
34}
35
36get_stat() {
37	local event opcode rpc
38
39	event="$1" opcode="$2" rpc=${3:-rpc_cmd}
40	if [[ -z "$opcode" ]]; then
41		"$rpc" accel_get_stats | jq -r ".$event"
42	else
43		"$rpc" accel_get_stats \
44			| jq -r ".operations[] | select(.opcode == \"$opcode\").$event"
45	fi
46}
47
48get_stat_bperf() { get_stat "$1" "$2" rpc_bperf; }
49
50update_stats() {
51	stats["sequence_executed"]=$(get_stat sequence_executed)
52	stats["encrypt_executed"]=$(get_stat executed encrypt)
53	stats["decrypt_executed"]=$(get_stat executed decrypt)
54	stats["copy_executed"]=$(get_stat executed copy)
55}
56
57tgtcleanup() {
58	rm -f "$input" "$output"
59	nvmftestfini
60}
61
62bperfcleanup() {
63	[[ -n "$bperfpid" ]] && killprocess $bperfpid
64}
65
66nvmftestinit
67nvmfappstart -m 0x2
68
69input=$(mktemp) output=$(mktemp)
70trap 'tgtcleanup; exit 1' SIGINT SIGTERM EXIT
71
72rpc_cmd <<- CONFIG
73	bdev_malloc_create 32 4096 -b malloc0
74	accel_crypto_key_create -c AES_XTS -k "${key0[0]}" -e "${key0[1]}" -n key0
75	accel_crypto_key_create -c AES_XTS -k "${key1[0]}" -e "${key1[1]}" -n key1
76	bdev_crypto_create malloc0 crypto0 -n key0
77	bdev_crypto_create crypto0 crypto1 -n key1
78	nvmf_create_transport $NVMF_TRANSPORT_OPTS
79	nvmf_create_subsystem $nqn -a
80	nvmf_subsystem_add_listener $nqn -t $TEST_TRANSPORT -a $NVMF_FIRST_TARGET_IP -s $NVMF_PORT
81	nvmf_subsystem_add_ns $nqn crypto1
82CONFIG
83
84# Remember initial stats
85update_stats
86
87# Write a single 64K request and check the stats
88dd if=/dev/urandom of="$input" bs=1K count=64
89spdk_dd --if "$input" --ob Nvme0n1 --bs $((64 * 1024)) --count 1
90(($(get_stat sequence_executed) == stats["sequence_executed"] + 1))
91(($(get_stat executed encrypt) == stats["encrypt_executed"] + 2))
92(($(get_stat executed decrypt) == stats["decrypt_executed"]))
93# No copies should be done - the copy from the malloc should translate to changing encrypt's
94# destination buffer
95(($(get_stat executed copy) == stats["copy_executed"]))
96update_stats
97
98# Now read that 64K, verify the stats and check that it matches what was written
99spdk_dd --of "$output" --ib Nvme0n1 --bs $((64 * 1024)) --count 1
100(($(get_stat sequence_executed) == stats["sequence_executed"] + 1))
101(($(get_stat executed encrypt) == stats["encrypt_executed"]))
102(($(get_stat executed decrypt) == stats["decrypt_executed"] + 2))
103(($(get_stat executed copy) == stats["copy_executed"]))
104cmp "$input" "$output"
105spdk_dd --if /dev/zero --ob Nvme0n1 --bs $((64 * 1024)) --count 1
106update_stats
107
108# Now do the same using 4K requests
109spdk_dd --if "$input" --ob Nvme0n1 --bs 4096 --count 16
110(($(get_stat sequence_executed) == stats["sequence_executed"] + 16))
111(($(get_stat executed encrypt) == stats["encrypt_executed"] + 32))
112(($(get_stat executed decrypt) == stats["decrypt_executed"]))
113(($(get_stat executed copy) == stats["copy_executed"]))
114update_stats
115
116# Check the reads
117: > "$output"
118spdk_dd --of "$output" --ib Nvme0n1 --bs 4096 --count 16
119(($(get_stat sequence_executed) == stats["sequence_executed"] + 16))
120(($(get_stat executed encrypt) == stats["encrypt_executed"]))
121(($(get_stat executed decrypt) == stats["decrypt_executed"] + 32))
122(($(get_stat executed copy) == stats["copy_executed"]))
123cmp "$input" "$output"
124
125trap - SIGINT SIGTERM EXIT
126tgtcleanup
127
128# Verify bdev crypto ENOMEM handling by setting low accel task count and sending IO with high qd
129trap 'bperfcleanup; exit 1' SIGINT SIGTERM EXIT
130
131"$rootdir/build/examples/bdevperf" -t 5 -w verify -o 4096 -q 256 --wait-for-rpc -z &
132bperfpid=$!
133
134waitforlisten $bperfpid
135rpc_cmd <<- CONFIG
136	accel_set_options --task-count 16
137	framework_start_init
138	bdev_malloc_create 32 4096 -b malloc0
139	accel_crypto_key_create -c AES_XTS -k "${key0[0]}" -e "${key0[1]}" -n key0
140	accel_crypto_key_create -c AES_XTS -k "${key1[0]}" -e "${key1[1]}" -n key1
141	bdev_crypto_create malloc0 crypto0 -n key0
142	bdev_crypto_create crypto0 crypto1 -n key1
143CONFIG
144
145"$rootdir/examples/bdev/bdevperf/bdevperf.py" perform_tests
146killprocess $bperfpid
147
148# Verify ENOMEM handling in the bdev layer by using the same accel configuration, but adding a
149# passthru bdev, which doesn't support memory domains/accel, to force bdev layer to append copies
150# and execute accel sequences
151"$rootdir/build/examples/bdevperf" -t 5 -w verify -o 4096 -q 256 --wait-for-rpc -z &
152bperfpid=$!
153
154waitforlisten $bperfpid
155rpc_cmd <<- CONFIG
156	accel_set_options --task-count 16
157	framework_start_init
158	bdev_malloc_create 32 4096 -b malloc0
159	accel_crypto_key_create -c AES_XTS -k "${key0[0]}" -e "${key0[1]}" -n key0
160	accel_crypto_key_create -c AES_XTS -k "${key1[0]}" -e "${key1[1]}" -n key1
161	bdev_passthru_create -p pt0 -b malloc0
162	bdev_crypto_create pt0 crypto0 -n key0
163	bdev_crypto_create crypto0 crypto1 -n key1
164CONFIG
165
166"$rootdir/examples/bdev/bdevperf/bdevperf.py" perform_tests
167killprocess $bperfpid
168
169trap - SIGINT SIGTERM EXIT
170killprocess $bperfpid
171wait $bperfpid
172
173# Check integration with the TCP transport in the NVMe driver by running I/O with data
174# digest enabled
175nvmftestinit
176nvmfappstart -m 0x2
177
178rpc_cmd <<- CONFIG
179	bdev_malloc_create 32 4096 -b malloc0
180	nvmf_create_transport -t tcp
181	nvmf_create_subsystem $nqn -a
182	nvmf_subsystem_add_listener $nqn -t tcp -a $NVMF_FIRST_TARGET_IP -s $NVMF_PORT
183	nvmf_subsystem_add_ns $nqn malloc0
184CONFIG
185
186trap 'bperfcleanup || :; nvmftestfini || :; exit 1' SIGINT SIGTERM EXIT
187"$rootdir/build/examples/bdevperf" -r "$bperfsock" -t 5 -w verify -o 4096 -q 256 \
188	--wait-for-rpc -z &
189bperfpid=$!
190
191waitforlisten $bperfpid "$bperfsock"
192rpc_bperf <<- CONFIG
193	bdev_set_options --disable-auto-examine
194	bdev_nvme_set_options --allow-accel-sequence
195	framework_start_init
196	bdev_nvme_attach_controller -t tcp -a $NVMF_FIRST_TARGET_IP -s $NVMF_PORT -f ipv4 -n $nqn -b nvme0 --ddgst
197	accel_crypto_key_create -c AES_XTS -k "${key0[0]}" -e "${key0[1]}" -n key0
198	bdev_crypto_create nvme0n1 crypto0 -n key0
199CONFIG
200
201"$rootdir/examples/bdev/bdevperf/bdevperf.py" -s "$bperfsock" perform_tests
202
203# Check the stats and verify that sequence is executed once for all operations (either encrypt+crc32
204# or decrypt+crc32)
205sequence=$(get_stat_bperf sequence_executed)
206encrypt=$(get_stat_bperf executed encrypt)
207decrypt=$(get_stat_bperf executed decrypt)
208crc32c=$(get_stat_bperf executed crc32c)
209
210((sequence > 0))
211((encrypt + decrypt == sequence))
212((encrypt + decrypt == crc32c))
213
214killprocess $bperfpid
215
216# Check the same with a larger block size to verify the digest calculation without in-capsule data
217"$rootdir/build/examples/bdevperf" -r "$bperfsock" -t 5 -w verify -o $((64 * 1024)) -q 32 \
218	--wait-for-rpc -z &
219bperfpid=$!
220
221waitforlisten $bperfpid "$bperfsock"
222rpc_bperf <<- CONFIG
223	bdev_set_options --disable-auto-examine
224	bdev_nvme_set_options --allow-accel-sequence
225	framework_start_init
226	bdev_nvme_attach_controller -t tcp -a $NVMF_FIRST_TARGET_IP -s $NVMF_PORT -f ipv4 -n $nqn -b nvme0 --ddgst
227	accel_crypto_key_create -c AES_XTS -k "${key0[0]}" -e "${key0[1]}" -n key0
228	bdev_crypto_create nvme0n1 crypto0 -n key0
229CONFIG
230
231"$rootdir/examples/bdev/bdevperf/bdevperf.py" -s "$bperfsock" perform_tests
232
233sequence=$(get_stat_bperf sequence_executed)
234encrypt=$(get_stat_bperf executed encrypt)
235decrypt=$(get_stat_bperf executed decrypt)
236crc32c=$(get_stat_bperf executed crc32c)
237
238((sequence > 0))
239((encrypt + decrypt == sequence))
240((encrypt + decrypt == crc32c))
241
242killprocess $bperfpid
243nvmftestfini
244
245trap - SIGINT SIGTERM EXIT
246