1#!/usr/bin/env bash 2# SPDX-License-Identifier: BSD-3-Clause 3# Copyright (C) 2022 Intel Corporation 4# All rights reserved. 5# 6testdir=$(readlink -f "$(dirname "$0")") 7rootdir=$(readlink -f "$testdir/../..") 8 9source "$rootdir/test/common/autotest_common.sh" 10source "$rootdir/test/vhost/common.sh" 11source "$testdir/common.sh" 12 13function cleanup() { 14 killprocess $vhostpid 15 killprocess $smapid 16 vm_kill_all 17} 18 19function create_device() { 20 "$rootdir/scripts/sma-client.py" <<- CREATE 21 { 22 "method": "CreateDevice", 23 "params": { 24 "virtio_blk": { 25 "physical_id": "$1", 26 "virtual_id": "0" 27 }, 28 "volume": { 29 "volume_id": "$(uuid2base64 $2)" 30 } 31 } 32 } 33 CREATE 34} 35 36function delete_device() { 37 "$rootdir/scripts/sma-client.py" <<- DELETE 38 { 39 "method": "DeleteDevice", 40 "params": { 41 "handle": "$1" 42 } 43 } 44 DELETE 45} 46 47trap "cleanup; exit 1" SIGINT SIGTERM EXIT 48 49vm_no=0 50timing_enter setup_vm 51vm_setup \ 52 --force=$vm_no \ 53 --disk-type=virtio \ 54 --qemu-args="-qmp tcp:localhost:9090,server,nowait -device pci-bridge,chassis_nr=1,id=pci.spdk.0 -device pci-bridge,chassis_nr=2,id=pci.spdk.1" \ 55 --os="$VM_IMAGE" 56 57vm_run $vm_no 58vm_wait_for_boot 300 $vm_no 59timing_exit setup_vm 60 61$rootdir/build/bin/vhost -S /var/tmp -m 0x3 & 62vhostpid=$! 63 64$rootdir/scripts/sma.py -c <( 65 cat <<- EOF 66 address: 127.0.0.1 67 port: 8080 68 devices: 69 - name: 'vhost_blk' 70 params: 71 buses: 72 - name: 'pci.spdk.0' 73 count: 32 74 - name: 'pci.spdk.1' 75 count: 32 76 qmp_addr: 127.0.0.1 77 qmp_port: 9090 78 crypto: 79 name: 'bdev_crypto' 80 params: 81 driver: 'crypto_aesni_mb' 82 EOF 83) & 84smapid=$! 85 86# Wait until the SMA starts listening 87sma_waitforlisten 88 89# Check that there is no vhost device on guest os 90[[ $(vm_exec $vm_no "lsblk | grep -E \"^vd.\" | wc -l") -eq 0 ]] 91 92# Prepare the target 93rpc_cmd bdev_null_create null0 100 4096 94rpc_cmd bdev_null_create null1 100 4096 95uuid=$(rpc_cmd bdev_get_bdevs -b null0 | jq -r '.[].uuid') 96uuid2=$(rpc_cmd bdev_get_bdevs -b null1 | jq -r '.[].uuid') 97 98# Create a couple of devices and verify them via RPC 99devid0=$(create_device 0 $uuid | jq -r '.handle') 100rpc_cmd vhost_get_controllers -n sma-0 101 102devid1=$(create_device 1 $uuid2 | jq -r '.handle') 103rpc_cmd vhost_get_controllers -n sma-0 104rpc_cmd vhost_get_controllers -n sma-1 105[[ "$devid0" != "$devid1" ]] 106 107# Check that there are two controllers (2 created above ) 108[[ $(rpc_cmd vhost_get_controllers | jq -r '. | length') -eq 2 ]] 109 110# Verify the method is idempotent and sending the same gRPCs won't create new 111# devices and will return the same handles 112tmp0=$(create_device 0 $uuid | jq -r '.handle') 113tmp1=$(create_device 1 $uuid2 | jq -r '.handle') 114 115# Try to duplicate device, this time with different uuid 116NOT create_device 1 $uuid | jq -r '.handle' 117 118# Check that there are execly two vhost device on guest os 119[[ $(vm_exec $vm_no "lsblk | grep -E \"^vd.\" | wc -l") -eq 2 ]] 120 121[[ $(rpc_cmd vhost_get_controllers | jq -r '. | length') -eq 2 ]] 122[[ "$tmp0" == "$devid0" ]] 123[[ "$tmp1" == "$devid1" ]] 124 125# Now delete both of them verifying via RPC 126delete_device "$devid0" 127NOT rpc_cmd vhost_get_controllers -n sma-0 128[[ $(rpc_cmd vhost_get_controllers | jq -r '. | length') -eq 1 ]] 129 130delete_device "$devid1" 131NOT rpc_cmd vhost_get_controllers -n sma-1 132[[ $(rpc_cmd vhost_get_controllers | jq -r '. | length') -eq 0 ]] 133 134# Finally check that removing a non-existing device is also successful 135delete_device "$devid0" 136delete_device "$devid1" 137 138# At the end check if vhost devices are gone 139[[ $(vm_exec $vm_no "lsblk | grep -E \"^vd.\" | wc -l") -eq 0 ]] 140 141# Create 31 bdevs, two already exist 142for ((i = 2; i < 33; i++)); do 143 rpc_cmd bdev_null_create null$i 100 4096 144done 145 146devids=() 147 148# Now try to add 33 devices, max for one bus + one device on the next bus 149for ((i = 0; i < 33; i++)); do 150 uuid=$(rpc_cmd bdev_get_bdevs -b null$i | jq -r '.[].uuid') 151 devids[$i]=$(create_device $i $uuid | jq -r '.handle') 152done 153 154[[ $(vm_exec $vm_no "lsblk | grep -E \"^vd.\" | wc -l") -eq 33 ]] 155 156# Cleanup at the end 157for ((i = 0; i < 33; i++)); do 158 delete_device ${devids[$i]} 159done 160 161# And back to none 162[[ $(vm_exec $vm_no "lsblk | grep -E \"^vd.\" | wc -l") -eq 0 ]] 163 164key0=1234567890abcdef1234567890abcdef 165rpc_cmd bdev_malloc_create -b malloc0 32 4096 166uuidc=$(rpc_cmd bdev_get_bdevs -b malloc0 | jq -r '.[].uuid') 167 168#Try to create controller with bdev crypto 169devid0=$( 170 "$rootdir/scripts/sma-client.py" <<- CREATE | jq -r '.handle' 171 { 172 "method": "CreateDevice", 173 "params": { 174 "virtio_blk": { 175 "physical_id": "0", 176 "virtual_id": "0" 177 }, 178 "volume": { 179 "volume_id": "$(uuid2base64 $uuidc)", 180 "crypto": { 181 "cipher": "$(get_cipher AES_CBC)", 182 "key": "$(format_key $key0)" 183 } 184 } 185 } 186 } 187 CREATE 188) 189 190[[ $(rpc_cmd vhost_get_controllers | jq -r '. | length') -eq 1 ]] 191bdev=$(rpc_cmd vhost_get_controllers | jq -r '.[].backend_specific.block.bdev') 192 193crypto_bdev=$(rpc_cmd bdev_get_bdevs | jq -r '.[] | select(.product_name == "crypto")') 194[[ $(jq -r '.driver_specific.crypto.key' <<< "$crypto_bdev") == "$key0" ]] 195[[ $(jq -r '.driver_specific.crypto.name' <<< "$crypto_bdev") == "$bdev" ]] 196 197# Delete crypto device and check if it's gone 198delete_device $devid0 199[[ $(rpc_cmd bdev_get_bdevs | jq -r '.[] | select(.product_name == "crypto")' | jq -r length) -eq 0 ]] 200 201# Test qos 202device_vhost=2 203device=$(create_device 0 $uuid | jq -r '.handle') 204 205# First check the capabilities 206diff <(get_qos_caps $device_vhost | jq --sort-keys) <( 207 jq --sort-keys <<- CAPS 208 { 209 "max_device_caps": { 210 "rw_iops": true, 211 "rd_bandwidth": true, 212 "wr_bandwidth": true, 213 "rw_bandwidth": true 214 }, 215 "max_volume_caps": { 216 "rw_iops": true, 217 "rd_bandwidth": true, 218 "wr_bandwidth": true, 219 "rw_bandwidth": true 220 } 221 } 222 CAPS 223) 224 225"$rootdir/scripts/sma-client.py" <<- EOF 226 { 227 "method": "SetQos", 228 "params": { 229 "device_handle": "$device", 230 "volume_id": "$(uuid2base64 $uuid)", 231 "maximum": { 232 "rd_iops": 0, 233 "wr_iops": 0, 234 "rw_iops": 3, 235 "rd_bandwidth": 4, 236 "wr_bandwidth": 5, 237 "rw_bandwidth": 6 238 } 239 } 240 } 241EOF 242 243# Make sure that limits were changed 244diff <(rpc_cmd bdev_get_bdevs -b null32 | jq --sort-keys '.[].assigned_rate_limits') <( 245 jq --sort-keys <<- EOF 246 { 247 "rw_ios_per_sec": 3000, 248 "rw_mbytes_per_sec": 6, 249 "r_mbytes_per_sec": 4, 250 "w_mbytes_per_sec": 5 251 } 252 EOF 253) 254 255# Try to set capabilities with empty volume id 256"$rootdir/scripts/sma-client.py" <<- EOF 257 { 258 "method": "SetQos", 259 "params": { 260 "device_handle": "$device", 261 "volume_id": "", 262 "maximum": { 263 "rd_iops": 0, 264 "wr_iops": 0, 265 "rw_iops": 4, 266 "rd_bandwidth": 5, 267 "wr_bandwidth": 6, 268 "rw_bandwidth": 7 269 } 270 } 271 } 272EOF 273 274# Make sure that limits were changed even if volume id is not set 275diff <(rpc_cmd bdev_get_bdevs -b null32 | jq --sort-keys '.[].assigned_rate_limits') <( 276 jq --sort-keys <<- EOF 277 { 278 "rw_ios_per_sec": 4000, 279 "rw_mbytes_per_sec": 7, 280 "r_mbytes_per_sec": 5, 281 "w_mbytes_per_sec": 6 282 } 283 EOF 284) 285 286# Try none-existing volume uuid 287NOT "$rootdir/scripts/sma-client.py" <<- EOF 288 { 289 "method": "SetQos", 290 "params": { 291 "device_handle": "$device", 292 "volume_id": "$(uuid2base64 $(uuidgen))", 293 "maximum": { 294 "rd_iops": 0, 295 "wr_iops": 0, 296 "rw_iops": 5, 297 "rd_bandwidth": 6, 298 "wr_bandwidth": 7, 299 "rw_bandwidth": 8 300 } 301 } 302 } 303EOF 304 305# Try invalid (too short) volume uuid 306NOT "$rootdir/scripts/sma-client.py" <<- EOF 307 { 308 "method": "SetQos", 309 "params": { 310 "device_handle": "$device", 311 "volume_id": "$(base64 <<<'invalid'))", 312 "maximum": { 313 "rd_iops": 0, 314 "wr_iops": 0, 315 "rw_iops": 5, 316 "rd_bandwidth": 6, 317 "wr_bandwidth": 7, 318 "rw_bandwidth": 8 319 } 320 } 321 } 322EOF 323 324# Values remain unchanged 325diff <(rpc_cmd bdev_get_bdevs -b null32 | jq --sort-keys '.[].assigned_rate_limits') <( 326 jq --sort-keys <<- EOF 327 { 328 "rw_ios_per_sec": 4000, 329 "rw_mbytes_per_sec": 7, 330 "r_mbytes_per_sec": 5, 331 "w_mbytes_per_sec": 6 332 } 333 EOF 334) 335 336delete_device "$device" 337 338cleanup 339trap - SIGINT SIGTERM EXIT 340