1#!/usr/bin/env bash 2# SPDX-License-Identifier: BSD-3-Clause 3# Copyright (C) 2018 Intel Corporation 4# All rights reserved. 5# 6testdir=$(readlink -f $(dirname $0)) 7rootdir=$(readlink -f $testdir/../../..) 8source $rootdir/test/common/autotest_common.sh 9source $rootdir/test/iscsi_tgt/common.sh 10 11iscsitestinit 12 13function run_fio() { 14 local bdev_name=$1 15 local iostats 16 local start_io_count 17 local start_bytes_read 18 local end_io_count 19 local end_bytes_read 20 local run_time=5 21 22 iostats=$($rpc_py bdev_get_iostat -b $bdev_name) 23 start_io_count=$(jq -r '.bdevs[0].num_read_ops' <<< "$iostats") 24 start_bytes_read=$(jq -r '.bdevs[0].bytes_read' <<< "$iostats") 25 26 $fio_py -p iscsi -i 1024 -d 128 -t randread -r $run_time 27 28 iostats=$($rpc_py bdev_get_iostat -b $bdev_name) 29 end_io_count=$(jq -r '.bdevs[0].num_read_ops' <<< "$iostats") 30 end_bytes_read=$(jq -r '.bdevs[0].bytes_read' <<< "$iostats") 31 32 IOPS_RESULT=$(((end_io_count - start_io_count) / run_time)) 33 BANDWIDTH_RESULT=$(((end_bytes_read - start_bytes_read) / run_time)) 34} 35 36function verify_qos_limits() { 37 local result=$1 38 local limit=$2 39 40 [ "$(bc <<< "$result > $limit*0.85")" -eq 1 ] \ 41 && [ "$(bc <<< "$result < $limit*1.05")" -eq 1 ] 42} 43 44if [ -z "$TARGET_IP" ]; then 45 echo "TARGET_IP not defined in environment" 46 exit 1 47fi 48 49if [ -z "$INITIATOR_IP" ]; then 50 echo "INITIATOR_IP not defined in environment" 51 exit 1 52fi 53 54MALLOC_BDEV_SIZE=64 55MALLOC_BLOCK_SIZE=512 56IOPS_RESULT= 57BANDWIDTH_RESULT= 58fio_py="$rootdir/scripts/fio-wrapper" 59 60timing_enter start_iscsi_tgt 61 62"${ISCSI_APP[@]}" & 63pid=$! 64echo "Process pid: $pid" 65trap 'killprocess $pid; iscsitestfini; exit 1' SIGINT SIGTERM EXIT 66waitforlisten $pid 67echo "iscsi_tgt is listening. Running tests..." 68 69timing_exit start_iscsi_tgt 70 71$rpc_py iscsi_create_portal_group $PORTAL_TAG $TARGET_IP:$ISCSI_PORT 72$rpc_py iscsi_create_initiator_group $INITIATOR_TAG $INITIATOR_NAME $NETMASK 73$rpc_py bdev_malloc_create $MALLOC_BDEV_SIZE $MALLOC_BLOCK_SIZE 74# "Malloc0:0" ==> use Malloc0 blockdev for LUN0 75# "1:2" ==> map PortalGroup1 to InitiatorGroup2 76# "64" ==> iSCSI queue depth 64 77# "-d" ==> disable CHAP authentication 78$rpc_py iscsi_create_target_node Target1 Target1_alias 'Malloc0:0' $PORTAL_TAG:$INITIATOR_TAG 64 -d 79sleep 1 80 81iscsiadm -m discovery -t sendtargets -p $TARGET_IP:$ISCSI_PORT 82iscsiadm -m node --login -p $TARGET_IP:$ISCSI_PORT 83 84trap 'iscsicleanup; killprocess $pid; iscsitestfini; exit 1' SIGINT SIGTERM EXIT 85 86# Run FIO without any QOS limits to determine the raw performance 87run_fio Malloc0 88 89# Set IOPS/bandwidth limit to 50% of the actual unrestrained performance. 90IOPS_LIMIT=$((IOPS_RESULT / 2)) 91BANDWIDTH_LIMIT=$((BANDWIDTH_RESULT / 2)) 92# Set READ bandwidth limit to 50% of the RW bandwidth limit to be able 93# to differentiate those two. 94READ_BANDWIDTH_LIMIT=$((BANDWIDTH_LIMIT / 2)) 95 96# Also round them down to nearest multiple of either 1000 IOPS or 1MB BW 97# which are the minimal QoS granularities 98IOPS_LIMIT=$((IOPS_LIMIT / 1000 * 1000)) 99BANDWIDTH_LIMIT_MB=$((BANDWIDTH_LIMIT / 1024 / 1024)) 100BANDWIDTH_LIMIT=$((BANDWIDTH_LIMIT_MB * 1024 * 1024)) 101READ_BANDWIDTH_LIMIT_MB=$((READ_BANDWIDTH_LIMIT / 1024 / 1024)) 102READ_BANDWIDTH_LIMIT=$((READ_BANDWIDTH_LIMIT_MB * 1024 * 1024)) 103 104# Limit the I/O rate by RPC, then confirm the observed rate matches. 105$rpc_py bdev_set_qos_limit Malloc0 --rw_ios_per_sec $IOPS_LIMIT 106run_fio Malloc0 107verify_qos_limits $IOPS_RESULT $IOPS_LIMIT 108 109# Now disable the rate limiting, and confirm the observed rate is not limited anymore. 110$rpc_py bdev_set_qos_limit Malloc0 --rw_ios_per_sec 0 111run_fio Malloc0 112[ "$IOPS_RESULT" -gt "$IOPS_LIMIT" ] 113 114# Limit the I/O rate again. 115$rpc_py bdev_set_qos_limit Malloc0 --rw_ios_per_sec $IOPS_LIMIT 116run_fio Malloc0 117verify_qos_limits $IOPS_RESULT $IOPS_LIMIT 118 119echo "I/O rate limiting tests successful" 120 121# Limit the I/O bandwidth rate by RPC, then confirm the observed rate matches. 122$rpc_py bdev_set_qos_limit Malloc0 --rw_ios_per_sec 0 --rw_mbytes_per_sec $BANDWIDTH_LIMIT_MB 123run_fio Malloc0 124verify_qos_limits $BANDWIDTH_RESULT $BANDWIDTH_LIMIT 125 126# Now disable the bandwidth rate limiting, and confirm the observed rate is not limited anymore. 127$rpc_py bdev_set_qos_limit Malloc0 --rw_mbytes_per_sec 0 128run_fio Malloc0 129[ "$BANDWIDTH_RESULT" -gt "$BANDWIDTH_LIMIT" ] 130 131# Limit the I/O bandwidth rate again with both read/write and read/only. 132$rpc_py bdev_set_qos_limit Malloc0 --rw_mbytes_per_sec $BANDWIDTH_LIMIT_MB --r_mbytes_per_sec $READ_BANDWIDTH_LIMIT_MB 133run_fio Malloc0 134verify_qos_limits $BANDWIDTH_RESULT $READ_BANDWIDTH_LIMIT 135 136echo "I/O bandwidth limiting tests successful" 137 138iscsicleanup 139$rpc_py iscsi_delete_target_node 'iqn.2016-06.io.spdk:Target1' 140 141rm -f ./local-job0-0-verify.state 142trap - SIGINT SIGTERM EXIT 143killprocess $pid 144 145iscsitestfini 146