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/log.h" 42 #include "spdk/rpc.h" 43 44 extern struct spdk_iscsi_conn *g_conns_array; // TODO: move this to an internal iSCSI header 45 46 static void 47 spdk_rpc_get_initiator_groups(struct spdk_jsonrpc_server_conn *conn, 48 const struct spdk_json_val *params, 49 const struct spdk_json_val *id) 50 { 51 struct spdk_json_write_ctx *w; 52 struct spdk_iscsi_init_grp *ig; 53 int i; 54 55 if (params != NULL) { 56 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 57 "get_initiator_groups requires no parameters"); 58 return; 59 } 60 61 if (id == NULL) { 62 return; 63 } 64 65 w = spdk_jsonrpc_begin_result(conn, id); 66 spdk_json_write_array_begin(w); 67 68 TAILQ_FOREACH(ig, &g_spdk_iscsi.ig_head, tailq) { 69 spdk_json_write_object_begin(w); 70 71 spdk_json_write_name(w, "initiators"); 72 spdk_json_write_array_begin(w); 73 for (i = 0; i < ig->ninitiators; i++) { 74 spdk_json_write_string(w, ig->initiators[i]); 75 } 76 spdk_json_write_array_end(w); 77 78 spdk_json_write_name(w, "tag"); 79 spdk_json_write_int32(w, ig->tag); 80 81 spdk_json_write_name(w, "netmasks"); 82 spdk_json_write_array_begin(w); 83 for (i = 0; i < ig->nnetmasks; i++) { 84 spdk_json_write_string(w, ig->netmasks[i]); 85 } 86 spdk_json_write_array_end(w); 87 88 spdk_json_write_object_end(w); 89 } 90 91 spdk_json_write_array_end(w); 92 93 spdk_jsonrpc_end_result(conn, w); 94 } 95 SPDK_RPC_REGISTER("get_initiator_groups", spdk_rpc_get_initiator_groups) 96 97 struct rpc_initiator_list { 98 size_t num_initiators; 99 char *initiators[MAX_INITIATOR]; 100 }; 101 102 static int 103 decode_rpc_initiator_list(const struct spdk_json_val *val, void *out) 104 { 105 struct rpc_initiator_list *list = out; 106 107 return spdk_json_decode_array(val, spdk_json_decode_string, list->initiators, MAX_INITIATOR, 108 &list->num_initiators, sizeof(char *)); 109 } 110 111 static void 112 free_rpc_initiator_list(struct rpc_initiator_list *list) 113 { 114 size_t i; 115 116 for (i = 0; i < list->num_initiators; i++) { 117 free(list->initiators[i]); 118 } 119 } 120 121 struct rpc_netmask_list { 122 size_t num_netmasks; 123 char *netmasks[MAX_NETMASK]; 124 }; 125 126 static int 127 decode_rpc_netmask_list(const struct spdk_json_val *val, void *out) 128 { 129 struct rpc_netmask_list *list = out; 130 131 return spdk_json_decode_array(val, spdk_json_decode_string, list->netmasks, MAX_NETMASK, 132 &list->num_netmasks, sizeof(char *)); 133 } 134 135 static void 136 free_rpc_netmask_list(struct rpc_netmask_list *list) 137 { 138 size_t i; 139 140 for (i = 0; i < list->num_netmasks; i++) { 141 free(list->netmasks[i]); 142 } 143 } 144 145 struct rpc_initiator_group { 146 int32_t tag; 147 struct rpc_initiator_list initiator_list; 148 struct rpc_netmask_list netmask_list; 149 }; 150 151 static void 152 free_rpc_initiator_group(struct rpc_initiator_group *ig) 153 { 154 free_rpc_initiator_list(&ig->initiator_list); 155 free_rpc_netmask_list(&ig->netmask_list); 156 } 157 158 static const struct spdk_json_object_decoder rpc_initiator_group_decoders[] = { 159 {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32}, 160 {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list}, 161 {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list}, 162 }; 163 164 static void 165 spdk_rpc_add_initiator_group(struct spdk_jsonrpc_server_conn *conn, 166 const struct spdk_json_val *params, 167 const struct spdk_json_val *id) 168 { 169 struct rpc_initiator_group req = {}; 170 size_t i; 171 char **initiators = NULL, **netmasks = NULL; 172 struct spdk_json_write_ctx *w; 173 174 if (spdk_json_decode_object(params, rpc_initiator_group_decoders, 175 sizeof(rpc_initiator_group_decoders) / sizeof(*rpc_initiator_group_decoders), &req)) { 176 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 177 goto invalid; 178 } 179 180 if (req.initiator_list.num_initiators == 0 || 181 req.netmask_list.num_netmasks == 0) { 182 goto invalid; 183 } 184 185 initiators = calloc(req.initiator_list.num_initiators, sizeof(char *)); 186 if (initiators == NULL) { 187 goto invalid; 188 } 189 for (i = 0; i < req.initiator_list.num_initiators; i++) { 190 initiators[i] = strdup(req.initiator_list.initiators[i]); 191 if (initiators[i] == NULL) { 192 goto invalid; 193 } 194 } 195 196 netmasks = calloc(req.netmask_list.num_netmasks, sizeof(char *)); 197 if (netmasks == NULL) { 198 goto invalid; 199 } 200 for (i = 0; i < req.netmask_list.num_netmasks; i++) { 201 netmasks[i] = strdup(req.netmask_list.netmasks[i]); 202 if (netmasks[i] == NULL) { 203 goto invalid; 204 } 205 } 206 207 if (spdk_iscsi_init_grp_create_from_initiator_list(req.tag, 208 req.initiator_list.num_initiators, 209 initiators, 210 req.netmask_list.num_netmasks, 211 netmasks)) { 212 SPDK_ERRLOG("create_from_initiator_list failed\n"); 213 goto invalid; 214 } 215 216 free_rpc_initiator_group(&req); 217 218 if (id == NULL) { 219 return; 220 } 221 222 w = spdk_jsonrpc_begin_result(conn, id); 223 spdk_json_write_bool(w, true); 224 spdk_jsonrpc_end_result(conn, w); 225 return; 226 227 invalid: 228 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 229 if (initiators) { 230 for (i = 0; i < req.initiator_list.num_initiators; i++) { 231 free(initiators[i]); 232 } 233 free(initiators); 234 } 235 if (netmasks) { 236 for (i = 0; i < req.netmask_list.num_netmasks; i++) { 237 free(netmasks[i]); 238 } 239 free(netmasks); 240 } 241 free_rpc_initiator_group(&req); 242 } 243 SPDK_RPC_REGISTER("add_initiator_group", spdk_rpc_add_initiator_group) 244 245 struct rpc_delete_initiator_group { 246 int32_t tag; 247 }; 248 249 static const struct spdk_json_object_decoder rpc_delete_initiator_group_decoders[] = { 250 {"tag", offsetof(struct rpc_delete_initiator_group, tag), spdk_json_decode_int32}, 251 }; 252 253 static void 254 spdk_rpc_delete_initiator_group(struct spdk_jsonrpc_server_conn *conn, 255 const struct spdk_json_val *params, 256 const struct spdk_json_val *id) 257 { 258 struct rpc_delete_initiator_group req = {}; 259 struct spdk_json_write_ctx *w; 260 struct spdk_iscsi_init_grp *ig; 261 262 if (spdk_json_decode_object(params, rpc_delete_initiator_group_decoders, 263 sizeof(rpc_delete_initiator_group_decoders) / sizeof(*rpc_delete_initiator_group_decoders), 264 &req)) { 265 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 266 goto invalid; 267 } 268 269 if (spdk_iscsi_init_grp_deletable(req.tag)) { 270 goto invalid; 271 } 272 273 ig = spdk_iscsi_init_grp_find_by_tag(req.tag); 274 if (!ig) { 275 goto invalid; 276 } 277 spdk_iscsi_tgt_node_delete_map(NULL, ig); 278 spdk_iscsi_init_grp_release(ig); 279 280 if (id == NULL) { 281 return; 282 } 283 284 w = spdk_jsonrpc_begin_result(conn, id); 285 spdk_json_write_bool(w, true); 286 spdk_jsonrpc_end_result(conn, w); 287 return; 288 289 invalid: 290 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 291 } 292 SPDK_RPC_REGISTER("delete_initiator_group", spdk_rpc_delete_initiator_group) 293 294 static void 295 spdk_rpc_get_target_nodes(struct spdk_jsonrpc_server_conn *conn, 296 const struct spdk_json_val *params, 297 const struct spdk_json_val *id) 298 { 299 struct spdk_iscsi_globals *iscsi = &g_spdk_iscsi; 300 struct spdk_json_write_ctx *w; 301 size_t tgt_idx; 302 int i; 303 304 if (params != NULL) { 305 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 306 "get_target_nodes requires no parameters"); 307 return; 308 } 309 310 if (id == NULL) { 311 return; 312 } 313 314 w = spdk_jsonrpc_begin_result(conn, id); 315 spdk_json_write_array_begin(w); 316 317 for (tgt_idx = 0 ; tgt_idx < MAX_ISCSI_TARGET_NODE; tgt_idx++) { 318 struct spdk_iscsi_tgt_node *tgtnode = iscsi->target[tgt_idx]; 319 320 if (tgtnode == NULL) { 321 continue; 322 } 323 324 spdk_json_write_object_begin(w); 325 326 spdk_json_write_name(w, "name"); 327 spdk_json_write_string(w, tgtnode->name); 328 329 if (tgtnode->alias) { 330 spdk_json_write_name(w, "alias_name"); 331 spdk_json_write_string(w, tgtnode->alias); 332 } 333 334 spdk_json_write_name(w, "pg_ig_maps"); 335 spdk_json_write_array_begin(w); 336 for (i = 0; i < tgtnode->maxmap; i++) { 337 spdk_json_write_object_begin(w); 338 spdk_json_write_name(w, "pg_tag"); 339 spdk_json_write_int32(w, tgtnode->map[i].pg->tag); 340 spdk_json_write_name(w, "ig_tag"); 341 spdk_json_write_int32(w, tgtnode->map[i].ig->tag); 342 spdk_json_write_object_end(w); 343 } 344 spdk_json_write_array_end(w); 345 346 spdk_json_write_name(w, "luns"); 347 spdk_json_write_array_begin(w); 348 for (i = 0; i < tgtnode->dev->maxlun; i++) { 349 if (tgtnode->dev->lun[i]) { 350 spdk_json_write_object_begin(w); 351 spdk_json_write_name(w, "name"); 352 spdk_json_write_string(w, tgtnode->dev->lun[i]->name); 353 spdk_json_write_name(w, "id"); 354 spdk_json_write_int32(w, tgtnode->dev->lun[i]->id); 355 spdk_json_write_object_end(w); 356 } 357 } 358 spdk_json_write_array_end(w); 359 360 spdk_json_write_name(w, "queue_depth"); 361 spdk_json_write_int32(w, tgtnode->queue_depth); 362 363 /* 364 * TODO: convert these to bool 365 */ 366 367 spdk_json_write_name(w, "chap_disabled"); 368 spdk_json_write_int32(w, tgtnode->auth_chap_disabled); 369 370 spdk_json_write_name(w, "chap_required"); 371 spdk_json_write_int32(w, tgtnode->auth_chap_required); 372 373 spdk_json_write_name(w, "chap_mutual"); 374 spdk_json_write_int32(w, tgtnode->auth_chap_mutual); 375 376 spdk_json_write_name(w, "chap_auth_group"); 377 spdk_json_write_int32(w, tgtnode->auth_group); 378 379 spdk_json_write_object_end(w); 380 } 381 spdk_json_write_array_end(w); 382 383 spdk_jsonrpc_end_result(conn, w); 384 } 385 SPDK_RPC_REGISTER("get_target_nodes", spdk_rpc_get_target_nodes) 386 387 struct rpc_pg_tags { 388 size_t num_tags; 389 int32_t tags[MAX_TARGET_MAP]; 390 }; 391 392 static int 393 decode_rpc_pg_tags(const struct spdk_json_val *val, void *out) 394 { 395 struct rpc_pg_tags *pg_tags = out; 396 397 return spdk_json_decode_array(val, spdk_json_decode_int32, pg_tags->tags, MAX_TARGET_MAP, 398 &pg_tags->num_tags, sizeof(int32_t)); 399 } 400 401 struct rpc_ig_tags { 402 size_t num_tags; 403 int32_t tags[MAX_TARGET_MAP]; 404 }; 405 406 static int 407 decode_rpc_ig_tags(const struct spdk_json_val *val, void *out) 408 { 409 struct rpc_ig_tags *ig_tags = out; 410 411 return spdk_json_decode_array(val, spdk_json_decode_int32, ig_tags->tags, MAX_TARGET_MAP, 412 &ig_tags->num_tags, sizeof(int32_t)); 413 } 414 415 #define RPC_CONSTRUCT_TARGET_NODE_MAX_LUN 64 416 417 struct rpc_lun_names { 418 size_t num_names; 419 char *names[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN]; 420 }; 421 422 static int 423 decode_rpc_lun_names(const struct spdk_json_val *val, void *out) 424 { 425 struct rpc_lun_names *lun_names = out; 426 427 return spdk_json_decode_array(val, spdk_json_decode_string, lun_names->names, 428 RPC_CONSTRUCT_TARGET_NODE_MAX_LUN, 429 &lun_names->num_names, sizeof(char *)); 430 } 431 432 static void 433 free_rpc_lun_names(struct rpc_lun_names *r) 434 { 435 size_t i; 436 437 for (i = 0; i < r->num_names; i++) { 438 free(r->names[i]); 439 } 440 } 441 442 struct rpc_lun_ids { 443 size_t num_ids; 444 int32_t ids[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN]; 445 }; 446 447 static int 448 decode_rpc_lun_ids(const struct spdk_json_val *val, void *out) 449 { 450 struct rpc_lun_ids *lun_ids = out; 451 452 return spdk_json_decode_array(val, spdk_json_decode_int32, lun_ids->ids, 453 RPC_CONSTRUCT_TARGET_NODE_MAX_LUN, 454 &lun_ids->num_ids, sizeof(int32_t)); 455 } 456 457 struct rpc_target_node { 458 char *name; 459 char *alias_name; 460 461 struct rpc_pg_tags pg_tags; 462 struct rpc_ig_tags ig_tags; 463 464 struct rpc_lun_names lun_names; 465 struct rpc_lun_ids lun_ids; 466 467 int32_t queue_depth; 468 int32_t chap_disabled; 469 int32_t chap_required; 470 int32_t chap_mutual; 471 int32_t chap_auth_group; 472 }; 473 474 static void 475 free_rpc_target_node(struct rpc_target_node *req) 476 { 477 free_rpc_lun_names(&req->lun_names); 478 } 479 480 static const struct spdk_json_object_decoder rpc_target_node_decoders[] = { 481 {"name", offsetof(struct rpc_target_node, name), spdk_json_decode_string}, 482 {"alias_name", offsetof(struct rpc_target_node, alias_name), spdk_json_decode_string}, 483 {"pg_tags", offsetof(struct rpc_target_node, pg_tags), decode_rpc_pg_tags}, 484 {"ig_tags", offsetof(struct rpc_target_node, ig_tags), decode_rpc_ig_tags}, 485 {"lun_names", offsetof(struct rpc_target_node, lun_names), decode_rpc_lun_names}, 486 {"lun_ids", offsetof(struct rpc_target_node, lun_ids), decode_rpc_lun_ids}, 487 {"queue_depth", offsetof(struct rpc_target_node, queue_depth), spdk_json_decode_int32}, 488 {"chap_disabled", offsetof(struct rpc_target_node, chap_disabled), spdk_json_decode_int32}, 489 {"chap_required", offsetof(struct rpc_target_node, chap_required), spdk_json_decode_int32}, 490 {"chap_mutual", offsetof(struct rpc_target_node, chap_mutual), spdk_json_decode_int32}, 491 {"chap_auth_group", offsetof(struct rpc_target_node, chap_auth_group), spdk_json_decode_int32}, 492 }; 493 494 static void 495 spdk_rpc_construct_target_node(struct spdk_jsonrpc_server_conn *conn, 496 const struct spdk_json_val *params, 497 const struct spdk_json_val *id) 498 { 499 struct rpc_target_node req = {}; 500 struct spdk_json_write_ctx *w; 501 struct spdk_iscsi_tgt_node *target; 502 503 if (spdk_json_decode_object(params, rpc_target_node_decoders, 504 sizeof(rpc_target_node_decoders) / sizeof(*rpc_target_node_decoders), 505 &req)) { 506 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 507 goto invalid; 508 } 509 510 if (req.pg_tags.num_tags != req.ig_tags.num_tags) { 511 SPDK_ERRLOG("pg_tags/ig_tags count mismatch\n"); 512 goto invalid; 513 } 514 515 if (req.lun_names.num_names != req.lun_ids.num_ids) { 516 SPDK_ERRLOG("lun_names/lun_ids count mismatch\n"); 517 goto invalid; 518 } 519 520 /* 521 * Use default parameters in a few places: 522 * index = -1 : automatically pick an index for the new target node 523 * alias = NULL 524 * 0, 0 = disable header/data digests 525 */ 526 target = spdk_iscsi_tgt_node_construct(-1, req.name, req.alias_name, 527 req.pg_tags.tags, 528 req.ig_tags.tags, 529 req.pg_tags.num_tags, 530 req.lun_names.names, 531 req.lun_ids.ids, 532 req.lun_names.num_names, 533 req.queue_depth, 534 req.chap_disabled, 535 req.chap_required, 536 req.chap_mutual, 537 req.chap_auth_group, 538 0, 0); 539 540 if (target == NULL) { 541 goto invalid; 542 } 543 544 free_rpc_target_node(&req); 545 546 if (id == NULL) { 547 return; 548 } 549 550 w = spdk_jsonrpc_begin_result(conn, id); 551 spdk_json_write_bool(w, true); 552 spdk_jsonrpc_end_result(conn, w); 553 return; 554 555 invalid: 556 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 557 free_rpc_target_node(&req); 558 } 559 SPDK_RPC_REGISTER("construct_target_node", spdk_rpc_construct_target_node) 560 561 struct rpc_delete_target_node { 562 char *name; 563 }; 564 565 static void 566 free_rpc_delete_target_node(struct rpc_delete_target_node *r) 567 { 568 free(r->name); 569 } 570 571 static const struct spdk_json_object_decoder rpc_delete_target_node_decoders[] = { 572 {"name", offsetof(struct rpc_delete_target_node, name), spdk_json_decode_string}, 573 }; 574 575 static void 576 spdk_rpc_delete_target_node(struct spdk_jsonrpc_server_conn *conn, 577 const struct spdk_json_val *params, 578 const struct spdk_json_val *id) 579 { 580 struct rpc_delete_target_node req = {}; 581 struct spdk_json_write_ctx *w; 582 583 if (spdk_json_decode_object(params, rpc_delete_target_node_decoders, 584 sizeof(rpc_delete_target_node_decoders) / sizeof(*rpc_delete_target_node_decoders), 585 &req)) { 586 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 587 goto invalid; 588 } 589 590 if (req.name == NULL) { 591 SPDK_ERRLOG("missing name param\n"); 592 goto invalid; 593 } 594 595 if (spdk_iscsi_shutdown_tgt_node_by_name(req.name)) { 596 SPDK_ERRLOG("shutdown_tgt_node_by_name failed\n"); 597 goto invalid; 598 } 599 600 free_rpc_delete_target_node(&req); 601 602 if (id == NULL) { 603 return; 604 } 605 606 w = spdk_jsonrpc_begin_result(conn, id); 607 spdk_json_write_bool(w, true); 608 spdk_jsonrpc_end_result(conn, w); 609 return; 610 611 invalid: 612 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 613 free_rpc_delete_target_node(&req); 614 } 615 SPDK_RPC_REGISTER("delete_target_node", spdk_rpc_delete_target_node) 616 617 static void 618 spdk_rpc_get_portal_groups(struct spdk_jsonrpc_server_conn *conn, 619 const struct spdk_json_val *params, 620 const struct spdk_json_val *id) 621 { 622 struct spdk_json_write_ctx *w; 623 struct spdk_iscsi_portal_grp *pg; 624 struct spdk_iscsi_portal *portal; 625 626 if (params != NULL) { 627 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 628 "get_portal_groups requires no parameters"); 629 return; 630 } 631 632 if (id == NULL) { 633 return; 634 } 635 636 w = spdk_jsonrpc_begin_result(conn, id); 637 spdk_json_write_array_begin(w); 638 639 TAILQ_FOREACH(pg, &g_spdk_iscsi.pg_head, tailq) { 640 spdk_json_write_object_begin(w); 641 642 spdk_json_write_name(w, "portals"); 643 spdk_json_write_array_begin(w); 644 TAILQ_FOREACH(portal, &pg->head, tailq) { 645 spdk_json_write_object_begin(w); 646 spdk_json_write_name(w, "host"); 647 spdk_json_write_string(w, portal->host); 648 spdk_json_write_name(w, "port"); 649 spdk_json_write_string(w, portal->port); 650 spdk_json_write_object_end(w); 651 } 652 spdk_json_write_array_end(w); 653 654 spdk_json_write_name(w, "tag"); 655 spdk_json_write_int32(w, pg->tag); 656 657 spdk_json_write_object_end(w); 658 } 659 660 spdk_json_write_array_end(w); 661 662 spdk_jsonrpc_end_result(conn, w); 663 } 664 SPDK_RPC_REGISTER("get_portal_groups", spdk_rpc_get_portal_groups) 665 666 struct rpc_portal { 667 char *host; 668 char *port; 669 }; 670 671 struct rpc_portal_list { 672 size_t num_portals; 673 struct rpc_portal portals[MAX_PORTAL]; 674 }; 675 676 struct rpc_portal_group { 677 int32_t tag; 678 struct rpc_portal_list portal_list; 679 }; 680 681 static void 682 free_rpc_portal(struct rpc_portal *portal) 683 { 684 free(portal->host); 685 portal->host = NULL; 686 free(portal->port); 687 portal->port = NULL; 688 } 689 690 static void 691 free_rpc_portal_list(struct rpc_portal_list *pl) 692 { 693 size_t i; 694 695 for (i = 0; i < pl->num_portals; i++) { 696 free_rpc_portal(&pl->portals[i]); 697 } 698 pl->num_portals = 0; 699 } 700 701 static void 702 free_rpc_portal_group(struct rpc_portal_group *pg) 703 { 704 free_rpc_portal_list(&pg->portal_list); 705 } 706 707 static const struct spdk_json_object_decoder rpc_portal_decoders[] = { 708 {"host", offsetof(struct rpc_portal, host), spdk_json_decode_string}, 709 {"port", offsetof(struct rpc_portal, port), spdk_json_decode_string}, 710 }; 711 712 static int 713 decode_rpc_portal(const struct spdk_json_val *val, void *out) 714 { 715 struct rpc_portal *portal = out; 716 717 return spdk_json_decode_object(val, rpc_portal_decoders, 718 sizeof(rpc_portal_decoders) / sizeof(*rpc_portal_decoders), 719 portal); 720 } 721 722 static int 723 decode_rpc_portal_list(const struct spdk_json_val *val, void *out) 724 { 725 struct rpc_portal_list *list = out; 726 727 return spdk_json_decode_array(val, decode_rpc_portal, list->portals, MAX_PORTAL, &list->num_portals, 728 sizeof(struct rpc_portal)); 729 } 730 731 static const struct spdk_json_object_decoder rpc_portal_group_decoders[] = { 732 {"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32}, 733 {"portals", offsetof(struct rpc_portal_group, portal_list), decode_rpc_portal_list}, 734 }; 735 736 static void 737 spdk_rpc_add_portal_group(struct spdk_jsonrpc_server_conn *conn, 738 const struct spdk_json_val *params, 739 const struct spdk_json_val *id) 740 { 741 struct rpc_portal_group req = {}; 742 struct spdk_iscsi_portal *portal_list[MAX_PORTAL] = {}; 743 struct spdk_json_write_ctx *w; 744 size_t i; 745 746 if (spdk_json_decode_object(params, rpc_portal_group_decoders, 747 sizeof(rpc_portal_group_decoders) / sizeof(*rpc_portal_group_decoders), 748 &req)) { 749 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 750 goto invalid; 751 } 752 753 for (i = 0; i < req.portal_list.num_portals; i++) { 754 portal_list[i] = spdk_iscsi_portal_create(req.portal_list.portals[i].host, 755 req.portal_list.portals[i].port, 0); 756 if (portal_list[i] == NULL) { 757 SPDK_ERRLOG("portal_list allocation failed\n"); 758 goto invalid; 759 } 760 } 761 762 if (spdk_iscsi_portal_grp_create_from_portal_list(req.tag, portal_list, 763 req.portal_list.num_portals)) { 764 SPDK_ERRLOG("create_from_portal_list failed\n"); 765 goto invalid; 766 } 767 768 /* 769 * Leave the host and port strings allocated here and don't call free_rpc_portal_group(), 770 * because the pointers are inserted directly into the portal group list. 771 */ 772 773 if (id == NULL) { 774 return; 775 } 776 777 w = spdk_jsonrpc_begin_result(conn, id); 778 spdk_json_write_bool(w, true); 779 spdk_jsonrpc_end_result(conn, w); 780 return; 781 782 invalid: 783 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 784 for (i = 0; i < req.portal_list.num_portals; i++) { 785 spdk_iscsi_portal_destroy(portal_list[i]); 786 } 787 free_rpc_portal_group(&req); 788 } 789 SPDK_RPC_REGISTER("add_portal_group", spdk_rpc_add_portal_group) 790 791 struct rpc_delete_portal_group { 792 int32_t tag; 793 }; 794 795 static const struct spdk_json_object_decoder rpc_delete_portal_group_decoders[] = { 796 {"tag", offsetof(struct rpc_delete_portal_group, tag), spdk_json_decode_int32}, 797 }; 798 799 static void 800 spdk_rpc_delete_portal_group(struct spdk_jsonrpc_server_conn *conn, 801 const struct spdk_json_val *params, 802 const struct spdk_json_val *id) 803 { 804 struct rpc_delete_portal_group req = {}; 805 struct spdk_json_write_ctx *w; 806 struct spdk_iscsi_portal_grp *pg; 807 808 if (spdk_json_decode_object(params, rpc_delete_portal_group_decoders, 809 sizeof(rpc_delete_portal_group_decoders) / sizeof(*rpc_delete_portal_group_decoders), 810 &req)) { 811 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 812 goto invalid; 813 } 814 815 if (spdk_iscsi_portal_grp_deletable(req.tag)) { 816 goto invalid; 817 } 818 819 pg = spdk_iscsi_portal_grp_find_by_tag(req.tag); 820 if (!pg) { 821 goto invalid; 822 } 823 824 spdk_iscsi_tgt_node_delete_map(pg, NULL); 825 spdk_iscsi_portal_grp_release(pg); 826 827 if (id == NULL) { 828 return; 829 } 830 831 w = spdk_jsonrpc_begin_result(conn, id); 832 spdk_json_write_bool(w, true); 833 spdk_jsonrpc_end_result(conn, w); 834 return; 835 836 invalid: 837 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 838 } 839 SPDK_RPC_REGISTER("delete_portal_group", spdk_rpc_delete_portal_group) 840 841 static void 842 spdk_rpc_get_iscsi_connections(struct spdk_jsonrpc_server_conn *conn, 843 const struct spdk_json_val *params, 844 const struct spdk_json_val *id) 845 { 846 struct spdk_json_write_ctx *w; 847 struct spdk_iscsi_conn *conns = g_conns_array; 848 int i; 849 uint16_t tsih; 850 851 if (params != NULL) { 852 spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 853 "get_iscsi_connections requires no parameters"); 854 return; 855 } 856 857 if (id == NULL) { 858 return; 859 } 860 861 w = spdk_jsonrpc_begin_result(conn, id); 862 spdk_json_write_array_begin(w); 863 864 for (i = 0; i < MAX_ISCSI_CONNECTIONS; i++) { 865 struct spdk_iscsi_conn *c = &conns[i]; 866 867 if (!c->is_valid) { 868 continue; 869 } 870 871 spdk_json_write_object_begin(w); 872 873 spdk_json_write_name(w, "id"); 874 spdk_json_write_int32(w, c->id); 875 876 spdk_json_write_name(w, "cid"); 877 spdk_json_write_int32(w, c->cid); 878 879 /* 880 * If we try to return data for a connection that has not 881 * logged in yet, the session will not be set. So in this 882 * case, return -1 for the tsih rather than segfaulting 883 * on the null c->sess. 884 */ 885 if (c->sess == NULL) { 886 tsih = -1; 887 } else { 888 tsih = c->sess->tsih; 889 } 890 spdk_json_write_name(w, "tsih"); 891 spdk_json_write_int32(w, tsih); 892 893 spdk_json_write_name(w, "is_idle"); 894 spdk_json_write_int32(w, c->is_idle); 895 896 spdk_json_write_name(w, "lcore_id"); 897 spdk_json_write_int32(w, c->lcore); 898 899 spdk_json_write_name(w, "initiator_addr"); 900 spdk_json_write_string(w, c->initiator_addr); 901 902 spdk_json_write_name(w, "target_addr"); 903 spdk_json_write_string(w, c->target_addr); 904 905 spdk_json_write_name(w, "target_node_name"); 906 spdk_json_write_string(w, c->target_short_name); 907 908 spdk_json_write_object_end(w); 909 } 910 spdk_json_write_array_end(w); 911 912 spdk_jsonrpc_end_result(conn, w); 913 } 914 SPDK_RPC_REGISTER("get_iscsi_connections", spdk_rpc_get_iscsi_connections) 915