1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>. 5 * Copyright (c) Intel Corporation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * * Neither the name of Intel Corporation nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include "iscsi/iscsi.h" 36 #include "iscsi/conn.h" 37 #include "iscsi/tgt_node.h" 38 #include "iscsi/portal_grp.h" 39 #include "iscsi/init_grp.h" 40 41 #include "spdk/rpc.h" 42 #include "spdk/util.h" 43 #include "spdk/event.h" 44 45 #include "spdk_internal/log.h" 46 47 static void 48 dump_initiator_group(struct spdk_json_write_ctx *w, struct spdk_iscsi_init_grp *ig) 49 { 50 struct spdk_iscsi_initiator_name *iname; 51 struct spdk_iscsi_initiator_netmask *imask; 52 53 spdk_json_write_object_begin(w); 54 55 spdk_json_write_name(w, "initiators"); 56 spdk_json_write_array_begin(w); 57 TAILQ_FOREACH(iname, &ig->initiator_head, tailq) { 58 spdk_json_write_string(w, iname->name); 59 } 60 spdk_json_write_array_end(w); 61 62 spdk_json_write_name(w, "tag"); 63 spdk_json_write_int32(w, ig->tag); 64 65 spdk_json_write_name(w, "netmasks"); 66 spdk_json_write_array_begin(w); 67 TAILQ_FOREACH(imask, &ig->netmask_head, tailq) { 68 spdk_json_write_string(w, imask->mask); 69 } 70 spdk_json_write_array_end(w); 71 72 spdk_json_write_object_end(w); 73 } 74 75 static void 76 spdk_rpc_get_initiator_groups(struct spdk_jsonrpc_request *request, 77 const struct spdk_json_val *params) 78 { 79 struct spdk_json_write_ctx *w; 80 struct spdk_iscsi_init_grp *ig; 81 82 if (params != NULL) { 83 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 84 "get_initiator_groups requires no parameters"); 85 return; 86 } 87 88 w = spdk_jsonrpc_begin_result(request); 89 if (w == NULL) { 90 return; 91 } 92 93 spdk_json_write_array_begin(w); 94 95 TAILQ_FOREACH(ig, &g_spdk_iscsi.ig_head, tailq) { 96 dump_initiator_group(w, ig); 97 } 98 99 spdk_json_write_array_end(w); 100 101 spdk_jsonrpc_end_result(request, w); 102 } 103 SPDK_RPC_REGISTER("get_initiator_groups", spdk_rpc_get_initiator_groups) 104 105 struct rpc_initiator_list { 106 size_t num_initiators; 107 char *initiators[MAX_INITIATOR]; 108 }; 109 110 static int 111 decode_rpc_initiator_list(const struct spdk_json_val *val, void *out) 112 { 113 struct rpc_initiator_list *list = out; 114 115 return spdk_json_decode_array(val, spdk_json_decode_string, list->initiators, MAX_INITIATOR, 116 &list->num_initiators, sizeof(char *)); 117 } 118 119 static void 120 free_rpc_initiator_list(struct rpc_initiator_list *list) 121 { 122 size_t i; 123 124 for (i = 0; i < list->num_initiators; i++) { 125 free(list->initiators[i]); 126 } 127 } 128 129 struct rpc_netmask_list { 130 size_t num_netmasks; 131 char *netmasks[MAX_NETMASK]; 132 }; 133 134 static int 135 decode_rpc_netmask_list(const struct spdk_json_val *val, void *out) 136 { 137 struct rpc_netmask_list *list = out; 138 139 return spdk_json_decode_array(val, spdk_json_decode_string, list->netmasks, MAX_NETMASK, 140 &list->num_netmasks, sizeof(char *)); 141 } 142 143 static void 144 free_rpc_netmask_list(struct rpc_netmask_list *list) 145 { 146 size_t i; 147 148 for (i = 0; i < list->num_netmasks; i++) { 149 free(list->netmasks[i]); 150 } 151 } 152 153 struct rpc_initiator_group { 154 int32_t tag; 155 struct rpc_initiator_list initiator_list; 156 struct rpc_netmask_list netmask_list; 157 }; 158 159 static void 160 free_rpc_initiator_group(struct rpc_initiator_group *ig) 161 { 162 free_rpc_initiator_list(&ig->initiator_list); 163 free_rpc_netmask_list(&ig->netmask_list); 164 } 165 166 static const struct spdk_json_object_decoder rpc_initiator_group_decoders[] = { 167 {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32}, 168 {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list}, 169 {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list}, 170 }; 171 172 static void 173 spdk_rpc_add_initiator_group(struct spdk_jsonrpc_request *request, 174 const struct spdk_json_val *params) 175 { 176 struct rpc_initiator_group req = {}; 177 struct spdk_json_write_ctx *w; 178 179 if (spdk_json_decode_object(params, rpc_initiator_group_decoders, 180 SPDK_COUNTOF(rpc_initiator_group_decoders), &req)) { 181 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 182 goto invalid; 183 } 184 185 if (req.initiator_list.num_initiators == 0 || 186 req.netmask_list.num_netmasks == 0) { 187 goto invalid; 188 } 189 190 if (spdk_iscsi_init_grp_create_from_initiator_list(req.tag, 191 req.initiator_list.num_initiators, 192 req.initiator_list.initiators, 193 req.netmask_list.num_netmasks, 194 req.netmask_list.netmasks)) { 195 SPDK_ERRLOG("create_from_initiator_list failed\n"); 196 goto invalid; 197 } 198 199 free_rpc_initiator_group(&req); 200 201 w = spdk_jsonrpc_begin_result(request); 202 if (w == NULL) { 203 return; 204 } 205 206 spdk_json_write_bool(w, true); 207 spdk_jsonrpc_end_result(request, w); 208 return; 209 210 invalid: 211 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 212 free_rpc_initiator_group(&req); 213 } 214 SPDK_RPC_REGISTER("add_initiator_group", spdk_rpc_add_initiator_group) 215 216 static const struct spdk_json_object_decoder rpc_add_or_delete_initiators_decoders[] = { 217 {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32}, 218 {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list, true}, 219 {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list, true}, 220 }; 221 222 static void 223 spdk_rpc_add_initiators_to_initiator_group(struct spdk_jsonrpc_request *request, 224 const struct spdk_json_val *params) 225 { 226 struct rpc_initiator_group req = {}; 227 struct spdk_json_write_ctx *w; 228 229 if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders, 230 SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) { 231 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 232 goto invalid; 233 } 234 235 if (spdk_iscsi_init_grp_add_initiators_from_initiator_list(req.tag, 236 req.initiator_list.num_initiators, 237 req.initiator_list.initiators, 238 req.netmask_list.num_netmasks, 239 req.netmask_list.netmasks)) { 240 SPDK_ERRLOG("add_initiators_from_initiator_list failed\n"); 241 goto invalid; 242 } 243 244 free_rpc_initiator_group(&req); 245 246 w = spdk_jsonrpc_begin_result(request); 247 if (w == NULL) { 248 return; 249 } 250 251 spdk_json_write_bool(w, true); 252 spdk_jsonrpc_end_result(request, w); 253 return; 254 255 invalid: 256 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 257 free_rpc_initiator_group(&req); 258 } 259 SPDK_RPC_REGISTER("add_initiators_to_initiator_group", spdk_rpc_add_initiators_to_initiator_group) 260 261 static void 262 spdk_rpc_delete_initiators_from_initiator_group(struct spdk_jsonrpc_request *request, 263 const struct spdk_json_val *params) 264 { 265 struct rpc_initiator_group req = {}; 266 struct spdk_json_write_ctx *w; 267 268 if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders, 269 SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) { 270 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 271 goto invalid; 272 } 273 274 if (spdk_iscsi_init_grp_delete_initiators_from_initiator_list(req.tag, 275 req.initiator_list.num_initiators, 276 req.initiator_list.initiators, 277 req.netmask_list.num_netmasks, 278 req.netmask_list.netmasks)) { 279 SPDK_ERRLOG("delete_initiators_from_initiator_list failed\n"); 280 goto invalid; 281 } 282 283 free_rpc_initiator_group(&req); 284 285 w = spdk_jsonrpc_begin_result(request); 286 if (w == NULL) { 287 return; 288 } 289 290 spdk_json_write_bool(w, true); 291 spdk_jsonrpc_end_result(request, w); 292 return; 293 294 invalid: 295 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 296 free_rpc_initiator_group(&req); 297 } 298 SPDK_RPC_REGISTER("delete_initiators_from_initiator_group", 299 spdk_rpc_delete_initiators_from_initiator_group) 300 301 struct rpc_delete_initiator_group { 302 int32_t tag; 303 }; 304 305 static const struct spdk_json_object_decoder rpc_delete_initiator_group_decoders[] = { 306 {"tag", offsetof(struct rpc_delete_initiator_group, tag), spdk_json_decode_int32}, 307 }; 308 309 static void 310 spdk_rpc_delete_initiator_group(struct spdk_jsonrpc_request *request, 311 const struct spdk_json_val *params) 312 { 313 struct rpc_delete_initiator_group req = {}; 314 struct spdk_json_write_ctx *w; 315 struct spdk_iscsi_init_grp *ig; 316 317 if (spdk_json_decode_object(params, rpc_delete_initiator_group_decoders, 318 SPDK_COUNTOF(rpc_delete_initiator_group_decoders), 319 &req)) { 320 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 321 goto invalid; 322 } 323 324 ig = spdk_iscsi_init_grp_unregister(req.tag); 325 if (!ig) { 326 goto invalid; 327 } 328 spdk_iscsi_tgt_node_delete_map(NULL, ig); 329 spdk_iscsi_init_grp_destroy(ig); 330 331 w = spdk_jsonrpc_begin_result(request); 332 if (w == NULL) { 333 return; 334 } 335 336 spdk_json_write_bool(w, true); 337 spdk_jsonrpc_end_result(request, w); 338 return; 339 340 invalid: 341 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 342 } 343 SPDK_RPC_REGISTER("delete_initiator_group", spdk_rpc_delete_initiator_group) 344 345 static void 346 dump_target_node(struct spdk_json_write_ctx *w, struct spdk_iscsi_tgt_node *tgtnode) 347 { 348 struct spdk_iscsi_pg_map *pg_map; 349 struct spdk_iscsi_ig_map *ig_map; 350 int i; 351 352 spdk_json_write_object_begin(w); 353 354 spdk_json_write_name(w, "name"); 355 spdk_json_write_string(w, tgtnode->name); 356 357 if (tgtnode->alias) { 358 spdk_json_write_name(w, "alias_name"); 359 spdk_json_write_string(w, tgtnode->alias); 360 } 361 362 spdk_json_write_name(w, "pg_ig_maps"); 363 spdk_json_write_array_begin(w); 364 TAILQ_FOREACH(pg_map, &tgtnode->pg_map_head, tailq) { 365 TAILQ_FOREACH(ig_map, &pg_map->ig_map_head, tailq) { 366 spdk_json_write_object_begin(w); 367 spdk_json_write_name(w, "pg_tag"); 368 spdk_json_write_int32(w, pg_map->pg->tag); 369 spdk_json_write_name(w, "ig_tag"); 370 spdk_json_write_int32(w, ig_map->ig->tag); 371 spdk_json_write_object_end(w); 372 } 373 } 374 spdk_json_write_array_end(w); 375 376 spdk_json_write_name(w, "luns"); 377 spdk_json_write_array_begin(w); 378 for (i = 0; i < SPDK_SCSI_DEV_MAX_LUN; i++) { 379 struct spdk_scsi_lun *lun = spdk_scsi_dev_get_lun(tgtnode->dev, i); 380 381 if (lun) { 382 spdk_json_write_object_begin(w); 383 spdk_json_write_name(w, "bdev_name"); 384 spdk_json_write_string(w, spdk_scsi_lun_get_bdev_name(lun)); 385 spdk_json_write_name(w, "id"); 386 spdk_json_write_int32(w, spdk_scsi_lun_get_id(lun)); 387 spdk_json_write_object_end(w); 388 } 389 } 390 spdk_json_write_array_end(w); 391 392 spdk_json_write_name(w, "queue_depth"); 393 spdk_json_write_int32(w, tgtnode->queue_depth); 394 395 spdk_json_write_name(w, "disable_chap"); 396 spdk_json_write_bool(w, tgtnode->disable_chap); 397 398 spdk_json_write_name(w, "require_chap"); 399 spdk_json_write_bool(w, tgtnode->require_chap); 400 401 spdk_json_write_name(w, "mutual_chap"); 402 spdk_json_write_bool(w, tgtnode->mutual_chap); 403 404 spdk_json_write_name(w, "chap_group"); 405 spdk_json_write_int32(w, tgtnode->chap_group); 406 407 spdk_json_write_name(w, "header_digest"); 408 spdk_json_write_bool(w, tgtnode->header_digest); 409 410 spdk_json_write_name(w, "data_digest"); 411 spdk_json_write_bool(w, tgtnode->data_digest); 412 413 spdk_json_write_object_end(w); 414 } 415 416 static void 417 spdk_rpc_get_target_nodes(struct spdk_jsonrpc_request *request, 418 const struct spdk_json_val *params) 419 { 420 struct spdk_json_write_ctx *w; 421 struct spdk_iscsi_tgt_node *tgtnode; 422 423 if (params != NULL) { 424 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 425 "get_target_nodes requires no parameters"); 426 return; 427 } 428 429 w = spdk_jsonrpc_begin_result(request); 430 if (w == NULL) { 431 return; 432 } 433 434 spdk_json_write_array_begin(w); 435 436 TAILQ_FOREACH(tgtnode, &g_spdk_iscsi.target_head, tailq) { 437 dump_target_node(w, tgtnode); 438 } 439 440 spdk_json_write_array_end(w); 441 442 spdk_jsonrpc_end_result(request, w); 443 } 444 SPDK_RPC_REGISTER("get_target_nodes", spdk_rpc_get_target_nodes) 445 446 struct rpc_pg_ig_map { 447 int32_t pg_tag; 448 int32_t ig_tag; 449 }; 450 451 static const struct spdk_json_object_decoder rpc_pg_ig_map_decoders[] = { 452 {"pg_tag", offsetof(struct rpc_pg_ig_map, pg_tag), spdk_json_decode_int32}, 453 {"ig_tag", offsetof(struct rpc_pg_ig_map, ig_tag), spdk_json_decode_int32}, 454 }; 455 456 static int 457 decode_rpc_pg_ig_map(const struct spdk_json_val *val, void *out) 458 { 459 struct rpc_pg_ig_map *pg_ig_map = out; 460 461 return spdk_json_decode_object(val, rpc_pg_ig_map_decoders, 462 SPDK_COUNTOF(rpc_pg_ig_map_decoders), 463 pg_ig_map); 464 } 465 466 struct rpc_pg_ig_maps { 467 size_t num_maps; 468 struct rpc_pg_ig_map maps[MAX_TARGET_MAP]; 469 }; 470 471 static int 472 decode_rpc_pg_ig_maps(const struct spdk_json_val *val, void *out) 473 { 474 struct rpc_pg_ig_maps *pg_ig_maps = out; 475 476 return spdk_json_decode_array(val, decode_rpc_pg_ig_map, pg_ig_maps->maps, 477 MAX_TARGET_MAP, &pg_ig_maps->num_maps, 478 sizeof(struct rpc_pg_ig_map)); 479 } 480 481 #define RPC_CONSTRUCT_TARGET_NODE_MAX_LUN 64 482 483 struct rpc_lun { 484 char *bdev_name; 485 int32_t lun_id; 486 }; 487 488 static const struct spdk_json_object_decoder rpc_lun_decoders[] = { 489 {"bdev_name", offsetof(struct rpc_lun, bdev_name), spdk_json_decode_string}, 490 {"lun_id", offsetof(struct rpc_lun, lun_id), spdk_json_decode_int32}, 491 }; 492 493 static int 494 decode_rpc_lun(const struct spdk_json_val *val, void *out) 495 { 496 struct rpc_lun *lun = out; 497 498 return spdk_json_decode_object(val, rpc_lun_decoders, 499 SPDK_COUNTOF(rpc_lun_decoders), lun); 500 } 501 502 struct rpc_luns { 503 size_t num_luns; 504 struct rpc_lun luns[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN]; 505 }; 506 507 static int 508 decode_rpc_luns(const struct spdk_json_val *val, void *out) 509 { 510 struct rpc_luns *luns = out; 511 512 return spdk_json_decode_array(val, decode_rpc_lun, luns->luns, 513 RPC_CONSTRUCT_TARGET_NODE_MAX_LUN, 514 &luns->num_luns, sizeof(struct rpc_lun)); 515 } 516 517 static void 518 free_rpc_luns(struct rpc_luns *p) 519 { 520 size_t i; 521 522 for (i = 0; i < p->num_luns; i++) { 523 free(p->luns[i].bdev_name); 524 } 525 } 526 527 struct rpc_target_node { 528 char *name; 529 char *alias_name; 530 531 struct rpc_pg_ig_maps pg_ig_maps; 532 struct rpc_luns luns; 533 534 int32_t queue_depth; 535 bool disable_chap; 536 bool require_chap; 537 bool mutual_chap; 538 int32_t chap_group; 539 540 bool header_digest; 541 bool data_digest; 542 }; 543 544 static void 545 free_rpc_target_node(struct rpc_target_node *req) 546 { 547 free(req->name); 548 free(req->alias_name); 549 free_rpc_luns(&req->luns); 550 } 551 552 static const struct spdk_json_object_decoder rpc_target_node_decoders[] = { 553 {"name", offsetof(struct rpc_target_node, name), spdk_json_decode_string}, 554 {"alias_name", offsetof(struct rpc_target_node, alias_name), spdk_json_decode_string}, 555 {"pg_ig_maps", offsetof(struct rpc_target_node, pg_ig_maps), decode_rpc_pg_ig_maps}, 556 {"luns", offsetof(struct rpc_target_node, luns), decode_rpc_luns}, 557 {"queue_depth", offsetof(struct rpc_target_node, queue_depth), spdk_json_decode_int32}, 558 {"disable_chap", offsetof(struct rpc_target_node, disable_chap), spdk_json_decode_bool, true}, 559 {"require_chap", offsetof(struct rpc_target_node, require_chap), spdk_json_decode_bool, true}, 560 {"mutual_chap", offsetof(struct rpc_target_node, mutual_chap), spdk_json_decode_bool, true}, 561 {"chap_group", offsetof(struct rpc_target_node, chap_group), spdk_json_decode_int32, true}, 562 {"header_digest", offsetof(struct rpc_target_node, header_digest), spdk_json_decode_bool, true}, 563 {"data_digest", offsetof(struct rpc_target_node, data_digest), spdk_json_decode_bool, true}, 564 }; 565 566 static void 567 spdk_rpc_construct_target_node(struct spdk_jsonrpc_request *request, 568 const struct spdk_json_val *params) 569 { 570 struct rpc_target_node req = {}; 571 struct spdk_json_write_ctx *w; 572 struct spdk_iscsi_tgt_node *target; 573 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 574 char *bdev_names[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN] = {0}; 575 int32_t lun_ids[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN] = {0}; 576 size_t i; 577 578 if (spdk_json_decode_object(params, rpc_target_node_decoders, 579 SPDK_COUNTOF(rpc_target_node_decoders), 580 &req)) { 581 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 582 goto invalid; 583 } 584 585 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 586 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 587 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 588 } 589 590 for (i = 0; i < req.luns.num_luns; i++) { 591 bdev_names[i] = req.luns.luns[i].bdev_name; 592 lun_ids[i] = req.luns.luns[i].lun_id; 593 } 594 595 /* 596 * Use default parameters in a few places: 597 * index = -1 : automatically pick an index for the new target node 598 * alias = NULL 599 */ 600 target = spdk_iscsi_tgt_node_construct(-1, req.name, req.alias_name, 601 pg_tags, 602 ig_tags, 603 req.pg_ig_maps.num_maps, 604 (const char **)bdev_names, 605 lun_ids, 606 req.luns.num_luns, 607 req.queue_depth, 608 req.disable_chap, 609 req.require_chap, 610 req.mutual_chap, 611 req.chap_group, 612 req.header_digest, 613 req.data_digest); 614 615 if (target == NULL) { 616 goto invalid; 617 } 618 619 free_rpc_target_node(&req); 620 621 w = spdk_jsonrpc_begin_result(request); 622 if (w == NULL) { 623 return; 624 } 625 626 spdk_json_write_bool(w, true); 627 spdk_jsonrpc_end_result(request, w); 628 return; 629 630 invalid: 631 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 632 free_rpc_target_node(&req); 633 } 634 SPDK_RPC_REGISTER("construct_target_node", spdk_rpc_construct_target_node) 635 636 struct rpc_tgt_node_pg_ig_maps { 637 char *name; 638 struct rpc_pg_ig_maps pg_ig_maps; 639 }; 640 641 static const struct spdk_json_object_decoder rpc_tgt_node_pg_ig_maps_decoders[] = { 642 {"name", offsetof(struct rpc_tgt_node_pg_ig_maps, name), spdk_json_decode_string}, 643 {"pg_ig_maps", offsetof(struct rpc_tgt_node_pg_ig_maps, pg_ig_maps), decode_rpc_pg_ig_maps}, 644 }; 645 646 static void 647 spdk_rpc_add_pg_ig_maps(struct spdk_jsonrpc_request *request, 648 const struct spdk_json_val *params) 649 { 650 struct rpc_tgt_node_pg_ig_maps req = {}; 651 struct spdk_json_write_ctx *w; 652 struct spdk_iscsi_tgt_node *target; 653 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 654 size_t i; 655 int rc; 656 657 if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders, 658 SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders), 659 &req)) { 660 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 661 goto invalid; 662 } 663 664 target = spdk_iscsi_find_tgt_node(req.name); 665 if (target == NULL) { 666 SPDK_ERRLOG("target is not found\n"); 667 goto invalid; 668 } 669 670 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 671 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 672 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 673 } 674 675 rc = spdk_iscsi_tgt_node_add_pg_ig_maps(target, pg_tags, ig_tags, 676 req.pg_ig_maps.num_maps); 677 if (rc < 0) { 678 SPDK_ERRLOG("add pg-ig maps failed\n"); 679 goto invalid; 680 } 681 682 free(req.name); 683 684 w = spdk_jsonrpc_begin_result(request); 685 if (w != NULL) { 686 spdk_json_write_bool(w, true); 687 spdk_jsonrpc_end_result(request, w); 688 } 689 return; 690 691 invalid: 692 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 693 "Invalid parameters"); 694 free(req.name); 695 } 696 SPDK_RPC_REGISTER("add_pg_ig_maps", spdk_rpc_add_pg_ig_maps) 697 698 static void 699 spdk_rpc_delete_pg_ig_maps(struct spdk_jsonrpc_request *request, 700 const struct spdk_json_val *params) 701 { 702 struct rpc_tgt_node_pg_ig_maps req = {}; 703 struct spdk_json_write_ctx *w; 704 struct spdk_iscsi_tgt_node *target; 705 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 706 size_t i; 707 int rc; 708 709 if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders, 710 SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders), 711 &req)) { 712 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 713 goto invalid; 714 } 715 716 target = spdk_iscsi_find_tgt_node(req.name); 717 if (target == NULL) { 718 SPDK_ERRLOG("target is not found\n"); 719 goto invalid; 720 } 721 722 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 723 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 724 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 725 } 726 727 rc = spdk_iscsi_tgt_node_delete_pg_ig_maps(target, pg_tags, ig_tags, 728 req.pg_ig_maps.num_maps); 729 if (rc < 0) { 730 SPDK_ERRLOG("remove pg-ig maps failed\n"); 731 goto invalid; 732 } 733 734 free(req.name); 735 736 w = spdk_jsonrpc_begin_result(request); 737 if (w != NULL) { 738 spdk_json_write_bool(w, true); 739 spdk_jsonrpc_end_result(request, w); 740 } 741 return; 742 743 invalid: 744 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 745 "Invalid parameters"); 746 free(req.name); 747 } 748 SPDK_RPC_REGISTER("delete_pg_ig_maps", spdk_rpc_delete_pg_ig_maps) 749 750 struct rpc_delete_target_node { 751 char *name; 752 }; 753 754 static void 755 free_rpc_delete_target_node(struct rpc_delete_target_node *r) 756 { 757 free(r->name); 758 } 759 760 static const struct spdk_json_object_decoder rpc_delete_target_node_decoders[] = { 761 {"name", offsetof(struct rpc_delete_target_node, name), spdk_json_decode_string}, 762 }; 763 764 static void 765 spdk_rpc_delete_target_node(struct spdk_jsonrpc_request *request, 766 const struct spdk_json_val *params) 767 { 768 struct rpc_delete_target_node req = {}; 769 struct spdk_json_write_ctx *w; 770 771 if (spdk_json_decode_object(params, rpc_delete_target_node_decoders, 772 SPDK_COUNTOF(rpc_delete_target_node_decoders), 773 &req)) { 774 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 775 goto invalid; 776 } 777 778 if (req.name == NULL) { 779 SPDK_ERRLOG("missing name param\n"); 780 goto invalid; 781 } 782 783 if (spdk_iscsi_shutdown_tgt_node_by_name(req.name)) { 784 SPDK_ERRLOG("shutdown_tgt_node_by_name failed\n"); 785 goto invalid; 786 } 787 788 free_rpc_delete_target_node(&req); 789 790 w = spdk_jsonrpc_begin_result(request); 791 if (w == NULL) { 792 return; 793 } 794 795 spdk_json_write_bool(w, true); 796 spdk_jsonrpc_end_result(request, w); 797 return; 798 799 invalid: 800 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 801 free_rpc_delete_target_node(&req); 802 } 803 SPDK_RPC_REGISTER("delete_target_node", spdk_rpc_delete_target_node) 804 805 static void 806 dump_portal_group(struct spdk_json_write_ctx *w, struct spdk_iscsi_portal_grp *pg) 807 { 808 struct spdk_iscsi_portal *portal; 809 810 spdk_json_write_object_begin(w); 811 812 spdk_json_write_name(w, "portals"); 813 spdk_json_write_array_begin(w); 814 TAILQ_FOREACH(portal, &pg->head, per_pg_tailq) { 815 spdk_json_write_object_begin(w); 816 spdk_json_write_name(w, "host"); 817 spdk_json_write_string(w, portal->host); 818 spdk_json_write_name(w, "port"); 819 spdk_json_write_string(w, portal->port); 820 spdk_json_write_name(w, "cpumask"); 821 spdk_json_write_string_fmt(w, "0x%s", spdk_cpuset_fmt(portal->cpumask)); 822 spdk_json_write_object_end(w); 823 } 824 spdk_json_write_array_end(w); 825 826 spdk_json_write_name(w, "tag"); 827 spdk_json_write_int32(w, pg->tag); 828 829 spdk_json_write_object_end(w); 830 } 831 832 static void 833 spdk_rpc_get_portal_groups(struct spdk_jsonrpc_request *request, 834 const struct spdk_json_val *params) 835 { 836 struct spdk_json_write_ctx *w; 837 struct spdk_iscsi_portal_grp *pg; 838 839 if (params != NULL) { 840 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 841 "get_portal_groups requires no parameters"); 842 return; 843 } 844 845 w = spdk_jsonrpc_begin_result(request); 846 if (w == NULL) { 847 return; 848 } 849 850 spdk_json_write_array_begin(w); 851 852 TAILQ_FOREACH(pg, &g_spdk_iscsi.pg_head, tailq) { 853 dump_portal_group(w, pg); 854 } 855 856 spdk_json_write_array_end(w); 857 858 spdk_jsonrpc_end_result(request, w); 859 } 860 SPDK_RPC_REGISTER("get_portal_groups", spdk_rpc_get_portal_groups) 861 862 struct rpc_portal { 863 char *host; 864 char *port; 865 char *cpumask; 866 }; 867 868 struct rpc_portal_list { 869 size_t num_portals; 870 struct rpc_portal portals[MAX_PORTAL]; 871 }; 872 873 struct rpc_portal_group { 874 int32_t tag; 875 struct rpc_portal_list portal_list; 876 }; 877 878 static void 879 free_rpc_portal(struct rpc_portal *portal) 880 { 881 free(portal->host); 882 free(portal->port); 883 free(portal->cpumask); 884 } 885 886 static void 887 free_rpc_portal_list(struct rpc_portal_list *pl) 888 { 889 size_t i; 890 891 for (i = 0; i < pl->num_portals; i++) { 892 free_rpc_portal(&pl->portals[i]); 893 } 894 pl->num_portals = 0; 895 } 896 897 static void 898 free_rpc_portal_group(struct rpc_portal_group *pg) 899 { 900 free_rpc_portal_list(&pg->portal_list); 901 } 902 903 static const struct spdk_json_object_decoder rpc_portal_decoders[] = { 904 {"host", offsetof(struct rpc_portal, host), spdk_json_decode_string}, 905 {"port", offsetof(struct rpc_portal, port), spdk_json_decode_string}, 906 {"cpumask", offsetof(struct rpc_portal, cpumask), spdk_json_decode_string, true}, 907 }; 908 909 static int 910 decode_rpc_portal(const struct spdk_json_val *val, void *out) 911 { 912 struct rpc_portal *portal = out; 913 914 return spdk_json_decode_object(val, rpc_portal_decoders, 915 SPDK_COUNTOF(rpc_portal_decoders), 916 portal); 917 } 918 919 static int 920 decode_rpc_portal_list(const struct spdk_json_val *val, void *out) 921 { 922 struct rpc_portal_list *list = out; 923 924 return spdk_json_decode_array(val, decode_rpc_portal, list->portals, MAX_PORTAL, &list->num_portals, 925 sizeof(struct rpc_portal)); 926 } 927 928 static const struct spdk_json_object_decoder rpc_portal_group_decoders[] = { 929 {"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32}, 930 {"portals", offsetof(struct rpc_portal_group, portal_list), decode_rpc_portal_list}, 931 }; 932 933 static void 934 spdk_rpc_add_portal_group(struct spdk_jsonrpc_request *request, 935 const struct spdk_json_val *params) 936 { 937 struct rpc_portal_group req = {}; 938 struct spdk_iscsi_portal_grp *pg = NULL; 939 struct spdk_iscsi_portal *portal; 940 struct spdk_json_write_ctx *w; 941 size_t i = 0; 942 int rc = -1; 943 944 if (spdk_json_decode_object(params, rpc_portal_group_decoders, 945 SPDK_COUNTOF(rpc_portal_group_decoders), 946 &req)) { 947 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 948 goto out; 949 } 950 951 pg = spdk_iscsi_portal_grp_create(req.tag); 952 if (pg == NULL) { 953 SPDK_ERRLOG("portal_grp_create failed\n"); 954 goto out; 955 } 956 for (i = 0; i < req.portal_list.num_portals; i++) { 957 portal = spdk_iscsi_portal_create(req.portal_list.portals[i].host, 958 req.portal_list.portals[i].port, 959 req.portal_list.portals[i].cpumask); 960 if (portal == NULL) { 961 SPDK_ERRLOG("portal_create failed\n"); 962 goto out; 963 } 964 spdk_iscsi_portal_grp_add_portal(pg, portal); 965 } 966 967 rc = spdk_iscsi_portal_grp_open(pg); 968 if (rc != 0) { 969 SPDK_ERRLOG("portal_grp_open failed\n"); 970 goto out; 971 } 972 973 rc = spdk_iscsi_portal_grp_register(pg); 974 if (rc != 0) { 975 SPDK_ERRLOG("portal_grp_register failed\n"); 976 } 977 978 out: 979 if (rc == 0) { 980 w = spdk_jsonrpc_begin_result(request); 981 if (w != NULL) { 982 spdk_json_write_bool(w, true); 983 spdk_jsonrpc_end_result(request, w); 984 } 985 } else { 986 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 987 988 if (pg != NULL) { 989 spdk_iscsi_portal_grp_release(pg); 990 } 991 } 992 free_rpc_portal_group(&req); 993 } 994 SPDK_RPC_REGISTER("add_portal_group", spdk_rpc_add_portal_group) 995 996 struct rpc_delete_portal_group { 997 int32_t tag; 998 }; 999 1000 static const struct spdk_json_object_decoder rpc_delete_portal_group_decoders[] = { 1001 {"tag", offsetof(struct rpc_delete_portal_group, tag), spdk_json_decode_int32}, 1002 }; 1003 1004 static void 1005 spdk_rpc_delete_portal_group(struct spdk_jsonrpc_request *request, 1006 const struct spdk_json_val *params) 1007 { 1008 struct rpc_delete_portal_group req = {}; 1009 struct spdk_json_write_ctx *w; 1010 struct spdk_iscsi_portal_grp *pg; 1011 1012 if (spdk_json_decode_object(params, rpc_delete_portal_group_decoders, 1013 SPDK_COUNTOF(rpc_delete_portal_group_decoders), 1014 &req)) { 1015 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1016 goto invalid; 1017 } 1018 1019 pg = spdk_iscsi_portal_grp_unregister(req.tag); 1020 if (!pg) { 1021 goto invalid; 1022 } 1023 1024 spdk_iscsi_tgt_node_delete_map(pg, NULL); 1025 spdk_iscsi_portal_grp_release(pg); 1026 1027 w = spdk_jsonrpc_begin_result(request); 1028 if (w == NULL) { 1029 return; 1030 } 1031 1032 spdk_json_write_bool(w, true); 1033 spdk_jsonrpc_end_result(request, w); 1034 return; 1035 1036 invalid: 1037 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 1038 } 1039 SPDK_RPC_REGISTER("delete_portal_group", spdk_rpc_delete_portal_group) 1040 1041 static void 1042 spdk_rpc_get_iscsi_connections(struct spdk_jsonrpc_request *request, 1043 const struct spdk_json_val *params) 1044 { 1045 struct spdk_json_write_ctx *w; 1046 struct spdk_iscsi_conn *conns = g_conns_array; 1047 int i; 1048 uint16_t tsih; 1049 1050 if (params != NULL) { 1051 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1052 "get_iscsi_connections requires no parameters"); 1053 return; 1054 } 1055 1056 w = spdk_jsonrpc_begin_result(request); 1057 if (w == NULL) { 1058 return; 1059 } 1060 1061 spdk_json_write_array_begin(w); 1062 1063 for (i = 0; i < MAX_ISCSI_CONNECTIONS; i++) { 1064 struct spdk_iscsi_conn *c = &conns[i]; 1065 1066 if (!c->is_valid) { 1067 continue; 1068 } 1069 1070 spdk_json_write_object_begin(w); 1071 1072 spdk_json_write_name(w, "id"); 1073 spdk_json_write_int32(w, c->id); 1074 1075 spdk_json_write_name(w, "cid"); 1076 spdk_json_write_int32(w, c->cid); 1077 1078 /* 1079 * If we try to return data for a connection that has not 1080 * logged in yet, the session will not be set. So in this 1081 * case, return -1 for the tsih rather than segfaulting 1082 * on the null c->sess. 1083 */ 1084 if (c->sess == NULL) { 1085 tsih = -1; 1086 } else { 1087 tsih = c->sess->tsih; 1088 } 1089 spdk_json_write_name(w, "tsih"); 1090 spdk_json_write_int32(w, tsih); 1091 1092 spdk_json_write_name(w, "lcore_id"); 1093 spdk_json_write_int32(w, c->lcore); 1094 1095 spdk_json_write_name(w, "initiator_addr"); 1096 spdk_json_write_string(w, c->initiator_addr); 1097 1098 spdk_json_write_name(w, "target_addr"); 1099 spdk_json_write_string(w, c->target_addr); 1100 1101 spdk_json_write_name(w, "target_node_name"); 1102 spdk_json_write_string(w, c->target_short_name); 1103 1104 spdk_json_write_object_end(w); 1105 } 1106 spdk_json_write_array_end(w); 1107 1108 spdk_jsonrpc_end_result(request, w); 1109 } 1110 SPDK_RPC_REGISTER("get_iscsi_connections", spdk_rpc_get_iscsi_connections) 1111 1112 struct rpc_target_lun { 1113 char *name; 1114 char *bdev_name; 1115 int32_t lun_id; 1116 }; 1117 1118 static void 1119 free_rpc_target_lun(struct rpc_target_lun *req) 1120 { 1121 free(req->name); 1122 free(req->bdev_name); 1123 } 1124 1125 static const struct spdk_json_object_decoder rpc_target_lun_decoders[] = { 1126 {"name", offsetof(struct rpc_target_lun, name), spdk_json_decode_string}, 1127 {"bdev_name", offsetof(struct rpc_target_lun, bdev_name), spdk_json_decode_string}, 1128 {"lun_id", offsetof(struct rpc_target_lun, lun_id), spdk_json_decode_int32, true}, 1129 }; 1130 1131 static void 1132 spdk_rpc_target_node_add_lun(struct spdk_jsonrpc_request *request, 1133 const struct spdk_json_val *params) 1134 { 1135 struct rpc_target_lun req = {}; 1136 struct spdk_json_write_ctx *w; 1137 struct spdk_iscsi_tgt_node *target; 1138 int rc; 1139 1140 req.lun_id = -1; 1141 1142 if (spdk_json_decode_object(params, rpc_target_lun_decoders, 1143 SPDK_COUNTOF(rpc_target_lun_decoders), &req)) { 1144 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1145 goto invalid; 1146 } 1147 1148 target = spdk_iscsi_find_tgt_node(req.name); 1149 if (target == NULL) { 1150 SPDK_ERRLOG("target is not found\n"); 1151 goto invalid; 1152 } 1153 1154 rc = spdk_iscsi_tgt_node_add_lun(target, req.bdev_name, req.lun_id); 1155 if (rc < 0) { 1156 SPDK_ERRLOG("add lun failed\n"); 1157 goto invalid; 1158 } 1159 1160 free_rpc_target_lun(&req); 1161 1162 w = spdk_jsonrpc_begin_result(request); 1163 if (w == NULL) { 1164 return; 1165 } 1166 1167 spdk_json_write_bool(w, true); 1168 spdk_jsonrpc_end_result(request, w); 1169 return; 1170 1171 invalid: 1172 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1173 "Invalid parameters"); 1174 free_rpc_target_lun(&req); 1175 } 1176 SPDK_RPC_REGISTER("target_node_add_lun", spdk_rpc_target_node_add_lun) 1177 1178 static void 1179 spdk_rpc_get_iscsi_global_params(struct spdk_jsonrpc_request *request, 1180 const struct spdk_json_val *params) 1181 { 1182 struct spdk_json_write_ctx *w; 1183 1184 if (params != NULL) { 1185 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1186 "get_iscsi_global_params requires no parameters"); 1187 return; 1188 } 1189 1190 w = spdk_jsonrpc_begin_result(request); 1191 if (w == NULL) { 1192 return; 1193 } 1194 1195 spdk_json_write_object_begin(w); 1196 1197 spdk_json_write_name(w, "auth_file"); 1198 spdk_json_write_string(w, g_spdk_iscsi.authfile); 1199 1200 spdk_json_write_name(w, "node_base"); 1201 spdk_json_write_string(w, g_spdk_iscsi.nodebase); 1202 1203 spdk_json_write_name(w, "max_sessions"); 1204 spdk_json_write_uint32(w, g_spdk_iscsi.MaxSessions); 1205 1206 spdk_json_write_name(w, "max_connections_per_session"); 1207 spdk_json_write_uint32(w, g_spdk_iscsi.MaxConnectionsPerSession); 1208 1209 spdk_json_write_name(w, "max_queue_depth"); 1210 spdk_json_write_uint32(w, g_spdk_iscsi.MaxQueueDepth); 1211 1212 spdk_json_write_name(w, "default_time2wait"); 1213 spdk_json_write_uint32(w, g_spdk_iscsi.DefaultTime2Wait); 1214 1215 spdk_json_write_name(w, "default_time2retain"); 1216 spdk_json_write_uint32(w, g_spdk_iscsi.DefaultTime2Retain); 1217 1218 spdk_json_write_name(w, "immediate_data"); 1219 spdk_json_write_bool(w, g_spdk_iscsi.ImmediateData); 1220 1221 spdk_json_write_name(w, "allow_duplicated_isid"); 1222 spdk_json_write_bool(w, g_spdk_iscsi.AllowDuplicateIsid); 1223 1224 spdk_json_write_name(w, "error_recovery_level"); 1225 spdk_json_write_uint32(w, g_spdk_iscsi.ErrorRecoveryLevel); 1226 1227 spdk_json_write_name(w, "timeout"); 1228 spdk_json_write_int32(w, g_spdk_iscsi.timeout); 1229 1230 spdk_json_write_name(w, "nop_in_interval"); 1231 spdk_json_write_int32(w, g_spdk_iscsi.nopininterval); 1232 1233 spdk_json_write_name(w, "discovery_auth_method"); 1234 if (g_spdk_iscsi.no_discovery_auth != 0) { 1235 spdk_json_write_string(w, "none"); 1236 } else if (g_spdk_iscsi.req_discovery_auth == 0) { 1237 spdk_json_write_string(w, "auto"); 1238 } else if (g_spdk_iscsi.req_discovery_auth_mutual != 0) { 1239 spdk_json_write_string(w, "chap mutual"); 1240 } else { 1241 spdk_json_write_string(w, "chap"); 1242 } 1243 1244 spdk_json_write_name(w, "discovery_auth_group"); 1245 spdk_json_write_int32(w, g_spdk_iscsi.discovery_auth_group); 1246 1247 spdk_json_write_name(w, "min_connections_per_core"); 1248 spdk_json_write_int32(w, spdk_iscsi_conn_get_min_per_core()); 1249 1250 spdk_json_write_object_end(w); 1251 1252 spdk_jsonrpc_end_result(request, w); 1253 } 1254 SPDK_RPC_REGISTER("get_iscsi_global_params", spdk_rpc_get_iscsi_global_params) 1255