From 045152b2204bb44c1e70093b61989c1900c729d6 Mon Sep 17 00:00:00 2001 From: Konrad Sztyber Date: Tue, 30 Aug 2022 06:14:59 +0200 Subject: [PATCH] test/sma: quality of service test The test verifies that bdev-based QoS settings are correctly applied on NVMe/TCP devices. Other device types supporting bdev-based QoS will share most of the code, so NVMe/TCP is a good test vehicle, as it's the easiest one to set up. Signed-off-by: Konrad Sztyber Change-Id: Ic715483e888a7219fd27367d527201d75e8b69a2 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/14270 Tested-by: SPDK CI Jenkins Reviewed-by: Tomasz Zawadzki Reviewed-by: Jim Harris --- test/sma/common.sh | 15 +++ test/sma/qos.sh | 238 +++++++++++++++++++++++++++++++++++++++++++++ test/sma/sma.sh | 1 + 3 files changed, 254 insertions(+) create mode 100755 test/sma/qos.sh diff --git a/test/sma/common.sh b/test/sma/common.sh index afa2ecbe8..5061f2cb6 100644 --- a/test/sma/common.sh +++ b/test/sma/common.sh @@ -35,3 +35,18 @@ uuid2nguid() { local uuid=${1^^} echo ${uuid//-/} } + +get_qos_caps() { + local rootdir + + rootdir="$(dirname $BASH_SOURCE)/../.." + + "$rootdir/scripts/sma-client.py" <<- EOF + { + "method": "GetQosCapabilities", + "params": { + "device_type": $1 + } + } + EOF +} diff --git a/test/sma/qos.sh b/test/sma/qos.sh new file mode 100755 index 000000000..60b117c7c --- /dev/null +++ b/test/sma/qos.sh @@ -0,0 +1,238 @@ +#!/usr/bin/env bash + +testdir=$(readlink -f "$(dirname "$0")") +rootdir=$(readlink -f "$testdir/../..") + +source "$rootdir/test/common/autotest_common.sh" +source "$testdir/common.sh" + +smac="$rootdir/scripts/sma-client.py" + +device_nvmf_tcp=3 +limit_reserved=$(printf '%u' $((2 ** 64 - 1))) + +cleanup() { + killprocess $tgtpid + killprocess $smapid +} + +create_device() { + $smac <<- EOF + { + "method": "CreateDevice", + "params": { + "nvmf_tcp": { + "subnqn": "nqn.2016-06.io.spdk:cnode0", + "adrfam": "ipv4", + "traddr": "127.0.0.1", + "trsvcid": "4420" + }, + "volume": { + "volume_id": "$(uuid2base64 $1)" + } + } + } + EOF +} + +trap "cleanup; exit 1" SIGINT SIGTERM EXIT + +$rootdir/build/bin/spdk_tgt & +tgtpid=$! + +$rootdir/scripts/sma.py -c <( + cat <<- EOF + address: 127.0.0.1 + port: 8080 + devices: + - name: 'nvmf_tcp' + EOF +) & +smapid=$! + +sma_waitforlisten + +# Prepare a device with a volume +rpc_cmd bdev_null_create null0 100 4096 +uuid=$(rpc_cmd bdev_get_bdevs -b null0 | jq -r '.[].uuid') +device=$(create_device $uuid | jq -r '.handle') + +# First check the capabilities +diff <(get_qos_caps $device_nvmf_tcp | jq --sort-keys) <( + jq --sort-keys <<- EOF + { + "max_volume_caps": { + "rw_iops": true, + "rd_bandwidth": true, + "wr_bandwidth": true, + "rw_bandwidth": true + } + } + EOF +) + +# Make sure that invalid device type causes an error +NOT get_qos_caps 1234 + +# Set a single limit and make sure it's changed (and nothing else was changed) +$smac <<- EOF + { + "method": "SetQos", + "params": { + "device_handle": "$device", + "volume_id": "$(uuid2base64 $uuid)", + "maximum": { + "rw_iops": 1 + } + } + } +EOF +diff <(rpc_cmd bdev_get_bdevs -b null0 | jq --sort-keys '.[].assigned_rate_limits') <( + jq --sort-keys <<- EOF + { + "rw_ios_per_sec": 1000, + "rw_mbytes_per_sec": 0, + "r_mbytes_per_sec": 0, + "w_mbytes_per_sec": 0 + } + EOF +) + +# Change two limits at the same time +$smac <<- EOF + { + "method": "SetQos", + "params": { + "device_handle": "$device", + "volume_id": "$(uuid2base64 $uuid)", + "maximum": { + "rw_iops": 2, + "rd_bandwidth": 8 + } + } + } +EOF +diff <(rpc_cmd bdev_get_bdevs -b null0 | jq --sort-keys '.[].assigned_rate_limits') <( + jq --sort-keys <<- EOF + { + "rw_ios_per_sec": 2000, + "rw_mbytes_per_sec": 0, + "r_mbytes_per_sec": 8, + "w_mbytes_per_sec": 0 + } + EOF +) + +# Check that it's possible to preserve existing values by specifying limit=UINT64_MAX +$smac <<- EOF + { + "method": "SetQos", + "params": { + "device_handle": "$device", + "volume_id": "$(uuid2base64 $uuid)", + "maximum": { + "rw_iops": $limit_reserved, + "rd_bandwidth": $limit_reserved, + "rw_bandwidth": 6 + } + } + } +EOF +diff <(rpc_cmd bdev_get_bdevs -b null0 | jq --sort-keys '.[].assigned_rate_limits') <( + jq --sort-keys <<- EOF + { + "rw_ios_per_sec": 2000, + "rw_mbytes_per_sec": 6, + "r_mbytes_per_sec": 8, + "w_mbytes_per_sec": 0 + } + EOF +) + +# Check that specyfing an unsupported limit results in an error +unsupported_max_limits=(rd_iops wr_iops) + +for limit in "${unsupported_max_limits[@]}"; do + NOT $smac <<- EOF + { + "method": "SetQos", + "params": { + "device_handle": "$device", + "volume_id": "$(uuid2base64 $uuid)", + "maximum": { + "rw_iops": $limit_reserved, + "rd_bandwidth": $limit_reserved, + "rw_bandwidth": $limit_reserved, + "$limit": 1 + } + } + } + EOF +done + +# Check non-existing device handle/volume_id +NOT $smac <<- EOF + { + "method": "SetQos", + "params": { + "device_handle": "${device}-invalid", + "volume_id": "$(uuid2base64 $uuid)", + "maximum": { + "rw_iops": 1 + } + } + } +EOF + +NOT $smac <<- EOF + { + "method": "SetQos", + "params": { + "device_handle": "$device", + "volume_id": "$(uuid2base64 $(uuidgen))", + "maximum": { + "rw_iops": 1 + } + } + } +EOF + +# Check that it's not possible to set limits without specyfing a volume/device +NOT $smac <<- EOF + { + "method": "SetQos", + "params": { + "device_handle": "$device", + "maximum": { + "rw_iops": 1 + } + } + } +EOF + +NOT $smac <<- EOF + { + "method": "SetQos", + "params": { + "volume_id": "$(uuid2base64 $uuid)", + "maximum": { + "rw_iops": 1 + } + } + } +EOF + +# Make sure that none of the 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": 2000, + "rw_mbytes_per_sec": 6, + "r_mbytes_per_sec": 8, + "w_mbytes_per_sec": 0 + } + EOF +) + +trap - SIGINT SIGTERM EXIT +cleanup diff --git a/test/sma/sma.sh b/test/sma/sma.sh index b4068834f..7459a938d 100755 --- a/test/sma/sma.sh +++ b/test/sma/sma.sh @@ -11,3 +11,4 @@ run_test "sma_plugins" $testdir/plugins.sh run_test "sma_discovery" $testdir/discovery.sh run_test "sma_vhost" $testdir/vhost_blk.sh run_test "sma_crypto" $testdir/crypto.sh +run_test "sma_qos" $testdir/qos.sh