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