xref: /spdk/test/sma/qos.sh (revision 99a43e75ed9ac3c87d23e3746173cf5a5a992544)
1#!/usr/bin/env bash
2#  SPDX-License-Identifier: BSD-3-Clause
3#  Copyright (C) 2022 Intel Corporation
4#  All rights reserved.
5#
6
7testdir=$(readlink -f "$(dirname "$0")")
8rootdir=$(readlink -f "$testdir/../..")
9
10source "$rootdir/test/common/autotest_common.sh"
11source "$testdir/common.sh"
12
13smac="$rootdir/scripts/sma-client.py"
14
15device_nvmf_tcp=3
16limit_reserved=$(printf '%u' $((2 ** 64 - 1)))
17
18cleanup() {
19	killprocess $tgtpid
20	killprocess $smapid
21}
22
23create_device() {
24	$smac <<- EOF
25		{
26		  "method": "CreateDevice",
27		  "params": {
28		    "nvmf_tcp": {
29		      "subnqn": "nqn.2016-06.io.spdk:cnode0",
30		      "adrfam": "ipv4",
31		      "traddr": "127.0.0.1",
32		      "trsvcid": "4420"
33		    },
34		    "volume": {
35		      "volume_id": "$(uuid2base64 $1)"
36		    }
37		  }
38		}
39	EOF
40}
41
42trap "cleanup; exit 1" SIGINT SIGTERM EXIT
43
44$rootdir/build/bin/spdk_tgt &
45tgtpid=$!
46
47$rootdir/scripts/sma.py -c <(
48	cat <<- EOF
49		address: 127.0.0.1
50		port: 8080
51		devices:
52		  - name: 'nvmf_tcp'
53	EOF
54) &
55smapid=$!
56
57sma_waitforlisten
58
59# Prepare a device with a volume
60rpc_cmd bdev_null_create null0 100 4096
61uuid=$(rpc_cmd bdev_get_bdevs -b null0 | jq -r '.[].uuid')
62device=$(create_device $uuid | jq -r '.handle')
63
64# First check the capabilities
65diff <(get_qos_caps $device_nvmf_tcp | jq --sort-keys) <(
66	jq --sort-keys <<- EOF
67		{
68		  "max_volume_caps": {
69		    "rw_iops": true,
70		    "rd_bandwidth": true,
71		    "wr_bandwidth": true,
72		    "rw_bandwidth": true
73		  }
74		}
75	EOF
76)
77
78# Make sure that invalid device type causes an error
79NOT get_qos_caps 1234
80
81# Set a single limit and make sure it's changed (and nothing else was changed)
82$smac <<- EOF
83	{
84	  "method": "SetQos",
85	  "params": {
86	    "device_handle": "$device",
87	    "volume_id": "$(uuid2base64 $uuid)",
88	    "maximum": {
89	      "rw_iops": 1
90	    }
91	  }
92	}
93EOF
94diff <(rpc_cmd bdev_get_bdevs -b null0 | jq --sort-keys '.[].assigned_rate_limits') <(
95	jq --sort-keys <<- EOF
96		{
97		  "rw_ios_per_sec": 1000,
98		  "rw_mbytes_per_sec": 0,
99		  "r_mbytes_per_sec": 0,
100		  "w_mbytes_per_sec": 0
101		}
102	EOF
103)
104
105# Change two limits at the same time
106$smac <<- EOF
107	{
108	  "method": "SetQos",
109	  "params": {
110	    "device_handle": "$device",
111	    "volume_id": "$(uuid2base64 $uuid)",
112	    "maximum": {
113	      "rw_iops": 2,
114	      "rd_bandwidth": 8
115	    }
116	  }
117	}
118EOF
119diff <(rpc_cmd bdev_get_bdevs -b null0 | jq --sort-keys '.[].assigned_rate_limits') <(
120	jq --sort-keys <<- EOF
121		{
122		  "rw_ios_per_sec": 2000,
123		  "rw_mbytes_per_sec": 0,
124		  "r_mbytes_per_sec": 8,
125		  "w_mbytes_per_sec": 0
126		}
127	EOF
128)
129
130# Check that it's possible to preserve existing values by specifying limit=UINT64_MAX
131$smac <<- EOF
132	{
133	  "method": "SetQos",
134	  "params": {
135	    "device_handle": "$device",
136	    "volume_id": "$(uuid2base64 $uuid)",
137	    "maximum": {
138	      "rw_iops": $limit_reserved,
139	      "rd_bandwidth": $limit_reserved,
140	      "rw_bandwidth": 6
141	    }
142	  }
143	}
144EOF
145diff <(rpc_cmd bdev_get_bdevs -b null0 | jq --sort-keys '.[].assigned_rate_limits') <(
146	jq --sort-keys <<- EOF
147		{
148		  "rw_ios_per_sec": 2000,
149		  "rw_mbytes_per_sec": 6,
150		  "r_mbytes_per_sec": 8,
151		  "w_mbytes_per_sec": 0
152		}
153	EOF
154)
155
156# Check that specyfing an unsupported limit results in an error
157unsupported_max_limits=(rd_iops wr_iops)
158
159for limit in "${unsupported_max_limits[@]}"; do
160	NOT $smac <<- EOF
161		{
162		  "method": "SetQos",
163		  "params": {
164		    "device_handle": "$device",
165		    "volume_id": "$(uuid2base64 $uuid)",
166		    "maximum": {
167		      "rw_iops": $limit_reserved,
168		      "rd_bandwidth": $limit_reserved,
169		      "rw_bandwidth": $limit_reserved,
170		      "$limit": 1
171		    }
172		  }
173		}
174	EOF
175done
176
177# Check non-existing device handle/volume_id
178NOT $smac <<- EOF
179	{
180	  "method": "SetQos",
181	  "params": {
182	    "device_handle": "${device}-invalid",
183	    "volume_id": "$(uuid2base64 $uuid)",
184	     "maximum": {
185	      "rw_iops": 1
186	    }
187	  }
188	}
189EOF
190
191NOT $smac <<- EOF
192	{
193	  "method": "SetQos",
194	  "params": {
195	    "device_handle": "$device",
196	    "volume_id": "$(uuid2base64 $(uuidgen))",
197	     "maximum": {
198	      "rw_iops": 1
199	    }
200	  }
201	}
202EOF
203
204# Check that it's not possible to set limits without specyfing a volume/device
205NOT $smac <<- EOF
206	{
207	  "method": "SetQos",
208	  "params": {
209	    "device_handle": "$device",
210	     "maximum": {
211	      "rw_iops": 1
212	    }
213	  }
214	}
215EOF
216
217NOT $smac <<- EOF
218	{
219	  "method": "SetQos",
220	  "params": {
221	    "volume_id": "$(uuid2base64 $uuid)",
222	     "maximum": {
223	      "rw_iops": 1
224	    }
225	  }
226	}
227EOF
228
229# Make sure that none of the limits were changed
230diff <(rpc_cmd bdev_get_bdevs -b null0 | jq --sort-keys '.[].assigned_rate_limits') <(
231	jq --sort-keys <<- EOF
232		{
233		  "rw_ios_per_sec": 2000,
234		  "rw_mbytes_per_sec": 6,
235		  "r_mbytes_per_sec": 8,
236		  "w_mbytes_per_sec": 0
237		}
238	EOF
239)
240
241trap - SIGINT SIGTERM EXIT
242cleanup
243