per Intel policy to include file commit date using git cmd below. The policy does not apply to non-Intel (C) notices. git log --follow -C90% --format=%ad --date default <file> | tail -1 and then pull just the year from the result. Intel copyrights were not added to files where Intel either had no contribution ot the contribution lacked substance (ie license header updates, formatting changes, etc) For intel copyrights added, --follow and -C95% were used. Signed-off-by: paul luse <paul.e.luse@intel.com> Change-Id: I2ef86976095b88a9bf5b1003e59f3943cd6bbe4c Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/15209 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Community-CI: Mellanox Build Bot Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Krzysztof Karas <krzysztof.karas@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
367 lines
11 KiB
Bash
Executable File
367 lines
11 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
# Copyright (C) 2022 Intel Corporation
|
|
# All rights reserved.
|
|
#
|
|
testdir=$(readlink -f "$(dirname "$0")")
|
|
rootdir=$(readlink -f "$testdir/../..")
|
|
|
|
source "$rootdir/test/common/autotest_common.sh"
|
|
source "$rootdir/test/vfio_user/common.sh"
|
|
source "$testdir/common.sh"
|
|
|
|
function create_device() {
|
|
local pfid=${1:-1}
|
|
local vfid=${2:-0}
|
|
|
|
"$rootdir/scripts/sma-client.py" <<- CREATE
|
|
{
|
|
"method": "CreateDevice",
|
|
"params": {
|
|
"nvme": {
|
|
"physical_id": "$pfid",
|
|
"virtual_id": "$vfid"
|
|
}
|
|
}
|
|
}
|
|
CREATE
|
|
}
|
|
|
|
function delete_device() {
|
|
"$rootdir/scripts/sma-client.py" <<- DELETE
|
|
{
|
|
"method": "DeleteDevice",
|
|
"params": {
|
|
"handle": "$1"
|
|
}
|
|
}
|
|
DELETE
|
|
}
|
|
|
|
function attach_volume() {
|
|
"$rootdir/scripts/sma-client.py" <<- ATTACH
|
|
{
|
|
"method": "AttachVolume",
|
|
"params": {
|
|
"device_handle": "$1",
|
|
"volume": {
|
|
"volume_id": "$(uuid2base64 $2)"
|
|
}
|
|
}
|
|
}
|
|
ATTACH
|
|
}
|
|
|
|
function detach_volume() {
|
|
"$rootdir/scripts/sma-client.py" <<- DETACH
|
|
{
|
|
"method": "DetachVolume",
|
|
"params": {
|
|
"device_handle": "$1",
|
|
"volume_id": "$(uuid2base64 $2)"
|
|
}
|
|
}
|
|
DETACH
|
|
}
|
|
|
|
function vm_count_nvme() {
|
|
vm_exec $1 "grep -l SPDK /sys/class/nvme/*/model" | wc -l
|
|
}
|
|
|
|
function vm_check_subsys_volume() {
|
|
local vm_id=$1
|
|
local nqn=$2
|
|
local uuid=$3
|
|
|
|
nvme="$(vm_exec $vm_id "grep -l $nqn /sys/class/nvme/*/subsysnqn" | awk -F/ '{print $5}')"
|
|
if [[ -z "$nvme" ]]; then
|
|
error "FAILED no NVMe on vm=$vm_id with nqn=$nqn"
|
|
return 1
|
|
fi
|
|
|
|
tmpuuid="$(vm_exec $vm_id "grep -l $uuid /sys/class/nvme/$nvme/nvme*/uuid")"
|
|
if [[ -z "$tmpuuid" ]]; then
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
function vm_check_subsys_nqn() {
|
|
sleep 1
|
|
nqn=$(vm_exec $1 "grep -l $2 /sys/class/nvme/*/subsysnqn")
|
|
if [[ -z "$nqn" ]]; then
|
|
error "FAILED no NVMe on vm=$1 with nqn=$2"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
function cleanup() {
|
|
vm_kill_all
|
|
killprocess $tgtpid
|
|
killprocess $smapid
|
|
if [ -e "${VFO_ROOT_PATH}" ]; then rm -rf "${VFO_ROOT_PATH}"; fi
|
|
}
|
|
|
|
trap "cleanup; exit 1" SIGINT SIGTERM EXIT
|
|
|
|
# SSH VM Password
|
|
VM_PASSWORD=root
|
|
vm_no=0
|
|
|
|
VFO_ROOT_PATH="/tmp/sma/vfio-user/qemu"
|
|
|
|
if [ -e "${VFO_ROOT_PATH}" ]; then rm -rf "${VFO_ROOT_PATH}"; fi
|
|
mkdir -p "${VFO_ROOT_PATH}"
|
|
|
|
# Cleanup old VM:
|
|
used_vms=$vm_no
|
|
vm_kill_all
|
|
|
|
vm_setup --os="$VM_IMAGE" --disk-type=virtio --force=$vm_no --qemu-args="-qmp tcp:localhost:10005,server,nowait \
|
|
-device pci-bridge,chassis_nr=1,id=pci.spdk.0 \
|
|
-device pci-bridge,chassis_nr=2,id=pci.spdk.1"
|
|
|
|
# Run pre-configured VM and wait for them to start
|
|
vm_run $vm_no
|
|
vm_wait_for_boot 300 $vm_no
|
|
|
|
# Start SPDK
|
|
$rootdir/build/bin/spdk_tgt &
|
|
tgtpid=$!
|
|
waitforlisten $tgtpid
|
|
|
|
# Prepare the target
|
|
rpc_cmd bdev_null_create null0 100 4096
|
|
rpc_cmd bdev_null_create null1 100 4096
|
|
|
|
# Start SMA server
|
|
$rootdir/scripts/sma.py -c <(
|
|
cat <<- EOF
|
|
devices:
|
|
- name: 'vfiouser'
|
|
params:
|
|
buses:
|
|
- name: 'pci.spdk.0'
|
|
count: 32
|
|
- name: 'pci.spdk.1'
|
|
count: 32
|
|
qmp_addr: 127.0.0.1
|
|
qmp_port: 10005
|
|
crypto:
|
|
name: 'bdev_crypto'
|
|
params:
|
|
driver: 'crypto_aesni_mb'
|
|
EOF
|
|
) &
|
|
smapid=$!
|
|
|
|
# Wait until the SMA starts listening
|
|
sma_waitforlisten
|
|
|
|
# Make sure a TCP transport has been created
|
|
rpc_cmd nvmf_get_transports --trtype VFIOUSER
|
|
|
|
# Make sure no nvme subsystems are present
|
|
[[ $(vm_exec ${vm_no} nvme list-subsys -o json | jq -r '.Subsystems | length') -eq 0 ]]
|
|
|
|
# Create a couple of devices and verify them via RPC and SSH
|
|
device0=$(create_device 0 0 | jq -r '.handle')
|
|
rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-0
|
|
vm_check_subsys_nqn $vm_no nqn.2016-06.io.spdk:vfiouser-0
|
|
|
|
# Check that there are two subsystems (1 created above + discovery)
|
|
[[ $(rpc_cmd nvmf_get_subsystems | jq -r '. | length') -eq 2 ]]
|
|
|
|
device1=$(create_device 1 0 | jq -r '.handle')
|
|
rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-0
|
|
rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-1
|
|
[[ "$device0" != "$device1" ]]
|
|
vm_check_subsys_nqn $vm_no nqn.2016-06.io.spdk:vfiouser-1
|
|
|
|
# Check that there are three subsystems (2 created above + discovery)
|
|
[[ $(rpc_cmd nvmf_get_subsystems | jq -r '. | length') -eq 3 ]]
|
|
|
|
# Verify the method is idempotent and sending the same gRPCs won't create new
|
|
# devices and will return the same IDs
|
|
tmp0=$(create_device 0 0 | jq -r '.handle')
|
|
tmp1=$(create_device 1 0 | jq -r '.handle')
|
|
|
|
[[ $(vm_count_nvme ${vm_no}) -eq 2 ]]
|
|
|
|
[[ $(rpc_cmd nvmf_get_subsystems | jq -r '. | length') -eq 3 ]]
|
|
[[ "$tmp0" == "$device0" ]]
|
|
[[ "$tmp1" == "$device1" ]]
|
|
|
|
# Now remove them verifying via RPC
|
|
delete_device "$device0"
|
|
NOT rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-0
|
|
rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-1
|
|
[[ $(rpc_cmd nvmf_get_subsystems | jq -r '. | length') -eq 2 ]]
|
|
[[ $(vm_count_nvme ${vm_no}) -eq 1 ]]
|
|
|
|
delete_device "$device1"
|
|
NOT rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-0
|
|
NOT rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-1
|
|
[[ $(rpc_cmd nvmf_get_subsystems | jq -r '. | length') -eq 1 ]]
|
|
[[ $(vm_count_nvme ${vm_no}) -eq 0 ]]
|
|
|
|
# Finally check that removing a non-existing device is also sucessful
|
|
delete_device "$device0"
|
|
delete_device "$device1"
|
|
|
|
# Check volume attach/detach
|
|
device0=$(create_device 0 0 | jq -r '.handle')
|
|
device1=$(create_device 1 0 | jq -r '.handle')
|
|
uuid0=$(rpc_cmd bdev_get_bdevs -b null0 | jq -r '.[].uuid')
|
|
uuid1=$(rpc_cmd bdev_get_bdevs -b null1 | jq -r '.[].uuid')
|
|
|
|
# Attach the first volume to a first subsystem
|
|
attach_volume "$device0" "$uuid0"
|
|
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-0 | jq -r '.[0].namespaces | length') -eq 1 ]]
|
|
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-1 | jq -r '.[0].namespaces | length') -eq 0 ]]
|
|
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-0 | jq -r '.[0].namespaces[0].uuid') == "$uuid0" ]]
|
|
vm_check_subsys_volume $vm_no nqn.2016-06.io.spdk:vfiouser-0 $uuid0
|
|
|
|
attach_volume "$device1" "$uuid1"
|
|
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-0 | jq -r '.[0].namespaces | length') -eq 1 ]]
|
|
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-1 | jq -r '.[0].namespaces | length') -eq 1 ]]
|
|
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-0 | jq -r '.[0].namespaces[0].uuid') == "$uuid0" ]]
|
|
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-1 | jq -r '.[0].namespaces[0].uuid') == "$uuid1" ]]
|
|
vm_check_subsys_volume $vm_no nqn.2016-06.io.spdk:vfiouser-1 $uuid1
|
|
|
|
# Attach the same device again and see that it won't fail
|
|
attach_volume "$device0" "$uuid0"
|
|
attach_volume "$device1" "$uuid1"
|
|
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-0 | jq -r '.[0].namespaces | length') -eq 1 ]]
|
|
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-1 | jq -r '.[0].namespaces | length') -eq 1 ]]
|
|
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-0 | jq -r '.[0].namespaces[0].uuid') == "$uuid0" ]]
|
|
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-1 | jq -r '.[0].namespaces[0].uuid') == "$uuid1" ]]
|
|
vm_check_subsys_volume $vm_no nqn.2016-06.io.spdk:vfiouser-0 $uuid0
|
|
NOT vm_check_subsys_volume $vm_no nqn.2016-06.io.spdk:vfiouser-0 $uuid1
|
|
vm_check_subsys_volume $vm_no nqn.2016-06.io.spdk:vfiouser-1 $uuid1
|
|
NOT vm_check_subsys_volume $vm_no nqn.2016-06.io.spdk:vfiouser-1 $uuid0
|
|
|
|
# Cross detach volumes and verify they not fail and have not been removed from the subsystems
|
|
detach_volume "$device0" "$uuid1"
|
|
detach_volume "$device1" "$uuid0"
|
|
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-0 | jq -r '.[0].namespaces | length') -eq 1 ]]
|
|
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-1 | jq -r '.[0].namespaces | length') -eq 1 ]]
|
|
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-0 | jq -r '.[0].namespaces[0].uuid') == "$uuid0" ]]
|
|
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-1 | jq -r '.[0].namespaces[0].uuid') == "$uuid1" ]]
|
|
vm_check_subsys_volume $vm_no nqn.2016-06.io.spdk:vfiouser-0 $uuid0
|
|
NOT vm_check_subsys_volume $vm_no nqn.2016-06.io.spdk:vfiouser-0 $uuid1
|
|
vm_check_subsys_volume $vm_no nqn.2016-06.io.spdk:vfiouser-1 $uuid1
|
|
NOT vm_check_subsys_volume $vm_no nqn.2016-06.io.spdk:vfiouser-1 $uuid0
|
|
|
|
# Detach volumes and verify they have been removed from the subsystems
|
|
detach_volume "$device0" "$uuid0"
|
|
detach_volume "$device1" "$uuid1"
|
|
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-0 | jq -r '.[0].namespaces | length') -eq 0 ]]
|
|
[[ $(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-1 | jq -r '.[0].namespaces | length') -eq 0 ]]
|
|
NOT vm_check_subsys_volume $vm_no nqn.2016-06.io.spdk:vfiouser-0 $uuid0
|
|
NOT vm_check_subsys_volume $vm_no nqn.2016-06.io.spdk:vfiouser-1 $uuid1
|
|
|
|
# Detach volumes once again and verify they will not fail
|
|
detach_volume "$device0" "$uuid0"
|
|
detach_volume "$device1" "$uuid1"
|
|
detach_volume "$device0" "$uuid1"
|
|
detach_volume "$device1" "$uuid0"
|
|
|
|
delete_device "$device0"
|
|
delete_device "$device1"
|
|
|
|
# Create device with allocation on second bus
|
|
device3=$(create_device 42 0 | jq -r '.handle')
|
|
vm_check_subsys_nqn $vm_no nqn.2016-06.io.spdk:vfiouser-42
|
|
|
|
# Verify that device can be found on second bus and properly deleted
|
|
delete_device "$device3"
|
|
NOT vm_check_subsys_nqn $vm_no nqn.2016-06.io.spdk:vfiouser-42
|
|
|
|
key0=1234567890abcdef1234567890abcdef
|
|
device0=$(create_device 0 0 | jq -r '.handle')
|
|
uuid0=$(rpc_cmd bdev_get_bdevs -b null0 | jq -r '.[].uuid')
|
|
|
|
# Now check vfio-user attach with bdev crypto
|
|
"$rootdir/scripts/sma-client.py" <<- ATTACH
|
|
{
|
|
"method": "AttachVolume",
|
|
"params": {
|
|
"device_handle": "$device0",
|
|
"volume": {
|
|
"volume_id": "$(uuid2base64 $uuid0)",
|
|
"crypto": {
|
|
"cipher": "$(get_cipher AES_CBC)",
|
|
"key": "$(format_key $key0)"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ATTACH
|
|
|
|
# Make sure that the namespace exposed in the subsystem is a crypto bdev
|
|
ns_bdev=$(rpc_cmd nvmf_get_subsystems nqn.2016-06.io.spdk:vfiouser-0 | jq -r '.[0].namespaces[0].name')
|
|
[[ $(rpc_cmd bdev_get_bdevs -b "$ns_bdev" | jq -r '.[0].product_name') == "crypto" ]]
|
|
crypto_bdev=$(rpc_cmd bdev_get_bdevs -b "$ns_bdev" | jq -r '.[] | select(.product_name == "crypto")')
|
|
[[ $(rpc_cmd bdev_get_bdevs | jq -r '[.[] | select(.product_name == "crypto")] | length') -eq 1 ]]
|
|
|
|
[[ $(jq -r '.driver_specific.crypto.key' <<< "$crypto_bdev") == "$key0" ]]
|
|
|
|
detach_volume "$device0" "$uuid0"
|
|
delete_device "$device0"
|
|
[[ $(rpc_cmd bdev_get_bdevs | jq -r '.[] | select(.product_name == "crypto")' | jq -r length) -eq 0 ]]
|
|
|
|
# Test qos
|
|
device_vfio_user=1
|
|
device0=$(create_device 0 0 | jq -r '.handle')
|
|
attach_volume "$device0" "$uuid0"
|
|
|
|
# First check the capabilities
|
|
diff <(get_qos_caps $device_vfio_user | jq --sort-keys) <(
|
|
jq --sort-keys <<- CAPS
|
|
{
|
|
"max_volume_caps": {
|
|
"rw_iops": true,
|
|
"rd_bandwidth": true,
|
|
"wr_bandwidth": true,
|
|
"rw_bandwidth": true
|
|
}
|
|
}
|
|
CAPS
|
|
)
|
|
|
|
"$rootdir/scripts/sma-client.py" <<- EOF
|
|
{
|
|
"method": "SetQos",
|
|
"params": {
|
|
"device_handle": "$device0",
|
|
"volume_id": "$(uuid2base64 $uuid0)",
|
|
"maximum": {
|
|
"rd_iops": 0,
|
|
"wr_iops": 0,
|
|
"rw_iops": 3,
|
|
"rd_bandwidth": 4,
|
|
"wr_bandwidth": 5,
|
|
"rw_bandwidth": 6
|
|
}
|
|
}
|
|
}
|
|
EOF
|
|
|
|
# Make sure that limits were changed
|
|
diff <(rpc_cmd bdev_get_bdevs -b null0 | jq --sort-keys '.[].assigned_rate_limits') <(
|
|
jq --sort-keys <<- EOF
|
|
{
|
|
"rw_ios_per_sec": 3000,
|
|
"rw_mbytes_per_sec": 6,
|
|
"r_mbytes_per_sec": 4,
|
|
"w_mbytes_per_sec": 5
|
|
}
|
|
EOF
|
|
)
|
|
|
|
detach_volume "$device0" "$uuid0"
|
|
delete_device "$device0"
|
|
|
|
cleanup
|
|
trap - SIGINT SIGTERM EXIT
|