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