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