2022-03-21 14:21:15 +00:00
|
|
|
#!/usr/bin/env bash
|
2022-11-02 15:49:40 +00:00
|
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
# Copyright (C) 2022 Intel Corporation
|
|
|
|
# All rights reserved.
|
|
|
|
#
|
2022-03-21 14:21:15 +00:00
|
|
|
testdir=$(readlink -f "$(dirname "$0")")
|
|
|
|
rootdir=$(readlink -f "$testdir/../..")
|
|
|
|
|
|
|
|
source "$rootdir/test/common/autotest_common.sh"
|
2022-08-10 15:57:17 +00:00
|
|
|
source "$rootdir/test/vfio_user/common.sh"
|
2022-03-21 14:21:15 +00:00
|
|
|
source "$testdir/common.sh"
|
|
|
|
|
|
|
|
function create_device() {
|
|
|
|
local pfid=${1:-1}
|
|
|
|
local vfid=${2:-0}
|
|
|
|
|
2022-08-31 13:53:06 +00:00
|
|
|
"$rootdir/scripts/sma-client.py" <<- CREATE
|
2022-03-21 14:21:15 +00:00
|
|
|
{
|
2022-08-31 13:53:06 +00:00
|
|
|
"method": "CreateDevice",
|
|
|
|
"params": {
|
|
|
|
"nvme": {
|
|
|
|
"physical_id": "$pfid",
|
|
|
|
"virtual_id": "$vfid"
|
|
|
|
}
|
|
|
|
}
|
2022-03-21 14:21:15 +00:00
|
|
|
}
|
2022-08-31 13:53:06 +00:00
|
|
|
CREATE
|
2022-03-21 14:21:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function delete_device() {
|
2022-08-31 13:53:06 +00:00
|
|
|
"$rootdir/scripts/sma-client.py" <<- DELETE
|
2022-03-21 14:21:15 +00:00
|
|
|
{
|
2022-08-31 13:53:06 +00:00
|
|
|
"method": "DeleteDevice",
|
|
|
|
"params": {
|
|
|
|
"handle": "$1"
|
|
|
|
}
|
2022-03-21 14:21:15 +00:00
|
|
|
}
|
2022-08-31 13:53:06 +00:00
|
|
|
DELETE
|
2022-03-21 14:21:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function attach_volume() {
|
2022-08-31 13:53:06 +00:00
|
|
|
"$rootdir/scripts/sma-client.py" <<- ATTACH
|
2022-03-21 14:21:15 +00:00
|
|
|
{
|
2022-08-31 13:53:06 +00:00
|
|
|
"method": "AttachVolume",
|
|
|
|
"params": {
|
|
|
|
"device_handle": "$1",
|
|
|
|
"volume": {
|
|
|
|
"volume_id": "$(uuid2base64 $2)"
|
|
|
|
}
|
|
|
|
}
|
2022-03-21 14:21:15 +00:00
|
|
|
}
|
2022-08-31 13:53:06 +00:00
|
|
|
ATTACH
|
2022-03-21 14:21:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function detach_volume() {
|
2022-08-31 13:53:06 +00:00
|
|
|
"$rootdir/scripts/sma-client.py" <<- DETACH
|
2022-03-21 14:21:15 +00:00
|
|
|
{
|
2022-08-31 13:53:06 +00:00
|
|
|
"method": "DetachVolume",
|
|
|
|
"params": {
|
|
|
|
"device_handle": "$1",
|
|
|
|
"volume_id": "$(uuid2base64 $2)"
|
|
|
|
}
|
2022-03-21 14:21:15 +00:00
|
|
|
}
|
2022-08-31 13:53:06 +00:00
|
|
|
DETACH
|
2022-03-21 14:21:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
|
2022-09-23 07:50:25 +00:00
|
|
|
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"
|
2022-03-21 14:21:15 +00:00
|
|
|
|
|
|
|
# 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
|
2022-09-23 07:50:25 +00:00
|
|
|
- name: 'pci.spdk.1'
|
|
|
|
count: 32
|
2022-03-21 14:21:15 +00:00
|
|
|
qmp_addr: 127.0.0.1
|
|
|
|
qmp_port: 10005
|
2022-08-11 13:55:56 +00:00
|
|
|
crypto:
|
|
|
|
name: 'bdev_crypto'
|
|
|
|
params:
|
|
|
|
driver: 'crypto_aesni_mb'
|
2022-03-21 14:21:15 +00:00
|
|
|
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 ]]
|
|
|
|
|
2022-11-02 15:09:36 +00:00
|
|
|
# Finally check that removing a non-existing device is also successful
|
2022-03-21 14:21:15 +00:00
|
|
|
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"
|
|
|
|
|
2022-09-23 07:50:25 +00:00
|
|
|
# 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
|
|
|
|
|
2022-08-11 13:55:56 +00:00
|
|
|
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 ]]
|
|
|
|
|
2022-09-02 13:18:47 +00:00
|
|
|
# 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"
|
|
|
|
|
2022-03-21 14:21:15 +00:00
|
|
|
cleanup
|
|
|
|
trap - SIGINT SIGTERM EXIT
|