1#!/usr/bin/env bash 2# SPDX-License-Identifier: BSD-3-Clause 3# Copyright (C) 2022 Intel Corporation 4# All rights reserved. 5# 6 7testdir=$(readlink -f "$(dirname "$0")") 8rootdir=$(readlink -f "$testdir/../..") 9 10source "$rootdir/test/common/autotest_common.sh" 11source "$testdir/common.sh" 12 13rpc_py="$rootdir/scripts/rpc.py" 14localnqn=nqn.2016-06.io.spdk:cnode0 15tgtnqn=nqn.2016-06.io.spdk:tgt0 16key0=1234567890abcdef1234567890abcdef 17key1=deadbeefcafebabefeedbeefbabecafe 18tgtsock=/var/tmp/spdk.sock2 19discovery_port=8009 20 21cleanup() { 22 killprocess $smapid 23 killprocess $hostpid 24 killprocess $tgtpid 25} 26 27gen_volume_params() { 28 local volume_id=$1 cipher=$2 key=$3 key2=$4 config 29 local -a params crypto 30 31 config=$( 32 cat <<- PARAMS 33 "volume_id": "$(uuid2base64 $volume_id)", 34 "nvmf": { 35 "hostnqn": "nqn.2016-06.io.spdk:host0", 36 "discovery": { 37 "discovery_endpoints": [ 38 { 39 "trtype": "tcp", 40 "traddr": "127.0.0.1", 41 "trsvcid": "$discovery_port" 42 } 43 ] 44 } 45 } 46 PARAMS 47 ) 48 params+=("$config") 49 50 local IFS="," 51 if [[ -n "$cipher" ]]; then 52 crypto+=("\"cipher\": $(get_cipher $cipher)") 53 crypto+=("\"key\": \"$(format_key $key)\"") 54 if [[ -n "$key2" ]]; then 55 crypto+=("\"key2\": \"$(format_key $key2)\"") 56 fi 57 58 crypto_config=$( 59 cat <<- PARAMS 60 "crypto": { 61 ${crypto[*]} 62 } 63 PARAMS 64 ) 65 66 params+=("$crypto_config") 67 fi 68 69 cat <<- PARAMS 70 "volume": { 71 ${params[*]} 72 } 73 PARAMS 74} 75 76create_device() { 77 "$rootdir/scripts/sma-client.py" <<- CREATE 78 { 79 "method": "CreateDevice", 80 "params": { 81 "nvmf_tcp": { 82 "subnqn": "$localnqn", 83 "adrfam": "ipv4", 84 "traddr": "127.0.0.1", 85 "trsvcid": "4420" 86 } 87 ${1:+, $(gen_volume_params "$@")} 88 } 89 } 90 CREATE 91} 92 93delete_device() { 94 "$rootdir/scripts/sma-client.py" <<- DELETE 95 { 96 "method": "DeleteDevice", 97 "params": { 98 "handle": "$1" 99 } 100 } 101 DELETE 102} 103 104attach_volume() { 105 local device=$1 106 shift 107 108 "$rootdir/scripts/sma-client.py" <<- ATTACH 109 { 110 "method": "AttachVolume", 111 "params": { 112 "device_handle": "$device", 113 $(gen_volume_params "$@") 114 } 115 } 116 ATTACH 117} 118 119detach_volume() { 120 "$rootdir/scripts/sma-client.py" <<- DETACH 121 { 122 "method": "DetachVolume", 123 "params": { 124 "device_handle": "$1", 125 "volume_id": "$(uuid2base64 $2)" 126 } 127 } 128 DETACH 129} 130 131verify_crypto_volume() { 132 local nqn=$1 uuid=$2 ns ns_bdev 133 134 ns=$(rpc_cmd nvmf_get_subsystems $nqn | jq -r '.[0].namespaces[0]') 135 ns_bdev=$(jq -r '.name' <<< "$ns") 136 137 # Make sure that the namespace is a crypto bdev and that there's only a single crypto bdev 138 [[ $(rpc_cmd bdev_get_bdevs -b "$ns_bdev" | jq -r '.[0].product_name') == crypto ]] 139 [[ $(rpc_cmd bdev_get_bdevs | jq -r '[.[] | select(.product_name == "crypto")] | length') -eq 1 ]] 140 # Check that the namespace's UUID/NGUID matches the one requested by the user 141 [[ $(jq -r '.uuid' <<< "$ns") == "$uuid" ]] 142 [[ $(jq -r '.nguid' <<< "$ns") == "$(uuid2nguid $uuid)" ]] 143} 144 145trap "cleanup; exit 1" SIGINT SIGTERM EXIT 146 147"$rootdir/build/bin/spdk_tgt" -m 0x1 --wait-for-rpc & 148hostpid=$! 149 150waitforlisten $hostpid 151 152# Configure host with accel crypto parameters 153$rpc_py dpdk_cryptodev_scan_accel_module 154rpc_cmd dpdk_cryptodev_set_driver -d crypto_aesni_mb 155$rpc_py accel_assign_opc -o encrypt -m dpdk_cryptodev 156$rpc_py accel_assign_opc -o decrypt -m dpdk_cryptodev 157$rpc_py framework_start_init 158 159"$rootdir/build/bin/spdk_tgt" -r "$tgtsock" -m 0x2 & 160tgtpid=$! 161 162$rootdir/scripts/sma.py -c <( 163 cat <<- CONFIG 164 address: 127.0.0.1 165 port: 8080 166 devices: 167 - name: 'nvmf_tcp' 168 crypto: 169 name: 'bdev_crypto' 170 CONFIG 171) & 172smapid=$! 173 174# Wait until the SMA starts listening 175sma_waitforlisten 176 177# Prepare the target 178uuid=$(uuidgen) 179waitforlisten "$tgtpid" "$tgtsock" 180$rpc_py -s "$tgtsock" << CONFIG 181 bdev_malloc_create -b malloc0 32 4096 -u $uuid 182 nvmf_create_transport -t tcp 183 nvmf_create_subsystem $tgtnqn -a 184 nvmf_subsystem_add_listener discovery -t tcp -a 127.0.0.1 -s $discovery_port 185 nvmf_subsystem_add_listener -t tcp -a 127.0.0.1 -s 4421 -f ipv4 $tgtnqn 186 nvmf_subsystem_add_ns $tgtnqn malloc0 187CONFIG 188 189# Create an empty device first 190device=$(create_device | jq -r '.handle') 191 192# First attach a volume without crypto 193attach_volume $device $uuid 194 195ns_bdev=$(rpc_cmd nvmf_get_subsystems $localnqn | jq -r '.[0].namespaces[0].name') 196[[ $(rpc_cmd bdev_get_bdevs -b "$ns_bdev" | jq -r '.[0].product_name') == 'NVMe disk' ]] 197[[ $(rpc_cmd bdev_get_bdevs | jq -r '[.[] | select(.product_name == "crypto")] | length') -eq 0 ]] 198[[ $(rpc_cmd nvmf_get_subsystems $localnqn | jq -r '.[0].namespaces[0].uuid') == "$uuid" ]] 199[[ $(rpc_cmd nvmf_get_subsystems $localnqn | jq -r '.[0].namespaces[0].nguid') == "$(uuid2nguid $uuid)" ]] 200 201detach_volume $device $uuid 202 203# Now attach a volume with crypto enabled 204attach_volume $device $uuid AES_CBC $key0 205 206[[ $(rpc_cmd bdev_nvme_get_discovery_info | jq -r '. | length') -eq 1 ]] 207[[ $(rpc_cmd nvmf_get_subsystems $localnqn | jq -r '.[0].namespaces | length') -eq 1 ]] 208# Make sure that the namespace exposed in the subsystem is a crypto bdev and is using malloc bdev's UUID 209verify_crypto_volume $localnqn $uuid 210# Check that it's using correct key 211crypto_bdev=$(rpc_cmd bdev_get_bdevs | jq -r '.[] | select(.product_name == "crypto")') 212key_name=$(jq -r '.driver_specific.crypto.key_name' <<< "$crypto_bdev") 213key_obj=$(rpc_cmd accel_crypto_keys_get -k $key_name) 214[[ $(jq -r '.[0].key' <<< "$key_obj") == "$key0" ]] 215[[ $(jq -r '.[0].cipher' <<< "$key_obj") == "AES_CBC" ]] 216 217# Attach the same volume again 218attach_volume $device $uuid AES_CBC $key0 219 220# Nothing should change 221[[ $(rpc_cmd bdev_nvme_get_discovery_info | jq -r '. | length') -eq 1 ]] 222[[ $(rpc_cmd nvmf_get_subsystems $localnqn | jq -r '.[0].namespaces | length') -eq 1 ]] 223verify_crypto_volume $localnqn $uuid 224crypto_bdev2=$(rpc_cmd bdev_get_bdevs | jq -r '.[] | select(.product_name == "crypto")') 225[[ $(jq -r '.name' <<< "$crypto_bdev") == $(jq -r '.name' <<< "$crypto_bdev2") ]] 226key_name=$(jq -r '.driver_specific.crypto.key_name' <<< "$crypto_bdev2") 227key_obj=$(rpc_cmd accel_crypto_keys_get -k $key_name) 228[[ $(jq -r '.[0].key' <<< "$key_obj") == "$key0" ]] 229[[ $(jq -r '.[0].cipher' <<< "$key_obj") == "AES_CBC" ]] 230 231# Try to do attach it again, but this time use a different crypto algorithm 232NOT attach_volume $device $uuid AES_XTS $key0 233# Check the same, this time changing the key 234NOT attach_volume $device $uuid AES_CBC $key1 235# Check the same, this time adding second key 236NOT attach_volume $device $uuid AES_CBC $key0 $key1 237# Check out-of-range cipher value 238NOT attach_volume $device $uuid 8 $key0 239 240# Make sure these failures haven't affected anything 241verify_crypto_volume $localnqn $uuid 242 243detach_volume $device $uuid 244 245# Check that if there's something wrong with crypto params, the volume won't get attached and 246# everything is cleaned up afterwards 247NOT attach_volume $device $uuid 8 $key0 248[[ $(rpc_cmd nvmf_get_subsystems $localnqn | jq -r '.[0].namespaces | length') -eq 0 ]] 249[[ $(rpc_cmd bdev_nvme_get_discovery_info | jq -r '. | length') -eq 0 ]] 250[[ $(rpc_cmd bdev_get_bdevs | jq -r length) -eq 0 ]] 251 252delete_device $device 253 254# Check that it's possible to create a device immediately specifying a volume with crypto 255device=$(create_device $uuid AES_CBC $key0 | jq -r '.handle') 256verify_crypto_volume $localnqn $uuid 257 258detach_volume $device $uuid 259delete_device $device 260 261# Try to create a device with incorrect volume crypto params, check that it fails and everything 262# is cleaned up afterwards 263NOT create_device $uuid 8 $key0 264[[ $(rpc_cmd bdev_nvme_get_discovery_info | jq -r '. | length') -eq 0 ]] 265[[ $(rpc_cmd bdev_get_bdevs | jq -r length) -eq 0 ]] 266[[ $(rpc_cmd nvmf_get_subsystems | jq -r "[.[] | select(.nqn == \"$localnqn\")] | length") -eq 0 ]] 267 268# Check that if crypto is disabled, it's not possible to attach a volume with crypto 269killprocess $smapid 270$rootdir/scripts/sma.py -c <( 271 cat <<- CONFIG 272 address: 127.0.0.1 273 port: 8080 274 devices: 275 - name: 'nvmf_tcp' 276 CONFIG 277) & 278smapid=$! 279 280sma_waitforlisten 281device=$(create_device | jq -r '.handle') 282 283NOT attach_volume $device $uuid AES_CBC $key0 284[[ $(rpc_cmd bdev_nvme_get_discovery_info | jq -r '. | length') -eq 0 ]] 285[[ $(rpc_cmd bdev_get_bdevs | jq -r length) -eq 0 ]] 286 287cleanup 288trap - SIGINT SIGTERM EXIT 289