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