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