xref: /spdk/lib/nvmf/nvmf_rpc.c (revision 784b9d48746955f210926648a0131f84f58de76f)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2016 Intel Corporation. All rights reserved.
3  *   Copyright (c) 2018-2021 Mellanox Technologies LTD. All rights reserved.
4  *   Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5  */
6 
7 #include "spdk/bdev.h"
8 #include "spdk/log.h"
9 #include "spdk/rpc.h"
10 #include "spdk/env.h"
11 #include "spdk/nvme.h"
12 #include "spdk/nvmf.h"
13 #include "spdk/string.h"
14 #include "spdk/util.h"
15 #include "spdk/bit_array.h"
16 
17 #include "spdk_internal/assert.h"
18 
19 #include "nvmf_internal.h"
20 
21 static int
22 json_write_hex_str(struct spdk_json_write_ctx *w, const void *data, size_t size)
23 {
24 	static const char hex_char[16] = "0123456789ABCDEF";
25 	const uint8_t *buf = data;
26 	char *str, *out;
27 	int rc;
28 
29 	str = malloc(size * 2 + 1);
30 	if (str == NULL) {
31 		return -1;
32 	}
33 
34 	out = str;
35 	while (size--) {
36 		unsigned byte = *buf++;
37 
38 		out[0] = hex_char[(byte >> 4) & 0xF];
39 		out[1] = hex_char[byte & 0xF];
40 
41 		out += 2;
42 	}
43 	*out = '\0';
44 
45 	rc = spdk_json_write_string(w, str);
46 	free(str);
47 
48 	return rc;
49 }
50 
51 static int
52 hex_nybble_to_num(char c)
53 {
54 	if (c >= '0' && c <= '9') {
55 		return c - '0';
56 	}
57 
58 	if (c >= 'a' && c <= 'f') {
59 		return c - 'a' + 0xA;
60 	}
61 
62 	if (c >= 'A' && c <= 'F') {
63 		return c - 'A' + 0xA;
64 	}
65 
66 	return -1;
67 }
68 
69 static int
70 hex_byte_to_num(const char *str)
71 {
72 	int hi, lo;
73 
74 	hi = hex_nybble_to_num(str[0]);
75 	if (hi < 0) {
76 		return hi;
77 	}
78 
79 	lo = hex_nybble_to_num(str[1]);
80 	if (lo < 0) {
81 		return lo;
82 	}
83 
84 	return hi * 16 + lo;
85 }
86 
87 static int
88 decode_hex_string_be(const char *str, uint8_t *out, size_t size)
89 {
90 	size_t i;
91 
92 	/* Decode a string in "ABCDEF012345" format to its binary representation */
93 	for (i = 0; i < size; i++) {
94 		int num = hex_byte_to_num(str);
95 
96 		if (num < 0) {
97 			/* Invalid hex byte or end of string */
98 			return -1;
99 		}
100 
101 		out[i] = (uint8_t)num;
102 		str += 2;
103 	}
104 
105 	if (i != size || *str != '\0') {
106 		/* Length mismatch */
107 		return -1;
108 	}
109 
110 	return 0;
111 }
112 
113 static int
114 decode_ns_nguid(const struct spdk_json_val *val, void *out)
115 {
116 	char *str = NULL;
117 	int rc;
118 
119 	rc = spdk_json_decode_string(val, &str);
120 	if (rc == 0) {
121 		/* 16-byte NGUID */
122 		rc = decode_hex_string_be(str, out, 16);
123 	}
124 
125 	free(str);
126 	return rc;
127 }
128 
129 static int
130 decode_ns_eui64(const struct spdk_json_val *val, void *out)
131 {
132 	char *str = NULL;
133 	int rc;
134 
135 	rc = spdk_json_decode_string(val, &str);
136 	if (rc == 0) {
137 		/* 8-byte EUI-64 */
138 		rc = decode_hex_string_be(str, out, 8);
139 	}
140 
141 	free(str);
142 	return rc;
143 }
144 
145 static int
146 decode_ns_uuid(const struct spdk_json_val *val, void *out)
147 {
148 	char *str = NULL;
149 	int rc;
150 
151 	rc = spdk_json_decode_string(val, &str);
152 	if (rc == 0) {
153 		rc = spdk_uuid_parse(out, str);
154 	}
155 
156 	free(str);
157 	return rc;
158 }
159 
160 struct rpc_get_subsystem {
161 	char *nqn;
162 	char *tgt_name;
163 };
164 
165 static const struct spdk_json_object_decoder rpc_get_subsystem_decoders[] = {
166 	{"nqn", offsetof(struct rpc_get_subsystem, nqn), spdk_json_decode_string, true},
167 	{"tgt_name", offsetof(struct rpc_get_subsystem, tgt_name), spdk_json_decode_string, true},
168 };
169 
170 static void
171 dump_nvmf_subsystem(struct spdk_json_write_ctx *w, struct spdk_nvmf_subsystem *subsystem)
172 {
173 	struct spdk_nvmf_host			*host;
174 	struct spdk_nvmf_subsystem_listener	*listener;
175 
176 	spdk_json_write_object_begin(w);
177 
178 	spdk_json_write_named_string(w, "nqn", spdk_nvmf_subsystem_get_nqn(subsystem));
179 	spdk_json_write_name(w, "subtype");
180 	if (spdk_nvmf_subsystem_get_type(subsystem) == SPDK_NVMF_SUBTYPE_NVME) {
181 		spdk_json_write_string(w, "NVMe");
182 	} else {
183 		spdk_json_write_string(w, "Discovery");
184 	}
185 
186 	spdk_json_write_named_array_begin(w, "listen_addresses");
187 
188 	for (listener = spdk_nvmf_subsystem_get_first_listener(subsystem); listener != NULL;
189 	     listener = spdk_nvmf_subsystem_get_next_listener(subsystem, listener)) {
190 		const struct spdk_nvme_transport_id *trid;
191 		const char *adrfam;
192 
193 		trid = spdk_nvmf_subsystem_listener_get_trid(listener);
194 
195 		spdk_json_write_object_begin(w);
196 		adrfam = spdk_nvme_transport_id_adrfam_str(trid->adrfam);
197 		if (adrfam == NULL) {
198 			adrfam = "unknown";
199 		}
200 		/* NOTE: "transport" is kept for compatibility; new code should use "trtype" */
201 		spdk_json_write_named_string(w, "transport", trid->trstring);
202 		spdk_json_write_named_string(w, "trtype", trid->trstring);
203 		spdk_json_write_named_string(w, "adrfam", adrfam);
204 		spdk_json_write_named_string(w, "traddr", trid->traddr);
205 		spdk_json_write_named_string(w, "trsvcid", trid->trsvcid);
206 		spdk_json_write_object_end(w);
207 	}
208 	spdk_json_write_array_end(w);
209 
210 	spdk_json_write_named_bool(w, "allow_any_host",
211 				   spdk_nvmf_subsystem_get_allow_any_host(subsystem));
212 
213 	spdk_json_write_named_array_begin(w, "hosts");
214 
215 	for (host = spdk_nvmf_subsystem_get_first_host(subsystem); host != NULL;
216 	     host = spdk_nvmf_subsystem_get_next_host(subsystem, host)) {
217 		spdk_json_write_object_begin(w);
218 		spdk_json_write_named_string(w, "nqn", spdk_nvmf_host_get_nqn(host));
219 		spdk_json_write_object_end(w);
220 	}
221 	spdk_json_write_array_end(w);
222 
223 	if (spdk_nvmf_subsystem_get_type(subsystem) == SPDK_NVMF_SUBTYPE_NVME) {
224 		struct spdk_nvmf_ns *ns;
225 		struct spdk_nvmf_ns_opts ns_opts;
226 		uint32_t max_namespaces;
227 
228 		spdk_json_write_named_string(w, "serial_number", spdk_nvmf_subsystem_get_sn(subsystem));
229 
230 		spdk_json_write_named_string(w, "model_number", spdk_nvmf_subsystem_get_mn(subsystem));
231 
232 		max_namespaces = spdk_nvmf_subsystem_get_max_namespaces(subsystem);
233 		if (max_namespaces != 0) {
234 			spdk_json_write_named_uint32(w, "max_namespaces", max_namespaces);
235 		}
236 
237 		spdk_json_write_named_uint32(w, "min_cntlid", spdk_nvmf_subsystem_get_min_cntlid(subsystem));
238 		spdk_json_write_named_uint32(w, "max_cntlid", spdk_nvmf_subsystem_get_max_cntlid(subsystem));
239 
240 		spdk_json_write_named_array_begin(w, "namespaces");
241 		for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL;
242 		     ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) {
243 			spdk_nvmf_ns_get_opts(ns, &ns_opts, sizeof(ns_opts));
244 			spdk_json_write_object_begin(w);
245 			spdk_json_write_named_int32(w, "nsid", spdk_nvmf_ns_get_id(ns));
246 			spdk_json_write_named_string(w, "bdev_name",
247 						     spdk_bdev_get_name(spdk_nvmf_ns_get_bdev(ns)));
248 			/* NOTE: "name" is kept for compatibility only - new code should use bdev_name. */
249 			spdk_json_write_named_string(w, "name",
250 						     spdk_bdev_get_name(spdk_nvmf_ns_get_bdev(ns)));
251 
252 			if (!spdk_mem_all_zero(ns_opts.nguid, sizeof(ns_opts.nguid))) {
253 				spdk_json_write_name(w, "nguid");
254 				json_write_hex_str(w, ns_opts.nguid, sizeof(ns_opts.nguid));
255 			}
256 
257 			if (!spdk_mem_all_zero(ns_opts.eui64, sizeof(ns_opts.eui64))) {
258 				spdk_json_write_name(w, "eui64");
259 				json_write_hex_str(w, ns_opts.eui64, sizeof(ns_opts.eui64));
260 			}
261 
262 			if (!spdk_mem_all_zero(&ns_opts.uuid, sizeof(ns_opts.uuid))) {
263 				char uuid_str[SPDK_UUID_STRING_LEN];
264 
265 				spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &ns_opts.uuid);
266 				spdk_json_write_named_string(w, "uuid", uuid_str);
267 			}
268 
269 			if (nvmf_subsystem_get_ana_reporting(subsystem)) {
270 				spdk_json_write_named_uint32(w, "anagrpid", ns_opts.anagrpid);
271 			}
272 
273 			spdk_json_write_object_end(w);
274 		}
275 		spdk_json_write_array_end(w);
276 	}
277 	spdk_json_write_object_end(w);
278 }
279 
280 static void
281 rpc_nvmf_get_subsystems(struct spdk_jsonrpc_request *request,
282 			const struct spdk_json_val *params)
283 {
284 	struct rpc_get_subsystem req = { 0 };
285 	struct spdk_json_write_ctx *w;
286 	struct spdk_nvmf_subsystem *subsystem = NULL;
287 	struct spdk_nvmf_tgt *tgt;
288 
289 	if (params) {
290 		if (spdk_json_decode_object(params, rpc_get_subsystem_decoders,
291 					    SPDK_COUNTOF(rpc_get_subsystem_decoders),
292 					    &req)) {
293 			SPDK_ERRLOG("spdk_json_decode_object failed\n");
294 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
295 			return;
296 		}
297 	}
298 
299 	tgt = spdk_nvmf_get_tgt(req.tgt_name);
300 	if (!tgt) {
301 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
302 						 "Unable to find a target.");
303 		free(req.tgt_name);
304 		free(req.nqn);
305 		return;
306 	}
307 
308 	if (req.nqn) {
309 		subsystem = spdk_nvmf_tgt_find_subsystem(tgt, req.nqn);
310 		if (!subsystem) {
311 			SPDK_ERRLOG("subsystem '%s' does not exist\n", req.nqn);
312 			spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
313 			free(req.tgt_name);
314 			free(req.nqn);
315 			return;
316 		}
317 	}
318 
319 	w = spdk_jsonrpc_begin_result(request);
320 	spdk_json_write_array_begin(w);
321 
322 	if (subsystem) {
323 		dump_nvmf_subsystem(w, subsystem);
324 	} else {
325 		for (subsystem = spdk_nvmf_subsystem_get_first(tgt); subsystem != NULL;
326 		     subsystem = spdk_nvmf_subsystem_get_next(subsystem)) {
327 			dump_nvmf_subsystem(w, subsystem);
328 		}
329 	}
330 
331 	spdk_json_write_array_end(w);
332 	spdk_jsonrpc_end_result(request, w);
333 	free(req.tgt_name);
334 	free(req.nqn);
335 }
336 SPDK_RPC_REGISTER("nvmf_get_subsystems", rpc_nvmf_get_subsystems, SPDK_RPC_RUNTIME)
337 
338 struct rpc_subsystem_create {
339 	char *nqn;
340 	char *serial_number;
341 	char *model_number;
342 	char *tgt_name;
343 	uint32_t max_namespaces;
344 	bool allow_any_host;
345 	bool ana_reporting;
346 	uint16_t min_cntlid;
347 	uint16_t max_cntlid;
348 };
349 
350 static const struct spdk_json_object_decoder rpc_subsystem_create_decoders[] = {
351 	{"nqn", offsetof(struct rpc_subsystem_create, nqn), spdk_json_decode_string},
352 	{"serial_number", offsetof(struct rpc_subsystem_create, serial_number), spdk_json_decode_string, true},
353 	{"model_number", offsetof(struct rpc_subsystem_create, model_number), spdk_json_decode_string, true},
354 	{"tgt_name", offsetof(struct rpc_subsystem_create, tgt_name), spdk_json_decode_string, true},
355 	{"max_namespaces", offsetof(struct rpc_subsystem_create, max_namespaces), spdk_json_decode_uint32, true},
356 	{"allow_any_host", offsetof(struct rpc_subsystem_create, allow_any_host), spdk_json_decode_bool, true},
357 	{"ana_reporting", offsetof(struct rpc_subsystem_create, ana_reporting), spdk_json_decode_bool, true},
358 	{"min_cntlid", offsetof(struct rpc_subsystem_create, min_cntlid), spdk_json_decode_uint16, true},
359 	{"max_cntlid", offsetof(struct rpc_subsystem_create, max_cntlid), spdk_json_decode_uint16, true},
360 };
361 
362 static void
363 rpc_nvmf_subsystem_started(struct spdk_nvmf_subsystem *subsystem,
364 			   void *cb_arg, int status)
365 {
366 	struct spdk_jsonrpc_request *request = cb_arg;
367 
368 	if (!status) {
369 		spdk_jsonrpc_send_bool_response(request, true);
370 	} else {
371 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
372 						     "Subsystem %s start failed",
373 						     subsystem->subnqn);
374 		spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
375 	}
376 }
377 
378 static void
379 rpc_nvmf_create_subsystem(struct spdk_jsonrpc_request *request,
380 			  const struct spdk_json_val *params)
381 {
382 	struct rpc_subsystem_create *req;
383 	struct spdk_nvmf_subsystem *subsystem = NULL;
384 	struct spdk_nvmf_tgt *tgt;
385 	int rc = -1;
386 
387 	req = calloc(1, sizeof(*req));
388 	if (!req) {
389 		SPDK_ERRLOG("Memory allocation failed\n");
390 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
391 						 "Memory allocation failed");
392 		return;
393 	}
394 	req->min_cntlid = NVMF_MIN_CNTLID;
395 	req->max_cntlid = NVMF_MAX_CNTLID;
396 
397 	if (spdk_json_decode_object(params, rpc_subsystem_create_decoders,
398 				    SPDK_COUNTOF(rpc_subsystem_create_decoders),
399 				    req)) {
400 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
401 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
402 		goto cleanup;
403 	}
404 
405 	tgt = spdk_nvmf_get_tgt(req->tgt_name);
406 	if (!tgt) {
407 		SPDK_ERRLOG("Unable to find target %s\n", req->tgt_name);
408 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
409 						     "Unable to find target %s", req->tgt_name);
410 		goto cleanup;
411 	}
412 
413 	subsystem = spdk_nvmf_subsystem_create(tgt, req->nqn, SPDK_NVMF_SUBTYPE_NVME,
414 					       req->max_namespaces);
415 	if (!subsystem) {
416 		SPDK_ERRLOG("Unable to create subsystem %s\n", req->nqn);
417 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
418 						     "Unable to create subsystem %s", req->nqn);
419 		goto cleanup;
420 	}
421 
422 	if (req->serial_number) {
423 		if (spdk_nvmf_subsystem_set_sn(subsystem, req->serial_number)) {
424 			SPDK_ERRLOG("Subsystem %s: invalid serial number '%s'\n", req->nqn, req->serial_number);
425 			spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
426 							     "Invalid SN %s", req->serial_number);
427 			goto cleanup;
428 		}
429 	}
430 
431 	if (req->model_number) {
432 		if (spdk_nvmf_subsystem_set_mn(subsystem, req->model_number)) {
433 			SPDK_ERRLOG("Subsystem %s: invalid model number '%s'\n", req->nqn, req->model_number);
434 			spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
435 							     "Invalid MN %s", req->model_number);
436 			goto cleanup;
437 		}
438 	}
439 
440 	spdk_nvmf_subsystem_set_allow_any_host(subsystem, req->allow_any_host);
441 
442 	spdk_nvmf_subsystem_set_ana_reporting(subsystem, req->ana_reporting);
443 
444 	if (nvmf_subsystem_set_cntlid_range(subsystem, req->min_cntlid, req->max_cntlid)) {
445 		SPDK_ERRLOG("Subsystem %s: invalid cntlid range [%u-%u]\n", req->nqn, req->min_cntlid,
446 			    req->max_cntlid);
447 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
448 						     "Invalid cntlid range [%u-%u]", req->min_cntlid, req->max_cntlid);
449 		goto cleanup;
450 	}
451 
452 	rc = spdk_nvmf_subsystem_start(subsystem,
453 				       rpc_nvmf_subsystem_started,
454 				       request);
455 	if (rc) {
456 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
457 						 "Failed to start subsystem");
458 	}
459 
460 cleanup:
461 	free(req->nqn);
462 	free(req->tgt_name);
463 	free(req->serial_number);
464 	free(req->model_number);
465 	free(req);
466 
467 	if (rc && subsystem) {
468 		spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
469 	}
470 }
471 SPDK_RPC_REGISTER("nvmf_create_subsystem", rpc_nvmf_create_subsystem, SPDK_RPC_RUNTIME)
472 
473 struct rpc_delete_subsystem {
474 	char *nqn;
475 	char *tgt_name;
476 };
477 
478 static void
479 free_rpc_delete_subsystem(struct rpc_delete_subsystem *r)
480 {
481 	free(r->nqn);
482 	free(r->tgt_name);
483 }
484 
485 static void
486 rpc_nvmf_subsystem_destroy_complete_cb(void *cb_arg)
487 {
488 	struct spdk_jsonrpc_request *request = cb_arg;
489 
490 	spdk_jsonrpc_send_bool_response(request, true);
491 }
492 
493 static void
494 rpc_nvmf_subsystem_stopped(struct spdk_nvmf_subsystem *subsystem,
495 			   void *cb_arg, int status)
496 {
497 	struct spdk_jsonrpc_request *request = cb_arg;
498 	int rc;
499 
500 	nvmf_subsystem_remove_all_listeners(subsystem, true);
501 	rc = spdk_nvmf_subsystem_destroy(subsystem, rpc_nvmf_subsystem_destroy_complete_cb, request);
502 	if (rc) {
503 		if (rc == -EINPROGRESS) {
504 			/* response will be sent in completion callback */
505 			return;
506 		} else {
507 			SPDK_ERRLOG("Subsystem destruction failed, rc %d\n", rc);
508 			spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
509 							     "Subsystem destruction failed, rc %d", rc);
510 			return;
511 		}
512 	}
513 	spdk_jsonrpc_send_bool_response(request, true);
514 }
515 
516 static const struct spdk_json_object_decoder rpc_delete_subsystem_decoders[] = {
517 	{"nqn", offsetof(struct rpc_delete_subsystem, nqn), spdk_json_decode_string},
518 	{"tgt_name", offsetof(struct rpc_delete_subsystem, tgt_name), spdk_json_decode_string, true},
519 };
520 
521 static void
522 rpc_nvmf_delete_subsystem(struct spdk_jsonrpc_request *request,
523 			  const struct spdk_json_val *params)
524 {
525 	struct rpc_delete_subsystem req = { 0 };
526 	struct spdk_nvmf_subsystem *subsystem;
527 	struct spdk_nvmf_tgt *tgt;
528 	int rc;
529 
530 	if (spdk_json_decode_object(params, rpc_delete_subsystem_decoders,
531 				    SPDK_COUNTOF(rpc_delete_subsystem_decoders),
532 				    &req)) {
533 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
534 		goto invalid;
535 	}
536 
537 	if (req.nqn == NULL) {
538 		SPDK_ERRLOG("missing name param\n");
539 		goto invalid;
540 	}
541 
542 	tgt = spdk_nvmf_get_tgt(req.tgt_name);
543 	if (!tgt) {
544 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
545 						 "Unable to find a target.");
546 		goto invalid_custom_response;
547 	}
548 
549 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, req.nqn);
550 	if (!subsystem) {
551 		goto invalid;
552 	}
553 
554 	free_rpc_delete_subsystem(&req);
555 
556 	rc = spdk_nvmf_subsystem_stop(subsystem,
557 				      rpc_nvmf_subsystem_stopped,
558 				      request);
559 	if (rc == -EBUSY) {
560 		SPDK_ERRLOG("Subsystem currently in another state change try again later.\n");
561 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
562 						 "Subsystem currently in another state change try again later.");
563 	} else if (rc != 0) {
564 		SPDK_ERRLOG("Unable to change state on subsystem. rc=%d\n", rc);
565 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
566 						     "Unable to change state on subsystem. rc=%d", rc);
567 	}
568 
569 	return;
570 
571 invalid:
572 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
573 invalid_custom_response:
574 	free_rpc_delete_subsystem(&req);
575 }
576 SPDK_RPC_REGISTER("nvmf_delete_subsystem", rpc_nvmf_delete_subsystem, SPDK_RPC_RUNTIME)
577 
578 struct rpc_listen_address {
579 	char *transport;
580 	char *adrfam;
581 	char *traddr;
582 	char *trsvcid;
583 };
584 
585 static const struct spdk_json_object_decoder rpc_listen_address_decoders[] = {
586 	/* NOTE: "transport" is kept for compatibility; new code should use "trtype" */
587 	{"transport", offsetof(struct rpc_listen_address, transport), spdk_json_decode_string, true},
588 	{"trtype", offsetof(struct rpc_listen_address, transport), spdk_json_decode_string, true},
589 	{"adrfam", offsetof(struct rpc_listen_address, adrfam), spdk_json_decode_string, true},
590 	{"traddr", offsetof(struct rpc_listen_address, traddr), spdk_json_decode_string},
591 	{"trsvcid", offsetof(struct rpc_listen_address, trsvcid), spdk_json_decode_string, true},
592 };
593 
594 static int
595 decode_rpc_listen_address(const struct spdk_json_val *val, void *out)
596 {
597 	struct rpc_listen_address *req = (struct rpc_listen_address *)out;
598 	if (spdk_json_decode_object(val, rpc_listen_address_decoders,
599 				    SPDK_COUNTOF(rpc_listen_address_decoders),
600 				    req)) {
601 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
602 		return -1;
603 	}
604 	return 0;
605 }
606 
607 static void
608 free_rpc_listen_address(struct rpc_listen_address *r)
609 {
610 	free(r->transport);
611 	free(r->adrfam);
612 	free(r->traddr);
613 	free(r->trsvcid);
614 }
615 
616 enum nvmf_rpc_listen_op {
617 	NVMF_RPC_LISTEN_ADD,
618 	NVMF_RPC_LISTEN_REMOVE,
619 	NVMF_RPC_LISTEN_SET_ANA_STATE,
620 };
621 
622 struct nvmf_rpc_listener_ctx {
623 	char				*nqn;
624 	char				*tgt_name;
625 	struct spdk_nvmf_tgt		*tgt;
626 	struct spdk_nvmf_transport	*transport;
627 	struct spdk_nvmf_subsystem	*subsystem;
628 	struct rpc_listen_address	address;
629 	char				*ana_state_str;
630 	enum spdk_nvme_ana_state	ana_state;
631 	uint32_t			anagrpid;
632 
633 	struct spdk_jsonrpc_request	*request;
634 	struct spdk_nvme_transport_id	trid;
635 	enum nvmf_rpc_listen_op		op;
636 	bool				response_sent;
637 	struct spdk_nvmf_listen_opts	opts;
638 };
639 
640 static const struct spdk_json_object_decoder nvmf_rpc_listener_decoder[] = {
641 	{"nqn", offsetof(struct nvmf_rpc_listener_ctx, nqn), spdk_json_decode_string},
642 	{"listen_address", offsetof(struct nvmf_rpc_listener_ctx, address), decode_rpc_listen_address},
643 	{"tgt_name", offsetof(struct nvmf_rpc_listener_ctx, tgt_name), spdk_json_decode_string, true},
644 };
645 
646 static void
647 nvmf_rpc_listener_ctx_free(struct nvmf_rpc_listener_ctx *ctx)
648 {
649 	free(ctx->nqn);
650 	free(ctx->tgt_name);
651 	free_rpc_listen_address(&ctx->address);
652 	free(ctx->ana_state_str);
653 	free(ctx);
654 }
655 
656 static void
657 nvmf_rpc_listen_resumed(struct spdk_nvmf_subsystem *subsystem,
658 			void *cb_arg, int status)
659 {
660 	struct nvmf_rpc_listener_ctx *ctx = cb_arg;
661 	struct spdk_jsonrpc_request *request;
662 
663 	request = ctx->request;
664 	if (ctx->response_sent) {
665 		/* If an error occurred, the response has already been sent. */
666 		nvmf_rpc_listener_ctx_free(ctx);
667 		return;
668 	}
669 
670 	nvmf_rpc_listener_ctx_free(ctx);
671 
672 	spdk_jsonrpc_send_bool_response(request, true);
673 }
674 
675 static void
676 nvmf_rpc_subsystem_listen(void *cb_arg, int status)
677 {
678 	struct nvmf_rpc_listener_ctx *ctx = cb_arg;
679 
680 	if (status) {
681 		/* Destroy the listener that we just created. Ignore the error code because
682 		 * the RPC is failing already anyway. */
683 		spdk_nvmf_tgt_stop_listen(ctx->tgt, &ctx->trid);
684 
685 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
686 						 "Invalid parameters");
687 		ctx->response_sent = true;
688 	}
689 
690 	if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) {
691 		if (!ctx->response_sent) {
692 			spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
693 							 "Internal error");
694 		}
695 		nvmf_rpc_listener_ctx_free(ctx);
696 		/* Can't really do anything to recover here - subsystem will remain paused. */
697 	}
698 }
699 static void
700 nvmf_rpc_stop_listen_async_done(void *cb_arg, int status)
701 {
702 	struct nvmf_rpc_listener_ctx *ctx = cb_arg;
703 
704 	if (status) {
705 		SPDK_ERRLOG("Unable to stop listener.\n");
706 		spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
707 						     "error stopping listener: %d", status);
708 		ctx->response_sent = true;
709 	}
710 
711 	if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) {
712 		if (!ctx->response_sent) {
713 			spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
714 							 "Internal error");
715 		}
716 		nvmf_rpc_listener_ctx_free(ctx);
717 		/* Can't really do anything to recover here - subsystem will remain paused. */
718 	}
719 }
720 
721 static void
722 nvmf_rpc_set_ana_state_done(void *cb_arg, int status)
723 {
724 	struct nvmf_rpc_listener_ctx *ctx = cb_arg;
725 
726 	if (status) {
727 		SPDK_ERRLOG("Unable to set ANA state.\n");
728 		spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
729 						     "error setting ANA state: %d", status);
730 		ctx->response_sent = true;
731 	}
732 
733 	if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) {
734 		if (!ctx->response_sent) {
735 			spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
736 							 "Internal error");
737 		}
738 		nvmf_rpc_listener_ctx_free(ctx);
739 		/* Can't really do anything to recover here - subsystem will remain paused. */
740 	}
741 }
742 
743 static void
744 nvmf_rpc_listen_paused(struct spdk_nvmf_subsystem *subsystem,
745 		       void *cb_arg, int status)
746 {
747 	struct nvmf_rpc_listener_ctx *ctx = cb_arg;
748 	int rc;
749 
750 	if (ctx->op == NVMF_RPC_LISTEN_ADD) {
751 		if (!nvmf_subsystem_find_listener(subsystem, &ctx->trid)) {
752 			rc = spdk_nvmf_tgt_listen_ext(ctx->tgt, &ctx->trid, &ctx->opts);
753 			if (rc == 0) {
754 				spdk_nvmf_subsystem_add_listener(ctx->subsystem, &ctx->trid, nvmf_rpc_subsystem_listen, ctx);
755 				return;
756 			}
757 
758 			spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
759 							 "Invalid parameters");
760 			ctx->response_sent = true;
761 		}
762 	} else if (ctx->op == NVMF_RPC_LISTEN_REMOVE) {
763 		rc = spdk_nvmf_subsystem_remove_listener(subsystem, &ctx->trid);
764 		if (rc == 0) {
765 			spdk_nvmf_transport_stop_listen_async(ctx->transport, &ctx->trid, subsystem,
766 							      nvmf_rpc_stop_listen_async_done, ctx);
767 			return;
768 		}
769 		SPDK_ERRLOG("Unable to remove listener, rc %d\n", rc);
770 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
771 						 "Invalid parameters");
772 		ctx->response_sent = true;
773 	} else if (ctx->op == NVMF_RPC_LISTEN_SET_ANA_STATE) {
774 		nvmf_subsystem_set_ana_state(subsystem, &ctx->trid, ctx->ana_state, ctx->anagrpid,
775 					     nvmf_rpc_set_ana_state_done, ctx);
776 		return;
777 	} else {
778 		SPDK_UNREACHABLE();
779 	}
780 
781 	if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_listen_resumed, ctx)) {
782 		if (!ctx->response_sent) {
783 			spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
784 							 "Internal error");
785 		}
786 		nvmf_rpc_listener_ctx_free(ctx);
787 		/* Can't really do anything to recover here - subsystem will remain paused. */
788 	}
789 }
790 
791 static int
792 rpc_listen_address_to_trid(const struct rpc_listen_address *address,
793 			   struct spdk_nvme_transport_id *trid)
794 {
795 	size_t len;
796 
797 	memset(trid, 0, sizeof(*trid));
798 
799 	if (spdk_nvme_transport_id_populate_trstring(trid, address->transport)) {
800 		SPDK_ERRLOG("Invalid transport string: %s\n", address->transport);
801 		return -EINVAL;
802 	}
803 
804 	if (spdk_nvme_transport_id_parse_trtype(&trid->trtype, address->transport)) {
805 		SPDK_ERRLOG("Invalid transport type: %s\n", address->transport);
806 		return -EINVAL;
807 	}
808 
809 	if (address->adrfam) {
810 		if (spdk_nvme_transport_id_parse_adrfam(&trid->adrfam, address->adrfam)) {
811 			SPDK_ERRLOG("Invalid adrfam: %s\n", address->adrfam);
812 			return -EINVAL;
813 		}
814 	} else {
815 		trid->adrfam = SPDK_NVMF_ADRFAM_IPV4;
816 	}
817 
818 	len = strlen(address->traddr);
819 	if (len > sizeof(trid->traddr) - 1) {
820 		SPDK_ERRLOG("Transport address longer than %zu characters: %s\n",
821 			    sizeof(trid->traddr) - 1, address->traddr);
822 		return -EINVAL;
823 	}
824 	memcpy(trid->traddr, address->traddr, len + 1);
825 
826 	trid->trsvcid[0] = '\0';
827 	if (address->trsvcid) {
828 		len = strlen(address->trsvcid);
829 		if (len > sizeof(trid->trsvcid) - 1) {
830 			SPDK_ERRLOG("Transport service id longer than %zu characters: %s\n",
831 				    sizeof(trid->trsvcid) - 1, address->trsvcid);
832 			return -EINVAL;
833 		}
834 		memcpy(trid->trsvcid, address->trsvcid, len + 1);
835 	}
836 
837 	return 0;
838 }
839 
840 static void
841 rpc_nvmf_subsystem_add_listener(struct spdk_jsonrpc_request *request,
842 				const struct spdk_json_val *params)
843 {
844 	struct nvmf_rpc_listener_ctx *ctx;
845 	struct spdk_nvmf_subsystem *subsystem;
846 	struct spdk_nvmf_tgt *tgt;
847 	int rc;
848 
849 	ctx = calloc(1, sizeof(*ctx));
850 	if (!ctx) {
851 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
852 		return;
853 	}
854 
855 	ctx->request = request;
856 
857 	if (spdk_json_decode_object_relaxed(params, nvmf_rpc_listener_decoder,
858 					    SPDK_COUNTOF(nvmf_rpc_listener_decoder),
859 					    ctx)) {
860 		SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n");
861 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
862 		nvmf_rpc_listener_ctx_free(ctx);
863 		return;
864 	}
865 
866 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
867 	if (!tgt) {
868 		SPDK_ERRLOG("Unable to find a target object.\n");
869 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
870 						 "Unable to find a target.");
871 		nvmf_rpc_listener_ctx_free(ctx);
872 		return;
873 	}
874 	ctx->tgt = tgt;
875 
876 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn);
877 	if (!subsystem) {
878 		SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
879 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
880 		nvmf_rpc_listener_ctx_free(ctx);
881 		return;
882 	}
883 
884 	ctx->subsystem = subsystem;
885 
886 	if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) {
887 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
888 						 "Invalid parameters");
889 		nvmf_rpc_listener_ctx_free(ctx);
890 		return;
891 	}
892 
893 	ctx->op = NVMF_RPC_LISTEN_ADD;
894 	spdk_nvmf_listen_opts_init(&ctx->opts, sizeof(ctx->opts));
895 	ctx->opts.transport_specific = params;
896 
897 	rc = spdk_nvmf_subsystem_pause(subsystem, 0, nvmf_rpc_listen_paused, ctx);
898 	if (rc != 0) {
899 		if (rc == -EBUSY) {
900 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
901 							 "subsystem busy, retry later.\n");
902 		} else {
903 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
904 		}
905 		nvmf_rpc_listener_ctx_free(ctx);
906 	}
907 }
908 SPDK_RPC_REGISTER("nvmf_subsystem_add_listener", rpc_nvmf_subsystem_add_listener,
909 		  SPDK_RPC_RUNTIME);
910 
911 static void
912 rpc_nvmf_subsystem_remove_listener(struct spdk_jsonrpc_request *request,
913 				   const struct spdk_json_val *params)
914 {
915 	struct nvmf_rpc_listener_ctx *ctx;
916 	struct spdk_nvmf_subsystem *subsystem;
917 	struct spdk_nvmf_tgt *tgt;
918 	int rc;
919 
920 	ctx = calloc(1, sizeof(*ctx));
921 	if (!ctx) {
922 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
923 		return;
924 	}
925 
926 	ctx->request = request;
927 
928 	if (spdk_json_decode_object(params, nvmf_rpc_listener_decoder,
929 				    SPDK_COUNTOF(nvmf_rpc_listener_decoder),
930 				    ctx)) {
931 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
932 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
933 		nvmf_rpc_listener_ctx_free(ctx);
934 		return;
935 	}
936 
937 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
938 	if (!tgt) {
939 		SPDK_ERRLOG("Unable to find a target object.\n");
940 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
941 						 "Unable to find a target.");
942 		nvmf_rpc_listener_ctx_free(ctx);
943 		return;
944 	}
945 	ctx->tgt = tgt;
946 
947 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn);
948 	if (!subsystem) {
949 		SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
950 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
951 		nvmf_rpc_listener_ctx_free(ctx);
952 		return;
953 	}
954 
955 	ctx->subsystem = subsystem;
956 
957 	if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) {
958 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
959 						 "Invalid parameters");
960 		nvmf_rpc_listener_ctx_free(ctx);
961 		return;
962 	}
963 
964 	ctx->transport = spdk_nvmf_tgt_get_transport(tgt, ctx->trid.trstring);
965 	if (!ctx->transport) {
966 		SPDK_ERRLOG("Unable to find %s transport. The transport must be created first also make sure it is properly registered.\n",
967 			    ctx->trid.trstring);
968 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
969 						 "Invalid parameters");
970 		nvmf_rpc_listener_ctx_free(ctx);
971 		return;
972 	}
973 
974 	ctx->op = NVMF_RPC_LISTEN_REMOVE;
975 
976 	rc = spdk_nvmf_subsystem_pause(subsystem, 0, nvmf_rpc_listen_paused, ctx);
977 	if (rc != 0) {
978 		if (rc == -EBUSY) {
979 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
980 							 "subsystem busy, retry later.\n");
981 		} else {
982 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
983 		}
984 		nvmf_rpc_listener_ctx_free(ctx);
985 	}
986 }
987 SPDK_RPC_REGISTER("nvmf_subsystem_remove_listener", rpc_nvmf_subsystem_remove_listener,
988 		  SPDK_RPC_RUNTIME);
989 
990 static const struct spdk_json_object_decoder nvmf_rpc_set_ana_state_decoder[] = {
991 	{"nqn", offsetof(struct nvmf_rpc_listener_ctx, nqn), spdk_json_decode_string},
992 	{"listen_address", offsetof(struct nvmf_rpc_listener_ctx, address), decode_rpc_listen_address},
993 	{"ana_state", offsetof(struct nvmf_rpc_listener_ctx, ana_state_str), spdk_json_decode_string},
994 	{"tgt_name", offsetof(struct nvmf_rpc_listener_ctx, tgt_name), spdk_json_decode_string, true},
995 	{"anagrpid", offsetof(struct nvmf_rpc_listener_ctx, anagrpid), spdk_json_decode_uint32, true},
996 };
997 
998 static int
999 rpc_ana_state_parse(const char *str, enum spdk_nvme_ana_state *ana_state)
1000 {
1001 	if (ana_state == NULL || str == NULL) {
1002 		return -EINVAL;
1003 	}
1004 
1005 	if (strcasecmp(str, "optimized") == 0) {
1006 		*ana_state = SPDK_NVME_ANA_OPTIMIZED_STATE;
1007 	} else if (strcasecmp(str, "non_optimized") == 0) {
1008 		*ana_state = SPDK_NVME_ANA_NON_OPTIMIZED_STATE;
1009 	} else if (strcasecmp(str, "inaccessible") == 0) {
1010 		*ana_state = SPDK_NVME_ANA_INACCESSIBLE_STATE;
1011 	} else {
1012 		return -ENOENT;
1013 	}
1014 
1015 	return 0;
1016 }
1017 
1018 static void
1019 rpc_nvmf_subsystem_listener_set_ana_state(struct spdk_jsonrpc_request *request,
1020 		const struct spdk_json_val *params)
1021 {
1022 	struct nvmf_rpc_listener_ctx *ctx;
1023 	struct spdk_nvmf_subsystem *subsystem;
1024 	struct spdk_nvmf_tgt *tgt;
1025 
1026 	ctx = calloc(1, sizeof(*ctx));
1027 	if (!ctx) {
1028 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1029 						 "Out of memory");
1030 		return;
1031 	}
1032 
1033 	ctx->request = request;
1034 
1035 	if (spdk_json_decode_object(params, nvmf_rpc_set_ana_state_decoder,
1036 				    SPDK_COUNTOF(nvmf_rpc_set_ana_state_decoder),
1037 				    ctx)) {
1038 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1039 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1040 						 "Invalid parameters");
1041 		nvmf_rpc_listener_ctx_free(ctx);
1042 		return;
1043 	}
1044 
1045 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
1046 	if (!tgt) {
1047 		SPDK_ERRLOG("Unable to find a target object.\n");
1048 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1049 						 "Unable to find a target.\n");
1050 		nvmf_rpc_listener_ctx_free(ctx);
1051 		return;
1052 	}
1053 
1054 	ctx->tgt = tgt;
1055 
1056 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn);
1057 	if (!subsystem) {
1058 		SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
1059 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1060 						     "Unable to find subsystem with NQN %s",
1061 						     ctx->nqn);
1062 		nvmf_rpc_listener_ctx_free(ctx);
1063 		return;
1064 	}
1065 
1066 	ctx->subsystem = subsystem;
1067 
1068 	if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) {
1069 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1070 						 "Invalid parameters");
1071 		nvmf_rpc_listener_ctx_free(ctx);
1072 		return;
1073 	}
1074 
1075 	if (rpc_ana_state_parse(ctx->ana_state_str, &ctx->ana_state)) {
1076 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1077 						 "Invalid parameters");
1078 		nvmf_rpc_listener_ctx_free(ctx);
1079 		return;
1080 	}
1081 
1082 	ctx->op = NVMF_RPC_LISTEN_SET_ANA_STATE;
1083 
1084 	if (spdk_nvmf_subsystem_pause(subsystem, 0, nvmf_rpc_listen_paused, ctx)) {
1085 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1086 						 "Internal error");
1087 		nvmf_rpc_listener_ctx_free(ctx);
1088 	}
1089 }
1090 SPDK_RPC_REGISTER("nvmf_subsystem_listener_set_ana_state",
1091 		  rpc_nvmf_subsystem_listener_set_ana_state, SPDK_RPC_RUNTIME);
1092 
1093 struct spdk_nvmf_ns_params {
1094 	char *bdev_name;
1095 	char *ptpl_file;
1096 	uint32_t nsid;
1097 	char nguid[16];
1098 	char eui64[8];
1099 	struct spdk_uuid uuid;
1100 	uint32_t anagrpid;
1101 };
1102 
1103 static const struct spdk_json_object_decoder rpc_ns_params_decoders[] = {
1104 	{"nsid", offsetof(struct spdk_nvmf_ns_params, nsid), spdk_json_decode_uint32, true},
1105 	{"bdev_name", offsetof(struct spdk_nvmf_ns_params, bdev_name), spdk_json_decode_string},
1106 	{"ptpl_file", offsetof(struct spdk_nvmf_ns_params, ptpl_file), spdk_json_decode_string, true},
1107 	{"nguid", offsetof(struct spdk_nvmf_ns_params, nguid), decode_ns_nguid, true},
1108 	{"eui64", offsetof(struct spdk_nvmf_ns_params, eui64), decode_ns_eui64, true},
1109 	{"uuid", offsetof(struct spdk_nvmf_ns_params, uuid), decode_ns_uuid, true},
1110 	{"anagrpid", offsetof(struct spdk_nvmf_ns_params, anagrpid), spdk_json_decode_uint32, true},
1111 };
1112 
1113 static int
1114 decode_rpc_ns_params(const struct spdk_json_val *val, void *out)
1115 {
1116 	struct spdk_nvmf_ns_params *ns_params = out;
1117 
1118 	return spdk_json_decode_object(val, rpc_ns_params_decoders,
1119 				       SPDK_COUNTOF(rpc_ns_params_decoders),
1120 				       ns_params);
1121 }
1122 
1123 struct nvmf_rpc_ns_ctx {
1124 	char *nqn;
1125 	char *tgt_name;
1126 	struct spdk_nvmf_ns_params ns_params;
1127 
1128 	struct spdk_jsonrpc_request *request;
1129 	bool response_sent;
1130 };
1131 
1132 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_ns_decoder[] = {
1133 	{"nqn", offsetof(struct nvmf_rpc_ns_ctx, nqn), spdk_json_decode_string},
1134 	{"namespace", offsetof(struct nvmf_rpc_ns_ctx, ns_params), decode_rpc_ns_params},
1135 	{"tgt_name", offsetof(struct nvmf_rpc_ns_ctx, tgt_name), spdk_json_decode_string, true},
1136 };
1137 
1138 static void
1139 nvmf_rpc_ns_ctx_free(struct nvmf_rpc_ns_ctx *ctx)
1140 {
1141 	free(ctx->nqn);
1142 	free(ctx->tgt_name);
1143 	free(ctx->ns_params.bdev_name);
1144 	free(ctx->ns_params.ptpl_file);
1145 	free(ctx);
1146 }
1147 
1148 static void
1149 nvmf_rpc_ns_failback_resumed(struct spdk_nvmf_subsystem *subsystem,
1150 			     void *cb_arg, int status)
1151 {
1152 	struct nvmf_rpc_ns_ctx *ctx = cb_arg;
1153 	struct spdk_jsonrpc_request *request = ctx->request;
1154 
1155 	if (status) {
1156 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1157 						 "Unable to add ns, subsystem in invalid state");
1158 	} else {
1159 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1160 						 "Unable to add ns, subsystem in active state");
1161 	}
1162 
1163 	nvmf_rpc_ns_ctx_free(ctx);
1164 }
1165 
1166 static void
1167 nvmf_rpc_ns_resumed(struct spdk_nvmf_subsystem *subsystem,
1168 		    void *cb_arg, int status)
1169 {
1170 	struct nvmf_rpc_ns_ctx *ctx = cb_arg;
1171 	struct spdk_jsonrpc_request *request = ctx->request;
1172 	uint32_t nsid = ctx->ns_params.nsid;
1173 	bool response_sent = ctx->response_sent;
1174 	struct spdk_json_write_ctx *w;
1175 	int rc;
1176 
1177 	/* The case where the call to add the namespace was successful, but the subsystem couldn't be resumed. */
1178 	if (status && !ctx->response_sent) {
1179 		rc = spdk_nvmf_subsystem_remove_ns(subsystem, nsid);
1180 		if (rc != 0) {
1181 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1182 							 "Unable to add ns, subsystem in invalid state");
1183 			nvmf_rpc_ns_ctx_free(ctx);
1184 			return;
1185 		}
1186 
1187 		rc = spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_ns_failback_resumed, ctx);
1188 		if (rc != 0) {
1189 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1190 			nvmf_rpc_ns_ctx_free(ctx);
1191 			return;
1192 		}
1193 
1194 		return;
1195 	}
1196 
1197 	nvmf_rpc_ns_ctx_free(ctx);
1198 
1199 	if (response_sent) {
1200 		return;
1201 	}
1202 
1203 	w = spdk_jsonrpc_begin_result(request);
1204 	spdk_json_write_uint32(w, nsid);
1205 	spdk_jsonrpc_end_result(request, w);
1206 }
1207 
1208 static void
1209 nvmf_rpc_ns_paused(struct spdk_nvmf_subsystem *subsystem,
1210 		   void *cb_arg, int status)
1211 {
1212 	struct nvmf_rpc_ns_ctx *ctx = cb_arg;
1213 	struct spdk_nvmf_ns_opts ns_opts;
1214 
1215 	spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
1216 	ns_opts.nsid = ctx->ns_params.nsid;
1217 
1218 	SPDK_STATIC_ASSERT(sizeof(ns_opts.nguid) == sizeof(ctx->ns_params.nguid), "size mismatch");
1219 	memcpy(ns_opts.nguid, ctx->ns_params.nguid, sizeof(ns_opts.nguid));
1220 
1221 	SPDK_STATIC_ASSERT(sizeof(ns_opts.eui64) == sizeof(ctx->ns_params.eui64), "size mismatch");
1222 	memcpy(ns_opts.eui64, ctx->ns_params.eui64, sizeof(ns_opts.eui64));
1223 
1224 	if (!spdk_mem_all_zero(&ctx->ns_params.uuid, sizeof(ctx->ns_params.uuid))) {
1225 		ns_opts.uuid = ctx->ns_params.uuid;
1226 	}
1227 
1228 	ns_opts.anagrpid = ctx->ns_params.anagrpid;
1229 
1230 	ctx->ns_params.nsid = spdk_nvmf_subsystem_add_ns_ext(subsystem, ctx->ns_params.bdev_name,
1231 			      &ns_opts, sizeof(ns_opts),
1232 			      ctx->ns_params.ptpl_file);
1233 	if (ctx->ns_params.nsid == 0) {
1234 		SPDK_ERRLOG("Unable to add namespace\n");
1235 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1236 						 "Invalid parameters");
1237 		ctx->response_sent = true;
1238 		goto resume;
1239 	}
1240 
1241 resume:
1242 	if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_ns_resumed, ctx)) {
1243 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1244 		nvmf_rpc_ns_ctx_free(ctx);
1245 	}
1246 }
1247 
1248 static void
1249 rpc_nvmf_subsystem_add_ns(struct spdk_jsonrpc_request *request,
1250 			  const struct spdk_json_val *params)
1251 {
1252 	struct nvmf_rpc_ns_ctx *ctx;
1253 	struct spdk_nvmf_subsystem *subsystem;
1254 	struct spdk_nvmf_tgt *tgt;
1255 	int rc;
1256 
1257 	ctx = calloc(1, sizeof(*ctx));
1258 	if (!ctx) {
1259 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1260 		return;
1261 	}
1262 
1263 	if (spdk_json_decode_object(params, nvmf_rpc_subsystem_ns_decoder,
1264 				    SPDK_COUNTOF(nvmf_rpc_subsystem_ns_decoder),
1265 				    ctx)) {
1266 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1267 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1268 		nvmf_rpc_ns_ctx_free(ctx);
1269 		return;
1270 	}
1271 
1272 	ctx->request = request;
1273 	ctx->response_sent = false;
1274 
1275 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
1276 	if (!tgt) {
1277 		SPDK_ERRLOG("Unable to find a target object.\n");
1278 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1279 						 "Unable to find a target.");
1280 		nvmf_rpc_ns_ctx_free(ctx);
1281 		return;
1282 	}
1283 
1284 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn);
1285 	if (!subsystem) {
1286 		SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
1287 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1288 		nvmf_rpc_ns_ctx_free(ctx);
1289 		return;
1290 	}
1291 
1292 	rc = spdk_nvmf_subsystem_pause(subsystem, ctx->ns_params.nsid, nvmf_rpc_ns_paused, ctx);
1293 	if (rc != 0) {
1294 		if (rc == -EBUSY) {
1295 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1296 							 "subsystem busy, retry later.\n");
1297 		} else {
1298 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1299 		}
1300 		nvmf_rpc_ns_ctx_free(ctx);
1301 	}
1302 }
1303 SPDK_RPC_REGISTER("nvmf_subsystem_add_ns", rpc_nvmf_subsystem_add_ns, SPDK_RPC_RUNTIME)
1304 
1305 struct nvmf_rpc_remove_ns_ctx {
1306 	char *nqn;
1307 	char *tgt_name;
1308 	uint32_t nsid;
1309 
1310 	struct spdk_jsonrpc_request *request;
1311 	bool response_sent;
1312 };
1313 
1314 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_remove_ns_decoder[] = {
1315 	{"nqn", offsetof(struct nvmf_rpc_remove_ns_ctx, nqn), spdk_json_decode_string},
1316 	{"nsid", offsetof(struct nvmf_rpc_remove_ns_ctx, nsid), spdk_json_decode_uint32},
1317 	{"tgt_name", offsetof(struct nvmf_rpc_remove_ns_ctx, tgt_name), spdk_json_decode_string, true},
1318 };
1319 
1320 static void
1321 nvmf_rpc_remove_ns_ctx_free(struct nvmf_rpc_remove_ns_ctx *ctx)
1322 {
1323 	free(ctx->nqn);
1324 	free(ctx->tgt_name);
1325 	free(ctx);
1326 }
1327 
1328 static void
1329 nvmf_rpc_remove_ns_resumed(struct spdk_nvmf_subsystem *subsystem,
1330 			   void *cb_arg, int status)
1331 {
1332 	struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg;
1333 	struct spdk_jsonrpc_request *request = ctx->request;
1334 	bool response_sent = ctx->response_sent;
1335 
1336 	nvmf_rpc_remove_ns_ctx_free(ctx);
1337 
1338 	if (response_sent) {
1339 		return;
1340 	}
1341 
1342 	spdk_jsonrpc_send_bool_response(request, true);
1343 }
1344 
1345 static void
1346 nvmf_rpc_remove_ns_paused(struct spdk_nvmf_subsystem *subsystem,
1347 			  void *cb_arg, int status)
1348 {
1349 	struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg;
1350 	int ret;
1351 
1352 	ret = spdk_nvmf_subsystem_remove_ns(subsystem, ctx->nsid);
1353 	if (ret < 0) {
1354 		SPDK_ERRLOG("Unable to remove namespace ID %u\n", ctx->nsid);
1355 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1356 						 "Invalid parameters");
1357 		ctx->response_sent = true;
1358 	}
1359 
1360 	if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_remove_ns_resumed, ctx)) {
1361 		if (!ctx->response_sent) {
1362 			spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1363 		}
1364 		nvmf_rpc_remove_ns_ctx_free(ctx);
1365 	}
1366 }
1367 
1368 static void
1369 rpc_nvmf_subsystem_remove_ns(struct spdk_jsonrpc_request *request,
1370 			     const struct spdk_json_val *params)
1371 {
1372 	struct nvmf_rpc_remove_ns_ctx *ctx;
1373 	struct spdk_nvmf_subsystem *subsystem;
1374 	struct spdk_nvmf_tgt *tgt;
1375 	int rc;
1376 
1377 	ctx = calloc(1, sizeof(*ctx));
1378 	if (!ctx) {
1379 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1380 		return;
1381 	}
1382 
1383 	if (spdk_json_decode_object(params, nvmf_rpc_subsystem_remove_ns_decoder,
1384 				    SPDK_COUNTOF(nvmf_rpc_subsystem_remove_ns_decoder),
1385 				    ctx)) {
1386 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1387 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1388 		nvmf_rpc_remove_ns_ctx_free(ctx);
1389 		return;
1390 	}
1391 
1392 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
1393 	if (!tgt) {
1394 		SPDK_ERRLOG("Unable to find a target object.\n");
1395 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1396 						 "Unable to find a target.");
1397 		nvmf_rpc_remove_ns_ctx_free(ctx);
1398 		return;
1399 	}
1400 
1401 	ctx->request = request;
1402 	ctx->response_sent = false;
1403 
1404 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn);
1405 	if (!subsystem) {
1406 		SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
1407 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1408 		nvmf_rpc_remove_ns_ctx_free(ctx);
1409 		return;
1410 	}
1411 
1412 	rc = spdk_nvmf_subsystem_pause(subsystem, ctx->nsid, nvmf_rpc_remove_ns_paused, ctx);
1413 	if (rc != 0) {
1414 		if (rc == -EBUSY) {
1415 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1416 							 "subsystem busy, retry later.\n");
1417 		} else {
1418 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1419 		}
1420 		nvmf_rpc_remove_ns_ctx_free(ctx);
1421 	}
1422 }
1423 SPDK_RPC_REGISTER("nvmf_subsystem_remove_ns", rpc_nvmf_subsystem_remove_ns, SPDK_RPC_RUNTIME)
1424 
1425 struct nvmf_rpc_host_ctx {
1426 	struct spdk_jsonrpc_request *request;
1427 	char *nqn;
1428 	char *host;
1429 	char *tgt_name;
1430 	bool allow_any_host;
1431 };
1432 
1433 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_host_decoder[] = {
1434 	{"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string},
1435 	{"host", offsetof(struct nvmf_rpc_host_ctx, host), spdk_json_decode_string},
1436 	{"tgt_name", offsetof(struct nvmf_rpc_host_ctx, tgt_name), spdk_json_decode_string, true},
1437 };
1438 
1439 static void
1440 nvmf_rpc_host_ctx_free(struct nvmf_rpc_host_ctx *ctx)
1441 {
1442 	free(ctx->nqn);
1443 	free(ctx->host);
1444 	free(ctx->tgt_name);
1445 }
1446 
1447 static void
1448 rpc_nvmf_subsystem_add_host(struct spdk_jsonrpc_request *request,
1449 			    const struct spdk_json_val *params)
1450 {
1451 	struct nvmf_rpc_host_ctx ctx = {};
1452 	struct spdk_nvmf_subsystem *subsystem;
1453 	struct spdk_nvmf_tgt *tgt;
1454 	int rc;
1455 
1456 	if (spdk_json_decode_object(params, nvmf_rpc_subsystem_host_decoder,
1457 				    SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder),
1458 				    &ctx)) {
1459 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1460 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1461 		nvmf_rpc_host_ctx_free(&ctx);
1462 		return;
1463 	}
1464 
1465 	tgt = spdk_nvmf_get_tgt(ctx.tgt_name);
1466 	if (!tgt) {
1467 		SPDK_ERRLOG("Unable to find a target object.\n");
1468 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1469 						 "Unable to find a target.");
1470 		nvmf_rpc_host_ctx_free(&ctx);
1471 		return;
1472 	}
1473 
1474 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx.nqn);
1475 	if (!subsystem) {
1476 		SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx.nqn);
1477 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1478 		nvmf_rpc_host_ctx_free(&ctx);
1479 		return;
1480 	}
1481 
1482 	rc = spdk_nvmf_subsystem_add_host(subsystem, ctx.host);
1483 	if (rc != 0) {
1484 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1485 		nvmf_rpc_host_ctx_free(&ctx);
1486 		return;
1487 	}
1488 
1489 	spdk_jsonrpc_send_bool_response(request, true);
1490 	nvmf_rpc_host_ctx_free(&ctx);
1491 }
1492 SPDK_RPC_REGISTER("nvmf_subsystem_add_host", rpc_nvmf_subsystem_add_host, SPDK_RPC_RUNTIME)
1493 
1494 static void
1495 rpc_nvmf_subsystem_remove_host_done(void *_ctx, int status)
1496 {
1497 	struct nvmf_rpc_host_ctx *ctx = _ctx;
1498 
1499 	spdk_jsonrpc_send_bool_response(ctx->request, true);
1500 	nvmf_rpc_host_ctx_free(ctx);
1501 	free(ctx);
1502 }
1503 
1504 static void
1505 rpc_nvmf_subsystem_remove_host(struct spdk_jsonrpc_request *request,
1506 			       const struct spdk_json_val *params)
1507 {
1508 	struct nvmf_rpc_host_ctx *ctx;
1509 	struct spdk_nvmf_subsystem *subsystem;
1510 	struct spdk_nvmf_tgt *tgt;
1511 	int rc;
1512 
1513 	ctx = calloc(1, sizeof(*ctx));
1514 	if (ctx == NULL) {
1515 		SPDK_ERRLOG("Unable to allocate context to perform RPC\n");
1516 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1517 		return;
1518 	}
1519 
1520 	ctx->request = request;
1521 
1522 	if (spdk_json_decode_object(params, nvmf_rpc_subsystem_host_decoder,
1523 				    SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder),
1524 				    ctx)) {
1525 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1526 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1527 		nvmf_rpc_host_ctx_free(ctx);
1528 		free(ctx);
1529 		return;
1530 	}
1531 
1532 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
1533 	if (!tgt) {
1534 		SPDK_ERRLOG("Unable to find a target object.\n");
1535 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1536 						 "Unable to find a target.");
1537 		nvmf_rpc_host_ctx_free(ctx);
1538 		free(ctx);
1539 		return;
1540 	}
1541 
1542 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn);
1543 	if (!subsystem) {
1544 		SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
1545 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1546 		nvmf_rpc_host_ctx_free(ctx);
1547 		free(ctx);
1548 		return;
1549 	}
1550 
1551 	rc = spdk_nvmf_subsystem_remove_host(subsystem, ctx->host);
1552 	if (rc != 0) {
1553 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1554 		nvmf_rpc_host_ctx_free(ctx);
1555 		free(ctx);
1556 		return;
1557 	}
1558 
1559 	rc = spdk_nvmf_subsystem_disconnect_host(subsystem, ctx->host,
1560 			rpc_nvmf_subsystem_remove_host_done,
1561 			ctx);
1562 	if (rc != 0) {
1563 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1564 		nvmf_rpc_host_ctx_free(ctx);
1565 		free(ctx);
1566 		return;
1567 	}
1568 }
1569 SPDK_RPC_REGISTER("nvmf_subsystem_remove_host", rpc_nvmf_subsystem_remove_host,
1570 		  SPDK_RPC_RUNTIME)
1571 
1572 
1573 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_any_host_decoder[] = {
1574 	{"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string},
1575 	{"allow_any_host", offsetof(struct nvmf_rpc_host_ctx, allow_any_host), spdk_json_decode_bool},
1576 	{"tgt_name", offsetof(struct nvmf_rpc_host_ctx, tgt_name), spdk_json_decode_string, true},
1577 };
1578 
1579 static void
1580 rpc_nvmf_subsystem_allow_any_host(struct spdk_jsonrpc_request *request,
1581 				  const struct spdk_json_val *params)
1582 {
1583 	struct nvmf_rpc_host_ctx ctx = {};
1584 	struct spdk_nvmf_subsystem *subsystem;
1585 	struct spdk_nvmf_tgt *tgt;
1586 	int rc;
1587 
1588 	if (spdk_json_decode_object(params, nvmf_rpc_subsystem_any_host_decoder,
1589 				    SPDK_COUNTOF(nvmf_rpc_subsystem_any_host_decoder),
1590 				    &ctx)) {
1591 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1592 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1593 		nvmf_rpc_host_ctx_free(&ctx);
1594 		return;
1595 	}
1596 
1597 	tgt = spdk_nvmf_get_tgt(ctx.tgt_name);
1598 	if (!tgt) {
1599 		SPDK_ERRLOG("Unable to find a target object.\n");
1600 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1601 						 "Unable to find a target.");
1602 		nvmf_rpc_host_ctx_free(&ctx);
1603 		return;
1604 	}
1605 
1606 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx.nqn);
1607 	if (!subsystem) {
1608 		SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx.nqn);
1609 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1610 		nvmf_rpc_host_ctx_free(&ctx);
1611 		return;
1612 	}
1613 
1614 	rc = spdk_nvmf_subsystem_set_allow_any_host(subsystem, ctx.allow_any_host);
1615 	if (rc != 0) {
1616 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1617 		nvmf_rpc_host_ctx_free(&ctx);
1618 		return;
1619 	}
1620 
1621 	spdk_jsonrpc_send_bool_response(request, true);
1622 	nvmf_rpc_host_ctx_free(&ctx);
1623 }
1624 SPDK_RPC_REGISTER("nvmf_subsystem_allow_any_host", rpc_nvmf_subsystem_allow_any_host,
1625 		  SPDK_RPC_RUNTIME)
1626 
1627 struct nvmf_rpc_target_ctx {
1628 	char *name;
1629 	uint32_t max_subsystems;
1630 	char *discovery_filter;
1631 };
1632 
1633 static int
1634 decode_discovery_filter(const struct spdk_json_val *val, void *out)
1635 {
1636 	enum spdk_nvmf_tgt_discovery_filter *_filter = (enum spdk_nvmf_tgt_discovery_filter *)out;
1637 	enum spdk_nvmf_tgt_discovery_filter filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY;
1638 	char *tokens = spdk_json_strdup(val);
1639 	char *tok;
1640 	int rc = -EINVAL;
1641 	bool all_specified = false;
1642 
1643 	if (!tokens) {
1644 		return -ENOMEM;
1645 	}
1646 
1647 	tok = strtok(tokens, ",");
1648 	while (tok) {
1649 		if (strncmp(tok, "match_any", 9) == 0) {
1650 			if (filter != SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY) {
1651 				goto out;
1652 			}
1653 			filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY;
1654 			all_specified = true;
1655 		} else {
1656 			if (all_specified) {
1657 				goto out;
1658 			}
1659 			if (strncmp(tok, "transport", 9) == 0) {
1660 				filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE;
1661 			} else if (strncmp(tok, "address", 7) == 0) {
1662 				filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS;
1663 			} else if (strncmp(tok, "svcid", 5) == 0) {
1664 				filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID;
1665 			} else {
1666 				SPDK_ERRLOG("Invalid value %s\n", tok);
1667 				goto out;
1668 			}
1669 		}
1670 
1671 		tok = strtok(NULL, ",");
1672 	}
1673 
1674 	rc = 0;
1675 	*_filter = filter;
1676 
1677 out:
1678 	free(tokens);
1679 
1680 	return rc;
1681 }
1682 
1683 static const struct spdk_json_object_decoder nvmf_rpc_create_target_decoder[] = {
1684 	{"name", offsetof(struct nvmf_rpc_target_ctx, name), spdk_json_decode_string},
1685 	{"max_subsystems", offsetof(struct nvmf_rpc_target_ctx, max_subsystems), spdk_json_decode_uint32, true},
1686 	{"discovery_filter", offsetof(struct nvmf_rpc_target_ctx, discovery_filter), decode_discovery_filter, true}
1687 };
1688 
1689 static void
1690 rpc_nvmf_create_target(struct spdk_jsonrpc_request *request,
1691 		       const struct spdk_json_val *params)
1692 {
1693 	struct spdk_nvmf_target_opts	opts;
1694 	struct nvmf_rpc_target_ctx	ctx = {0};
1695 	struct spdk_nvmf_tgt		*tgt;
1696 	struct spdk_json_write_ctx	*w;
1697 
1698 	/* Decode parameters the first time to get the transport type */
1699 	if (spdk_json_decode_object(params, nvmf_rpc_create_target_decoder,
1700 				    SPDK_COUNTOF(nvmf_rpc_create_target_decoder),
1701 				    &ctx)) {
1702 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1703 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1704 		goto out;
1705 	}
1706 
1707 	snprintf(opts.name, NVMF_TGT_NAME_MAX_LENGTH, "%s", ctx.name);
1708 	opts.max_subsystems = ctx.max_subsystems;
1709 
1710 	if (spdk_nvmf_get_tgt(opts.name) != NULL) {
1711 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1712 						 "Target already exists.");
1713 		goto out;
1714 	}
1715 
1716 	tgt = spdk_nvmf_tgt_create(&opts);
1717 
1718 	if (tgt == NULL) {
1719 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1720 						 "Unable to create the requested target.");
1721 		goto out;
1722 	}
1723 
1724 	w = spdk_jsonrpc_begin_result(request);
1725 	spdk_json_write_string(w, spdk_nvmf_tgt_get_name(tgt));
1726 	spdk_jsonrpc_end_result(request, w);
1727 out:
1728 	free(ctx.name);
1729 	free(ctx.discovery_filter);
1730 }
1731 /* private */ SPDK_RPC_REGISTER("nvmf_create_target", rpc_nvmf_create_target, SPDK_RPC_RUNTIME);
1732 
1733 static const struct spdk_json_object_decoder nvmf_rpc_destroy_target_decoder[] = {
1734 	{"name", offsetof(struct nvmf_rpc_target_ctx, name), spdk_json_decode_string},
1735 };
1736 
1737 static void
1738 nvmf_rpc_destroy_target_done(void *ctx, int status)
1739 {
1740 	struct spdk_jsonrpc_request	*request = ctx;
1741 
1742 	spdk_jsonrpc_send_bool_response(request, true);
1743 }
1744 
1745 static void
1746 rpc_nvmf_delete_target(struct spdk_jsonrpc_request *request,
1747 		       const struct spdk_json_val *params)
1748 {
1749 	struct nvmf_rpc_target_ctx	ctx = {0};
1750 	struct spdk_nvmf_tgt		*tgt;
1751 
1752 	/* Decode parameters the first time to get the transport type */
1753 	if (spdk_json_decode_object(params, nvmf_rpc_destroy_target_decoder,
1754 				    SPDK_COUNTOF(nvmf_rpc_destroy_target_decoder),
1755 				    &ctx)) {
1756 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1757 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1758 		free(ctx.name);
1759 		return;
1760 	}
1761 
1762 	tgt = spdk_nvmf_get_tgt(ctx.name);
1763 
1764 	if (tgt == NULL) {
1765 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1766 						 "The specified target doesn't exist, cannot delete it.");
1767 		free(ctx.name);
1768 		return;
1769 	}
1770 
1771 	spdk_nvmf_tgt_destroy(tgt, nvmf_rpc_destroy_target_done, request);
1772 	free(ctx.name);
1773 }
1774 /* private */ SPDK_RPC_REGISTER("nvmf_delete_target", rpc_nvmf_delete_target, SPDK_RPC_RUNTIME);
1775 
1776 static void
1777 rpc_nvmf_get_targets(struct spdk_jsonrpc_request *request,
1778 		     const struct spdk_json_val *params)
1779 {
1780 	struct spdk_json_write_ctx	*w;
1781 	struct spdk_nvmf_tgt		*tgt;
1782 	const char			*name;
1783 
1784 	if (params != NULL) {
1785 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1786 						 "nvmf_get_targets has no parameters.");
1787 		return;
1788 	}
1789 
1790 	w = spdk_jsonrpc_begin_result(request);
1791 	spdk_json_write_array_begin(w);
1792 
1793 	tgt = spdk_nvmf_get_first_tgt();
1794 
1795 	while (tgt != NULL) {
1796 		name = spdk_nvmf_tgt_get_name(tgt);
1797 		spdk_json_write_string(w, name);
1798 		tgt = spdk_nvmf_get_next_tgt(tgt);
1799 	}
1800 
1801 	spdk_json_write_array_end(w);
1802 	spdk_jsonrpc_end_result(request, w);
1803 }
1804 /* private */ SPDK_RPC_REGISTER("nvmf_get_targets", rpc_nvmf_get_targets, SPDK_RPC_RUNTIME);
1805 
1806 struct nvmf_rpc_create_transport_ctx {
1807 	char				*trtype;
1808 	char				*tgt_name;
1809 	struct spdk_nvmf_transport_opts	opts;
1810 	struct spdk_jsonrpc_request	*request;
1811 	struct spdk_nvmf_transport	*transport;
1812 	int				status;
1813 };
1814 
1815 /**
1816  * `max_qpairs_per_ctrlr` represents both admin and IO qpairs, that confuses
1817  * users when they configure a transport using RPC. So it was decided to
1818  * deprecate `max_qpairs_per_ctrlr` RPC parameter and use `max_io_qpairs_per_ctrlr`
1819  * But internal logic remains unchanged and SPDK expects that
1820  * spdk_nvmf_transport_opts::max_qpairs_per_ctrlr includes an admin qpair.
1821  * This function parses the number of IO qpairs and adds +1 for admin qpair.
1822  */
1823 static int
1824 nvmf_rpc_decode_max_io_qpairs(const struct spdk_json_val *val, void *out)
1825 {
1826 	uint16_t *i = out;
1827 	int rc;
1828 
1829 	rc = spdk_json_number_to_uint16(val, i);
1830 	if (rc == 0) {
1831 		(*i)++;
1832 	}
1833 
1834 	return rc;
1835 }
1836 
1837 static const struct spdk_json_object_decoder nvmf_rpc_create_transport_decoder[] = {
1838 	{	"trtype", offsetof(struct nvmf_rpc_create_transport_ctx, trtype), spdk_json_decode_string},
1839 	{
1840 		"max_queue_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_queue_depth),
1841 		spdk_json_decode_uint16, true
1842 	},
1843 	{
1844 		"max_io_qpairs_per_ctrlr", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_qpairs_per_ctrlr),
1845 		nvmf_rpc_decode_max_io_qpairs, true
1846 	},
1847 	{
1848 		"in_capsule_data_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.in_capsule_data_size),
1849 		spdk_json_decode_uint32, true
1850 	},
1851 	{
1852 		"max_io_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_io_size),
1853 		spdk_json_decode_uint32, true
1854 	},
1855 	{
1856 		"io_unit_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.io_unit_size),
1857 		spdk_json_decode_uint32, true
1858 	},
1859 	{
1860 		"max_aq_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_aq_depth),
1861 		spdk_json_decode_uint32, true
1862 	},
1863 	{
1864 		"num_shared_buffers", offsetof(struct nvmf_rpc_create_transport_ctx, opts.num_shared_buffers),
1865 		spdk_json_decode_uint32, true
1866 	},
1867 	{
1868 		"buf_cache_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.buf_cache_size),
1869 		spdk_json_decode_uint32, true
1870 	},
1871 	{
1872 		"dif_insert_or_strip", offsetof(struct nvmf_rpc_create_transport_ctx, opts.dif_insert_or_strip),
1873 		spdk_json_decode_bool, true
1874 	},
1875 	{
1876 		"abort_timeout_sec", offsetof(struct nvmf_rpc_create_transport_ctx, opts.abort_timeout_sec),
1877 		spdk_json_decode_uint32, true
1878 	},
1879 	{
1880 		"zcopy", offsetof(struct nvmf_rpc_create_transport_ctx, opts.zcopy),
1881 		spdk_json_decode_bool, true
1882 	},
1883 	{
1884 		"tgt_name", offsetof(struct nvmf_rpc_create_transport_ctx, tgt_name),
1885 		spdk_json_decode_string, true
1886 	},
1887 	{
1888 		"acceptor_poll_rate", offsetof(struct nvmf_rpc_create_transport_ctx, opts.acceptor_poll_rate),
1889 		spdk_json_decode_uint32, true
1890 	},
1891 };
1892 
1893 static void
1894 nvmf_rpc_create_transport_ctx_free(struct nvmf_rpc_create_transport_ctx *ctx)
1895 {
1896 	free(ctx->trtype);
1897 	free(ctx->tgt_name);
1898 	free(ctx);
1899 }
1900 
1901 static void
1902 nvmf_rpc_transport_destroy_done_cb(void *cb_arg)
1903 {
1904 	struct nvmf_rpc_create_transport_ctx *ctx = cb_arg;
1905 
1906 	spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1907 					     "Failed to add transport to tgt.(%d)", ctx->status);
1908 	nvmf_rpc_create_transport_ctx_free(ctx);
1909 }
1910 
1911 static void
1912 nvmf_rpc_tgt_add_transport_done(void *cb_arg, int status)
1913 {
1914 	struct nvmf_rpc_create_transport_ctx *ctx = cb_arg;
1915 
1916 	if (status) {
1917 		SPDK_ERRLOG("Failed to add transport to tgt.(%d)\n", status);
1918 		ctx->status = status;
1919 		spdk_nvmf_transport_destroy(ctx->transport, nvmf_rpc_transport_destroy_done_cb, ctx);
1920 		return;
1921 	}
1922 
1923 	spdk_jsonrpc_send_bool_response(ctx->request, true);
1924 	nvmf_rpc_create_transport_ctx_free(ctx);
1925 }
1926 
1927 static void
1928 rpc_nvmf_create_transport(struct spdk_jsonrpc_request *request,
1929 			  const struct spdk_json_val *params)
1930 {
1931 	struct nvmf_rpc_create_transport_ctx *ctx;
1932 	struct spdk_nvmf_tgt *tgt;
1933 
1934 	ctx = calloc(1, sizeof(*ctx));
1935 	if (!ctx) {
1936 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1937 		return;
1938 	}
1939 
1940 	/* Decode parameters the first time to get the transport type */
1941 	if (spdk_json_decode_object_relaxed(params, nvmf_rpc_create_transport_decoder,
1942 					    SPDK_COUNTOF(nvmf_rpc_create_transport_decoder),
1943 					    ctx)) {
1944 		SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n");
1945 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1946 		nvmf_rpc_create_transport_ctx_free(ctx);
1947 		return;
1948 	}
1949 
1950 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
1951 	if (!tgt) {
1952 		SPDK_ERRLOG("Unable to find a target object.\n");
1953 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1954 						 "Unable to find a target.");
1955 		nvmf_rpc_create_transport_ctx_free(ctx);
1956 		return;
1957 	}
1958 
1959 	/* Initialize all the transport options (based on transport type) and decode the
1960 	 * parameters again to update any options passed in rpc create transport call.
1961 	 */
1962 	if (!spdk_nvmf_transport_opts_init(ctx->trtype, &ctx->opts, sizeof(ctx->opts))) {
1963 		/* This can happen if user specifies PCIE transport type which isn't valid for
1964 		 * NVMe-oF.
1965 		 */
1966 		SPDK_ERRLOG("Invalid transport type '%s'\n", ctx->trtype);
1967 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1968 						     "Invalid transport type '%s'", ctx->trtype);
1969 		nvmf_rpc_create_transport_ctx_free(ctx);
1970 		return;
1971 	}
1972 
1973 	if (spdk_json_decode_object_relaxed(params, nvmf_rpc_create_transport_decoder,
1974 					    SPDK_COUNTOF(nvmf_rpc_create_transport_decoder),
1975 					    ctx)) {
1976 		SPDK_ERRLOG("spdk_json_decode_object_relaxed failed\n");
1977 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1978 		nvmf_rpc_create_transport_ctx_free(ctx);
1979 		return;
1980 	}
1981 
1982 	if (spdk_nvmf_tgt_get_transport(tgt, ctx->trtype)) {
1983 		SPDK_ERRLOG("Transport type '%s' already exists\n", ctx->trtype);
1984 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1985 						     "Transport type '%s' already exists", ctx->trtype);
1986 		nvmf_rpc_create_transport_ctx_free(ctx);
1987 		return;
1988 	}
1989 
1990 	/* Transport can parse additional params themselves */
1991 	ctx->opts.transport_specific = params;
1992 
1993 	ctx->transport = spdk_nvmf_transport_create(ctx->trtype, &ctx->opts);
1994 
1995 	if (!ctx->transport) {
1996 		SPDK_ERRLOG("Transport type '%s' create failed\n", ctx->trtype);
1997 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1998 						     "Transport type '%s' create failed", ctx->trtype);
1999 		nvmf_rpc_create_transport_ctx_free(ctx);
2000 		return;
2001 	}
2002 
2003 	/* add transport to target */
2004 	ctx->request = request;
2005 	spdk_nvmf_tgt_add_transport(tgt, ctx->transport, nvmf_rpc_tgt_add_transport_done, ctx);
2006 }
2007 SPDK_RPC_REGISTER("nvmf_create_transport", rpc_nvmf_create_transport, SPDK_RPC_RUNTIME)
2008 
2009 struct rpc_get_transport {
2010 	char *trtype;
2011 	char *tgt_name;
2012 };
2013 
2014 static const struct spdk_json_object_decoder rpc_get_transport_decoders[] = {
2015 	{"trtype", offsetof(struct rpc_get_transport, trtype), spdk_json_decode_string, true},
2016 	{"tgt_name", offsetof(struct rpc_get_transport, tgt_name), spdk_json_decode_string, true},
2017 };
2018 
2019 static void
2020 rpc_nvmf_get_transports(struct spdk_jsonrpc_request *request,
2021 			const struct spdk_json_val *params)
2022 {
2023 	struct rpc_get_transport req = { 0 };
2024 	struct spdk_json_write_ctx *w;
2025 	struct spdk_nvmf_transport *transport = NULL;
2026 	struct spdk_nvmf_tgt *tgt;
2027 
2028 	if (params) {
2029 		if (spdk_json_decode_object(params, rpc_get_transport_decoders,
2030 					    SPDK_COUNTOF(rpc_get_transport_decoders),
2031 					    &req)) {
2032 			SPDK_ERRLOG("spdk_json_decode_object failed\n");
2033 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
2034 			return;
2035 		}
2036 	}
2037 
2038 	tgt = spdk_nvmf_get_tgt(req.tgt_name);
2039 	if (!tgt) {
2040 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2041 						 "Unable to find a target.");
2042 		free(req.trtype);
2043 		free(req.tgt_name);
2044 		return;
2045 	}
2046 
2047 	if (req.trtype) {
2048 		transport = spdk_nvmf_tgt_get_transport(tgt, req.trtype);
2049 		if (transport == NULL) {
2050 			SPDK_ERRLOG("transport '%s' does not exist\n", req.trtype);
2051 			spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV));
2052 			free(req.trtype);
2053 			free(req.tgt_name);
2054 			return;
2055 		}
2056 	}
2057 
2058 	w = spdk_jsonrpc_begin_result(request);
2059 	spdk_json_write_array_begin(w);
2060 
2061 	if (transport) {
2062 		nvmf_transport_dump_opts(transport, w, false);
2063 	} else {
2064 		for (transport = spdk_nvmf_transport_get_first(tgt); transport != NULL;
2065 		     transport = spdk_nvmf_transport_get_next(transport)) {
2066 			nvmf_transport_dump_opts(transport, w, false);
2067 		}
2068 	}
2069 
2070 	spdk_json_write_array_end(w);
2071 	spdk_jsonrpc_end_result(request, w);
2072 	free(req.trtype);
2073 	free(req.tgt_name);
2074 }
2075 SPDK_RPC_REGISTER("nvmf_get_transports", rpc_nvmf_get_transports, SPDK_RPC_RUNTIME)
2076 
2077 struct rpc_nvmf_get_stats_ctx {
2078 	char *tgt_name;
2079 	struct spdk_nvmf_tgt *tgt;
2080 	struct spdk_jsonrpc_request *request;
2081 	struct spdk_json_write_ctx *w;
2082 };
2083 
2084 static const struct spdk_json_object_decoder rpc_get_stats_decoders[] = {
2085 	{"tgt_name", offsetof(struct rpc_nvmf_get_stats_ctx, tgt_name), spdk_json_decode_string, true},
2086 };
2087 
2088 static void
2089 free_get_stats_ctx(struct rpc_nvmf_get_stats_ctx *ctx)
2090 {
2091 	free(ctx->tgt_name);
2092 	free(ctx);
2093 }
2094 
2095 static void
2096 rpc_nvmf_get_stats_done(struct spdk_io_channel_iter *i, int status)
2097 {
2098 	struct rpc_nvmf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
2099 
2100 	spdk_json_write_array_end(ctx->w);
2101 	spdk_json_write_object_end(ctx->w);
2102 	spdk_jsonrpc_end_result(ctx->request, ctx->w);
2103 	free_get_stats_ctx(ctx);
2104 }
2105 
2106 static void
2107 _rpc_nvmf_get_stats(struct spdk_io_channel_iter *i)
2108 {
2109 	struct rpc_nvmf_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
2110 	struct spdk_io_channel *ch;
2111 	struct spdk_nvmf_poll_group *group;
2112 
2113 	ch = spdk_get_io_channel(ctx->tgt);
2114 	group = spdk_io_channel_get_ctx(ch);
2115 
2116 	spdk_nvmf_poll_group_dump_stat(group, ctx->w);
2117 
2118 	spdk_put_io_channel(ch);
2119 	spdk_for_each_channel_continue(i, 0);
2120 }
2121 
2122 
2123 static void
2124 rpc_nvmf_get_stats(struct spdk_jsonrpc_request *request,
2125 		   const struct spdk_json_val *params)
2126 {
2127 	struct rpc_nvmf_get_stats_ctx *ctx;
2128 
2129 	ctx = calloc(1, sizeof(*ctx));
2130 	if (!ctx) {
2131 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2132 						 "Memory allocation error");
2133 		return;
2134 	}
2135 	ctx->request = request;
2136 
2137 	if (params) {
2138 		if (spdk_json_decode_object(params, rpc_get_stats_decoders,
2139 					    SPDK_COUNTOF(rpc_get_stats_decoders),
2140 					    ctx)) {
2141 			SPDK_ERRLOG("spdk_json_decode_object failed\n");
2142 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
2143 			free_get_stats_ctx(ctx);
2144 			return;
2145 		}
2146 	}
2147 
2148 	ctx->tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
2149 	if (!ctx->tgt) {
2150 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2151 						 "Unable to find a target.");
2152 		free_get_stats_ctx(ctx);
2153 		return;
2154 	}
2155 
2156 	ctx->w = spdk_jsonrpc_begin_result(ctx->request);
2157 	spdk_json_write_object_begin(ctx->w);
2158 	spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz());
2159 	spdk_json_write_named_array_begin(ctx->w, "poll_groups");
2160 
2161 	spdk_for_each_channel(ctx->tgt,
2162 			      _rpc_nvmf_get_stats,
2163 			      ctx,
2164 			      rpc_nvmf_get_stats_done);
2165 }
2166 
2167 SPDK_RPC_REGISTER("nvmf_get_stats", rpc_nvmf_get_stats, SPDK_RPC_RUNTIME)
2168 
2169 static void
2170 dump_nvmf_ctrlr(struct spdk_json_write_ctx *w, struct spdk_nvmf_ctrlr *ctrlr)
2171 {
2172 	char uuid_str[SPDK_UUID_STRING_LEN] = {};
2173 	uint32_t count;
2174 
2175 	spdk_json_write_object_begin(w);
2176 
2177 	spdk_json_write_named_uint32(w, "cntlid", ctrlr->cntlid);
2178 
2179 	spdk_json_write_named_string(w, "hostnqn", ctrlr->hostnqn);
2180 
2181 	spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &ctrlr->hostid);
2182 	spdk_json_write_named_string(w, "hostid", uuid_str);
2183 
2184 	count = spdk_bit_array_count_set(ctrlr->qpair_mask);
2185 	spdk_json_write_named_uint32(w, "num_io_qpairs", count);
2186 
2187 	spdk_json_write_object_end(w);
2188 }
2189 
2190 static const char *
2191 nvmf_qpair_state_str(enum spdk_nvmf_qpair_state state)
2192 {
2193 	switch (state) {
2194 	case SPDK_NVMF_QPAIR_UNINITIALIZED:
2195 		return "uninitialized";
2196 	case SPDK_NVMF_QPAIR_ACTIVE:
2197 		return "active";
2198 	case SPDK_NVMF_QPAIR_DEACTIVATING:
2199 		return "deactivating";
2200 	case SPDK_NVMF_QPAIR_ERROR:
2201 		return "error";
2202 	default:
2203 		return NULL;
2204 	}
2205 }
2206 
2207 static void
2208 dump_nvmf_qpair(struct spdk_json_write_ctx *w, struct spdk_nvmf_qpair *qpair)
2209 {
2210 	struct spdk_nvme_transport_id listen_trid = {};
2211 
2212 	spdk_json_write_object_begin(w);
2213 
2214 	spdk_json_write_named_uint32(w, "cntlid", qpair->ctrlr->cntlid);
2215 	spdk_json_write_named_uint32(w, "qid", qpair->qid);
2216 	spdk_json_write_named_string(w, "state", nvmf_qpair_state_str(qpair->state));
2217 
2218 	if (spdk_nvmf_qpair_get_listen_trid(qpair, &listen_trid) == 0) {
2219 		nvmf_transport_listen_dump_opts(qpair->transport, &listen_trid, w);
2220 	}
2221 
2222 	spdk_json_write_object_end(w);
2223 }
2224 
2225 static const char *
2226 nvme_ana_state_str(enum spdk_nvme_ana_state ana_state)
2227 {
2228 	switch (ana_state) {
2229 	case SPDK_NVME_ANA_OPTIMIZED_STATE:
2230 		return "optimized";
2231 	case SPDK_NVME_ANA_NON_OPTIMIZED_STATE:
2232 		return "non_optimized";
2233 	case SPDK_NVME_ANA_INACCESSIBLE_STATE:
2234 		return "inaccessible";
2235 	case SPDK_NVME_ANA_PERSISTENT_LOSS_STATE:
2236 		return "persistent_loss";
2237 	case SPDK_NVME_ANA_CHANGE_STATE:
2238 		return "change";
2239 	default:
2240 		return NULL;
2241 	}
2242 }
2243 
2244 static void
2245 dump_nvmf_subsystem_listener(struct spdk_json_write_ctx *w,
2246 			     struct spdk_nvmf_subsystem_listener *listener)
2247 {
2248 	const struct spdk_nvme_transport_id *trid = listener->trid;
2249 	const char *adrfam;
2250 	uint32_t i;
2251 
2252 	spdk_json_write_object_begin(w);
2253 
2254 	spdk_json_write_named_object_begin(w, "address");
2255 	adrfam = spdk_nvme_transport_id_adrfam_str(trid->adrfam);
2256 	if (adrfam == NULL) {
2257 		adrfam = "unknown";
2258 	}
2259 	spdk_json_write_named_string(w, "trtype", trid->trstring);
2260 	spdk_json_write_named_string(w, "adrfam", adrfam);
2261 	spdk_json_write_named_string(w, "traddr", trid->traddr);
2262 	spdk_json_write_named_string(w, "trsvcid", trid->trsvcid);
2263 	spdk_json_write_object_end(w);
2264 
2265 	if (nvmf_subsystem_get_ana_reporting(listener->subsystem)) {
2266 		spdk_json_write_named_array_begin(w, "ana_states");
2267 		for (i = 0; i < listener->subsystem->max_nsid; i++) {
2268 			spdk_json_write_object_begin(w);
2269 			spdk_json_write_named_uint32(w, "ana_group", i + 1);
2270 			spdk_json_write_named_string(w, "ana_state",
2271 						     nvme_ana_state_str(listener->ana_state[i]));
2272 			spdk_json_write_object_end(w);
2273 		}
2274 		spdk_json_write_array_end(w);
2275 	}
2276 
2277 	spdk_json_write_object_end(w);
2278 }
2279 
2280 struct rpc_subsystem_query_ctx {
2281 	char *nqn;
2282 	char *tgt_name;
2283 	struct spdk_nvmf_subsystem *subsystem;
2284 	struct spdk_jsonrpc_request *request;
2285 	struct spdk_json_write_ctx *w;
2286 };
2287 
2288 static const struct spdk_json_object_decoder rpc_subsystem_query_decoders[] = {
2289 	{"nqn", offsetof(struct rpc_subsystem_query_ctx, nqn), spdk_json_decode_string},
2290 	{"tgt_name", offsetof(struct rpc_subsystem_query_ctx, tgt_name), spdk_json_decode_string, true},
2291 };
2292 
2293 static void
2294 free_rpc_subsystem_query_ctx(struct rpc_subsystem_query_ctx *ctx)
2295 {
2296 	free(ctx->nqn);
2297 	free(ctx->tgt_name);
2298 	free(ctx);
2299 }
2300 
2301 static void
2302 rpc_nvmf_get_controllers_paused(struct spdk_nvmf_subsystem *subsystem,
2303 				void *cb_arg, int status)
2304 {
2305 	struct rpc_subsystem_query_ctx *ctx = cb_arg;
2306 	struct spdk_json_write_ctx *w;
2307 	struct spdk_nvmf_ctrlr *ctrlr;
2308 
2309 	w = spdk_jsonrpc_begin_result(ctx->request);
2310 
2311 	spdk_json_write_array_begin(w);
2312 	TAILQ_FOREACH(ctrlr, &ctx->subsystem->ctrlrs, link) {
2313 		dump_nvmf_ctrlr(w, ctrlr);
2314 	}
2315 	spdk_json_write_array_end(w);
2316 
2317 	spdk_jsonrpc_end_result(ctx->request, w);
2318 
2319 	if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) {
2320 		SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn);
2321 		/* FIXME: RPC should fail if resuming the subsystem failed. */
2322 	}
2323 
2324 	free_rpc_subsystem_query_ctx(ctx);
2325 }
2326 
2327 static void
2328 rpc_nvmf_get_qpairs_done(struct spdk_io_channel_iter *i, int status)
2329 {
2330 	struct rpc_subsystem_query_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
2331 
2332 	spdk_json_write_array_end(ctx->w);
2333 	spdk_jsonrpc_end_result(ctx->request, ctx->w);
2334 
2335 	if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) {
2336 		SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn);
2337 		/* FIXME: RPC should fail if resuming the subsystem failed. */
2338 	}
2339 
2340 	free_rpc_subsystem_query_ctx(ctx);
2341 }
2342 
2343 static void
2344 rpc_nvmf_get_qpairs(struct spdk_io_channel_iter *i)
2345 {
2346 	struct rpc_subsystem_query_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
2347 	struct spdk_io_channel *ch;
2348 	struct spdk_nvmf_poll_group *group;
2349 	struct spdk_nvmf_qpair *qpair;
2350 
2351 	ch = spdk_io_channel_iter_get_channel(i);
2352 	group = spdk_io_channel_get_ctx(ch);
2353 
2354 	TAILQ_FOREACH(qpair, &group->qpairs, link) {
2355 		if (qpair->ctrlr->subsys == ctx->subsystem) {
2356 			dump_nvmf_qpair(ctx->w, qpair);
2357 		}
2358 	}
2359 
2360 	spdk_for_each_channel_continue(i, 0);
2361 }
2362 
2363 static void
2364 rpc_nvmf_get_qpairs_paused(struct spdk_nvmf_subsystem *subsystem,
2365 			   void *cb_arg, int status)
2366 {
2367 	struct rpc_subsystem_query_ctx *ctx = cb_arg;
2368 
2369 	ctx->w = spdk_jsonrpc_begin_result(ctx->request);
2370 
2371 	spdk_json_write_array_begin(ctx->w);
2372 
2373 	spdk_for_each_channel(ctx->subsystem->tgt,
2374 			      rpc_nvmf_get_qpairs,
2375 			      ctx,
2376 			      rpc_nvmf_get_qpairs_done);
2377 }
2378 
2379 static void
2380 rpc_nvmf_get_listeners_paused(struct spdk_nvmf_subsystem *subsystem,
2381 			      void *cb_arg, int status)
2382 {
2383 	struct rpc_subsystem_query_ctx *ctx = cb_arg;
2384 	struct spdk_json_write_ctx *w;
2385 	struct spdk_nvmf_subsystem_listener *listener;
2386 
2387 	w = spdk_jsonrpc_begin_result(ctx->request);
2388 
2389 	spdk_json_write_array_begin(w);
2390 
2391 	for (listener = spdk_nvmf_subsystem_get_first_listener(ctx->subsystem);
2392 	     listener != NULL;
2393 	     listener = spdk_nvmf_subsystem_get_next_listener(ctx->subsystem, listener)) {
2394 		dump_nvmf_subsystem_listener(w, listener);
2395 	}
2396 	spdk_json_write_array_end(w);
2397 
2398 	spdk_jsonrpc_end_result(ctx->request, w);
2399 
2400 	if (spdk_nvmf_subsystem_resume(ctx->subsystem, NULL, NULL)) {
2401 		SPDK_ERRLOG("Resuming subsystem with NQN %s failed\n", ctx->nqn);
2402 		/* FIXME: RPC should fail if resuming the subsystem failed. */
2403 	}
2404 
2405 	free_rpc_subsystem_query_ctx(ctx);
2406 }
2407 
2408 static void
2409 _rpc_nvmf_subsystem_query(struct spdk_jsonrpc_request *request,
2410 			  const struct spdk_json_val *params,
2411 			  spdk_nvmf_subsystem_state_change_done cb_fn)
2412 {
2413 	struct rpc_subsystem_query_ctx *ctx;
2414 	struct spdk_nvmf_subsystem *subsystem;
2415 	struct spdk_nvmf_tgt *tgt;
2416 
2417 	ctx = calloc(1, sizeof(*ctx));
2418 	if (!ctx) {
2419 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2420 						 "Out of memory");
2421 		return;
2422 	}
2423 
2424 	ctx->request = request;
2425 
2426 	if (spdk_json_decode_object(params, rpc_subsystem_query_decoders,
2427 				    SPDK_COUNTOF(rpc_subsystem_query_decoders),
2428 				    ctx)) {
2429 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
2430 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
2431 						 "Invalid parameters");
2432 		free_rpc_subsystem_query_ctx(ctx);
2433 		return;
2434 	}
2435 
2436 	tgt = spdk_nvmf_get_tgt(ctx->tgt_name);
2437 	if (!tgt) {
2438 		SPDK_ERRLOG("Unable to find a target object.\n");
2439 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2440 						 "Unable to find a target");
2441 		free_rpc_subsystem_query_ctx(ctx);
2442 		return;
2443 	}
2444 
2445 	subsystem = spdk_nvmf_tgt_find_subsystem(tgt, ctx->nqn);
2446 	if (!subsystem) {
2447 		SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
2448 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
2449 						 "Invalid parameters");
2450 		free_rpc_subsystem_query_ctx(ctx);
2451 		return;
2452 	}
2453 
2454 	ctx->subsystem = subsystem;
2455 
2456 	if (spdk_nvmf_subsystem_pause(subsystem, 0, cb_fn, ctx)) {
2457 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
2458 						 "Internal error");
2459 		free_rpc_subsystem_query_ctx(ctx);
2460 		return;
2461 	}
2462 }
2463 
2464 static void
2465 rpc_nvmf_subsystem_get_controllers(struct spdk_jsonrpc_request *request,
2466 				   const struct spdk_json_val *params)
2467 {
2468 	_rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_controllers_paused);
2469 }
2470 SPDK_RPC_REGISTER("nvmf_subsystem_get_controllers", rpc_nvmf_subsystem_get_controllers,
2471 		  SPDK_RPC_RUNTIME);
2472 
2473 static void
2474 rpc_nvmf_subsystem_get_qpairs(struct spdk_jsonrpc_request *request,
2475 			      const struct spdk_json_val *params)
2476 {
2477 	_rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_qpairs_paused);
2478 }
2479 SPDK_RPC_REGISTER("nvmf_subsystem_get_qpairs", rpc_nvmf_subsystem_get_qpairs, SPDK_RPC_RUNTIME);
2480 
2481 static void
2482 rpc_nvmf_subsystem_get_listeners(struct spdk_jsonrpc_request *request,
2483 				 const struct spdk_json_val *params)
2484 {
2485 	_rpc_nvmf_subsystem_query(request, params, rpc_nvmf_get_listeners_paused);
2486 }
2487 SPDK_RPC_REGISTER("nvmf_subsystem_get_listeners", rpc_nvmf_subsystem_get_listeners,
2488 		  SPDK_RPC_RUNTIME);
2489