]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/lib/event/subsystems/nvmf/nvmf_rpc.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / lib / event / subsystems / nvmf / nvmf_rpc.c
CommitLineData
11fdf7f2
TL
1/*-
2 * BSD LICENSE
3 *
9f95a23c
TL
4 * Copyright (c) Intel Corporation. All rights reserved.
5 * Copyright (c) 2018 Mellanox Technologies LTD. All rights reserved.
11fdf7f2
TL
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
45static int
46json_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
75static int
76hex_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
93static int
94hex_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
111static int
112decode_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
137static int
138decode_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
153static int
154decode_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
169static int
170decode_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
184static void
185dump_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
9f95a23c 192 spdk_json_write_named_string(w, "nqn", spdk_nvmf_subsystem_get_nqn(subsystem));
11fdf7f2
TL
193 spdk_json_write_name(w, "subtype");
194 if (spdk_nvmf_subsystem_get_type(subsystem) == SPDK_NVMF_SUBTYPE_NVME) {
195 spdk_json_write_string(w, "NVMe");
196 } else {
197 spdk_json_write_string(w, "Discovery");
198 }
199
9f95a23c 200 spdk_json_write_named_array_begin(w, "listen_addresses");
11fdf7f2
TL
201
202 for (listener = spdk_nvmf_subsystem_get_first_listener(subsystem); listener != NULL;
203 listener = spdk_nvmf_subsystem_get_next_listener(subsystem, listener)) {
204 const struct spdk_nvme_transport_id *trid;
205 const char *trtype;
206 const char *adrfam;
207
208 trid = spdk_nvmf_listener_get_trid(listener);
209
210 spdk_json_write_object_begin(w);
211 trtype = spdk_nvme_transport_id_trtype_str(trid->trtype);
212 if (trtype == NULL) {
213 trtype = "unknown";
214 }
215 adrfam = spdk_nvme_transport_id_adrfam_str(trid->adrfam);
216 if (adrfam == NULL) {
217 adrfam = "unknown";
218 }
219 /* NOTE: "transport" is kept for compatibility; new code should use "trtype" */
9f95a23c
TL
220 spdk_json_write_named_string(w, "transport", trtype);
221 spdk_json_write_named_string(w, "trtype", trtype);
222 spdk_json_write_named_string(w, "adrfam", adrfam);
223 spdk_json_write_named_string(w, "traddr", trid->traddr);
224 spdk_json_write_named_string(w, "trsvcid", trid->trsvcid);
11fdf7f2
TL
225 spdk_json_write_object_end(w);
226 }
227 spdk_json_write_array_end(w);
228
9f95a23c
TL
229 spdk_json_write_named_bool(w, "allow_any_host",
230 spdk_nvmf_subsystem_get_allow_any_host(subsystem));
11fdf7f2 231
9f95a23c 232 spdk_json_write_named_array_begin(w, "hosts");
11fdf7f2
TL
233
234 for (host = spdk_nvmf_subsystem_get_first_host(subsystem); host != NULL;
235 host = spdk_nvmf_subsystem_get_next_host(subsystem, host)) {
236 spdk_json_write_object_begin(w);
9f95a23c 237 spdk_json_write_named_string(w, "nqn", spdk_nvmf_host_get_nqn(host));
11fdf7f2
TL
238 spdk_json_write_object_end(w);
239 }
240 spdk_json_write_array_end(w);
241
242 if (spdk_nvmf_subsystem_get_type(subsystem) == SPDK_NVMF_SUBTYPE_NVME) {
243 struct spdk_nvmf_ns *ns;
244 struct spdk_nvmf_ns_opts ns_opts;
245 uint32_t max_namespaces;
246
9f95a23c
TL
247 spdk_json_write_named_string(w, "serial_number", spdk_nvmf_subsystem_get_sn(subsystem));
248
249 spdk_json_write_named_string(w, "model_number", spdk_nvmf_subsystem_get_mn(subsystem));
11fdf7f2
TL
250
251 max_namespaces = spdk_nvmf_subsystem_get_max_namespaces(subsystem);
252 if (max_namespaces != 0) {
253 spdk_json_write_named_uint32(w, "max_namespaces", max_namespaces);
254 }
255
9f95a23c 256 spdk_json_write_named_array_begin(w, "namespaces");
11fdf7f2
TL
257 for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL;
258 ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) {
259 spdk_nvmf_ns_get_opts(ns, &ns_opts, sizeof(ns_opts));
260 spdk_json_write_object_begin(w);
9f95a23c
TL
261 spdk_json_write_named_int32(w, "nsid", spdk_nvmf_ns_get_id(ns));
262 spdk_json_write_named_string(w, "bdev_name",
263 spdk_bdev_get_name(spdk_nvmf_ns_get_bdev(ns)));
11fdf7f2 264 /* NOTE: "name" is kept for compatibility only - new code should use bdev_name. */
9f95a23c
TL
265 spdk_json_write_named_string(w, "name",
266 spdk_bdev_get_name(spdk_nvmf_ns_get_bdev(ns)));
11fdf7f2
TL
267
268 if (!spdk_mem_all_zero(ns_opts.nguid, sizeof(ns_opts.nguid))) {
269 spdk_json_write_name(w, "nguid");
270 json_write_hex_str(w, ns_opts.nguid, sizeof(ns_opts.nguid));
271 }
272
273 if (!spdk_mem_all_zero(ns_opts.eui64, sizeof(ns_opts.eui64))) {
274 spdk_json_write_name(w, "eui64");
275 json_write_hex_str(w, ns_opts.eui64, sizeof(ns_opts.eui64));
276 }
277
278 if (!spdk_mem_all_zero(&ns_opts.uuid, sizeof(ns_opts.uuid))) {
279 char uuid_str[SPDK_UUID_STRING_LEN];
280
281 spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &ns_opts.uuid);
9f95a23c 282 spdk_json_write_named_string(w, "uuid", uuid_str);
11fdf7f2
TL
283 }
284
285 spdk_json_write_object_end(w);
286 }
287 spdk_json_write_array_end(w);
288 }
289 spdk_json_write_object_end(w);
290}
291
292static void
293spdk_rpc_get_nvmf_subsystems(struct spdk_jsonrpc_request *request,
294 const struct spdk_json_val *params)
295{
296 struct spdk_json_write_ctx *w;
297 struct spdk_nvmf_subsystem *subsystem;
298
299 if (params != NULL) {
300 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
301 "get_nvmf_subsystems requires no parameters");
302 return;
303 }
304
305 w = spdk_jsonrpc_begin_result(request);
306 if (w == NULL) {
307 return;
308 }
309
310 spdk_json_write_array_begin(w);
311 subsystem = spdk_nvmf_subsystem_get_first(g_spdk_nvmf_tgt);
312 while (subsystem) {
313 dump_nvmf_subsystem(w, subsystem);
314 subsystem = spdk_nvmf_subsystem_get_next(subsystem);
315 }
316 spdk_json_write_array_end(w);
317 spdk_jsonrpc_end_result(request, w);
318}
319SPDK_RPC_REGISTER("get_nvmf_subsystems", spdk_rpc_get_nvmf_subsystems, SPDK_RPC_RUNTIME)
320
321struct rpc_subsystem_create {
322 char *nqn;
323 char *serial_number;
9f95a23c 324 char *model_number;
11fdf7f2
TL
325 uint32_t max_namespaces;
326 bool allow_any_host;
327};
328
329static const struct spdk_json_object_decoder rpc_subsystem_create_decoders[] = {
330 {"nqn", offsetof(struct rpc_subsystem_create, nqn), spdk_json_decode_string},
331 {"serial_number", offsetof(struct rpc_subsystem_create, serial_number), spdk_json_decode_string, true},
9f95a23c 332 {"model_number", offsetof(struct rpc_subsystem_create, model_number), spdk_json_decode_string, true},
11fdf7f2
TL
333 {"max_namespaces", offsetof(struct rpc_subsystem_create, max_namespaces), spdk_json_decode_uint32, true},
334 {"allow_any_host", offsetof(struct rpc_subsystem_create, allow_any_host), spdk_json_decode_bool, true},
335};
336
337static void
338spdk_rpc_nvmf_subsystem_started(struct spdk_nvmf_subsystem *subsystem,
339 void *cb_arg, int status)
340{
341 struct spdk_jsonrpc_request *request = cb_arg;
342 struct spdk_json_write_ctx *w;
343
344 w = spdk_jsonrpc_begin_result(request);
345 if (w == NULL) {
346 return;
347 }
348
349 spdk_json_write_bool(w, true);
350 spdk_jsonrpc_end_result(request, w);
351}
352
353static void
354spdk_rpc_nvmf_subsystem_create(struct spdk_jsonrpc_request *request,
355 const struct spdk_json_val *params)
356{
357 struct rpc_subsystem_create *req;
358 struct spdk_nvmf_subsystem *subsystem;
359
360 req = calloc(1, sizeof(*req));
361 if (!req) {
362 goto invalid;
363 }
364
365 if (spdk_json_decode_object(params, rpc_subsystem_create_decoders,
366 SPDK_COUNTOF(rpc_subsystem_create_decoders),
367 req)) {
368 SPDK_ERRLOG("spdk_json_decode_object failed\n");
369 goto invalid;
370 }
371
372 subsystem = spdk_nvmf_subsystem_create(g_spdk_nvmf_tgt, req->nqn, SPDK_NVMF_SUBTYPE_NVME,
373 req->max_namespaces);
374 if (!subsystem) {
375 goto invalid;
376 }
377
378 if (req->serial_number) {
379 if (spdk_nvmf_subsystem_set_sn(subsystem, req->serial_number)) {
380 SPDK_ERRLOG("Subsystem %s: invalid serial number '%s'\n", req->nqn, req->serial_number);
381 goto invalid;
382 }
383 }
384
9f95a23c
TL
385 if (req->model_number) {
386 if (spdk_nvmf_subsystem_set_mn(subsystem, req->model_number)) {
387 SPDK_ERRLOG("Subsystem %s: invalid model number '%s'\n", req->nqn, req->model_number);
388 goto invalid;
389 }
390 }
391
11fdf7f2
TL
392 spdk_nvmf_subsystem_set_allow_any_host(subsystem, req->allow_any_host);
393
394 free(req->nqn);
395 free(req->serial_number);
9f95a23c 396 free(req->model_number);
11fdf7f2
TL
397 free(req);
398
399 spdk_nvmf_subsystem_start(subsystem,
400 spdk_rpc_nvmf_subsystem_started,
401 request);
402
403 return;
404
405invalid:
406 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
407 if (req) {
408 free(req->nqn);
409 free(req->serial_number);
9f95a23c 410 free(req->model_number);
11fdf7f2
TL
411 }
412 free(req);
413}
414SPDK_RPC_REGISTER("nvmf_subsystem_create", spdk_rpc_nvmf_subsystem_create, SPDK_RPC_RUNTIME)
415
416struct rpc_delete_subsystem {
417 char *nqn;
418};
419
420static void
421free_rpc_delete_subsystem(struct rpc_delete_subsystem *r)
422{
423 free(r->nqn);
424}
425
426static void
427spdk_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
444static const struct spdk_json_object_decoder rpc_delete_subsystem_decoders[] = {
445 {"nqn", offsetof(struct rpc_delete_subsystem, nqn), spdk_json_decode_string},
446};
447
448static void
449spdk_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
480invalid:
481 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
482 free_rpc_delete_subsystem(&req);
483}
484SPDK_RPC_REGISTER("delete_nvmf_subsystem", spdk_rpc_delete_nvmf_subsystem, SPDK_RPC_RUNTIME)
485
486struct 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
496struct rpc_listen_addresses {
497 size_t num_listen_address;
498 struct rpc_listen_address addresses[RPC_MAX_LISTEN_ADDRESSES];
499};
500
501static 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
510static int
511decode_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
523static void
524free_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
532enum nvmf_rpc_listen_op {
533 NVMF_RPC_LISTEN_ADD,
534 NVMF_RPC_LISTEN_REMOVE,
535};
536
537struct 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
548static 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
553static void
554nvmf_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
561static void
562nvmf_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
587static void
588nvmf_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
613static void
614nvmf_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
644static int
645rpc_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
685static void
9f95a23c
TL
686spdk_rpc_nvmf_subsystem_add_listener(struct spdk_jsonrpc_request *request,
687 const struct spdk_json_val *params)
11fdf7f2
TL
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}
9f95a23c
TL
734SPDK_RPC_REGISTER("nvmf_subsystem_add_listener", spdk_rpc_nvmf_subsystem_add_listener,
735 SPDK_RPC_RUNTIME);
11fdf7f2
TL
736
737static void
9f95a23c
TL
738spdk_rpc_nvmf_subsystem_remove_listener(struct spdk_jsonrpc_request *request,
739 const struct spdk_json_val *params)
11fdf7f2
TL
740{
741 struct nvmf_rpc_listener_ctx *ctx;
742 struct spdk_nvmf_subsystem *subsystem;
743
744 ctx = calloc(1, sizeof(*ctx));
745 if (!ctx) {
746 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
747 return;
748 }
749
750 ctx->request = request;
751
752 if (spdk_json_decode_object(params, nvmf_rpc_listener_decoder,
753 SPDK_COUNTOF(nvmf_rpc_listener_decoder),
754 ctx)) {
755 SPDK_ERRLOG("spdk_json_decode_object failed\n");
756 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
757 nvmf_rpc_listener_ctx_free(ctx);
758 return;
759 }
760
761 subsystem = spdk_nvmf_tgt_find_subsystem(g_spdk_nvmf_tgt, ctx->nqn);
762 if (!subsystem) {
763 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
764 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
765 nvmf_rpc_listener_ctx_free(ctx);
766 return;
767 }
768
769 ctx->subsystem = subsystem;
770
771 if (rpc_listen_address_to_trid(&ctx->address, &ctx->trid)) {
772 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
773 "Invalid parameters");
774 nvmf_rpc_listener_ctx_free(ctx);
775 return;
776 }
777
778 ctx->op = NVMF_RPC_LISTEN_REMOVE;
779
780 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_listen_paused, ctx)) {
781 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
782 nvmf_rpc_listener_ctx_free(ctx);
783 return;
784 }
785
786}
9f95a23c 787SPDK_RPC_REGISTER("nvmf_subsystem_remove_listener", spdk_rpc_nvmf_subsystem_remove_listener,
11fdf7f2
TL
788 SPDK_RPC_RUNTIME);
789
790struct spdk_nvmf_ns_params {
791 char *bdev_name;
792 uint32_t nsid;
793 char nguid[16];
794 char eui64[8];
795 struct spdk_uuid uuid;
796};
797
798struct rpc_namespaces {
799 size_t num_ns;
800 struct spdk_nvmf_ns_params ns_params[RPC_MAX_NAMESPACES];
801};
802
803
804static const struct spdk_json_object_decoder rpc_ns_params_decoders[] = {
805 {"nsid", offsetof(struct spdk_nvmf_ns_params, nsid), spdk_json_decode_uint32, true},
806 {"bdev_name", offsetof(struct spdk_nvmf_ns_params, bdev_name), spdk_json_decode_string},
807 {"nguid", offsetof(struct spdk_nvmf_ns_params, nguid), decode_ns_nguid, true},
808 {"eui64", offsetof(struct spdk_nvmf_ns_params, eui64), decode_ns_eui64, true},
809 {"uuid", offsetof(struct spdk_nvmf_ns_params, uuid), decode_ns_uuid, true},
810};
811
812static int
813decode_rpc_ns_params(const struct spdk_json_val *val, void *out)
814{
815 struct spdk_nvmf_ns_params *ns_params = out;
816
817 return spdk_json_decode_object(val, rpc_ns_params_decoders,
818 SPDK_COUNTOF(rpc_ns_params_decoders),
819 ns_params);
820}
821
822struct nvmf_rpc_ns_ctx {
823 char *nqn;
824 struct spdk_nvmf_ns_params ns_params;
825
826 struct spdk_jsonrpc_request *request;
827 bool response_sent;
828};
829
830static const struct spdk_json_object_decoder nvmf_rpc_subsystem_ns_decoder[] = {
831 {"nqn", offsetof(struct nvmf_rpc_ns_ctx, nqn), spdk_json_decode_string},
832 {"namespace", offsetof(struct nvmf_rpc_ns_ctx, ns_params), decode_rpc_ns_params},
833};
834
835static void
836nvmf_rpc_ns_ctx_free(struct nvmf_rpc_ns_ctx *ctx)
837{
838 free(ctx->nqn);
839 free(ctx->ns_params.bdev_name);
840 free(ctx);
841}
842
843static void
844nvmf_rpc_ns_resumed(struct spdk_nvmf_subsystem *subsystem,
845 void *cb_arg, int status)
846{
847 struct nvmf_rpc_ns_ctx *ctx = cb_arg;
848 struct spdk_jsonrpc_request *request = ctx->request;
849 uint32_t nsid = ctx->ns_params.nsid;
850 bool response_sent = ctx->response_sent;
851 struct spdk_json_write_ctx *w;
852
853 nvmf_rpc_ns_ctx_free(ctx);
854
855 if (response_sent) {
856 return;
857 }
858
859 w = spdk_jsonrpc_begin_result(request);
860 if (w == NULL) {
861 return;
862 }
863
864 spdk_json_write_uint32(w, nsid);
865 spdk_jsonrpc_end_result(request, w);
866}
867
868static void
869nvmf_rpc_ns_paused(struct spdk_nvmf_subsystem *subsystem,
870 void *cb_arg, int status)
871{
872 struct nvmf_rpc_ns_ctx *ctx = cb_arg;
873 struct spdk_nvmf_ns_opts ns_opts;
874 struct spdk_bdev *bdev;
875
876 bdev = spdk_bdev_get_by_name(ctx->ns_params.bdev_name);
877 if (!bdev) {
878 SPDK_ERRLOG("No bdev with name %s\n", ctx->ns_params.bdev_name);
879 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
880 "Invalid parameters");
881 ctx->response_sent = true;
882 goto resume;
883 }
884
885 spdk_nvmf_ns_opts_get_defaults(&ns_opts, sizeof(ns_opts));
886 ns_opts.nsid = ctx->ns_params.nsid;
887
888 SPDK_STATIC_ASSERT(sizeof(ns_opts.nguid) == sizeof(ctx->ns_params.nguid), "size mismatch");
889 memcpy(ns_opts.nguid, ctx->ns_params.nguid, sizeof(ns_opts.nguid));
890
891 SPDK_STATIC_ASSERT(sizeof(ns_opts.eui64) == sizeof(ctx->ns_params.eui64), "size mismatch");
892 memcpy(ns_opts.eui64, ctx->ns_params.eui64, sizeof(ns_opts.eui64));
893
894 if (!spdk_mem_all_zero(&ctx->ns_params.uuid, sizeof(ctx->ns_params.uuid))) {
895 ns_opts.uuid = ctx->ns_params.uuid;
896 }
897
9f95a23c 898 ctx->ns_params.nsid = spdk_nvmf_subsystem_add_ns(subsystem, bdev, &ns_opts, sizeof(ns_opts), NULL);
11fdf7f2
TL
899 if (ctx->ns_params.nsid == 0) {
900 SPDK_ERRLOG("Unable to add namespace\n");
901 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
902 "Invalid parameters");
903 ctx->response_sent = true;
904 goto resume;
905 }
906
907resume:
908 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_ns_resumed, ctx)) {
909 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
910 nvmf_rpc_ns_ctx_free(ctx);
911 return;
912 }
913}
914
915static void
9f95a23c
TL
916spdk_rpc_nvmf_subsystem_add_ns(struct spdk_jsonrpc_request *request,
917 const struct spdk_json_val *params)
11fdf7f2
TL
918{
919 struct nvmf_rpc_ns_ctx *ctx;
920 struct spdk_nvmf_subsystem *subsystem;
921
922 ctx = calloc(1, sizeof(*ctx));
923 if (!ctx) {
924 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
925 return;
926 }
927
928 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_ns_decoder,
929 SPDK_COUNTOF(nvmf_rpc_subsystem_ns_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_ns_ctx_free(ctx);
934 return;
935 }
936
937 ctx->request = request;
938 ctx->response_sent = false;
939
940 subsystem = spdk_nvmf_tgt_find_subsystem(g_spdk_nvmf_tgt, ctx->nqn);
941 if (!subsystem) {
942 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
943 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
944 nvmf_rpc_ns_ctx_free(ctx);
945 return;
946 }
947
948 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_ns_paused, ctx)) {
949 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
950 nvmf_rpc_ns_ctx_free(ctx);
951 return;
952 }
953}
9f95a23c 954SPDK_RPC_REGISTER("nvmf_subsystem_add_ns", spdk_rpc_nvmf_subsystem_add_ns, SPDK_RPC_RUNTIME)
11fdf7f2
TL
955
956struct nvmf_rpc_remove_ns_ctx {
957 char *nqn;
958 uint32_t nsid;
959
960 struct spdk_jsonrpc_request *request;
961 bool response_sent;
962};
963
964static const struct spdk_json_object_decoder nvmf_rpc_subsystem_remove_ns_decoder[] = {
965 {"nqn", offsetof(struct nvmf_rpc_remove_ns_ctx, nqn), spdk_json_decode_string},
966 {"nsid", offsetof(struct nvmf_rpc_remove_ns_ctx, nsid), spdk_json_decode_uint32},
967};
968
969static void
970nvmf_rpc_remove_ns_ctx_free(struct nvmf_rpc_remove_ns_ctx *ctx)
971{
972 free(ctx->nqn);
973 free(ctx);
974}
975
976static void
977nvmf_rpc_remove_ns_resumed(struct spdk_nvmf_subsystem *subsystem,
978 void *cb_arg, int status)
979{
980 struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg;
981 struct spdk_jsonrpc_request *request = ctx->request;
982 bool response_sent = ctx->response_sent;
983 struct spdk_json_write_ctx *w;
984
985 nvmf_rpc_remove_ns_ctx_free(ctx);
986
987 if (response_sent) {
988 return;
989 }
990
991 w = spdk_jsonrpc_begin_result(request);
992 if (w == NULL) {
993 return;
994 }
995
996 spdk_json_write_bool(w, true);
997 spdk_jsonrpc_end_result(request, w);
998}
999
1000static void
1001nvmf_rpc_remove_ns_remove_done(struct spdk_nvmf_subsystem *subsystem, void *cb_arg, int status)
1002{
1003 struct nvmf_rpc_remove_ns_ctx *ctx;
1004
1005 ctx = cb_arg;
1006
1007 if (status != 0) {
1008 SPDK_ERRLOG("Unable to remove namespace ID %u\n", ctx->nsid);
1009 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1010 "Invalid parameters");
1011 ctx->response_sent = true;
1012 }
1013
1014 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_remove_ns_resumed, ctx)) {
1015 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1016 nvmf_rpc_remove_ns_ctx_free(ctx);
1017 return;
1018 }
1019}
1020
1021static void
1022nvmf_rpc_remove_ns_paused(struct spdk_nvmf_subsystem *subsystem,
1023 void *cb_arg, int status)
1024{
1025 struct nvmf_rpc_remove_ns_ctx *ctx = cb_arg;
1026 int ret;
1027
1028 ret = spdk_nvmf_subsystem_remove_ns(subsystem, ctx->nsid, nvmf_rpc_remove_ns_remove_done, ctx);
1029 if (ret < 0) {
1030 SPDK_ERRLOG("Unable to remove namespace ID %u\n", ctx->nsid);
1031 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1032 "Invalid parameters");
1033 ctx->response_sent = true;
1034 spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_remove_ns_resumed, ctx);
1035 }
1036}
1037
1038static void
9f95a23c
TL
1039spdk_rpc_nvmf_subsystem_remove_ns(struct spdk_jsonrpc_request *request,
1040 const struct spdk_json_val *params)
11fdf7f2
TL
1041{
1042 struct nvmf_rpc_remove_ns_ctx *ctx;
1043 struct spdk_nvmf_subsystem *subsystem;
1044
1045 ctx = calloc(1, sizeof(*ctx));
1046 if (!ctx) {
1047 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1048 return;
1049 }
1050
1051 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_remove_ns_decoder,
1052 SPDK_COUNTOF(nvmf_rpc_subsystem_remove_ns_decoder),
1053 ctx)) {
1054 SPDK_ERRLOG("spdk_json_decode_object failed\n");
1055 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1056 nvmf_rpc_remove_ns_ctx_free(ctx);
1057 return;
1058 }
1059
1060 ctx->request = request;
1061 ctx->response_sent = false;
1062
1063 subsystem = spdk_nvmf_tgt_find_subsystem(g_spdk_nvmf_tgt, ctx->nqn);
1064 if (!subsystem) {
1065 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
1066 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1067 nvmf_rpc_remove_ns_ctx_free(ctx);
1068 return;
1069 }
1070
1071 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_remove_ns_paused, ctx)) {
1072 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1073 nvmf_rpc_remove_ns_ctx_free(ctx);
1074 return;
1075 }
1076}
9f95a23c 1077SPDK_RPC_REGISTER("nvmf_subsystem_remove_ns", spdk_rpc_nvmf_subsystem_remove_ns, SPDK_RPC_RUNTIME)
11fdf7f2
TL
1078
1079enum nvmf_rpc_host_op {
1080 NVMF_RPC_HOST_ADD,
1081 NVMF_RPC_HOST_REMOVE,
1082 NVMF_RPC_HOST_ALLOW_ANY,
1083};
1084
1085struct nvmf_rpc_host_ctx {
1086 struct spdk_jsonrpc_request *request;
1087
1088 char *nqn;
1089 char *host;
1090
1091 enum nvmf_rpc_host_op op;
1092
1093 bool allow_any_host;
1094
1095 bool response_sent;
1096};
1097
1098static const struct spdk_json_object_decoder nvmf_rpc_subsystem_host_decoder[] = {
1099 {"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string},
1100 {"host", offsetof(struct nvmf_rpc_host_ctx, host), spdk_json_decode_string},
1101};
1102
1103static void
1104nvmf_rpc_host_ctx_free(struct nvmf_rpc_host_ctx *ctx)
1105{
1106 free(ctx->nqn);
1107 free(ctx->host);
1108 free(ctx);
1109}
1110
1111static void
1112nvmf_rpc_host_resumed(struct spdk_nvmf_subsystem *subsystem,
1113 void *cb_arg, int status)
1114{
1115 struct nvmf_rpc_host_ctx *ctx = cb_arg;
1116 struct spdk_jsonrpc_request *request;
1117 struct spdk_json_write_ctx *w;
1118 bool response_sent = ctx->response_sent;
1119
1120 request = ctx->request;
1121 nvmf_rpc_host_ctx_free(ctx);
1122
1123 if (response_sent) {
1124 return;
1125 }
1126
1127 w = spdk_jsonrpc_begin_result(request);
1128 if (w == NULL) {
1129 return;
1130 }
1131
1132 spdk_json_write_bool(w, true);
1133 spdk_jsonrpc_end_result(request, w);
1134}
1135
1136static void
1137nvmf_rpc_host_paused(struct spdk_nvmf_subsystem *subsystem,
1138 void *cb_arg, int status)
1139{
1140 struct nvmf_rpc_host_ctx *ctx = cb_arg;
1141 int rc = -1;
1142
1143 switch (ctx->op) {
1144 case NVMF_RPC_HOST_ADD:
1145 rc = spdk_nvmf_subsystem_add_host(subsystem, ctx->host);
1146 break;
1147 case NVMF_RPC_HOST_REMOVE:
1148 rc = spdk_nvmf_subsystem_remove_host(subsystem, ctx->host);
1149 break;
1150 case NVMF_RPC_HOST_ALLOW_ANY:
1151 rc = spdk_nvmf_subsystem_set_allow_any_host(subsystem, ctx->allow_any_host);
1152 break;
1153 }
1154
1155 if (rc != 0) {
1156 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1157 ctx->response_sent = true;
1158 }
1159
1160 if (spdk_nvmf_subsystem_resume(subsystem, nvmf_rpc_host_resumed, ctx)) {
1161 if (!ctx->response_sent) {
1162 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1163 }
1164 nvmf_rpc_host_ctx_free(ctx);
1165 return;
1166 }
1167}
1168
1169static void
9f95a23c
TL
1170spdk_rpc_nvmf_subsystem_add_host(struct spdk_jsonrpc_request *request,
1171 const struct spdk_json_val *params)
11fdf7f2
TL
1172{
1173 struct nvmf_rpc_host_ctx *ctx;
1174 struct spdk_nvmf_subsystem *subsystem;
1175
1176 ctx = calloc(1, sizeof(*ctx));
1177 if (!ctx) {
1178 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1179 return;
1180 }
1181
1182 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_host_decoder,
1183 SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder),
1184 ctx)) {
1185 SPDK_ERRLOG("spdk_json_decode_object failed\n");
1186 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1187 nvmf_rpc_host_ctx_free(ctx);
1188 return;
1189 }
1190
1191 ctx->request = request;
1192 ctx->op = NVMF_RPC_HOST_ADD;
1193 ctx->response_sent = false;
1194
1195 subsystem = spdk_nvmf_tgt_find_subsystem(g_spdk_nvmf_tgt, ctx->nqn);
1196 if (!subsystem) {
1197 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
1198 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1199 nvmf_rpc_host_ctx_free(ctx);
1200 return;
1201 }
1202
1203 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_host_paused, ctx)) {
1204 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1205 nvmf_rpc_host_ctx_free(ctx);
1206 return;
1207 }
1208}
9f95a23c 1209SPDK_RPC_REGISTER("nvmf_subsystem_add_host", spdk_rpc_nvmf_subsystem_add_host, SPDK_RPC_RUNTIME)
11fdf7f2
TL
1210
1211static void
9f95a23c
TL
1212spdk_rpc_nvmf_subsystem_remove_host(struct spdk_jsonrpc_request *request,
1213 const struct spdk_json_val *params)
11fdf7f2
TL
1214{
1215 struct nvmf_rpc_host_ctx *ctx;
1216 struct spdk_nvmf_subsystem *subsystem;
1217
1218 ctx = calloc(1, sizeof(*ctx));
1219 if (!ctx) {
1220 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1221 return;
1222 }
1223
1224 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_host_decoder,
1225 SPDK_COUNTOF(nvmf_rpc_subsystem_host_decoder),
1226 ctx)) {
1227 SPDK_ERRLOG("spdk_json_decode_object failed\n");
1228 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1229 nvmf_rpc_host_ctx_free(ctx);
1230 return;
1231 }
1232
1233 ctx->request = request;
1234 ctx->op = NVMF_RPC_HOST_REMOVE;
1235 ctx->response_sent = false;
1236
1237 subsystem = spdk_nvmf_tgt_find_subsystem(g_spdk_nvmf_tgt, ctx->nqn);
1238 if (!subsystem) {
1239 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
1240 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1241 nvmf_rpc_host_ctx_free(ctx);
1242 return;
1243 }
1244
1245 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_host_paused, ctx)) {
1246 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1247 nvmf_rpc_host_ctx_free(ctx);
1248 return;
1249 }
1250}
9f95a23c
TL
1251SPDK_RPC_REGISTER("nvmf_subsystem_remove_host", spdk_rpc_nvmf_subsystem_remove_host,
1252 SPDK_RPC_RUNTIME)
11fdf7f2
TL
1253
1254
1255static const struct spdk_json_object_decoder nvmf_rpc_subsystem_any_host_decoder[] = {
1256 {"nqn", offsetof(struct nvmf_rpc_host_ctx, nqn), spdk_json_decode_string},
1257 {"allow_any_host", offsetof(struct nvmf_rpc_host_ctx, allow_any_host), spdk_json_decode_bool},
1258};
1259
1260static void
9f95a23c
TL
1261spdk_rpc_nvmf_subsystem_allow_any_host(struct spdk_jsonrpc_request *request,
1262 const struct spdk_json_val *params)
11fdf7f2
TL
1263{
1264 struct nvmf_rpc_host_ctx *ctx;
1265 struct spdk_nvmf_subsystem *subsystem;
1266
1267 ctx = calloc(1, sizeof(*ctx));
1268 if (!ctx) {
1269 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1270 return;
1271 }
1272
1273 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_any_host_decoder,
1274 SPDK_COUNTOF(nvmf_rpc_subsystem_any_host_decoder),
1275 ctx)) {
1276 SPDK_ERRLOG("spdk_json_decode_object failed\n");
1277 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1278 nvmf_rpc_host_ctx_free(ctx);
1279 return;
1280 }
1281
1282 ctx->request = request;
1283 ctx->op = NVMF_RPC_HOST_ALLOW_ANY;
1284 ctx->response_sent = false;
1285
1286 subsystem = spdk_nvmf_tgt_find_subsystem(g_spdk_nvmf_tgt, ctx->nqn);
1287 if (!subsystem) {
1288 SPDK_ERRLOG("Unable to find subsystem with NQN %s\n", ctx->nqn);
1289 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1290 nvmf_rpc_host_ctx_free(ctx);
1291 return;
1292 }
1293
1294 if (spdk_nvmf_subsystem_pause(subsystem, nvmf_rpc_host_paused, ctx)) {
1295 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Internal error");
1296 nvmf_rpc_host_ctx_free(ctx);
1297 return;
1298 }
1299}
9f95a23c 1300SPDK_RPC_REGISTER("nvmf_subsystem_allow_any_host", spdk_rpc_nvmf_subsystem_allow_any_host,
11fdf7f2
TL
1301 SPDK_RPC_RUNTIME)
1302
1303static const struct spdk_json_object_decoder nvmf_rpc_subsystem_tgt_opts_decoder[] = {
9f95a23c 1304 {"max_subsystems", 0, spdk_json_decode_uint32, true}
11fdf7f2
TL
1305};
1306
1307static void
9f95a23c
TL
1308spdk_rpc_set_nvmf_target_max_subsystems(struct spdk_jsonrpc_request *request,
1309 const struct spdk_json_val *params)
11fdf7f2 1310{
11fdf7f2 1311 struct spdk_json_write_ctx *w;
9f95a23c 1312 uint32_t max_subsystems = 0;
11fdf7f2 1313
9f95a23c 1314 if (g_spdk_nvmf_tgt_max_subsystems != 0) {
11fdf7f2
TL
1315 SPDK_ERRLOG("this RPC must not be called more than once.\n");
1316 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1317 "Must not call more than once");
1318 return;
1319 }
1320
11fdf7f2
TL
1321 if (params != NULL) {
1322 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_tgt_opts_decoder,
9f95a23c 1323 SPDK_COUNTOF(nvmf_rpc_subsystem_tgt_opts_decoder), &max_subsystems)) {
11fdf7f2
TL
1324 SPDK_ERRLOG("spdk_json_decode_object() failed\n");
1325 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1326 "Invalid parameters");
1327 return;
1328 }
1329 }
1330
9f95a23c 1331 g_spdk_nvmf_tgt_max_subsystems = max_subsystems;
11fdf7f2
TL
1332
1333 w = spdk_jsonrpc_begin_result(request);
1334 if (w == NULL) {
1335 return;
1336 }
1337
1338 spdk_json_write_bool(w, true);
1339 spdk_jsonrpc_end_result(request, w);
1340}
9f95a23c
TL
1341SPDK_RPC_REGISTER("set_nvmf_target_max_subsystems", spdk_rpc_set_nvmf_target_max_subsystems,
1342 SPDK_RPC_STARTUP)
11fdf7f2
TL
1343
1344static int decode_conn_sched(const struct spdk_json_val *val, void *out)
1345{
1346 enum spdk_nvmf_connect_sched *sched = out;
1347
1348 if (spdk_json_strequal(val, "roundrobin") == true) {
1349 *sched = CONNECT_SCHED_ROUND_ROBIN;
1350 } else if (spdk_json_strequal(val, "hostip") == true) {
1351 *sched = CONNECT_SCHED_HOST_IP;
1352 } else {
1353 SPDK_ERRLOG("Invalid connection scheduling parameter\n");
1354 return -EINVAL;
1355 }
1356
1357 return 0;
1358}
1359
1360static const struct spdk_json_object_decoder nvmf_rpc_subsystem_tgt_conf_decoder[] = {
1361 {"acceptor_poll_rate", offsetof(struct spdk_nvmf_tgt_conf, acceptor_poll_rate), spdk_json_decode_uint32, true},
1362 {"conn_sched", offsetof(struct spdk_nvmf_tgt_conf, conn_sched), decode_conn_sched, true},
1363};
1364
1365static void
9f95a23c 1366spdk_rpc_set_nvmf_target_config(struct spdk_jsonrpc_request *request,
11fdf7f2
TL
1367 const struct spdk_json_val *params)
1368{
1369 struct spdk_nvmf_tgt_conf *conf;
1370 struct spdk_json_write_ctx *w;
1371
1372 if (g_spdk_nvmf_tgt_conf != NULL) {
1373 SPDK_ERRLOG("this RPC must not be called more than once.\n");
1374 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1375 "Must not call more than once");
1376 return;
1377 }
1378
1379 conf = calloc(1, sizeof(*conf));
1380 if (conf == NULL) {
1381 SPDK_ERRLOG("calloc() failed for target config\n");
1382 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1383 "Out of memory");
1384 return;
1385 }
1386
1387 conf->acceptor_poll_rate = ACCEPT_TIMEOUT_US;
1388 conf->conn_sched = DEFAULT_CONN_SCHED;
1389
1390 if (params != NULL) {
1391 if (spdk_json_decode_object(params, nvmf_rpc_subsystem_tgt_conf_decoder,
1392 SPDK_COUNTOF(nvmf_rpc_subsystem_tgt_conf_decoder), conf)) {
1393 free(conf);
1394 SPDK_ERRLOG("spdk_json_decode_object() failed\n");
1395 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1396 "Invalid parameters");
1397 return;
1398 }
1399 }
1400
1401 g_spdk_nvmf_tgt_conf = conf;
1402
1403 w = spdk_jsonrpc_begin_result(request);
1404 if (w == NULL) {
1405 return;
1406 }
1407
1408 spdk_json_write_bool(w, true);
1409 spdk_jsonrpc_end_result(request, w);
1410}
9f95a23c 1411SPDK_RPC_REGISTER("set_nvmf_target_config", spdk_rpc_set_nvmf_target_config, SPDK_RPC_STARTUP)
11fdf7f2
TL
1412
1413struct nvmf_rpc_create_transport_ctx {
1414 char *trtype;
1415 struct spdk_nvmf_transport_opts opts;
1416 struct spdk_jsonrpc_request *request;
1417};
1418
1419static const struct spdk_json_object_decoder nvmf_rpc_create_transport_decoder[] = {
1420 { "trtype", offsetof(struct nvmf_rpc_create_transport_ctx, trtype), spdk_json_decode_string},
1421 {
1422 "max_queue_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_queue_depth),
1423 spdk_json_decode_uint16, true
1424 },
1425 {
1426 "max_qpairs_per_ctrlr", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_qpairs_per_ctrlr),
1427 spdk_json_decode_uint16, true
1428 },
1429 {
1430 "in_capsule_data_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.in_capsule_data_size),
1431 spdk_json_decode_uint32, true
1432 },
1433 {
1434 "max_io_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_io_size),
1435 spdk_json_decode_uint32, true
1436 },
1437 {
1438 "io_unit_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.io_unit_size),
1439 spdk_json_decode_uint32, true
1440 },
1441 {
1442 "max_aq_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_aq_depth),
1443 spdk_json_decode_uint32, true
1444 },
9f95a23c
TL
1445 {
1446 "num_shared_buffers", offsetof(struct nvmf_rpc_create_transport_ctx, opts.num_shared_buffers),
1447 spdk_json_decode_uint32, true
1448 },
1449 {
1450 "buf_cache_size", offsetof(struct nvmf_rpc_create_transport_ctx, opts.buf_cache_size),
1451 spdk_json_decode_uint32, true
1452 },
1453 {
1454 "max_srq_depth", offsetof(struct nvmf_rpc_create_transport_ctx, opts.max_srq_depth),
1455 spdk_json_decode_uint32, true
1456 },
1457 {
1458 "no_srq", offsetof(struct nvmf_rpc_create_transport_ctx, opts.no_srq),
1459 spdk_json_decode_bool, true
1460 },
11fdf7f2
TL
1461};
1462
1463static void
1464nvmf_rpc_create_transport_ctx_free(struct nvmf_rpc_create_transport_ctx *ctx)
1465{
1466 free(ctx->trtype);
1467 free(ctx);
1468}
1469
1470static void
1471nvmf_rpc_tgt_add_transport_done(void *cb_arg, int status)
1472{
1473 struct nvmf_rpc_create_transport_ctx *ctx = cb_arg;
1474 struct spdk_jsonrpc_request *request;
1475 struct spdk_json_write_ctx *w;
1476
1477 request = ctx->request;
1478 nvmf_rpc_create_transport_ctx_free(ctx);
1479
1480 if (status) {
1481 SPDK_ERRLOG("Failed to add transport to tgt.(%d)\n", status);
1482 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1483 "Failed to add transport to tgt.(%d)\n",
1484 status);
1485 return;
1486 }
1487
1488 w = spdk_jsonrpc_begin_result(request);
1489 if (w == NULL) {
1490 return;
1491 }
1492
1493 spdk_json_write_bool(w, true);
1494 spdk_jsonrpc_end_result(request, w);
1495}
1496
1497static void
9f95a23c
TL
1498spdk_rpc_nvmf_create_transport(struct spdk_jsonrpc_request *request,
1499 const struct spdk_json_val *params)
11fdf7f2
TL
1500{
1501 struct nvmf_rpc_create_transport_ctx *ctx;
1502 enum spdk_nvme_transport_type trtype;
1503 struct spdk_nvmf_transport *transport;
1504
1505 ctx = calloc(1, sizeof(*ctx));
1506 if (!ctx) {
1507 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
1508 return;
1509 }
1510
1511 /* Decode parameters the first time to get the transport type */
1512 if (spdk_json_decode_object(params, nvmf_rpc_create_transport_decoder,
1513 SPDK_COUNTOF(nvmf_rpc_create_transport_decoder),
1514 ctx)) {
1515 SPDK_ERRLOG("spdk_json_decode_object failed\n");
1516 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1517 nvmf_rpc_create_transport_ctx_free(ctx);
1518 return;
1519 }
1520
1521 if (spdk_nvme_transport_id_parse_trtype(&trtype, ctx->trtype)) {
1522 SPDK_ERRLOG("Invalid transport type '%s'\n", ctx->trtype);
1523 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1524 "Invalid transport type '%s'\n", ctx->trtype);
1525 nvmf_rpc_create_transport_ctx_free(ctx);
1526 return;
1527 }
1528
1529 /* Initialize all the transport options (based on transport type) and decode the
1530 * parameters again to update any options passed in rpc create transport call.
1531 */
9f95a23c
TL
1532 if (!spdk_nvmf_transport_opts_init(trtype, &ctx->opts)) {
1533 /* This can happen if user specifies PCIE transport type which isn't valid for
1534 * NVMe-oF.
1535 */
1536 SPDK_ERRLOG("Invalid transport type '%s'\n", ctx->trtype);
1537 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1538 "Invalid transport type '%s'\n", ctx->trtype);
1539 nvmf_rpc_create_transport_ctx_free(ctx);
1540 return;
1541 }
1542
11fdf7f2
TL
1543 if (spdk_json_decode_object(params, nvmf_rpc_create_transport_decoder,
1544 SPDK_COUNTOF(nvmf_rpc_create_transport_decoder),
1545 ctx)) {
1546 SPDK_ERRLOG("spdk_json_decode_object failed\n");
1547 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
1548 nvmf_rpc_create_transport_ctx_free(ctx);
1549 return;
1550 }
1551
1552 if (spdk_nvmf_tgt_get_transport(g_spdk_nvmf_tgt, trtype)) {
1553 SPDK_ERRLOG("Transport type '%s' already exists\n", ctx->trtype);
1554 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1555 "Transport type '%s' already exists\n", ctx->trtype);
1556 nvmf_rpc_create_transport_ctx_free(ctx);
1557 return;
1558 }
1559
1560 transport = spdk_nvmf_transport_create(trtype, &ctx->opts);
1561
1562 if (!transport) {
1563 SPDK_ERRLOG("Transport type '%s' create failed\n", ctx->trtype);
1564 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1565 "Transport type '%s' create failed\n", ctx->trtype);
1566 nvmf_rpc_create_transport_ctx_free(ctx);
1567 return;
1568 }
1569
1570 /* add transport to target */
1571 ctx->request = request;
1572 spdk_nvmf_tgt_add_transport(g_spdk_nvmf_tgt, transport, nvmf_rpc_tgt_add_transport_done, ctx);
1573}
1574
9f95a23c
TL
1575SPDK_RPC_REGISTER("nvmf_create_transport", spdk_rpc_nvmf_create_transport, SPDK_RPC_RUNTIME)
1576
1577static void
1578dump_nvmf_transport(struct spdk_json_write_ctx *w, struct spdk_nvmf_transport *transport)
1579{
1580 const struct spdk_nvmf_transport_opts *opts = spdk_nvmf_get_transport_opts(transport);
1581 spdk_nvme_transport_type_t type = spdk_nvmf_get_transport_type(transport);
1582
1583 spdk_json_write_object_begin(w);
1584
1585 spdk_json_write_named_string(w, "trtype", spdk_nvme_transport_id_trtype_str(type));
1586 spdk_json_write_named_uint32(w, "max_queue_depth", opts->max_queue_depth);
1587 spdk_json_write_named_uint32(w, "max_qpairs_per_ctrlr", opts->max_qpairs_per_ctrlr);
1588 spdk_json_write_named_uint32(w, "in_capsule_data_size", opts->in_capsule_data_size);
1589 spdk_json_write_named_uint32(w, "max_io_size", opts->max_io_size);
1590 spdk_json_write_named_uint32(w, "io_unit_size", opts->io_unit_size);
1591 spdk_json_write_named_uint32(w, "max_aq_depth", opts->max_aq_depth);
1592 spdk_json_write_named_uint32(w, "num_shared_buffers", opts->num_shared_buffers);
1593 spdk_json_write_named_uint32(w, "buf_cache_size", opts->buf_cache_size);
1594 if (type == SPDK_NVME_TRANSPORT_RDMA) {
1595 spdk_json_write_named_uint32(w, "max_srq_depth", opts->max_srq_depth);
1596 spdk_json_write_named_bool(w, "no_srq", opts->no_srq);
1597 }
1598
1599 spdk_json_write_object_end(w);
1600}
1601
1602static void
1603spdk_rpc_get_nvmf_transports(struct spdk_jsonrpc_request *request,
1604 const struct spdk_json_val *params)
1605{
1606 struct spdk_json_write_ctx *w;
1607 struct spdk_nvmf_transport *transport;
1608
1609 if (params != NULL) {
1610 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1611 "get_nvmf_transports requires no parameters");
1612 return;
1613 }
1614
1615 w = spdk_jsonrpc_begin_result(request);
1616 if (w == NULL) {
1617 return;
1618 }
1619
1620 spdk_json_write_array_begin(w);
1621 transport = spdk_nvmf_transport_get_first(g_spdk_nvmf_tgt);
1622 while (transport) {
1623 dump_nvmf_transport(w, transport);
1624 transport = spdk_nvmf_transport_get_next(transport);
1625 }
1626 spdk_json_write_array_end(w);
1627 spdk_jsonrpc_end_result(request, w);
1628}
1629SPDK_RPC_REGISTER("get_nvmf_transports", spdk_rpc_get_nvmf_transports, SPDK_RPC_RUNTIME)