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 "spdk/stdinc.h" 36 #include "spdk/env.h" 37 #include "spdk/string.h" 38 #include "spdk/sock.h" 39 #include "spdk/likely.h" 40 41 #include "iscsi/iscsi.h" 42 #include "iscsi/init_grp.h" 43 #include "iscsi/portal_grp.h" 44 #include "iscsi/conn.h" 45 #include "iscsi/task.h" 46 #include "iscsi/tgt_node.h" 47 48 #include "spdk/log.h" 49 50 struct spdk_iscsi_opts *g_spdk_iscsi_opts = NULL; 51 52 static struct spdk_thread *g_init_thread = NULL; 53 static spdk_iscsi_init_cb g_init_cb_fn = NULL; 54 static void *g_init_cb_arg = NULL; 55 56 static spdk_iscsi_fini_cb g_fini_cb_fn; 57 static void *g_fini_cb_arg; 58 59 #define ISCSI_DATA_BUFFER_ALIGNMENT (0x1000) 60 #define ISCSI_DATA_BUFFER_MASK (ISCSI_DATA_BUFFER_ALIGNMENT - 1) 61 62 static void 63 mobj_ctor(struct spdk_mempool *mp, __attribute__((unused)) void *arg, 64 void *_m, __attribute__((unused)) unsigned i) 65 { 66 struct spdk_mobj *m = _m; 67 68 m->mp = mp; 69 m->buf = (uint8_t *)m + sizeof(struct spdk_mobj); 70 m->buf = (void *)((uintptr_t)((uint8_t *)m->buf + ISCSI_DATA_BUFFER_ALIGNMENT) & 71 ~ISCSI_DATA_BUFFER_MASK); 72 } 73 74 #define NUM_PDU_PER_CONNECTION(iscsi) (2 * (iscsi->MaxQueueDepth + \ 75 iscsi->MaxLargeDataInPerConnection + \ 76 2 * iscsi->MaxR2TPerConnection + 8)) 77 #define PDU_POOL_SIZE(iscsi) (iscsi->MaxConnections * NUM_PDU_PER_CONNECTION(iscsi)) 78 #define IMMEDIATE_DATA_POOL_SIZE(iscsi) (iscsi->MaxConnections * 128) 79 #define DATA_OUT_POOL_SIZE(iscsi) (iscsi->MaxConnections * MAX_DATA_OUT_PER_CONNECTION) 80 81 static int 82 iscsi_initialize_pdu_pool(void) 83 { 84 struct spdk_iscsi_globals *iscsi = &g_iscsi; 85 int imm_mobj_size = SPDK_BDEV_BUF_SIZE_WITH_MD(iscsi_get_max_immediate_data_size()) + 86 sizeof(struct spdk_mobj) + ISCSI_DATA_BUFFER_ALIGNMENT; 87 int dout_mobj_size = SPDK_BDEV_BUF_SIZE_WITH_MD(SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH) + 88 sizeof(struct spdk_mobj) + ISCSI_DATA_BUFFER_ALIGNMENT; 89 90 /* create PDU pool */ 91 iscsi->pdu_pool = spdk_mempool_create("PDU_Pool", 92 PDU_POOL_SIZE(iscsi), 93 sizeof(struct spdk_iscsi_pdu), 94 256, SPDK_ENV_SOCKET_ID_ANY); 95 if (!iscsi->pdu_pool) { 96 SPDK_ERRLOG("create PDU pool failed\n"); 97 return -1; 98 } 99 100 iscsi->pdu_immediate_data_pool = spdk_mempool_create_ctor("PDU_immediate_data_Pool", 101 IMMEDIATE_DATA_POOL_SIZE(iscsi), 102 imm_mobj_size, 256, 103 SPDK_ENV_SOCKET_ID_ANY, 104 mobj_ctor, NULL); 105 if (!iscsi->pdu_immediate_data_pool) { 106 SPDK_ERRLOG("create PDU immediate data pool failed\n"); 107 return -1; 108 } 109 110 iscsi->pdu_data_out_pool = spdk_mempool_create_ctor("PDU_data_out_Pool", 111 DATA_OUT_POOL_SIZE(iscsi), 112 dout_mobj_size, 256, 113 SPDK_ENV_SOCKET_ID_ANY, 114 mobj_ctor, NULL); 115 if (!iscsi->pdu_data_out_pool) { 116 SPDK_ERRLOG("create PDU data out pool failed\n"); 117 return -1; 118 } 119 120 return 0; 121 } 122 123 static void 124 iscsi_sess_ctor(struct spdk_mempool *pool, void *arg, void *session_buf, 125 unsigned index) 126 { 127 struct spdk_iscsi_globals *iscsi = arg; 128 struct spdk_iscsi_sess *sess = session_buf; 129 130 iscsi->session[index] = sess; 131 132 /* tsih 0 is reserved, so start tsih values at 1. */ 133 sess->tsih = index + 1; 134 } 135 136 #define DEFAULT_TASK_POOL_SIZE 32768 137 138 static int 139 iscsi_initialize_task_pool(void) 140 { 141 struct spdk_iscsi_globals *iscsi = &g_iscsi; 142 143 /* create scsi_task pool */ 144 iscsi->task_pool = spdk_mempool_create("SCSI_TASK_Pool", 145 DEFAULT_TASK_POOL_SIZE, 146 sizeof(struct spdk_iscsi_task), 147 128, SPDK_ENV_SOCKET_ID_ANY); 148 if (!iscsi->task_pool) { 149 SPDK_ERRLOG("create task pool failed\n"); 150 return -1; 151 } 152 153 return 0; 154 } 155 156 #define SESSION_POOL_SIZE(iscsi) (iscsi->MaxSessions) 157 static int 158 iscsi_initialize_session_pool(void) 159 { 160 struct spdk_iscsi_globals *iscsi = &g_iscsi; 161 162 iscsi->session_pool = spdk_mempool_create_ctor("Session_Pool", 163 SESSION_POOL_SIZE(iscsi), 164 sizeof(struct spdk_iscsi_sess), 0, 165 SPDK_ENV_SOCKET_ID_ANY, 166 iscsi_sess_ctor, iscsi); 167 if (!iscsi->session_pool) { 168 SPDK_ERRLOG("create session pool failed\n"); 169 return -1; 170 } 171 172 return 0; 173 } 174 175 static int 176 iscsi_initialize_all_pools(void) 177 { 178 if (iscsi_initialize_pdu_pool() != 0) { 179 return -1; 180 } 181 182 if (iscsi_initialize_session_pool() != 0) { 183 return -1; 184 } 185 186 if (iscsi_initialize_task_pool() != 0) { 187 return -1; 188 } 189 190 return 0; 191 } 192 193 static void 194 iscsi_check_pool(struct spdk_mempool *pool, size_t count) 195 { 196 if (pool && spdk_mempool_count(pool) != count) { 197 SPDK_ERRLOG("spdk_mempool_count(%s) == %zu, should be %zu\n", 198 spdk_mempool_get_name(pool), spdk_mempool_count(pool), count); 199 } 200 } 201 202 static void 203 iscsi_check_pools(void) 204 { 205 struct spdk_iscsi_globals *iscsi = &g_iscsi; 206 207 iscsi_check_pool(iscsi->pdu_pool, PDU_POOL_SIZE(iscsi)); 208 iscsi_check_pool(iscsi->session_pool, SESSION_POOL_SIZE(iscsi)); 209 iscsi_check_pool(iscsi->pdu_immediate_data_pool, IMMEDIATE_DATA_POOL_SIZE(iscsi)); 210 iscsi_check_pool(iscsi->pdu_data_out_pool, DATA_OUT_POOL_SIZE(iscsi)); 211 iscsi_check_pool(iscsi->task_pool, DEFAULT_TASK_POOL_SIZE); 212 } 213 214 static void 215 iscsi_free_pools(void) 216 { 217 struct spdk_iscsi_globals *iscsi = &g_iscsi; 218 219 spdk_mempool_free(iscsi->pdu_pool); 220 spdk_mempool_free(iscsi->session_pool); 221 spdk_mempool_free(iscsi->pdu_immediate_data_pool); 222 spdk_mempool_free(iscsi->pdu_data_out_pool); 223 spdk_mempool_free(iscsi->task_pool); 224 } 225 226 void iscsi_put_pdu(struct spdk_iscsi_pdu *pdu) 227 { 228 if (!pdu) { 229 return; 230 } 231 232 assert(pdu->ref > 0); 233 pdu->ref--; 234 235 if (pdu->ref == 0) { 236 if (pdu->mobj) { 237 spdk_mempool_put(pdu->mobj->mp, (void *)pdu->mobj); 238 } 239 240 if (pdu->data && !pdu->data_from_mempool) { 241 free(pdu->data); 242 } 243 244 spdk_mempool_put(g_iscsi.pdu_pool, (void *)pdu); 245 } 246 } 247 248 struct spdk_iscsi_pdu *iscsi_get_pdu(struct spdk_iscsi_conn *conn) 249 { 250 struct spdk_iscsi_pdu *pdu; 251 252 assert(conn != NULL); 253 pdu = spdk_mempool_get(g_iscsi.pdu_pool); 254 if (!pdu) { 255 SPDK_ERRLOG("Unable to get PDU\n"); 256 abort(); 257 } 258 259 /* we do not want to zero out the last part of the structure reserved for AHS and sense data */ 260 memset(pdu, 0, offsetof(struct spdk_iscsi_pdu, ahs)); 261 pdu->ref = 1; 262 pdu->conn = conn; 263 264 return pdu; 265 } 266 267 static void 268 iscsi_log_globals(void) 269 { 270 SPDK_DEBUGLOG(iscsi, "AuthFile %s\n", 271 g_iscsi.authfile ? g_iscsi.authfile : "(none)"); 272 SPDK_DEBUGLOG(iscsi, "NodeBase %s\n", g_iscsi.nodebase); 273 SPDK_DEBUGLOG(iscsi, "MaxSessions %d\n", g_iscsi.MaxSessions); 274 SPDK_DEBUGLOG(iscsi, "MaxConnectionsPerSession %d\n", 275 g_iscsi.MaxConnectionsPerSession); 276 SPDK_DEBUGLOG(iscsi, "MaxQueueDepth %d\n", g_iscsi.MaxQueueDepth); 277 SPDK_DEBUGLOG(iscsi, "DefaultTime2Wait %d\n", 278 g_iscsi.DefaultTime2Wait); 279 SPDK_DEBUGLOG(iscsi, "DefaultTime2Retain %d\n", 280 g_iscsi.DefaultTime2Retain); 281 SPDK_DEBUGLOG(iscsi, "FirstBurstLength %d\n", 282 g_iscsi.FirstBurstLength); 283 SPDK_DEBUGLOG(iscsi, "ImmediateData %s\n", 284 g_iscsi.ImmediateData ? "Yes" : "No"); 285 SPDK_DEBUGLOG(iscsi, "AllowDuplicateIsid %s\n", 286 g_iscsi.AllowDuplicateIsid ? "Yes" : "No"); 287 SPDK_DEBUGLOG(iscsi, "ErrorRecoveryLevel %d\n", 288 g_iscsi.ErrorRecoveryLevel); 289 SPDK_DEBUGLOG(iscsi, "Timeout %d\n", g_iscsi.timeout); 290 SPDK_DEBUGLOG(iscsi, "NopInInterval %d\n", 291 g_iscsi.nopininterval); 292 if (g_iscsi.disable_chap) { 293 SPDK_DEBUGLOG(iscsi, 294 "DiscoveryAuthMethod None\n"); 295 } else if (!g_iscsi.require_chap) { 296 SPDK_DEBUGLOG(iscsi, 297 "DiscoveryAuthMethod Auto\n"); 298 } else { 299 SPDK_DEBUGLOG(iscsi, 300 "DiscoveryAuthMethod %s %s\n", 301 g_iscsi.require_chap ? "CHAP" : "", 302 g_iscsi.mutual_chap ? "Mutual" : ""); 303 } 304 305 if (g_iscsi.chap_group == 0) { 306 SPDK_DEBUGLOG(iscsi, 307 "DiscoveryAuthGroup None\n"); 308 } else { 309 SPDK_DEBUGLOG(iscsi, 310 "DiscoveryAuthGroup AuthGroup%d\n", 311 g_iscsi.chap_group); 312 } 313 314 SPDK_DEBUGLOG(iscsi, "MaxLargeDataInPerConnection %d\n", 315 g_iscsi.MaxLargeDataInPerConnection); 316 317 SPDK_DEBUGLOG(iscsi, "MaxR2TPerConnection %d\n", 318 g_iscsi.MaxR2TPerConnection); 319 } 320 321 static void 322 iscsi_opts_init(struct spdk_iscsi_opts *opts) 323 { 324 opts->MaxSessions = DEFAULT_MAX_SESSIONS; 325 opts->MaxConnectionsPerSession = DEFAULT_MAX_CONNECTIONS_PER_SESSION; 326 opts->MaxQueueDepth = DEFAULT_MAX_QUEUE_DEPTH; 327 opts->DefaultTime2Wait = DEFAULT_DEFAULTTIME2WAIT; 328 opts->DefaultTime2Retain = DEFAULT_DEFAULTTIME2RETAIN; 329 opts->FirstBurstLength = SPDK_ISCSI_FIRST_BURST_LENGTH; 330 opts->ImmediateData = DEFAULT_IMMEDIATEDATA; 331 opts->AllowDuplicateIsid = false; 332 opts->ErrorRecoveryLevel = DEFAULT_ERRORRECOVERYLEVEL; 333 opts->timeout = DEFAULT_TIMEOUT; 334 opts->nopininterval = DEFAULT_NOPININTERVAL; 335 opts->disable_chap = false; 336 opts->require_chap = false; 337 opts->mutual_chap = false; 338 opts->chap_group = 0; 339 opts->authfile = NULL; 340 opts->nodebase = NULL; 341 opts->MaxLargeDataInPerConnection = DEFAULT_MAX_LARGE_DATAIN_PER_CONNECTION; 342 opts->MaxR2TPerConnection = DEFAULT_MAXR2T; 343 } 344 345 struct spdk_iscsi_opts * 346 iscsi_opts_alloc(void) 347 { 348 struct spdk_iscsi_opts *opts; 349 350 opts = calloc(1, sizeof(*opts)); 351 if (!opts) { 352 SPDK_ERRLOG("calloc() failed for iscsi options\n"); 353 return NULL; 354 } 355 356 iscsi_opts_init(opts); 357 358 return opts; 359 } 360 361 void 362 iscsi_opts_free(struct spdk_iscsi_opts *opts) 363 { 364 free(opts->authfile); 365 free(opts->nodebase); 366 free(opts); 367 } 368 369 /* Deep copy of spdk_iscsi_opts */ 370 struct spdk_iscsi_opts * 371 iscsi_opts_copy(struct spdk_iscsi_opts *src) 372 { 373 struct spdk_iscsi_opts *dst; 374 375 dst = calloc(1, sizeof(*dst)); 376 if (!dst) { 377 SPDK_ERRLOG("calloc() failed for iscsi options\n"); 378 return NULL; 379 } 380 381 if (src->authfile) { 382 dst->authfile = strdup(src->authfile); 383 if (!dst->authfile) { 384 free(dst); 385 SPDK_ERRLOG("failed to strdup for auth file %s\n", src->authfile); 386 return NULL; 387 } 388 } 389 390 if (src->nodebase) { 391 dst->nodebase = strdup(src->nodebase); 392 if (!dst->nodebase) { 393 free(dst->authfile); 394 free(dst); 395 SPDK_ERRLOG("failed to strdup for nodebase %s\n", src->nodebase); 396 return NULL; 397 } 398 } 399 400 dst->MaxSessions = src->MaxSessions; 401 dst->MaxConnectionsPerSession = src->MaxConnectionsPerSession; 402 dst->MaxQueueDepth = src->MaxQueueDepth; 403 dst->DefaultTime2Wait = src->DefaultTime2Wait; 404 dst->DefaultTime2Retain = src->DefaultTime2Retain; 405 dst->FirstBurstLength = src->FirstBurstLength; 406 dst->ImmediateData = src->ImmediateData; 407 dst->AllowDuplicateIsid = src->AllowDuplicateIsid; 408 dst->ErrorRecoveryLevel = src->ErrorRecoveryLevel; 409 dst->timeout = src->timeout; 410 dst->nopininterval = src->nopininterval; 411 dst->disable_chap = src->disable_chap; 412 dst->require_chap = src->require_chap; 413 dst->mutual_chap = src->mutual_chap; 414 dst->chap_group = src->chap_group; 415 dst->MaxLargeDataInPerConnection = src->MaxLargeDataInPerConnection; 416 dst->MaxR2TPerConnection = src->MaxR2TPerConnection; 417 418 return dst; 419 } 420 421 static int 422 iscsi_opts_verify(struct spdk_iscsi_opts *opts) 423 { 424 if (!opts->nodebase) { 425 opts->nodebase = strdup(SPDK_ISCSI_DEFAULT_NODEBASE); 426 if (opts->nodebase == NULL) { 427 SPDK_ERRLOG("strdup() failed for default nodebase\n"); 428 return -ENOMEM; 429 } 430 } 431 432 if (opts->MaxSessions == 0 || opts->MaxSessions > 65535) { 433 SPDK_ERRLOG("%d is invalid. MaxSessions must be more than 0 and no more than 65535\n", 434 opts->MaxSessions); 435 return -EINVAL; 436 } 437 438 if (opts->MaxConnectionsPerSession == 0 || opts->MaxConnectionsPerSession > 65535) { 439 SPDK_ERRLOG("%d is invalid. MaxConnectionsPerSession must be more than 0 and no more than 65535\n", 440 opts->MaxConnectionsPerSession); 441 return -EINVAL; 442 } 443 444 if (opts->MaxQueueDepth == 0 || opts->MaxQueueDepth > 256) { 445 SPDK_ERRLOG("%d is invalid. MaxQueueDepth must be more than 0 and no more than 256\n", 446 opts->MaxQueueDepth); 447 return -EINVAL; 448 } 449 450 if (opts->DefaultTime2Wait > 3600) { 451 SPDK_ERRLOG("%d is invalid. DefaultTime2Wait must be no more than 3600\n", 452 opts->DefaultTime2Wait); 453 return -EINVAL; 454 } 455 456 if (opts->DefaultTime2Retain > 3600) { 457 SPDK_ERRLOG("%d is invalid. DefaultTime2Retain must be no more than 3600\n", 458 opts->DefaultTime2Retain); 459 return -EINVAL; 460 } 461 462 if (opts->FirstBurstLength >= SPDK_ISCSI_MIN_FIRST_BURST_LENGTH) { 463 if (opts->FirstBurstLength > SPDK_ISCSI_MAX_BURST_LENGTH) { 464 SPDK_ERRLOG("FirstBurstLength %d shall not exceed MaxBurstLength %d\n", 465 opts->FirstBurstLength, SPDK_ISCSI_MAX_BURST_LENGTH); 466 return -EINVAL; 467 } 468 } else { 469 SPDK_ERRLOG("FirstBurstLength %d shall be no less than %d\n", 470 opts->FirstBurstLength, SPDK_ISCSI_MIN_FIRST_BURST_LENGTH); 471 return -EINVAL; 472 } 473 474 if (opts->ErrorRecoveryLevel > 2) { 475 SPDK_ERRLOG("ErrorRecoveryLevel %d is not supported.\n", opts->ErrorRecoveryLevel); 476 return -EINVAL; 477 } 478 479 if (opts->timeout < 0) { 480 SPDK_ERRLOG("%d is invalid. timeout must not be less than 0\n", opts->timeout); 481 return -EINVAL; 482 } 483 484 if (opts->nopininterval < 0 || opts->nopininterval > MAX_NOPININTERVAL) { 485 SPDK_ERRLOG("%d is invalid. nopinterval must be between 0 and %d\n", 486 opts->nopininterval, MAX_NOPININTERVAL); 487 return -EINVAL; 488 } 489 490 if (!iscsi_check_chap_params(opts->disable_chap, opts->require_chap, 491 opts->mutual_chap, opts->chap_group)) { 492 SPDK_ERRLOG("CHAP params in opts are illegal combination\n"); 493 return -EINVAL; 494 } 495 496 if (opts->MaxLargeDataInPerConnection == 0) { 497 SPDK_ERRLOG("0 is invalid. MaxLargeDataInPerConnection must be more than 0\n"); 498 return -EINVAL; 499 } 500 501 if (opts->MaxR2TPerConnection == 0) { 502 SPDK_ERRLOG("0 is invalid. MaxR2TPerConnection must be more than 0\n"); 503 return -EINVAL; 504 } 505 506 return 0; 507 } 508 509 static int 510 iscsi_set_global_params(struct spdk_iscsi_opts *opts) 511 { 512 int rc; 513 514 rc = iscsi_opts_verify(opts); 515 if (rc != 0) { 516 SPDK_ERRLOG("spdk_iscsi_opts_verify() failed\n"); 517 return rc; 518 } 519 520 if (opts->authfile != NULL) { 521 g_iscsi.authfile = strdup(opts->authfile); 522 if (!g_iscsi.authfile) { 523 SPDK_ERRLOG("failed to strdup for auth file %s\n", opts->authfile); 524 return -ENOMEM; 525 } 526 } 527 528 g_iscsi.nodebase = strdup(opts->nodebase); 529 if (!g_iscsi.nodebase) { 530 SPDK_ERRLOG("failed to strdup for nodebase %s\n", opts->nodebase); 531 return -ENOMEM; 532 } 533 534 g_iscsi.MaxSessions = opts->MaxSessions; 535 g_iscsi.MaxConnectionsPerSession = opts->MaxConnectionsPerSession; 536 g_iscsi.MaxQueueDepth = opts->MaxQueueDepth; 537 g_iscsi.DefaultTime2Wait = opts->DefaultTime2Wait; 538 g_iscsi.DefaultTime2Retain = opts->DefaultTime2Retain; 539 g_iscsi.FirstBurstLength = opts->FirstBurstLength; 540 g_iscsi.ImmediateData = opts->ImmediateData; 541 g_iscsi.AllowDuplicateIsid = opts->AllowDuplicateIsid; 542 g_iscsi.ErrorRecoveryLevel = opts->ErrorRecoveryLevel; 543 g_iscsi.timeout = opts->timeout; 544 g_iscsi.nopininterval = opts->nopininterval; 545 g_iscsi.disable_chap = opts->disable_chap; 546 g_iscsi.require_chap = opts->require_chap; 547 g_iscsi.mutual_chap = opts->mutual_chap; 548 g_iscsi.chap_group = opts->chap_group; 549 g_iscsi.MaxLargeDataInPerConnection = opts->MaxLargeDataInPerConnection; 550 g_iscsi.MaxR2TPerConnection = opts->MaxR2TPerConnection; 551 552 iscsi_log_globals(); 553 554 return 0; 555 } 556 557 int 558 iscsi_set_discovery_auth(bool disable_chap, bool require_chap, bool mutual_chap, 559 int32_t chap_group) 560 { 561 if (!iscsi_check_chap_params(disable_chap, require_chap, mutual_chap, 562 chap_group)) { 563 SPDK_ERRLOG("CHAP params are illegal combination\n"); 564 return -EINVAL; 565 } 566 567 pthread_mutex_lock(&g_iscsi.mutex); 568 g_iscsi.disable_chap = disable_chap; 569 g_iscsi.require_chap = require_chap; 570 g_iscsi.mutual_chap = mutual_chap; 571 g_iscsi.chap_group = chap_group; 572 pthread_mutex_unlock(&g_iscsi.mutex); 573 574 return 0; 575 } 576 577 int 578 iscsi_auth_group_add_secret(struct spdk_iscsi_auth_group *group, 579 const char *user, const char *secret, 580 const char *muser, const char *msecret) 581 { 582 struct spdk_iscsi_auth_secret *_secret; 583 size_t len; 584 585 if (user == NULL || secret == NULL) { 586 SPDK_ERRLOG("user and secret must be specified\n"); 587 return -EINVAL; 588 } 589 590 if (muser != NULL && msecret == NULL) { 591 SPDK_ERRLOG("msecret must be specified with muser\n"); 592 return -EINVAL; 593 } 594 595 TAILQ_FOREACH(_secret, &group->secret_head, tailq) { 596 if (strcmp(_secret->user, user) == 0) { 597 SPDK_ERRLOG("user for secret is duplicated\n"); 598 return -EEXIST; 599 } 600 } 601 602 _secret = calloc(1, sizeof(*_secret)); 603 if (_secret == NULL) { 604 SPDK_ERRLOG("calloc() failed for CHAP secret\n"); 605 return -ENOMEM; 606 } 607 608 len = strnlen(user, sizeof(_secret->user)); 609 if (len > sizeof(_secret->user) - 1) { 610 SPDK_ERRLOG("CHAP user longer than %zu characters: %s\n", 611 sizeof(_secret->user) - 1, user); 612 free(_secret); 613 return -EINVAL; 614 } 615 memcpy(_secret->user, user, len); 616 617 len = strnlen(secret, sizeof(_secret->secret)); 618 if (len > sizeof(_secret->secret) - 1) { 619 SPDK_ERRLOG("CHAP secret longer than %zu characters: %s\n", 620 sizeof(_secret->secret) - 1, secret); 621 free(_secret); 622 return -EINVAL; 623 } 624 memcpy(_secret->secret, secret, len); 625 626 if (muser != NULL) { 627 len = strnlen(muser, sizeof(_secret->muser)); 628 if (len > sizeof(_secret->muser) - 1) { 629 SPDK_ERRLOG("Mutual CHAP user longer than %zu characters: %s\n", 630 sizeof(_secret->muser) - 1, muser); 631 free(_secret); 632 return -EINVAL; 633 } 634 memcpy(_secret->muser, muser, len); 635 636 len = strnlen(msecret, sizeof(_secret->msecret)); 637 if (len > sizeof(_secret->msecret) - 1) { 638 SPDK_ERRLOG("Mutual CHAP secret longer than %zu characters: %s\n", 639 sizeof(_secret->msecret) - 1, msecret); 640 free(_secret); 641 return -EINVAL; 642 } 643 memcpy(_secret->msecret, msecret, len); 644 } 645 646 TAILQ_INSERT_TAIL(&group->secret_head, _secret, tailq); 647 return 0; 648 } 649 650 int 651 iscsi_auth_group_delete_secret(struct spdk_iscsi_auth_group *group, 652 const char *user) 653 { 654 struct spdk_iscsi_auth_secret *_secret; 655 656 if (user == NULL) { 657 SPDK_ERRLOG("user must be specified\n"); 658 return -EINVAL; 659 } 660 661 TAILQ_FOREACH(_secret, &group->secret_head, tailq) { 662 if (strcmp(_secret->user, user) == 0) { 663 break; 664 } 665 } 666 667 if (_secret == NULL) { 668 SPDK_ERRLOG("secret is not found\n"); 669 return -ENODEV; 670 } 671 672 TAILQ_REMOVE(&group->secret_head, _secret, tailq); 673 free(_secret); 674 675 return 0; 676 } 677 678 int 679 iscsi_add_auth_group(int32_t tag, struct spdk_iscsi_auth_group **_group) 680 { 681 struct spdk_iscsi_auth_group *group; 682 683 TAILQ_FOREACH(group, &g_iscsi.auth_group_head, tailq) { 684 if (group->tag == tag) { 685 SPDK_ERRLOG("Auth group (%d) already exists\n", tag); 686 return -EEXIST; 687 } 688 } 689 690 group = calloc(1, sizeof(*group)); 691 if (group == NULL) { 692 SPDK_ERRLOG("calloc() failed for auth group\n"); 693 return -ENOMEM; 694 } 695 696 TAILQ_INIT(&group->secret_head); 697 group->tag = tag; 698 699 TAILQ_INSERT_TAIL(&g_iscsi.auth_group_head, group, tailq); 700 701 *_group = group; 702 return 0; 703 } 704 705 void 706 iscsi_delete_auth_group(struct spdk_iscsi_auth_group *group) 707 { 708 struct spdk_iscsi_auth_secret *_secret, *tmp; 709 710 TAILQ_REMOVE(&g_iscsi.auth_group_head, group, tailq); 711 712 TAILQ_FOREACH_SAFE(_secret, &group->secret_head, tailq, tmp) { 713 TAILQ_REMOVE(&group->secret_head, _secret, tailq); 714 free(_secret); 715 } 716 free(group); 717 } 718 719 struct spdk_iscsi_auth_group * 720 iscsi_find_auth_group_by_tag(int32_t tag) 721 { 722 struct spdk_iscsi_auth_group *group; 723 724 TAILQ_FOREACH(group, &g_iscsi.auth_group_head, tailq) { 725 if (group->tag == tag) { 726 return group; 727 } 728 } 729 730 return NULL; 731 } 732 733 static void 734 iscsi_auth_groups_destroy(void) 735 { 736 struct spdk_iscsi_auth_group *group, *tmp; 737 738 TAILQ_FOREACH_SAFE(group, &g_iscsi.auth_group_head, tailq, tmp) { 739 iscsi_delete_auth_group(group); 740 } 741 } 742 743 static int 744 iscsi_parse_auth_group(struct spdk_conf_section *sp) 745 { 746 int rc; 747 int i; 748 int tag; 749 const char *val, *user, *secret, *muser, *msecret; 750 struct spdk_iscsi_auth_group *group = NULL; 751 752 val = spdk_conf_section_get_val(sp, "Comment"); 753 if (val != NULL) { 754 SPDK_DEBUGLOG(iscsi, "Comment %s\n", val); 755 } 756 757 tag = spdk_conf_section_get_num(sp); 758 759 rc = iscsi_add_auth_group(tag, &group); 760 if (rc != 0) { 761 SPDK_ERRLOG("Failed to add auth group\n"); 762 return rc; 763 } 764 765 for (i = 0; ; i++) { 766 val = spdk_conf_section_get_nval(sp, "Auth", i); 767 if (val == NULL) { 768 break; 769 } 770 771 user = spdk_conf_section_get_nmval(sp, "Auth", i, 0); 772 secret = spdk_conf_section_get_nmval(sp, "Auth", i, 1); 773 muser = spdk_conf_section_get_nmval(sp, "Auth", i, 2); 774 msecret = spdk_conf_section_get_nmval(sp, "Auth", i, 3); 775 776 rc = iscsi_auth_group_add_secret(group, user, secret, muser, msecret); 777 if (rc != 0) { 778 SPDK_ERRLOG("Failed to add secret to auth group\n"); 779 iscsi_delete_auth_group(group); 780 return rc; 781 } 782 } 783 784 return 0; 785 } 786 787 static int 788 iscsi_parse_auth_info(void) 789 { 790 struct spdk_conf *config; 791 struct spdk_conf_section *sp; 792 int rc; 793 794 config = spdk_conf_allocate(); 795 if (!config) { 796 SPDK_ERRLOG("Failed to allocate config file\n"); 797 return -ENOMEM; 798 } 799 800 rc = spdk_conf_read(config, g_iscsi.authfile); 801 if (rc != 0) { 802 SPDK_INFOLOG(iscsi, "Failed to load auth file\n"); 803 spdk_conf_free(config); 804 return rc; 805 } 806 807 sp = spdk_conf_first_section(config); 808 while (sp != NULL) { 809 if (spdk_conf_section_match_prefix(sp, "AuthGroup")) { 810 if (spdk_conf_section_get_num(sp) == 0) { 811 SPDK_ERRLOG("Group 0 is invalid\n"); 812 iscsi_auth_groups_destroy(); 813 spdk_conf_free(config); 814 return -EINVAL; 815 } 816 817 rc = iscsi_parse_auth_group(sp); 818 if (rc != 0) { 819 SPDK_ERRLOG("parse_auth_group() failed\n"); 820 iscsi_auth_groups_destroy(); 821 spdk_conf_free(config); 822 return rc; 823 } 824 } 825 sp = spdk_conf_next_section(sp); 826 } 827 828 spdk_conf_free(config); 829 return 0; 830 } 831 832 static struct spdk_iscsi_auth_secret * 833 iscsi_find_auth_secret(const char *authuser, int ag_tag) 834 { 835 struct spdk_iscsi_auth_group *group; 836 struct spdk_iscsi_auth_secret *_secret; 837 838 TAILQ_FOREACH(group, &g_iscsi.auth_group_head, tailq) { 839 if (group->tag == ag_tag) { 840 TAILQ_FOREACH(_secret, &group->secret_head, tailq) { 841 if (strcmp(_secret->user, authuser) == 0) { 842 return _secret; 843 } 844 } 845 } 846 } 847 848 return NULL; 849 } 850 851 int 852 iscsi_chap_get_authinfo(struct iscsi_chap_auth *auth, const char *authuser, 853 int ag_tag) 854 { 855 struct spdk_iscsi_auth_secret *_secret; 856 857 if (authuser == NULL) { 858 return -EINVAL; 859 } 860 861 if (auth->user[0] != '\0') { 862 memset(auth->user, 0, sizeof(auth->user)); 863 memset(auth->secret, 0, sizeof(auth->secret)); 864 memset(auth->muser, 0, sizeof(auth->muser)); 865 memset(auth->msecret, 0, sizeof(auth->msecret)); 866 } 867 868 pthread_mutex_lock(&g_iscsi.mutex); 869 870 _secret = iscsi_find_auth_secret(authuser, ag_tag); 871 if (_secret == NULL) { 872 pthread_mutex_unlock(&g_iscsi.mutex); 873 874 SPDK_ERRLOG("CHAP secret is not found: user:%s, tag:%d\n", 875 authuser, ag_tag); 876 return -ENOENT; 877 } 878 879 memcpy(auth->user, _secret->user, sizeof(auth->user)); 880 memcpy(auth->secret, _secret->secret, sizeof(auth->secret)); 881 882 if (_secret->muser[0] != '\0') { 883 memcpy(auth->muser, _secret->muser, sizeof(auth->muser)); 884 memcpy(auth->msecret, _secret->msecret, sizeof(auth->msecret)); 885 } 886 887 pthread_mutex_unlock(&g_iscsi.mutex); 888 return 0; 889 } 890 891 static int 892 iscsi_initialize_global_params(void) 893 { 894 int rc; 895 896 if (!g_spdk_iscsi_opts) { 897 g_spdk_iscsi_opts = iscsi_opts_alloc(); 898 if (!g_spdk_iscsi_opts) { 899 SPDK_ERRLOG("iscsi_opts_alloc_failed() failed\n"); 900 return -ENOMEM; 901 } 902 } 903 904 rc = iscsi_set_global_params(g_spdk_iscsi_opts); 905 if (rc != 0) { 906 SPDK_ERRLOG("iscsi_set_global_params() failed\n"); 907 } 908 909 iscsi_opts_free(g_spdk_iscsi_opts); 910 g_spdk_iscsi_opts = NULL; 911 912 return rc; 913 } 914 915 static void 916 iscsi_init_complete(int rc) 917 { 918 spdk_iscsi_init_cb cb_fn = g_init_cb_fn; 919 void *cb_arg = g_init_cb_arg; 920 921 g_init_cb_fn = NULL; 922 g_init_cb_arg = NULL; 923 924 cb_fn(cb_arg, rc); 925 } 926 927 static void 928 iscsi_parse_configuration(void) 929 { 930 int rc = 0; 931 932 if (g_iscsi.authfile != NULL) { 933 if (access(g_iscsi.authfile, R_OK) == 0) { 934 rc = iscsi_parse_auth_info(); 935 if (rc < 0) { 936 SPDK_ERRLOG("iscsi_parse_auth_info() failed\n"); 937 } 938 } else { 939 SPDK_INFOLOG(iscsi, "CHAP secret file is not found in the path %s\n", 940 g_iscsi.authfile); 941 } 942 } 943 944 iscsi_init_complete(rc); 945 } 946 947 static int 948 iscsi_poll_group_poll(void *ctx) 949 { 950 struct spdk_iscsi_poll_group *group = ctx; 951 struct spdk_iscsi_conn *conn, *tmp; 952 int rc; 953 954 if (spdk_unlikely(STAILQ_EMPTY(&group->connections))) { 955 return SPDK_POLLER_IDLE; 956 } 957 958 rc = spdk_sock_group_poll(group->sock_group); 959 if (rc < 0) { 960 SPDK_ERRLOG("Failed to poll sock_group=%p\n", group->sock_group); 961 } 962 963 STAILQ_FOREACH_SAFE(conn, &group->connections, pg_link, tmp) { 964 if (conn->state == ISCSI_CONN_STATE_EXITING) { 965 iscsi_conn_destruct(conn); 966 } 967 } 968 969 return rc != 0 ? SPDK_POLLER_BUSY : SPDK_POLLER_IDLE; 970 } 971 972 static int 973 iscsi_poll_group_handle_nop(void *ctx) 974 { 975 struct spdk_iscsi_poll_group *group = ctx; 976 struct spdk_iscsi_conn *conn, *tmp; 977 978 STAILQ_FOREACH_SAFE(conn, &group->connections, pg_link, tmp) { 979 iscsi_conn_handle_nop(conn); 980 } 981 982 return SPDK_POLLER_BUSY; 983 } 984 985 static int 986 iscsi_poll_group_create(void *io_device, void *ctx_buf) 987 { 988 struct spdk_iscsi_poll_group *pg = ctx_buf; 989 990 STAILQ_INIT(&pg->connections); 991 pg->sock_group = spdk_sock_group_create(NULL); 992 assert(pg->sock_group != NULL); 993 994 pg->poller = SPDK_POLLER_REGISTER(iscsi_poll_group_poll, pg, 0); 995 /* set the period to 1 sec */ 996 pg->nop_poller = SPDK_POLLER_REGISTER(iscsi_poll_group_handle_nop, pg, 1000000); 997 998 return 0; 999 } 1000 1001 static void 1002 iscsi_poll_group_destroy(void *io_device, void *ctx_buf) 1003 { 1004 struct spdk_iscsi_poll_group *pg = ctx_buf; 1005 struct spdk_io_channel *ch; 1006 struct spdk_thread *thread; 1007 1008 assert(pg->poller != NULL); 1009 assert(pg->sock_group != NULL); 1010 1011 spdk_sock_group_close(&pg->sock_group); 1012 spdk_poller_unregister(&pg->poller); 1013 spdk_poller_unregister(&pg->nop_poller); 1014 1015 ch = spdk_io_channel_from_ctx(pg); 1016 thread = spdk_io_channel_get_thread(ch); 1017 1018 assert(thread == spdk_get_thread()); 1019 1020 spdk_thread_exit(thread); 1021 } 1022 1023 static void 1024 _iscsi_init_thread_done(void *ctx) 1025 { 1026 struct spdk_iscsi_poll_group *pg = ctx; 1027 1028 TAILQ_INSERT_TAIL(&g_iscsi.poll_group_head, pg, link); 1029 if (--g_iscsi.refcnt == 0) { 1030 iscsi_parse_configuration(); 1031 } 1032 } 1033 1034 static void 1035 _iscsi_init_thread(void *ctx) 1036 { 1037 struct spdk_io_channel *ch; 1038 struct spdk_iscsi_poll_group *pg; 1039 1040 ch = spdk_get_io_channel(&g_iscsi); 1041 pg = spdk_io_channel_get_ctx(ch); 1042 1043 spdk_thread_send_msg(g_init_thread, _iscsi_init_thread_done, pg); 1044 } 1045 1046 static void 1047 initialize_iscsi_poll_group(void) 1048 { 1049 struct spdk_cpuset tmp_cpumask = {}; 1050 uint32_t i; 1051 char thread_name[32]; 1052 struct spdk_thread *thread; 1053 1054 spdk_io_device_register(&g_iscsi, iscsi_poll_group_create, iscsi_poll_group_destroy, 1055 sizeof(struct spdk_iscsi_poll_group), "iscsi_tgt"); 1056 1057 /* Create threads for CPU cores active for this application, and send a 1058 * message to each thread to create a poll group on it. 1059 */ 1060 g_init_thread = spdk_get_thread(); 1061 assert(g_init_thread != NULL); 1062 assert(g_iscsi.refcnt == 0); 1063 1064 SPDK_ENV_FOREACH_CORE(i) { 1065 spdk_cpuset_zero(&tmp_cpumask); 1066 spdk_cpuset_set_cpu(&tmp_cpumask, i, true); 1067 snprintf(thread_name, sizeof(thread_name), "iscsi_poll_group_%u", i); 1068 1069 thread = spdk_thread_create(thread_name, &tmp_cpumask); 1070 assert(thread != NULL); 1071 1072 g_iscsi.refcnt++; 1073 spdk_thread_send_msg(thread, _iscsi_init_thread, NULL); 1074 } 1075 } 1076 1077 static int 1078 iscsi_parse_globals(void) 1079 { 1080 int rc; 1081 1082 rc = iscsi_initialize_global_params(); 1083 if (rc != 0) { 1084 SPDK_ERRLOG("iscsi_initialize_iscsi_global_params() failed\n"); 1085 return rc; 1086 } 1087 1088 g_iscsi.session = calloc(1, sizeof(struct spdk_iscsi_sess *) * g_iscsi.MaxSessions); 1089 if (!g_iscsi.session) { 1090 SPDK_ERRLOG("calloc() failed for session array\n"); 1091 return -1; 1092 } 1093 1094 /* 1095 * For now, just support same number of total connections, rather 1096 * than MaxSessions * MaxConnectionsPerSession. After we add better 1097 * handling for low resource conditions from our various buffer 1098 * pools, we can bump this up to support more connections. 1099 */ 1100 g_iscsi.MaxConnections = g_iscsi.MaxSessions; 1101 1102 rc = iscsi_initialize_all_pools(); 1103 if (rc != 0) { 1104 SPDK_ERRLOG("initialize_all_pools() failed\n"); 1105 free(g_iscsi.session); 1106 g_iscsi.session = NULL; 1107 return -1; 1108 } 1109 1110 rc = initialize_iscsi_conns(); 1111 if (rc < 0) { 1112 SPDK_ERRLOG("initialize_iscsi_conns() failed\n"); 1113 free(g_iscsi.session); 1114 g_iscsi.session = NULL; 1115 return rc; 1116 } 1117 1118 initialize_iscsi_poll_group(); 1119 return 0; 1120 } 1121 1122 void 1123 spdk_iscsi_init(spdk_iscsi_init_cb cb_fn, void *cb_arg) 1124 { 1125 int rc; 1126 1127 assert(cb_fn != NULL); 1128 g_init_cb_fn = cb_fn; 1129 g_init_cb_arg = cb_arg; 1130 1131 rc = iscsi_parse_globals(); 1132 if (rc < 0) { 1133 SPDK_ERRLOG("iscsi_parse_globals() failed\n"); 1134 iscsi_init_complete(-1); 1135 } 1136 1137 /* 1138 * iscsi_parse_configuration() will be called as the callback to 1139 * spdk_initialize_iscsi_poll_group() and will complete iSCSI 1140 * subsystem initialization. 1141 */ 1142 } 1143 1144 void 1145 spdk_iscsi_fini(spdk_iscsi_fini_cb cb_fn, void *cb_arg) 1146 { 1147 g_fini_cb_fn = cb_fn; 1148 g_fini_cb_arg = cb_arg; 1149 1150 iscsi_portal_grp_close_all(); 1151 shutdown_iscsi_conns(); 1152 } 1153 1154 static void 1155 iscsi_fini_done(void *io_device) 1156 { 1157 free(g_iscsi.authfile); 1158 free(g_iscsi.nodebase); 1159 1160 pthread_mutex_destroy(&g_iscsi.mutex); 1161 g_fini_cb_fn(g_fini_cb_arg); 1162 } 1163 1164 static void 1165 _iscsi_fini_dev_unreg(struct spdk_io_channel_iter *i, int status) 1166 { 1167 iscsi_check_pools(); 1168 iscsi_free_pools(); 1169 free(g_iscsi.session); 1170 1171 assert(TAILQ_EMPTY(&g_iscsi.poll_group_head)); 1172 1173 iscsi_shutdown_tgt_nodes(); 1174 iscsi_init_grps_destroy(); 1175 iscsi_portal_grps_destroy(); 1176 iscsi_auth_groups_destroy(); 1177 1178 spdk_io_device_unregister(&g_iscsi, iscsi_fini_done); 1179 } 1180 1181 static void 1182 _iscsi_fini_thread(struct spdk_io_channel_iter *i) 1183 { 1184 struct spdk_io_channel *ch; 1185 struct spdk_iscsi_poll_group *pg; 1186 1187 ch = spdk_io_channel_iter_get_channel(i); 1188 pg = spdk_io_channel_get_ctx(ch); 1189 1190 pthread_mutex_lock(&g_iscsi.mutex); 1191 TAILQ_REMOVE(&g_iscsi.poll_group_head, pg, link); 1192 pthread_mutex_unlock(&g_iscsi.mutex); 1193 1194 spdk_put_io_channel(ch); 1195 1196 spdk_for_each_channel_continue(i, 0); 1197 } 1198 1199 void 1200 shutdown_iscsi_conns_done(void) 1201 { 1202 spdk_for_each_channel(&g_iscsi, _iscsi_fini_thread, NULL, _iscsi_fini_dev_unreg); 1203 } 1204 1205 void 1206 iscsi_opts_info_json(struct spdk_json_write_ctx *w) 1207 { 1208 spdk_json_write_object_begin(w); 1209 1210 if (g_iscsi.authfile != NULL) { 1211 spdk_json_write_named_string(w, "auth_file", g_iscsi.authfile); 1212 } 1213 spdk_json_write_named_string(w, "node_base", g_iscsi.nodebase); 1214 1215 spdk_json_write_named_uint32(w, "max_sessions", g_iscsi.MaxSessions); 1216 spdk_json_write_named_uint32(w, "max_connections_per_session", 1217 g_iscsi.MaxConnectionsPerSession); 1218 1219 spdk_json_write_named_uint32(w, "max_queue_depth", g_iscsi.MaxQueueDepth); 1220 1221 spdk_json_write_named_uint32(w, "default_time2wait", g_iscsi.DefaultTime2Wait); 1222 spdk_json_write_named_uint32(w, "default_time2retain", g_iscsi.DefaultTime2Retain); 1223 1224 spdk_json_write_named_uint32(w, "first_burst_length", g_iscsi.FirstBurstLength); 1225 1226 spdk_json_write_named_bool(w, "immediate_data", g_iscsi.ImmediateData); 1227 1228 spdk_json_write_named_bool(w, "allow_duplicated_isid", g_iscsi.AllowDuplicateIsid); 1229 1230 spdk_json_write_named_uint32(w, "error_recovery_level", g_iscsi.ErrorRecoveryLevel); 1231 1232 spdk_json_write_named_int32(w, "nop_timeout", g_iscsi.timeout); 1233 spdk_json_write_named_int32(w, "nop_in_interval", g_iscsi.nopininterval); 1234 1235 spdk_json_write_named_bool(w, "disable_chap", g_iscsi.disable_chap); 1236 spdk_json_write_named_bool(w, "require_chap", g_iscsi.require_chap); 1237 spdk_json_write_named_bool(w, "mutual_chap", g_iscsi.mutual_chap); 1238 spdk_json_write_named_int32(w, "chap_group", g_iscsi.chap_group); 1239 1240 spdk_json_write_named_uint32(w, "max_large_datain_per_connection", 1241 g_iscsi.MaxLargeDataInPerConnection); 1242 spdk_json_write_named_uint32(w, "max_r2t_per_connection", 1243 g_iscsi.MaxR2TPerConnection); 1244 1245 spdk_json_write_object_end(w); 1246 } 1247 1248 static void 1249 iscsi_auth_group_info_json(struct spdk_iscsi_auth_group *group, 1250 struct spdk_json_write_ctx *w) 1251 { 1252 struct spdk_iscsi_auth_secret *_secret; 1253 1254 spdk_json_write_object_begin(w); 1255 1256 spdk_json_write_named_int32(w, "tag", group->tag); 1257 1258 spdk_json_write_named_array_begin(w, "secrets"); 1259 TAILQ_FOREACH(_secret, &group->secret_head, tailq) { 1260 spdk_json_write_object_begin(w); 1261 1262 spdk_json_write_named_string(w, "user", _secret->user); 1263 spdk_json_write_named_string(w, "secret", _secret->secret); 1264 1265 if (_secret->muser[0] != '\0') { 1266 spdk_json_write_named_string(w, "muser", _secret->muser); 1267 spdk_json_write_named_string(w, "msecret", _secret->msecret); 1268 } 1269 1270 spdk_json_write_object_end(w); 1271 } 1272 spdk_json_write_array_end(w); 1273 1274 spdk_json_write_object_end(w); 1275 } 1276 1277 static void 1278 iscsi_auth_group_config_json(struct spdk_iscsi_auth_group *group, 1279 struct spdk_json_write_ctx *w) 1280 { 1281 spdk_json_write_object_begin(w); 1282 1283 spdk_json_write_named_string(w, "method", "iscsi_create_auth_group"); 1284 1285 spdk_json_write_name(w, "params"); 1286 iscsi_auth_group_info_json(group, w); 1287 1288 spdk_json_write_object_end(w); 1289 } 1290 1291 void 1292 iscsi_auth_groups_info_json(struct spdk_json_write_ctx *w) 1293 { 1294 struct spdk_iscsi_auth_group *group; 1295 1296 TAILQ_FOREACH(group, &g_iscsi.auth_group_head, tailq) { 1297 iscsi_auth_group_info_json(group, w); 1298 } 1299 } 1300 1301 static void 1302 iscsi_auth_groups_config_json(struct spdk_json_write_ctx *w) 1303 { 1304 struct spdk_iscsi_auth_group *group; 1305 1306 TAILQ_FOREACH(group, &g_iscsi.auth_group_head, tailq) { 1307 iscsi_auth_group_config_json(group, w); 1308 } 1309 } 1310 1311 static void 1312 iscsi_opts_config_json(struct spdk_json_write_ctx *w) 1313 { 1314 spdk_json_write_object_begin(w); 1315 1316 spdk_json_write_named_string(w, "method", "iscsi_set_options"); 1317 1318 spdk_json_write_name(w, "params"); 1319 iscsi_opts_info_json(w); 1320 1321 spdk_json_write_object_end(w); 1322 } 1323 1324 void 1325 spdk_iscsi_config_json(struct spdk_json_write_ctx *w) 1326 { 1327 spdk_json_write_array_begin(w); 1328 iscsi_opts_config_json(w); 1329 iscsi_portal_grps_config_json(w); 1330 iscsi_init_grps_config_json(w); 1331 iscsi_tgt_nodes_config_json(w); 1332 iscsi_auth_groups_config_json(w); 1333 spdk_json_write_array_end(w); 1334 } 1335 1336 SPDK_LOG_REGISTER_COMPONENT(iscsi) 1337