]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/lib/event/subsystems/nvmf/nvmf_rpc.c
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / spdk / lib / event / subsystems / nvmf / nvmf_rpc.c
1 /*-
2 * BSD LICENSE
3 *
4 * Copyright (c) Intel Corporation.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include "event_nvmf.h"
35
36 #include "spdk/bdev.h"
37 #include "spdk/log.h"
38 #include "spdk/rpc.h"
39 #include "spdk/env.h"
40 #include "spdk/nvme.h"
41 #include "spdk/nvmf.h"
42 #include "spdk/string.h"
43 #include "spdk/util.h"
44
45 static int
46 json_write_hex_str(struct spdk_json_write_ctx *w, const void *data, size_t size)
47 {
48 static const char hex_char[16] = "0123456789ABCDEF";
49 const uint8_t *buf = data;
50 char *str, *out;
51 int rc;
52
53 str = malloc(size * 2 + 1);
54 if (str == NULL) {
55 return -1;
56 }
57
58 out = str;
59 while (size--) {
60 unsigned byte = *buf++;
61
62 out[0] = hex_char[(byte >> 4) & 0xF];
63 out[1] = hex_char[byte & 0xF];
64
65 out += 2;
66 }
67 *out = '\0';
68
69 rc = spdk_json_write_string(w, str);
70 free(str);
71
72 return rc;
73 }
74
75 static int
76 hex_nybble_to_num(char c)
77 {
78 if (c >= '0' && c <= '9') {
79 return c - '0';
80 }
81
82 if (c >= 'a' && c <= 'f') {
83 return c - 'a' + 0xA;
84 }
85
86 if (c >= 'A' && c <= 'F') {
87 return c - 'A' + 0xA;
88 }
89
90 return -1;
91 }
92
93 static int
94 hex_byte_to_num(const char *str)
95 {
96 int hi, lo;
97
98 hi = hex_nybble_to_num(str[0]);
99 if (hi < 0) {
100 return hi;
101 }
102
103 lo = hex_nybble_to_num(str[1]);
104 if (lo < 0) {
105 return lo;
106 }
107
108 return hi * 16 + lo;
109 }
110
111 static int
112 decode_hex_string_be(const char *str, uint8_t *out, size_t size)
113 {
114 size_t i;
115
116 /* Decode a string in "ABCDEF012345" format to its binary representation */
117 for (i = 0; i < size; i++) {
118 int num = hex_byte_to_num(str);
119
120 if (num < 0) {
121 /* Invalid hex byte or end of string */
122 return -1;
123 }
124
125 out[i] = (uint8_t)num;
126 str += 2;
127 }
128
129 if (i != size || *str != '\0') {
130 /* Length mismatch */
131 return -1;
132 }
133
134 return 0;
135 }
136
137 static int
138 decode_ns_nguid(const struct spdk_json_val *val, void *out)
139 {
140 char *str = NULL;
141 int rc;
142
143 rc = spdk_json_decode_string(val, &str);
144 if (rc == 0) {
145 /* 16-byte NGUID */
146 rc = decode_hex_string_be(str, out, 16);
147 }
148
149 free(str);
150 return rc;
151 }
152
153 static int
154 decode_ns_eui64(const struct spdk_json_val *val, void *out)
155 {
156 char *str = NULL;
157 int rc;
158
159 rc = spdk_json_decode_string(val, &str);
160 if (rc == 0) {
161 /* 8-byte EUI-64 */
162 rc = decode_hex_string_be(str, out, 8);
163 }
164
165 free(str);
166 return rc;
167 }
168
169 static int
170 decode_ns_uuid(const struct spdk_json_val *val, void *out)
171 {
172 char *str = NULL;
173 int rc;
174
175 rc = spdk_json_decode_string(val, &str);
176 if (rc == 0) {
177 rc = spdk_uuid_parse(out, str);
178 }
179
180 free(str);
181 return rc;
182 }
183
184 static void
185 dump_nvmf_subsystem(struct spdk_json_write_ctx *w, struct spdk_nvmf_subsystem *subsystem)
186 {
187 struct spdk_nvmf_host *host;
188 struct spdk_nvmf_listener *listener;
189
190 spdk_json_write_object_begin(w);
191
192 spdk_json_write_name(w, "nqn");
193 spdk_json_write_string(w, spdk_nvmf_subsystem_get_nqn(subsystem));
194 spdk_json_write_name(w, "subtype");
195 if (spdk_nvmf_subsystem_get_type(subsystem) == SPDK_NVMF_SUBTYPE_NVME) {
196 spdk_json_write_string(w, "NVMe");
197 } else {
198 spdk_json_write_string(w, "Discovery");
199 }
200
201 spdk_json_write_name(w, "listen_addresses");
202 spdk_json_write_array_begin(w);
203
204 for (listener = spdk_nvmf_subsystem_get_first_listener(subsystem); listener != NULL;
205 listener = spdk_nvmf_subsystem_get_next_listener(subsystem, listener)) {
206 const struct spdk_nvme_transport_id *trid;
207 const char *trtype;
208 const char *adrfam;
209
210 trid = spdk_nvmf_listener_get_trid(listener);
211
212 spdk_json_write_object_begin(w);
213 trtype = spdk_nvme_transport_id_trtype_str(trid->trtype);
214 if (trtype == NULL) {
215 trtype = "unknown";
216 }
217 adrfam = spdk_nvme_transport_id_adrfam_str(trid->adrfam);
218 if (adrfam == NULL) {
219 adrfam = "unknown";
220 }
221 /* NOTE: "transport" is kept for compatibility; new code should use "trtype" */
222 spdk_json_write_name(w, "transport");
223 spdk_json_write_string(w, trtype);
224 spdk_json_write_name(w, "trtype");
225 spdk_json_write_string(w, trtype);
226 spdk_json_write_name(w, "adrfam");
227 spdk_json_write_string(w, adrfam);
228 spdk_json_write_name(w, "traddr");
229 spdk_json_write_string(w, trid->traddr);
230 spdk_json_write_name(w, "trsvcid");
231 spdk_json_write_string(w, trid->trsvcid);
232 spdk_json_write_object_end(w);
233 }
234 spdk_json_write_array_end(w);
235
236 spdk_json_write_name(w, "allow_any_host");
237 spdk_json_write_bool(w, spdk_nvmf_subsystem_get_allow_any_host(subsystem));
238
239 spdk_json_write_name(w, "hosts");
240 spdk_json_write_array_begin(w);
241
242 for (host = spdk_nvmf_subsystem_get_first_host(subsystem); host != NULL;
243 host = spdk_nvmf_subsystem_get_next_host(subsystem, host)) {
244 spdk_json_write_object_begin(w);
245 spdk_json_write_name(w, "nqn");
246 spdk_json_write_string(w, spdk_nvmf_host_get_nqn(host));
247 spdk_json_write_object_end(w);
248 }
249 spdk_json_write_array_end(w);
250
251 if (spdk_nvmf_subsystem_get_type(subsystem) == SPDK_NVMF_SUBTYPE_NVME) {
252 struct spdk_nvmf_ns *ns;
253 struct spdk_nvmf_ns_opts ns_opts;
254 uint32_t max_namespaces;
255
256 spdk_json_write_name(w, "serial_number");
257 spdk_json_write_string(w, spdk_nvmf_subsystem_get_sn(subsystem));
258
259 max_namespaces = spdk_nvmf_subsystem_get_max_namespaces(subsystem);
260 if (max_namespaces != 0) {
261 spdk_json_write_named_uint32(w, "max_namespaces", max_namespaces);
262 }
263
264 spdk_json_write_name(w, "namespaces");
265 spdk_json_write_array_begin(w);
266 for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL;
267 ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) {
268 spdk_nvmf_ns_get_opts(ns, &ns_opts, sizeof(ns_opts));
269 spdk_json_write_object_begin(w);
270 spdk_json_write_name(w, "nsid");
271 spdk_json_write_int32(w, spdk_nvmf_ns_get_id(ns));
272 spdk_json_write_name(w, "bdev_name");
273 spdk_json_write_string(w, spdk_bdev_get_name(spdk_nvmf_ns_get_bdev(ns)));
274 /* NOTE: "name" is kept for compatibility only - new code should use bdev_name. */
275 spdk_json_write_name(w, "name");
276 spdk_json_write_string(w, spdk_bdev_get_name(spdk_nvmf_ns_get_bdev(ns)));
277
278 if (!spdk_mem_all_zero(ns_opts.nguid, sizeof(ns_opts.nguid))) {
279 spdk_json_write_name(w, "nguid");
280 json_write_hex_str(w, ns_opts.nguid, sizeof(ns_opts.nguid));
281 }
282
283 if (!spdk_mem_all_zero(ns_opts.eui64, sizeof(ns_opts.eui64))) {
284 spdk_json_write_name(w, "eui64");
285 json_write_hex_str(w, ns_opts.eui64, sizeof(ns_opts.eui64));
286 }
287
288 if (!spdk_mem_all_zero(&ns_opts.uuid, sizeof(ns_opts.uuid))) {
289 char uuid_str[SPDK_UUID_STRING_LEN];
290
291 spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &ns_opts.uuid);
292 spdk_json_write_name(w, "uuid");
293 spdk_json_write_string(w, uuid_str);
294 }
295
296 spdk_json_write_object_end(w);
297 }
298 spdk_json_write_array_end(w);
299 }
300 spdk_json_write_object_end(w);
301 }
302
303 static void
304 spdk_rpc_get_nvmf_subsystems(struct spdk_jsonrpc_request *request,
305 const struct spdk_json_val *params)
306 {
307 struct spdk_json_write_ctx *w;
308 struct spdk_nvmf_subsystem *subsystem;
309
310 if (params != NULL) {
311 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
312 "get_nvmf_subsystems requires no parameters");
313 return;
314 }
315
316 w = spdk_jsonrpc_begin_result(request);
317 if (w == NULL) {
318 return;
319 }
320
321 spdk_json_write_array_begin(w);
322 subsystem = spdk_nvmf_subsystem_get_first(g_spdk_nvmf_tgt);
323 while (subsystem) {
324 dump_nvmf_subsystem(w, subsystem);
325 subsystem = spdk_nvmf_subsystem_get_next(subsystem);
326 }
327 spdk_json_write_array_end(w);
328 spdk_jsonrpc_end_result(request, w);
329 }
330 SPDK_RPC_REGISTER("get_nvmf_subsystems", spdk_rpc_get_nvmf_subsystems, SPDK_RPC_RUNTIME)
331
332 struct rpc_subsystem_create {
333 char *nqn;
334 char *serial_number;
335 uint32_t max_namespaces;
336 bool allow_any_host;
337 };
338
339 static const struct spdk_json_object_decoder rpc_subsystem_create_decoders[] = {
340 {"nqn", offsetof(struct rpc_subsystem_create, nqn), spdk_json_decode_string},
341 {"serial_number", offsetof(struct rpc_subsystem_create, serial_number), spdk_json_decode_string, true},
342 {"max_namespaces", offsetof(struct rpc_subsystem_create, max_namespaces), spdk_json_decode_uint32, true},
343 {"allow_any_host", offsetof(struct rpc_subsystem_create, allow_any_host), spdk_json_decode_bool, true},
344 };
345
346 static void
347 spdk_rpc_nvmf_subsystem_started(struct spdk_nvmf_subsystem *subsystem,
348 void *cb_arg, int status)
349 {
350 struct spdk_jsonrpc_request *request = cb_arg;
351 struct spdk_json_write_ctx *w;
352
353 w = spdk_jsonrpc_begin_result(request);
354 if (w == NULL) {
355 return;
356 }
357
358 spdk_json_write_bool(w, true);
359 spdk_jsonrpc_end_result(request, w);
360 }
361
362 static void
363 spdk_rpc_nvmf_subsystem_create(struct spdk_jsonrpc_request *request,
364 const struct spdk_json_val *params)
365 {
366 struct rpc_subsystem_create *req;
367 struct spdk_nvmf_subsystem *subsystem;
368
369 req = calloc(1, sizeof(*req));
370 if (!req) {
371 goto invalid;
372 }
373
374 if (spdk_json_decode_object(params, rpc_subsystem_create_decoders,
375 SPDK_COUNTOF(rpc_subsystem_create_decoders),
376 req)) {
377 SPDK_ERRLOG("spdk_json_decode_object failed\n");
378 goto invalid;
379 }
380
381 subsystem = spdk_nvmf_subsystem_create(g_spdk_nvmf_tgt, req->nqn, SPDK_NVMF_SUBTYPE_NVME,
382 req->max_namespaces);
383 if (!subsystem) {
384 goto invalid;
385 }
386
387 if (req->serial_number) {
388 if (spdk_nvmf_subsystem_set_sn(subsystem, req->serial_number)) {
389 SPDK_ERRLOG("Subsystem %s: invalid serial number '%s'\n", req->nqn, req->serial_number);
390 goto invalid;
391 }
392 }
393
394 spdk_nvmf_subsystem_set_allow_any_host(subsystem, req->allow_any_host);
395
396 free(req->nqn);
397 free(req->serial_number);
398 free(req);
399
400 spdk_nvmf_subsystem_start(subsystem,
401 spdk_rpc_nvmf_subsystem_started,
402 request);
403
404 return;
405
406 invalid:
407 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
408 if (req) {
409 free(req->nqn);
410 free(req->serial_number);
411 }
412 free(req);
413 }
414 SPDK_RPC_REGISTER("nvmf_subsystem_create", spdk_rpc_nvmf_subsystem_create, SPDK_RPC_RUNTIME)
415
416 struct rpc_delete_subsystem {
417 char *nqn;
418 };
419
420 static void
421 free_rpc_delete_subsystem(struct rpc_delete_subsystem *r)
422 {
423 free(r->nqn);
424 }
425
426 static void
427 spdk_rpc_nvmf_subsystem_stopped(struct spdk_nvmf_subsystem *subsystem,
428 void *cb_arg, int status)
429 {
430 struct spdk_jsonrpc_request *request = cb_arg;
431 struct spdk_json_write_ctx *w;
432
433 spdk_nvmf_subsystem_destroy(subsystem);
434
435 w = spdk_jsonrpc_begin_result(request);
436 if (w == NULL) {
437 return;
438 }
439
440 spdk_json_write_bool(w, true);
441 spdk_jsonrpc_end_result(request, w);
442 }
443
444 static const struct spdk_json_object_decoder rpc_delete_subsystem_decoders[] = {
445 {"nqn", offsetof(struct rpc_delete_subsystem, nqn), spdk_json_decode_string},
446 };
447
448 static void
449 spdk_rpc_delete_nvmf_subsystem(struct spdk_jsonrpc_request *request,
450 const struct spdk_json_val *params)
451 {
452 struct rpc_delete_subsystem req = {};
453 struct spdk_nvmf_subsystem *subsystem;
454
455 if (spdk_json_decode_object(params, rpc_delete_subsystem_decoders,
456 SPDK_COUNTOF(rpc_delete_subsystem_decoders),
457 &req)) {
458 SPDK_ERRLOG("spdk_json_decode_object failed\n");
459 goto invalid;
460 }
461
462 if (req.nqn == NULL) {
463 SPDK_ERRLOG("missing name param\n");
464 goto invalid;
465 }
466
467 subsystem = spdk_nvmf_tgt_find_subsystem(g_spdk_nvmf_tgt, req.nqn);
468 if (!subsystem) {
469 goto invalid;
470 }
471
472 free_rpc_delete_subsystem(&req);
473
474 spdk_nvmf_subsystem_stop(subsystem,
475 spdk_rpc_nvmf_subsystem_stopped,
476 request);
477
478 return;
479
480 invalid:
481 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
482 free_rpc_delete_subsystem(&req);
483 }
484 SPDK_RPC_REGISTER("delete_nvmf_subsystem", spdk_rpc_delete_nvmf_subsystem, SPDK_RPC_RUNTIME)
485
486 struct rpc_listen_address {
487 char *transport;
488 char *adrfam;
489 char *traddr;
490 char *trsvcid;
491 };
492
493 #define RPC_MAX_LISTEN_ADDRESSES 255
494 #define RPC_MAX_NAMESPACES 255
495
496 struct rpc_listen_addresses {
497 size_t num_listen_address;
498 struct rpc_listen_address addresses[RPC_MAX_LISTEN_ADDRESSES];
499 };
500
501 static const struct spdk_json_object_decoder rpc_listen_address_decoders[] = {
502 /* NOTE: "transport" is kept for compatibility; new code should use "trtype" */
503 {"transport", offsetof(struct rpc_listen_address, transport), spdk_json_decode_string, true},
504 {"trtype", offsetof(struct rpc_listen_address, transport), spdk_json_decode_string, true},
505 {"adrfam", offsetof(struct rpc_listen_address, adrfam), spdk_json_decode_string, true},
506 {"traddr", offsetof(struct rpc_listen_address, traddr), spdk_json_decode_string},
507 {"trsvcid", offsetof(struct rpc_listen_address, trsvcid), spdk_json_decode_string},
508 };
509
510 static int
511 decode_rpc_listen_address(const struct spdk_json_val *val, void *out)
512 {
513 struct rpc_listen_address *req = (struct rpc_listen_address *)out;
514 if (spdk_json_decode_object(val, rpc_listen_address_decoders,
515 SPDK_COUNTOF(rpc_listen_address_decoders),
516 req)) {
517 SPDK_ERRLOG("spdk_json_decode_object failed\n");
518 return -1;
519 }
520 return 0;
521 }
522
523 static void
524 free_rpc_listen_address(struct rpc_listen_address *r)
525 {
526 free(r->transport);
527 free(r->adrfam);
528 free(r->traddr);
529 free(r->trsvcid);
530 }
531
532 enum nvmf_rpc_listen_op {
533 NVMF_RPC_LISTEN_ADD,
534 NVMF_RPC_LISTEN_REMOVE,
535 };
536
537 struct nvmf_rpc_listener_ctx {
538 char *nqn;
539 struct spdk_nvmf_subsystem *subsystem;
540 struct rpc_listen_address address;
541
542 struct spdk_jsonrpc_request *request;
543 struct spdk_nvme_transport_id trid;
544 enum nvmf_rpc_listen_op op;
545 bool response_sent;
546 };
547
548 static const struct spdk_json_object_decoder nvmf_rpc_listener_decoder[] = {
549 {"nqn", offsetof(struct nvmf_rpc_listener_ctx, nqn), spdk_json_decode_string},
550 {"listen_address", offsetof(struct nvmf_rpc_listener_ctx, address), decode_rpc_listen_address},
551 };
552
553 static void
554 nvmf_rpc_listener_ctx_free(struct nvmf_rpc_listener_ctx *ctx)
555 {
556 free(ctx->nqn);
557 free_rpc_listen_address(&ctx->address);
558 free(ctx);
559 }
560
561 static void
562 nvmf_rpc_listen_resumed(struct spdk_nvmf_subsystem *subsystem,
563 void *cb_arg, int status)
564 {
565 struct nvmf_rpc_listener_ctx *ctx = cb_arg;
566 struct spdk_jsonrpc_request *request;
567 struct spdk_json_write_ctx *w;
568
569 request = ctx->request;
570 if (ctx->response_sent) {
571 /* If an error occurred, the response has already been sent. */
572 nvmf_rpc_listener_ctx_free(ctx);
573 return;
574 }
575
576 nvmf_rpc_listener_ctx_free(ctx);
577
578 w = spdk_jsonrpc_begin_result(request);
579 if (w == NULL) {
580 return;
581 }
582
583 spdk_json_write_bool(w, true);
584 spdk_jsonrpc_end_result(request, w);
585 }
586
587 static void
588 nvmf_rpc_tgt_listen(void *cb_arg, int status)
589 {
590 struct nvmf_rpc_listener_ctx *ctx = cb_arg;
591
592 if (status) {
593 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
594 "Invalid parameters");
595 ctx->response_sent = true;
596 } else {
597 if (spdk_nvmf_subsystem_add_listener(ctx->subsystem, &ctx->trid)) {
598 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
599 "Invalid parameters");
600 ctx->response_sent = true;
601 }
602 }
603
604 if (spdk_nvmf_subsystem_resume(ctx->subsystem, nvmf_rpc_listen_resumed, ctx)) {
605 if (!ctx->response_sent) {
606 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
607 }
608 nvmf_rpc_listener_ctx_free(ctx);
609 /* Can't really do anything to recover here - subsystem will remain paused. */
610 }
611 }
612
613 static void
614 nvmf_rpc_listen_paused(struct spdk_nvmf_subsystem *subsystem,
615 void *cb_arg, int status)
616 {
617 struct nvmf_rpc_listener_ctx *ctx = cb_arg;
618
619 if (ctx->op == NVMF_RPC_LISTEN_ADD) {
620 spdk_nvmf_tgt_listen(g_spdk_nvmf_tgt, &ctx->trid, nvmf_rpc_tgt_listen, ctx);
621 return;
622 } else if (ctx->op == NVMF_RPC_LISTEN_REMOVE) {
623 if (spdk_nvmf_subsystem_remove_listener(subsystem, &ctx->trid)) {
624 SPDK_ERRLOG("Unable to remove listener.\n");
625 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
626 "Invalid parameters");
627 ctx->response_sent = true;
628 }
629 } else {
630 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
631 "Invalid parameters");
632 ctx->response_sent = true;
633 }
634
635 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_listen_resumed, ctx)) {
636 if (!ctx->response_sent) {
637 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
638 }
639 nvmf_rpc_listener_ctx_free(ctx);
640 /* Can't really do anything to recover here - subsystem will remain paused. */
641 }
642 }
643
644 static int
645 rpc_listen_address_to_trid(const struct rpc_listen_address *address,
646 struct spdk_nvme_transport_id *trid)
647 {
648 size_t len;
649
650 memset(trid, 0, sizeof(*trid));
651
652 if (spdk_nvme_transport_id_parse_trtype(&trid->trtype, address->transport)) {
653 SPDK_ERRLOG("Invalid transport type: %s\n", address->transport);
654 return -EINVAL;
655 }
656
657 if (address->adrfam) {
658 if (spdk_nvme_transport_id_parse_adrfam(&trid->adrfam, address->adrfam)) {
659 SPDK_ERRLOG("Invalid adrfam: %s\n", address->adrfam);
660 return -EINVAL;
661 }
662 } else {
663 trid->adrfam = SPDK_NVMF_ADRFAM_IPV4;
664 }
665
666 len = strlen(address->traddr);
667 if (len > sizeof(trid->traddr) - 1) {
668 SPDK_ERRLOG("Transport address longer than %zu characters: %s\n",
669 sizeof(trid->traddr) - 1, address->traddr);
670 return -EINVAL;
671 }
672 memcpy(trid->traddr, address->traddr, len + 1);
673
674 len = strlen(address->trsvcid);
675 if (len > sizeof(trid->trsvcid) - 1) {
676 SPDK_ERRLOG("Transport service id longer than %zu characters: %s\n",
677 sizeof(trid->trsvcid) - 1, address->trsvcid);
678 return -EINVAL;
679 }
680 memcpy(trid->trsvcid, address->trsvcid, len + 1);
681
682 return 0;
683 }
684
685 static void
686 nvmf_rpc_subsystem_add_listener(struct spdk_jsonrpc_request *request,
687 const struct spdk_json_val *params)
688 {
689 struct nvmf_rpc_listener_ctx *ctx;
690 struct spdk_nvmf_subsystem *subsystem;
691
692 ctx = calloc(1, sizeof(*ctx));
693 if (!ctx) {
694 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
695 return;
696 }
697
698 ctx->request = request;
699
700 if (spdk_json_decode_object(params, nvmf_rpc_listener_decoder,
701 SPDK_COUNTOF(nvmf_rpc_listener_decoder),
702 ctx)) {
703 SPDK_ERRLOG("spdk_json_decode_object failed\n");
704 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
705 nvmf_rpc_listener_ctx_free(ctx);
706 return;
707 }
708
709 subsystem = spdk_nvmf_tgt_find_subsystem(g_spdk_nvmf_tgt, ctx->nqn);
710 if (!subsystem) {
711 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
712 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
713 nvmf_rpc_listener_ctx_free(ctx);
714 return;
715 }
716
717 ctx->subsystem = subsystem;
718
719 if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) {
720 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
721 "Invalid parameters");
722 nvmf_rpc_listener_ctx_free(ctx);
723 return;
724 }
725
726 ctx->op = NVMF_RPC_LISTEN_ADD;
727
728 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_listen_paused, ctx)) {
729 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
730 nvmf_rpc_listener_ctx_free(ctx);
731 return;
732 }
733 }
734 SPDK_RPC_REGISTER("nvmf_subsystem_add_listener", nvmf_rpc_subsystem_add_listener, SPDK_RPC_RUNTIME);
735
736 static void
737 nvmf_rpc_subsystem_remove_listener(struct spdk_jsonrpc_request *request,
738 const struct spdk_json_val *params)
739 {
740 struct nvmf_rpc_listener_ctx *ctx;
741 struct spdk_nvmf_subsystem *subsystem;
742
743 ctx = calloc(1, sizeof(*ctx));
744 if (!ctx) {
745 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
746 return;
747 }
748
749 ctx->request = request;
750
751 if (spdk_json_decode_object(params, nvmf_rpc_listener_decoder,
752 SPDK_COUNTOF(nvmf_rpc_listener_decoder),
753 ctx)) {
754 SPDK_ERRLOG("spdk_json_decode_object failed\n");
755 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
756 nvmf_rpc_listener_ctx_free(ctx);
757 return;
758 }
759
760 subsystem = spdk_nvmf_tgt_find_subsystem(g_spdk_nvmf_tgt, ctx->nqn);
761 if (!subsystem) {
762 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
763 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
764 nvmf_rpc_listener_ctx_free(ctx);
765 return;
766 }
767
768 ctx->subsystem = subsystem;
769
770 if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) {
771 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
772 "Invalid parameters");
773 nvmf_rpc_listener_ctx_free(ctx);
774 return;
775 }
776
777 ctx->op = NVMF_RPC_LISTEN_REMOVE;
778
779 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_listen_paused, ctx)) {
780 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
781 nvmf_rpc_listener_ctx_free(ctx);
782 return;
783 }
784
785 }
786 SPDK_RPC_REGISTER("nvmf_subsystem_remove_listener", nvmf_rpc_subsystem_remove_listener,
787 SPDK_RPC_RUNTIME);
788
789 struct spdk_nvmf_ns_params {
790 char *bdev_name;
791 uint32_t nsid;
792 char nguid[16];
793 char eui64[8];
794 struct spdk_uuid uuid;
795 };
796
797 struct rpc_namespaces {
798 size_t num_ns;
799 struct spdk_nvmf_ns_params ns_params[RPC_MAX_NAMESPACES];
800 };
801
802
803 static const struct spdk_json_object_decoder rpc_ns_params_decoders[] = {
804 {"nsid", offsetof(struct spdk_nvmf_ns_params, nsid), spdk_json_decode_uint32, true},
805 {"bdev_name", offsetof(struct spdk_nvmf_ns_params, bdev_name), spdk_json_decode_string},
806 {"nguid", offsetof(struct spdk_nvmf_ns_params, nguid), decode_ns_nguid, true},
807 {"eui64", offsetof(struct spdk_nvmf_ns_params, eui64), decode_ns_eui64, true},
808 {"uuid", offsetof(struct spdk_nvmf_ns_params, uuid), decode_ns_uuid, true},
809 };
810
811 static int
812 decode_rpc_ns_params(const struct spdk_json_val *val, void *out)
813 {
814 struct spdk_nvmf_ns_params *ns_params = out;
815
816 return spdk_json_decode_object(val, rpc_ns_params_decoders,
817 SPDK_COUNTOF(rpc_ns_params_decoders),
818 ns_params);
819 }
820
821 struct nvmf_rpc_ns_ctx {
822 char *nqn;
823 struct spdk_nvmf_ns_params ns_params;
824
825 struct spdk_jsonrpc_request *request;
826 bool response_sent;
827 };
828
829 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_ns_decoder[] = {
830 {"nqn", offsetof(struct nvmf_rpc_ns_ctx, nqn), spdk_json_decode_string},
831 {"namespace", offsetof(struct nvmf_rpc_ns_ctx, ns_params), decode_rpc_ns_params},
832 };
833
834 static void
835 nvmf_rpc_ns_ctx_free(struct nvmf_rpc_ns_ctx *ctx)
836 {
837 free(ctx->nqn);
838 free(ctx->ns_params.bdev_name);
839 free(ctx);
840 }
841
842 static void
843 nvmf_rpc_ns_resumed(struct spdk_nvmf_subsystem *subsystem,
844 void *cb_arg, int status)
845 {
846 struct nvmf_rpc_ns_ctx *ctx = cb_arg;
847 struct spdk_jsonrpc_request *request = ctx->request;
848 uint32_t nsid = ctx->ns_params.nsid;
849 bool response_sent = ctx->response_sent;
850 struct spdk_json_write_ctx *w;
851
852 nvmf_rpc_ns_ctx_free(ctx);
853
854 if (response_sent) {
855 return;
856 }
857
858 w = spdk_jsonrpc_begin_result(request);
859 if (w == NULL) {
860 return;
861 }
862
863 spdk_json_write_uint32(w, nsid);
864 spdk_jsonrpc_end_result(request, w);
865 }
866
867 static void
868 nvmf_rpc_ns_paused(struct spdk_nvmf_subsystem *subsystem,
869 void *cb_arg, int status)
870 {
871 struct nvmf_rpc_ns_ctx *ctx = cb_arg;
872 struct spdk_nvmf_ns_opts ns_opts;
873 struct spdk_bdev *bdev;
874
875 bdev = spdk_bdev_get_by_name(ctx->ns_params.bdev_name);
876 if (!bdev) {
877 SPDK_ERRLOG("No bdev with name %s\n", ctx->ns_params.bdev_name);
878 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
879 "Invalid parameters");
880 ctx->response_sent = true;
881 goto resume;
882 }
883
884 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
885 ns_opts.nsid = ctx->ns_params.nsid;
886
887 SPDK_STATIC_ASSERT(sizeof(ns_opts.nguid) == sizeof(ctx->ns_params.nguid), "size mismatch");
888 memcpy(ns_opts.nguid, ctx->ns_params.nguid, sizeof(ns_opts.nguid));
889
890 SPDK_STATIC_ASSERT(sizeof(ns_opts.eui64) == sizeof(ctx->ns_params.eui64), "size mismatch");
891 memcpy(ns_opts.eui64, ctx->ns_params.eui64, sizeof(ns_opts.eui64));
892
893 if (!spdk_mem_all_zero(&ctx->ns_params.uuid, sizeof(ctx->ns_params.uuid))) {
894 ns_opts.uuid = ctx->ns_params.uuid;
895 }
896
897 ctx->ns_params.nsid = spdk_nvmf_subsystem_add_ns(subsystem, bdev, &ns_opts, sizeof(ns_opts));
898 if (ctx->ns_params.nsid == 0) {
899 SPDK_ERRLOG("Unable to add namespace\n");
900 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
901 "Invalid parameters");
902 ctx->response_sent = true;
903 goto resume;
904 }
905
906 resume:
907 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_ns_resumed, ctx)) {
908 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
909 nvmf_rpc_ns_ctx_free(ctx);
910 return;
911 }
912 }
913
914 static void
915 nvmf_rpc_subsystem_add_ns(struct spdk_jsonrpc_request *request,
916 const struct spdk_json_val *params)
917 {
918 struct nvmf_rpc_ns_ctx *ctx;
919 struct spdk_nvmf_subsystem *subsystem;
920
921 ctx = calloc(1, sizeof(*ctx));
922 if (!ctx) {
923 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
924 return;
925 }
926
927 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_ns_decoder,
928 SPDK_COUNTOF(nvmf_rpc_subsystem_ns_decoder),
929 ctx)) {
930 SPDK_ERRLOG("spdk_json_decode_object failed\n");
931 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
932 nvmf_rpc_ns_ctx_free(ctx);
933 return;
934 }
935
936 ctx->request = request;
937 ctx->response_sent = false;
938
939 subsystem = spdk_nvmf_tgt_find_subsystem(g_spdk_nvmf_tgt, ctx->nqn);
940 if (!subsystem) {
941 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
942 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
943 nvmf_rpc_ns_ctx_free(ctx);
944 return;
945 }
946
947 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_ns_paused, ctx)) {
948 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
949 nvmf_rpc_ns_ctx_free(ctx);
950 return;
951 }
952 }
953 SPDK_RPC_REGISTER("nvmf_subsystem_add_ns", nvmf_rpc_subsystem_add_ns, SPDK_RPC_RUNTIME)
954
955 struct nvmf_rpc_remove_ns_ctx {
956 char *nqn;
957 uint32_t nsid;
958
959 struct spdk_jsonrpc_request *request;
960 bool response_sent;
961 };
962
963 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_remove_ns_decoder[] = {
964 {"nqn", offsetof(struct nvmf_rpc_remove_ns_ctx, nqn), spdk_json_decode_string},
965 {"nsid", offsetof(struct nvmf_rpc_remove_ns_ctx, nsid), spdk_json_decode_uint32},
966 };
967
968 static void
969 nvmf_rpc_remove_ns_ctx_free(struct nvmf_rpc_remove_ns_ctx *ctx)
970 {
971 free(ctx->nqn);
972 free(ctx);
973 }
974
975 static void
976 nvmf_rpc_remove_ns_resumed(struct spdk_nvmf_subsystem *subsystem,
977 void *cb_arg, int status)
978 {
979 struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg;
980 struct spdk_jsonrpc_request *request = ctx->request;
981 bool response_sent = ctx->response_sent;
982 struct spdk_json_write_ctx *w;
983
984 nvmf_rpc_remove_ns_ctx_free(ctx);
985
986 if (response_sent) {
987 return;
988 }
989
990 w = spdk_jsonrpc_begin_result(request);
991 if (w == NULL) {
992 return;
993 }
994
995 spdk_json_write_bool(w, true);
996 spdk_jsonrpc_end_result(request, w);
997 }
998
999 static void
1000 nvmf_rpc_remove_ns_remove_done(struct spdk_nvmf_subsystem *subsystem, void *cb_arg, int status)
1001 {
1002 struct nvmf_rpc_remove_ns_ctx *ctx;
1003
1004 ctx = cb_arg;
1005
1006 if (status != 0) {
1007 SPDK_ERRLOG("Unable to remove namespace ID %u\n", ctx->nsid);
1008 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1009 "Invalid parameters");
1010 ctx->response_sent = true;
1011 }
1012
1013 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_remove_ns_resumed, ctx)) {
1014 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1015 nvmf_rpc_remove_ns_ctx_free(ctx);
1016 return;
1017 }
1018 }
1019
1020 static void
1021 nvmf_rpc_remove_ns_paused(struct spdk_nvmf_subsystem *subsystem,
1022 void *cb_arg, int status)
1023 {
1024 struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg;
1025 int ret;
1026
1027 ret = spdk_nvmf_subsystem_remove_ns(subsystem, ctx->nsid, nvmf_rpc_remove_ns_remove_done, ctx);
1028 if (ret < 0) {
1029 SPDK_ERRLOG("Unable to remove namespace ID %u\n", ctx->nsid);
1030 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1031 "Invalid parameters");
1032 ctx->response_sent = true;
1033 spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_remove_ns_resumed, ctx);
1034 }
1035 }
1036
1037 static void
1038 nvmf_rpc_subsystem_remove_ns(struct spdk_jsonrpc_request *request,
1039 const struct spdk_json_val *params)
1040 {
1041 struct nvmf_rpc_remove_ns_ctx *ctx;
1042 struct spdk_nvmf_subsystem *subsystem;
1043
1044 ctx = calloc(1, sizeof(*ctx));
1045 if (!ctx) {
1046 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1047 return;
1048 }
1049
1050 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_remove_ns_decoder,
1051 SPDK_COUNTOF(nvmf_rpc_subsystem_remove_ns_decoder),
1052 ctx)) {
1053 SPDK_ERRLOG("spdk_json_decode_object failed\n");
1054 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1055 nvmf_rpc_remove_ns_ctx_free(ctx);
1056 return;
1057 }
1058
1059 ctx->request = request;
1060 ctx->response_sent = false;
1061
1062 subsystem = spdk_nvmf_tgt_find_subsystem(g_spdk_nvmf_tgt, ctx->nqn);
1063 if (!subsystem) {
1064 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
1065 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1066 nvmf_rpc_remove_ns_ctx_free(ctx);
1067 return;
1068 }
1069
1070 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_remove_ns_paused, ctx)) {
1071 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1072 nvmf_rpc_remove_ns_ctx_free(ctx);
1073 return;
1074 }
1075 }
1076 SPDK_RPC_REGISTER("nvmf_subsystem_remove_ns", nvmf_rpc_subsystem_remove_ns, SPDK_RPC_RUNTIME)
1077
1078 enum nvmf_rpc_host_op {
1079 NVMF_RPC_HOST_ADD,
1080 NVMF_RPC_HOST_REMOVE,
1081 NVMF_RPC_HOST_ALLOW_ANY,
1082 };
1083
1084 struct nvmf_rpc_host_ctx {
1085 struct spdk_jsonrpc_request *request;
1086
1087 char *nqn;
1088 char *host;
1089
1090 enum nvmf_rpc_host_op op;
1091
1092 bool allow_any_host;
1093
1094 bool response_sent;
1095 };
1096
1097 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_host_decoder[] = {
1098 {"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string},
1099 {"host", offsetof(struct nvmf_rpc_host_ctx, host), spdk_json_decode_string},
1100 };
1101
1102 static void
1103 nvmf_rpc_host_ctx_free(struct nvmf_rpc_host_ctx *ctx)
1104 {
1105 free(ctx->nqn);
1106 free(ctx->host);
1107 free(ctx);
1108 }
1109
1110 static void
1111 nvmf_rpc_host_resumed(struct spdk_nvmf_subsystem *subsystem,
1112 void *cb_arg, int status)
1113 {
1114 struct nvmf_rpc_host_ctx *ctx = cb_arg;
1115 struct spdk_jsonrpc_request *request;
1116 struct spdk_json_write_ctx *w;
1117 bool response_sent = ctx->response_sent;
1118
1119 request = ctx->request;
1120 nvmf_rpc_host_ctx_free(ctx);
1121
1122 if (response_sent) {
1123 return;
1124 }
1125
1126 w = spdk_jsonrpc_begin_result(request);
1127 if (w == NULL) {
1128 return;
1129 }
1130
1131 spdk_json_write_bool(w, true);
1132 spdk_jsonrpc_end_result(request, w);
1133 }
1134
1135 static void
1136 nvmf_rpc_host_paused(struct spdk_nvmf_subsystem *subsystem,
1137 void *cb_arg, int status)
1138 {
1139 struct nvmf_rpc_host_ctx *ctx = cb_arg;
1140 int rc = -1;
1141
1142 switch (ctx->op) {
1143 case NVMF_RPC_HOST_ADD:
1144 rc = spdk_nvmf_subsystem_add_host(subsystem, ctx->host);
1145 break;
1146 case NVMF_RPC_HOST_REMOVE:
1147 rc = spdk_nvmf_subsystem_remove_host(subsystem, ctx->host);
1148 break;
1149 case NVMF_RPC_HOST_ALLOW_ANY:
1150 rc = spdk_nvmf_subsystem_set_allow_any_host(subsystem, ctx->allow_any_host);
1151 break;
1152 }
1153
1154 if (rc != 0) {
1155 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1156 ctx->response_sent = true;
1157 }
1158
1159 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_host_resumed, ctx)) {
1160 if (!ctx->response_sent) {
1161 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1162 }
1163 nvmf_rpc_host_ctx_free(ctx);
1164 return;
1165 }
1166 }
1167
1168 static void
1169 nvmf_rpc_subsystem_add_host(struct spdk_jsonrpc_request *request,
1170 const struct spdk_json_val *params)
1171 {
1172 struct nvmf_rpc_host_ctx *ctx;
1173 struct spdk_nvmf_subsystem *subsystem;
1174
1175 ctx = calloc(1, sizeof(*ctx));
1176 if (!ctx) {
1177 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1178 return;
1179 }
1180
1181 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_host_decoder,
1182 SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder),
1183 ctx)) {
1184 SPDK_ERRLOG("spdk_json_decode_object failed\n");
1185 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1186 nvmf_rpc_host_ctx_free(ctx);
1187 return;
1188 }
1189
1190 ctx->request = request;
1191 ctx->op = NVMF_RPC_HOST_ADD;
1192 ctx->response_sent = false;
1193
1194 subsystem = spdk_nvmf_tgt_find_subsystem(g_spdk_nvmf_tgt, ctx->nqn);
1195 if (!subsystem) {
1196 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
1197 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1198 nvmf_rpc_host_ctx_free(ctx);
1199 return;
1200 }
1201
1202 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_host_paused, ctx)) {
1203 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1204 nvmf_rpc_host_ctx_free(ctx);
1205 return;
1206 }
1207 }
1208 SPDK_RPC_REGISTER("nvmf_subsystem_add_host", nvmf_rpc_subsystem_add_host, SPDK_RPC_RUNTIME)
1209
1210 static void
1211 nvmf_rpc_subsystem_remove_host(struct spdk_jsonrpc_request *request,
1212 const struct spdk_json_val *params)
1213 {
1214 struct nvmf_rpc_host_ctx *ctx;
1215 struct spdk_nvmf_subsystem *subsystem;
1216
1217 ctx = calloc(1, sizeof(*ctx));
1218 if (!ctx) {
1219 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1220 return;
1221 }
1222
1223 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_host_decoder,
1224 SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder),
1225 ctx)) {
1226 SPDK_ERRLOG("spdk_json_decode_object failed\n");
1227 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1228 nvmf_rpc_host_ctx_free(ctx);
1229 return;
1230 }
1231
1232 ctx->request = request;
1233 ctx->op = NVMF_RPC_HOST_REMOVE;
1234 ctx->response_sent = false;
1235
1236 subsystem = spdk_nvmf_tgt_find_subsystem(g_spdk_nvmf_tgt, ctx->nqn);
1237 if (!subsystem) {
1238 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
1239 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1240 nvmf_rpc_host_ctx_free(ctx);
1241 return;
1242 }
1243
1244 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_host_paused, ctx)) {
1245 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1246 nvmf_rpc_host_ctx_free(ctx);
1247 return;
1248 }
1249 }
1250 SPDK_RPC_REGISTER("nvmf_subsystem_remove_host", nvmf_rpc_subsystem_remove_host, SPDK_RPC_RUNTIME)
1251
1252
1253 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_any_host_decoder[] = {
1254 {"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string},
1255 {"allow_any_host", offsetof(struct nvmf_rpc_host_ctx, allow_any_host), spdk_json_decode_bool},
1256 };
1257
1258 static void
1259 nvmf_rpc_subsystem_allow_any_host(struct spdk_jsonrpc_request *request,
1260 const struct spdk_json_val *params)
1261 {
1262 struct nvmf_rpc_host_ctx *ctx;
1263 struct spdk_nvmf_subsystem *subsystem;
1264
1265 ctx = calloc(1, sizeof(*ctx));
1266 if (!ctx) {
1267 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1268 return;
1269 }
1270
1271 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_any_host_decoder,
1272 SPDK_COUNTOF(nvmf_rpc_subsystem_any_host_decoder),
1273 ctx)) {
1274 SPDK_ERRLOG("spdk_json_decode_object failed\n");
1275 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1276 nvmf_rpc_host_ctx_free(ctx);
1277 return;
1278 }
1279
1280 ctx->request = request;
1281 ctx->op = NVMF_RPC_HOST_ALLOW_ANY;
1282 ctx->response_sent = false;
1283
1284 subsystem = spdk_nvmf_tgt_find_subsystem(g_spdk_nvmf_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_host_ctx_free(ctx);
1289 return;
1290 }
1291
1292 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_host_paused, ctx)) {
1293 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1294 nvmf_rpc_host_ctx_free(ctx);
1295 return;
1296 }
1297 }
1298 SPDK_RPC_REGISTER("nvmf_subsystem_allow_any_host", nvmf_rpc_subsystem_allow_any_host,
1299 SPDK_RPC_RUNTIME)
1300
1301 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_tgt_opts_decoder[] = {
1302 {"max_queue_depth", offsetof(struct spdk_nvmf_tgt_opts, max_queue_depth), spdk_json_decode_uint16, true},
1303 {"max_qpairs_per_ctrlr", offsetof(struct spdk_nvmf_tgt_opts, max_qpairs_per_ctrlr), spdk_json_decode_uint16, true},
1304 {"in_capsule_data_size", offsetof(struct spdk_nvmf_tgt_opts, in_capsule_data_size), spdk_json_decode_uint32, true},
1305 {"max_io_size", offsetof(struct spdk_nvmf_tgt_opts, max_io_size), spdk_json_decode_uint32, true},
1306 {"max_subsystems", offsetof(struct spdk_nvmf_tgt_opts, max_subsystems), spdk_json_decode_uint32, true},
1307 {"io_unit_size", offsetof(struct spdk_nvmf_tgt_opts, io_unit_size), spdk_json_decode_uint32, true},
1308 };
1309
1310 static void
1311 nvmf_rpc_subsystem_set_tgt_opts(struct spdk_jsonrpc_request *request,
1312 const struct spdk_json_val *params)
1313 {
1314 struct spdk_nvmf_tgt_opts *opts;
1315 struct spdk_json_write_ctx *w;
1316
1317 if (g_spdk_nvmf_tgt_opts != NULL) {
1318 SPDK_ERRLOG("this RPC must not be called more than once.\n");
1319 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1320 "Must not call more than once");
1321 return;
1322 }
1323
1324 opts = calloc(1, sizeof(*opts));
1325 if (opts == NULL) {
1326 SPDK_ERRLOG("malloc() failed for target options\n");
1327 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1328 "Out of memory");
1329 return;
1330 }
1331
1332 spdk_nvmf_tgt_opts_init(opts);
1333
1334 if (params != NULL) {
1335 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_tgt_opts_decoder,
1336 SPDK_COUNTOF(nvmf_rpc_subsystem_tgt_opts_decoder), opts)) {
1337 free(opts);
1338 SPDK_ERRLOG("spdk_json_decode_object() failed\n");
1339 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1340 "Invalid parameters");
1341 return;
1342 }
1343 }
1344
1345 g_spdk_nvmf_tgt_opts = opts;
1346
1347 w = spdk_jsonrpc_begin_result(request);
1348 if (w == NULL) {
1349 return;
1350 }
1351
1352 spdk_json_write_bool(w, true);
1353 spdk_jsonrpc_end_result(request, w);
1354 }
1355 SPDK_RPC_REGISTER("set_nvmf_target_options", nvmf_rpc_subsystem_set_tgt_opts, SPDK_RPC_STARTUP)
1356
1357 static int decode_conn_sched(const struct spdk_json_val *val, void *out)
1358 {
1359 enum spdk_nvmf_connect_sched *sched = out;
1360
1361 if (spdk_json_strequal(val, "roundrobin") == true) {
1362 *sched = CONNECT_SCHED_ROUND_ROBIN;
1363 } else if (spdk_json_strequal(val, "hostip") == true) {
1364 *sched = CONNECT_SCHED_HOST_IP;
1365 } else {
1366 SPDK_ERRLOG("Invalid connection scheduling parameter\n");
1367 return -EINVAL;
1368 }
1369
1370 return 0;
1371 }
1372
1373 static const struct spdk_json_object_decoder nvmf_rpc_subsystem_tgt_conf_decoder[] = {
1374 {"acceptor_poll_rate", offsetof(struct spdk_nvmf_tgt_conf, acceptor_poll_rate), spdk_json_decode_uint32, true},
1375 {"conn_sched", offsetof(struct spdk_nvmf_tgt_conf, conn_sched), decode_conn_sched, true},
1376 };
1377
1378 static void
1379 nvmf_rpc_subsystem_set_tgt_conf(struct spdk_jsonrpc_request *request,
1380 const struct spdk_json_val *params)
1381 {
1382 struct spdk_nvmf_tgt_conf *conf;
1383 struct spdk_json_write_ctx *w;
1384
1385 if (g_spdk_nvmf_tgt_conf != NULL) {
1386 SPDK_ERRLOG("this RPC must not be called more than once.\n");
1387 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1388 "Must not call more than once");
1389 return;
1390 }
1391
1392 conf = calloc(1, sizeof(*conf));
1393 if (conf == NULL) {
1394 SPDK_ERRLOG("calloc() failed for target config\n");
1395 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1396 "Out of memory");
1397 return;
1398 }
1399
1400 conf->acceptor_poll_rate = ACCEPT_TIMEOUT_US;
1401 conf->conn_sched = DEFAULT_CONN_SCHED;
1402
1403 if (params != NULL) {
1404 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_tgt_conf_decoder,
1405 SPDK_COUNTOF(nvmf_rpc_subsystem_tgt_conf_decoder), conf)) {
1406 free(conf);
1407 SPDK_ERRLOG("spdk_json_decode_object() failed\n");
1408 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1409 "Invalid parameters");
1410 return;
1411 }
1412 }
1413
1414 g_spdk_nvmf_tgt_conf = conf;
1415
1416 w = spdk_jsonrpc_begin_result(request);
1417 if (w == NULL) {
1418 return;
1419 }
1420
1421 spdk_json_write_bool(w, true);
1422 spdk_jsonrpc_end_result(request, w);
1423 }
1424 SPDK_RPC_REGISTER("set_nvmf_target_config", nvmf_rpc_subsystem_set_tgt_conf, SPDK_RPC_STARTUP)
1425
1426 struct nvmf_rpc_create_transport_ctx {
1427 char *trtype;
1428 struct spdk_nvmf_transport_opts opts;
1429 struct spdk_jsonrpc_request *request;
1430 };
1431
1432 static const struct spdk_json_object_decoder nvmf_rpc_create_transport_decoder[] = {
1433 { "trtype", offsetof(struct nvmf_rpc_create_transport_ctx, trtype), spdk_json_decode_string},
1434 {
1435 "max_queue_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_queue_depth),
1436 spdk_json_decode_uint16, true
1437 },
1438 {
1439 "max_qpairs_per_ctrlr", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_qpairs_per_ctrlr),
1440 spdk_json_decode_uint16, true
1441 },
1442 {
1443 "in_capsule_data_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.in_capsule_data_size),
1444 spdk_json_decode_uint32, true
1445 },
1446 {
1447 "max_io_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_io_size),
1448 spdk_json_decode_uint32, true
1449 },
1450 {
1451 "io_unit_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.io_unit_size),
1452 spdk_json_decode_uint32, true
1453 },
1454 {
1455 "max_aq_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_aq_depth),
1456 spdk_json_decode_uint32, true
1457 },
1458 };
1459
1460 static void
1461 nvmf_rpc_create_transport_ctx_free(struct nvmf_rpc_create_transport_ctx *ctx)
1462 {
1463 free(ctx->trtype);
1464 free(ctx);
1465 }
1466
1467 static void
1468 nvmf_rpc_tgt_add_transport_done(void *cb_arg, int status)
1469 {
1470 struct nvmf_rpc_create_transport_ctx *ctx = cb_arg;
1471 struct spdk_jsonrpc_request *request;
1472 struct spdk_json_write_ctx *w;
1473
1474 request = ctx->request;
1475 nvmf_rpc_create_transport_ctx_free(ctx);
1476
1477 if (status) {
1478 SPDK_ERRLOG("Failed to add transport to tgt.(%d)\n", status);
1479 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1480 "Failed to add transport to tgt.(%d)\n",
1481 status);
1482 return;
1483 }
1484
1485 w = spdk_jsonrpc_begin_result(request);
1486 if (w == NULL) {
1487 return;
1488 }
1489
1490 spdk_json_write_bool(w, true);
1491 spdk_jsonrpc_end_result(request, w);
1492 }
1493
1494 static void
1495 nvmf_rpc_create_transport(struct spdk_jsonrpc_request *request,
1496 const struct spdk_json_val *params)
1497 {
1498 struct nvmf_rpc_create_transport_ctx *ctx;
1499 enum spdk_nvme_transport_type trtype;
1500 struct spdk_nvmf_transport *transport;
1501
1502 ctx = calloc(1, sizeof(*ctx));
1503 if (!ctx) {
1504 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1505 return;
1506 }
1507
1508 /* Decode parameters the first time to get the transport type */
1509 if (spdk_json_decode_object(params, nvmf_rpc_create_transport_decoder,
1510 SPDK_COUNTOF(nvmf_rpc_create_transport_decoder),
1511 ctx)) {
1512 SPDK_ERRLOG("spdk_json_decode_object failed\n");
1513 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1514 nvmf_rpc_create_transport_ctx_free(ctx);
1515 return;
1516 }
1517
1518 if (spdk_nvme_transport_id_parse_trtype(&trtype, ctx->trtype)) {
1519 SPDK_ERRLOG("Invalid transport type '%s'\n", ctx->trtype);
1520 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1521 "Invalid transport type '%s'\n", ctx->trtype);
1522 nvmf_rpc_create_transport_ctx_free(ctx);
1523 return;
1524 }
1525
1526 /* Initialize all the transport options (based on transport type) and decode the
1527 * parameters again to update any options passed in rpc create transport call.
1528 */
1529 spdk_nvmf_transport_opts_init(trtype, &ctx->opts);
1530 if (spdk_json_decode_object(params, nvmf_rpc_create_transport_decoder,
1531 SPDK_COUNTOF(nvmf_rpc_create_transport_decoder),
1532 ctx)) {
1533 SPDK_ERRLOG("spdk_json_decode_object failed\n");
1534 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1535 nvmf_rpc_create_transport_ctx_free(ctx);
1536 return;
1537 }
1538
1539 if (spdk_nvmf_tgt_get_transport(g_spdk_nvmf_tgt, trtype)) {
1540 SPDK_ERRLOG("Transport type '%s' already exists\n", ctx->trtype);
1541 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1542 "Transport type '%s' already exists\n", ctx->trtype);
1543 nvmf_rpc_create_transport_ctx_free(ctx);
1544 return;
1545 }
1546
1547 transport = spdk_nvmf_transport_create(trtype, &ctx->opts);
1548
1549 if (!transport) {
1550 SPDK_ERRLOG("Transport type '%s' create failed\n", ctx->trtype);
1551 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1552 "Transport type '%s' create failed\n", ctx->trtype);
1553 nvmf_rpc_create_transport_ctx_free(ctx);
1554 return;
1555 }
1556
1557 /* add transport to target */
1558 ctx->request = request;
1559 spdk_nvmf_tgt_add_transport(g_spdk_nvmf_tgt, transport, nvmf_rpc_tgt_add_transport_done, ctx);
1560 }
1561
1562 SPDK_RPC_REGISTER("nvmf_create_transport", nvmf_rpc_create_transport, SPDK_RPC_RUNTIME)