xref: /spdk/test/iscsi_tgt/qos/qos.sh (revision eb53c23236cccb6b698b7ca70ee783da1c574b5f)
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