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