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