1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>. 5 * Copyright (c) Intel Corporation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * * Neither the name of Intel Corporation nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include "spdk/stdinc.h" 36 #include "spdk/env.h" 37 #include "spdk/string.h" 38 #include "spdk/sock.h" 39 #include "spdk/likely.h" 40 41 #include "iscsi/iscsi.h" 42 #include "iscsi/init_grp.h" 43 #include "iscsi/portal_grp.h" 44 #include "iscsi/conn.h" 45 #include "iscsi/task.h" 46 #include "iscsi/tgt_node.h" 47 48 #include "spdk_internal/log.h" 49 50 struct spdk_iscsi_opts *g_spdk_iscsi_opts = NULL; 51 52 static struct spdk_thread *g_init_thread = NULL; 53 static spdk_iscsi_init_cb g_init_cb_fn = NULL; 54 static void *g_init_cb_arg = NULL; 55 56 static spdk_iscsi_fini_cb g_fini_cb_fn; 57 static void *g_fini_cb_arg; 58 59 #define ISCSI_CONFIG_TMPL \ 60 "[iSCSI]\n" \ 61 " # node name (not include optional part)\n" \ 62 " # Users can optionally change this to fit their environment.\n" \ 63 " NodeBase \"%s\"\n" \ 64 "\n" \ 65 " # files\n" \ 66 " %s %s\n" \ 67 "\n" \ 68 " # socket I/O timeout sec. (polling is infinity)\n" \ 69 " Timeout %d\n" \ 70 "\n" \ 71 " # authentication information for discovery session\n" \ 72 " DiscoveryAuthMethod %s\n" \ 73 " DiscoveryAuthGroup %s\n" \ 74 "\n" \ 75 " MaxSessions %d\n" \ 76 " MaxConnectionsPerSession %d\n" \ 77 " MaxConnections %d\n" \ 78 " MaxQueueDepth %d\n" \ 79 "\n" \ 80 " # iSCSI initial parameters negotiate with initiators\n" \ 81 " # NOTE: incorrect values might crash\n" \ 82 " DefaultTime2Wait %d\n" \ 83 " DefaultTime2Retain %d\n" \ 84 "\n" \ 85 " FirstBurstLength %d\n" \ 86 " ImmediateData %s\n" \ 87 " ErrorRecoveryLevel %d\n" \ 88 "\n" 89 90 static void 91 iscsi_globals_config_text(FILE *fp) 92 { 93 const char *authmethod = "None"; 94 char authgroup[32] = "None"; 95 96 if (NULL == fp) { 97 return; 98 } 99 100 if (g_iscsi.require_chap) { 101 authmethod = "CHAP"; 102 } else if (g_iscsi.mutual_chap) { 103 authmethod = "CHAP Mutual"; 104 } else if (!g_iscsi.disable_chap) { 105 authmethod = "Auto"; 106 } 107 108 if (g_iscsi.chap_group) { 109 snprintf(authgroup, sizeof(authgroup), "AuthGroup%d", g_iscsi.chap_group); 110 } 111 112 fprintf(fp, ISCSI_CONFIG_TMPL, 113 g_iscsi.nodebase, 114 g_iscsi.authfile ? "AuthFile" : "", 115 g_iscsi.authfile ? g_iscsi.authfile : "", 116 g_iscsi.timeout, authmethod, authgroup, 117 g_iscsi.MaxSessions, g_iscsi.MaxConnectionsPerSession, 118 g_iscsi.MaxConnections, 119 g_iscsi.MaxQueueDepth, 120 g_iscsi.DefaultTime2Wait, g_iscsi.DefaultTime2Retain, 121 g_iscsi.FirstBurstLength, 122 (g_iscsi.ImmediateData) ? "Yes" : "No", 123 g_iscsi.ErrorRecoveryLevel); 124 } 125 126 #define ISCSI_DATA_BUFFER_ALIGNMENT (0x1000) 127 #define ISCSI_DATA_BUFFER_MASK (ISCSI_DATA_BUFFER_ALIGNMENT - 1) 128 129 static void 130 mobj_ctor(struct spdk_mempool *mp, __attribute__((unused)) void *arg, 131 void *_m, __attribute__((unused)) unsigned i) 132 { 133 struct spdk_mobj *m = _m; 134 135 m->mp = mp; 136 m->buf = (uint8_t *)m + sizeof(struct spdk_mobj); 137 m->buf = (void *)((unsigned long)((uint8_t *)m->buf + ISCSI_DATA_BUFFER_ALIGNMENT) & 138 ~ISCSI_DATA_BUFFER_MASK); 139 } 140 141 #define NUM_PDU_PER_CONNECTION(iscsi) (2 * (iscsi->MaxQueueDepth + \ 142 iscsi->MaxLargeDataInPerConnection + \ 143 2 * iscsi->MaxR2TPerConnection + 8)) 144 #define PDU_POOL_SIZE(iscsi) (iscsi->MaxConnections * NUM_PDU_PER_CONNECTION(iscsi)) 145 #define IMMEDIATE_DATA_POOL_SIZE(iscsi) (iscsi->MaxConnections * 128) 146 #define DATA_OUT_POOL_SIZE(iscsi) (iscsi->MaxConnections * MAX_DATA_OUT_PER_CONNECTION) 147 148 static int 149 iscsi_initialize_pdu_pool(void) 150 { 151 struct spdk_iscsi_globals *iscsi = &g_iscsi; 152 int imm_mobj_size = SPDK_BDEV_BUF_SIZE_WITH_MD(iscsi_get_max_immediate_data_size()) + 153 sizeof(struct spdk_mobj) + ISCSI_DATA_BUFFER_ALIGNMENT; 154 int dout_mobj_size = SPDK_BDEV_BUF_SIZE_WITH_MD(SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH) + 155 sizeof(struct spdk_mobj) + ISCSI_DATA_BUFFER_ALIGNMENT; 156 157 /* create PDU pool */ 158 iscsi->pdu_pool = spdk_mempool_create("PDU_Pool", 159 PDU_POOL_SIZE(iscsi), 160 sizeof(struct spdk_iscsi_pdu), 161 256, SPDK_ENV_SOCKET_ID_ANY); 162 if (!iscsi->pdu_pool) { 163 SPDK_ERRLOG("create PDU pool failed\n"); 164 return -1; 165 } 166 167 iscsi->pdu_immediate_data_pool = spdk_mempool_create_ctor("PDU_immediate_data_Pool", 168 IMMEDIATE_DATA_POOL_SIZE(iscsi), 169 imm_mobj_size, 256, 170 SPDK_ENV_SOCKET_ID_ANY, 171 mobj_ctor, NULL); 172 if (!iscsi->pdu_immediate_data_pool) { 173 SPDK_ERRLOG("create PDU immediate data pool failed\n"); 174 return -1; 175 } 176 177 iscsi->pdu_data_out_pool = spdk_mempool_create_ctor("PDU_data_out_Pool", 178 DATA_OUT_POOL_SIZE(iscsi), 179 dout_mobj_size, 256, 180 SPDK_ENV_SOCKET_ID_ANY, 181 mobj_ctor, NULL); 182 if (!iscsi->pdu_data_out_pool) { 183 SPDK_ERRLOG("create PDU data out pool failed\n"); 184 return -1; 185 } 186 187 return 0; 188 } 189 190 static void 191 iscsi_sess_ctor(struct spdk_mempool *pool, void *arg, void *session_buf, 192 unsigned index) 193 { 194 struct spdk_iscsi_globals *iscsi = arg; 195 struct spdk_iscsi_sess *sess = session_buf; 196 197 iscsi->session[index] = sess; 198 199 /* tsih 0 is reserved, so start tsih values at 1. */ 200 sess->tsih = index + 1; 201 } 202 203 #define DEFAULT_TASK_POOL_SIZE 32768 204 205 static int 206 iscsi_initialize_task_pool(void) 207 { 208 struct spdk_iscsi_globals *iscsi = &g_iscsi; 209 210 /* create scsi_task pool */ 211 iscsi->task_pool = spdk_mempool_create("SCSI_TASK_Pool", 212 DEFAULT_TASK_POOL_SIZE, 213 sizeof(struct spdk_iscsi_task), 214 128, SPDK_ENV_SOCKET_ID_ANY); 215 if (!iscsi->task_pool) { 216 SPDK_ERRLOG("create task pool failed\n"); 217 return -1; 218 } 219 220 return 0; 221 } 222 223 #define SESSION_POOL_SIZE(iscsi) (iscsi->MaxSessions) 224 static int 225 iscsi_initialize_session_pool(void) 226 { 227 struct spdk_iscsi_globals *iscsi = &g_iscsi; 228 229 iscsi->session_pool = spdk_mempool_create_ctor("Session_Pool", 230 SESSION_POOL_SIZE(iscsi), 231 sizeof(struct spdk_iscsi_sess), 0, 232 SPDK_ENV_SOCKET_ID_ANY, 233 iscsi_sess_ctor, iscsi); 234 if (!iscsi->session_pool) { 235 SPDK_ERRLOG("create session pool failed\n"); 236 return -1; 237 } 238 239 return 0; 240 } 241 242 static int 243 iscsi_initialize_all_pools(void) 244 { 245 if (iscsi_initialize_pdu_pool() != 0) { 246 return -1; 247 } 248 249 if (iscsi_initialize_session_pool() != 0) { 250 return -1; 251 } 252 253 if (iscsi_initialize_task_pool() != 0) { 254 return -1; 255 } 256 257 return 0; 258 } 259 260 static void 261 iscsi_check_pool(struct spdk_mempool *pool, size_t count) 262 { 263 if (pool && spdk_mempool_count(pool) != count) { 264 SPDK_ERRLOG("spdk_mempool_count(%s) == %zu, should be %zu\n", 265 spdk_mempool_get_name(pool), spdk_mempool_count(pool), count); 266 } 267 } 268 269 static void 270 iscsi_check_pools(void) 271 { 272 struct spdk_iscsi_globals *iscsi = &g_iscsi; 273 274 iscsi_check_pool(iscsi->pdu_pool, PDU_POOL_SIZE(iscsi)); 275 iscsi_check_pool(iscsi->session_pool, SESSION_POOL_SIZE(iscsi)); 276 iscsi_check_pool(iscsi->pdu_immediate_data_pool, IMMEDIATE_DATA_POOL_SIZE(iscsi)); 277 iscsi_check_pool(iscsi->pdu_data_out_pool, DATA_OUT_POOL_SIZE(iscsi)); 278 iscsi_check_pool(iscsi->task_pool, DEFAULT_TASK_POOL_SIZE); 279 } 280 281 static void 282 iscsi_free_pools(void) 283 { 284 struct spdk_iscsi_globals *iscsi = &g_iscsi; 285 286 spdk_mempool_free(iscsi->pdu_pool); 287 spdk_mempool_free(iscsi->session_pool); 288 spdk_mempool_free(iscsi->pdu_immediate_data_pool); 289 spdk_mempool_free(iscsi->pdu_data_out_pool); 290 spdk_mempool_free(iscsi->task_pool); 291 } 292 293 void iscsi_put_pdu(struct spdk_iscsi_pdu *pdu) 294 { 295 if (!pdu) { 296 return; 297 } 298 299 assert(pdu->ref > 0); 300 pdu->ref--; 301 302 if (pdu->ref == 0) { 303 if (pdu->mobj) { 304 spdk_mempool_put(pdu->mobj->mp, (void *)pdu->mobj); 305 } 306 307 if (pdu->data && !pdu->data_from_mempool) { 308 free(pdu->data); 309 } 310 311 spdk_mempool_put(g_iscsi.pdu_pool, (void *)pdu); 312 } 313 } 314 315 struct spdk_iscsi_pdu *iscsi_get_pdu(struct spdk_iscsi_conn *conn) 316 { 317 struct spdk_iscsi_pdu *pdu; 318 319 assert(conn != NULL); 320 pdu = spdk_mempool_get(g_iscsi.pdu_pool); 321 if (!pdu) { 322 SPDK_ERRLOG("Unable to get PDU\n"); 323 abort(); 324 } 325 326 /* we do not want to zero out the last part of the structure reserved for AHS and sense data */ 327 memset(pdu, 0, offsetof(struct spdk_iscsi_pdu, ahs)); 328 pdu->ref = 1; 329 pdu->conn = conn; 330 331 return pdu; 332 } 333 334 static void 335 iscsi_log_globals(void) 336 { 337 SPDK_DEBUGLOG(iscsi, "AuthFile %s\n", 338 g_iscsi.authfile ? g_iscsi.authfile : "(none)"); 339 SPDK_DEBUGLOG(iscsi, "NodeBase %s\n", g_iscsi.nodebase); 340 SPDK_DEBUGLOG(iscsi, "MaxSessions %d\n", g_iscsi.MaxSessions); 341 SPDK_DEBUGLOG(iscsi, "MaxConnectionsPerSession %d\n", 342 g_iscsi.MaxConnectionsPerSession); 343 SPDK_DEBUGLOG(iscsi, "MaxQueueDepth %d\n", g_iscsi.MaxQueueDepth); 344 SPDK_DEBUGLOG(iscsi, "DefaultTime2Wait %d\n", 345 g_iscsi.DefaultTime2Wait); 346 SPDK_DEBUGLOG(iscsi, "DefaultTime2Retain %d\n", 347 g_iscsi.DefaultTime2Retain); 348 SPDK_DEBUGLOG(iscsi, "FirstBurstLength %d\n", 349 g_iscsi.FirstBurstLength); 350 SPDK_DEBUGLOG(iscsi, "ImmediateData %s\n", 351 g_iscsi.ImmediateData ? "Yes" : "No"); 352 SPDK_DEBUGLOG(iscsi, "AllowDuplicateIsid %s\n", 353 g_iscsi.AllowDuplicateIsid ? "Yes" : "No"); 354 SPDK_DEBUGLOG(iscsi, "ErrorRecoveryLevel %d\n", 355 g_iscsi.ErrorRecoveryLevel); 356 SPDK_DEBUGLOG(iscsi, "Timeout %d\n", g_iscsi.timeout); 357 SPDK_DEBUGLOG(iscsi, "NopInInterval %d\n", 358 g_iscsi.nopininterval); 359 if (g_iscsi.disable_chap) { 360 SPDK_DEBUGLOG(iscsi, 361 "DiscoveryAuthMethod None\n"); 362 } else if (!g_iscsi.require_chap) { 363 SPDK_DEBUGLOG(iscsi, 364 "DiscoveryAuthMethod Auto\n"); 365 } else { 366 SPDK_DEBUGLOG(iscsi, 367 "DiscoveryAuthMethod %s %s\n", 368 g_iscsi.require_chap ? "CHAP" : "", 369 g_iscsi.mutual_chap ? "Mutual" : ""); 370 } 371 372 if (g_iscsi.chap_group == 0) { 373 SPDK_DEBUGLOG(iscsi, 374 "DiscoveryAuthGroup None\n"); 375 } else { 376 SPDK_DEBUGLOG(iscsi, 377 "DiscoveryAuthGroup AuthGroup%d\n", 378 g_iscsi.chap_group); 379 } 380 381 SPDK_DEBUGLOG(iscsi, "MaxLargeDataInPerConnection %d\n", 382 g_iscsi.MaxLargeDataInPerConnection); 383 384 SPDK_DEBUGLOG(iscsi, "MaxR2TPerConnection %d\n", 385 g_iscsi.MaxR2TPerConnection); 386 } 387 388 static void 389 iscsi_opts_init(struct spdk_iscsi_opts *opts) 390 { 391 opts->MaxSessions = DEFAULT_MAX_SESSIONS; 392 opts->MaxConnectionsPerSession = DEFAULT_MAX_CONNECTIONS_PER_SESSION; 393 opts->MaxQueueDepth = DEFAULT_MAX_QUEUE_DEPTH; 394 opts->DefaultTime2Wait = DEFAULT_DEFAULTTIME2WAIT; 395 opts->DefaultTime2Retain = DEFAULT_DEFAULTTIME2RETAIN; 396 opts->FirstBurstLength = SPDK_ISCSI_FIRST_BURST_LENGTH; 397 opts->ImmediateData = DEFAULT_IMMEDIATEDATA; 398 opts->AllowDuplicateIsid = false; 399 opts->ErrorRecoveryLevel = DEFAULT_ERRORRECOVERYLEVEL; 400 opts->timeout = DEFAULT_TIMEOUT; 401 opts->nopininterval = DEFAULT_NOPININTERVAL; 402 opts->disable_chap = false; 403 opts->require_chap = false; 404 opts->mutual_chap = false; 405 opts->chap_group = 0; 406 opts->authfile = NULL; 407 opts->nodebase = NULL; 408 opts->MaxLargeDataInPerConnection = DEFAULT_MAX_LARGE_DATAIN_PER_CONNECTION; 409 opts->MaxR2TPerConnection = DEFAULT_MAXR2T; 410 } 411 412 struct spdk_iscsi_opts * 413 iscsi_opts_alloc(void) 414 { 415 struct spdk_iscsi_opts *opts; 416 417 opts = calloc(1, sizeof(*opts)); 418 if (!opts) { 419 SPDK_ERRLOG("calloc() failed for iscsi options\n"); 420 return NULL; 421 } 422 423 iscsi_opts_init(opts); 424 425 return opts; 426 } 427 428 void 429 iscsi_opts_free(struct spdk_iscsi_opts *opts) 430 { 431 free(opts->authfile); 432 free(opts->nodebase); 433 free(opts); 434 } 435 436 /* Deep copy of spdk_iscsi_opts */ 437 struct spdk_iscsi_opts * 438 iscsi_opts_copy(struct spdk_iscsi_opts *src) 439 { 440 struct spdk_iscsi_opts *dst; 441 442 dst = calloc(1, sizeof(*dst)); 443 if (!dst) { 444 SPDK_ERRLOG("calloc() failed for iscsi options\n"); 445 return NULL; 446 } 447 448 if (src->authfile) { 449 dst->authfile = strdup(src->authfile); 450 if (!dst->authfile) { 451 free(dst); 452 SPDK_ERRLOG("failed to strdup for auth file %s\n", src->authfile); 453 return NULL; 454 } 455 } 456 457 if (src->nodebase) { 458 dst->nodebase = strdup(src->nodebase); 459 if (!dst->nodebase) { 460 free(dst->authfile); 461 free(dst); 462 SPDK_ERRLOG("failed to strdup for nodebase %s\n", src->nodebase); 463 return NULL; 464 } 465 } 466 467 dst->MaxSessions = src->MaxSessions; 468 dst->MaxConnectionsPerSession = src->MaxConnectionsPerSession; 469 dst->MaxQueueDepth = src->MaxQueueDepth; 470 dst->DefaultTime2Wait = src->DefaultTime2Wait; 471 dst->DefaultTime2Retain = src->DefaultTime2Retain; 472 dst->FirstBurstLength = src->FirstBurstLength; 473 dst->ImmediateData = src->ImmediateData; 474 dst->AllowDuplicateIsid = src->AllowDuplicateIsid; 475 dst->ErrorRecoveryLevel = src->ErrorRecoveryLevel; 476 dst->timeout = src->timeout; 477 dst->nopininterval = src->nopininterval; 478 dst->disable_chap = src->disable_chap; 479 dst->require_chap = src->require_chap; 480 dst->mutual_chap = src->mutual_chap; 481 dst->chap_group = src->chap_group; 482 dst->MaxLargeDataInPerConnection = src->MaxLargeDataInPerConnection; 483 dst->MaxR2TPerConnection = src->MaxR2TPerConnection; 484 485 return dst; 486 } 487 488 static int 489 iscsi_read_config_file_params(struct spdk_conf_section *sp, 490 struct spdk_iscsi_opts *opts) 491 { 492 const char *val; 493 int MaxSessions; 494 int MaxConnectionsPerSession; 495 int MaxQueueDepth; 496 int DefaultTime2Wait; 497 int DefaultTime2Retain; 498 int FirstBurstLength; 499 int ErrorRecoveryLevel; 500 int timeout; 501 int nopininterval; 502 const char *ag_tag; 503 int ag_tag_i; 504 int i; 505 506 val = spdk_conf_section_get_val(sp, "Comment"); 507 if (val != NULL) { 508 SPDK_DEBUGLOG(iscsi, "Comment %s\n", val); 509 } 510 511 val = spdk_conf_section_get_val(sp, "AuthFile"); 512 if (val != NULL) { 513 opts->authfile = strdup(val); 514 if (!opts->authfile) { 515 SPDK_ERRLOG("strdup() failed for AuthFile\n"); 516 return -ENOMEM; 517 } 518 } 519 520 val = spdk_conf_section_get_val(sp, "NodeBase"); 521 if (val != NULL) { 522 opts->nodebase = strdup(val); 523 if (!opts->nodebase) { 524 free(opts->authfile); 525 SPDK_ERRLOG("strdup() failed for NodeBase\n"); 526 return -ENOMEM; 527 } 528 } 529 530 MaxSessions = spdk_conf_section_get_intval(sp, "MaxSessions"); 531 if (MaxSessions >= 0) { 532 opts->MaxSessions = MaxSessions; 533 } 534 535 MaxConnectionsPerSession = spdk_conf_section_get_intval(sp, "MaxConnectionsPerSession"); 536 if (MaxConnectionsPerSession >= 0) { 537 opts->MaxConnectionsPerSession = MaxConnectionsPerSession; 538 } 539 540 MaxQueueDepth = spdk_conf_section_get_intval(sp, "MaxQueueDepth"); 541 if (MaxQueueDepth >= 0) { 542 opts->MaxQueueDepth = MaxQueueDepth; 543 } 544 545 DefaultTime2Wait = spdk_conf_section_get_intval(sp, "DefaultTime2Wait"); 546 if (DefaultTime2Wait >= 0) { 547 opts->DefaultTime2Wait = DefaultTime2Wait; 548 } 549 550 DefaultTime2Retain = spdk_conf_section_get_intval(sp, "DefaultTime2Retain"); 551 if (DefaultTime2Retain >= 0) { 552 opts->DefaultTime2Retain = DefaultTime2Retain; 553 } 554 555 FirstBurstLength = spdk_conf_section_get_intval(sp, "FirstBurstLength"); 556 if (FirstBurstLength >= 0) { 557 opts->FirstBurstLength = FirstBurstLength; 558 } 559 560 opts->ImmediateData = spdk_conf_section_get_boolval(sp, "ImmediateData", 561 opts->ImmediateData); 562 563 /* This option is only for test. 564 * If AllowDuplicateIsid is enabled, it allows different connections carrying 565 * TSIH=0 login the target within the same session. 566 */ 567 opts->AllowDuplicateIsid = spdk_conf_section_get_boolval(sp, "AllowDuplicateIsid", 568 opts->AllowDuplicateIsid); 569 570 ErrorRecoveryLevel = spdk_conf_section_get_intval(sp, "ErrorRecoveryLevel"); 571 if (ErrorRecoveryLevel >= 0) { 572 opts->ErrorRecoveryLevel = ErrorRecoveryLevel; 573 } 574 timeout = spdk_conf_section_get_intval(sp, "Timeout"); 575 if (timeout >= 0) { 576 opts->timeout = timeout; 577 } 578 nopininterval = spdk_conf_section_get_intval(sp, "NopInInterval"); 579 if (nopininterval >= 0) { 580 opts->nopininterval = nopininterval; 581 } 582 val = spdk_conf_section_get_val(sp, "DiscoveryAuthMethod"); 583 if (val != NULL) { 584 for (i = 0; ; i++) { 585 val = spdk_conf_section_get_nmval(sp, "DiscoveryAuthMethod", 0, i); 586 if (val == NULL) { 587 break; 588 } 589 if (strcasecmp(val, "CHAP") == 0) { 590 opts->require_chap = true; 591 } else if (strcasecmp(val, "Mutual") == 0) { 592 opts->require_chap = true; 593 opts->mutual_chap = true; 594 } else if (strcasecmp(val, "Auto") == 0) { 595 opts->disable_chap = false; 596 opts->require_chap = false; 597 opts->mutual_chap = false; 598 } else if (strcasecmp(val, "None") == 0) { 599 opts->disable_chap = true; 600 opts->require_chap = false; 601 opts->mutual_chap = false; 602 } else { 603 SPDK_ERRLOG("unknown CHAP mode %s\n", val); 604 } 605 } 606 if (opts->mutual_chap && !opts->require_chap) { 607 free(opts->authfile); 608 free(opts->nodebase); 609 SPDK_ERRLOG("CHAP must set to be required when using mutual CHAP.\n"); 610 return -EINVAL; 611 } 612 } 613 val = spdk_conf_section_get_val(sp, "DiscoveryAuthGroup"); 614 if (val != NULL) { 615 ag_tag = val; 616 if (strcasecmp(ag_tag, "None") == 0) { 617 opts->chap_group = 0; 618 } else { 619 if (strncasecmp(ag_tag, "AuthGroup", 620 strlen("AuthGroup")) != 0 621 || sscanf(ag_tag, "%*[^0-9]%d", &ag_tag_i) != 1 622 || ag_tag_i == 0) { 623 SPDK_ERRLOG("invalid auth group %s, ignoring\n", ag_tag); 624 } else { 625 opts->chap_group = ag_tag_i; 626 } 627 } 628 } 629 630 return 0; 631 } 632 633 static int 634 iscsi_opts_verify(struct spdk_iscsi_opts *opts) 635 { 636 if (!opts->nodebase) { 637 opts->nodebase = strdup(SPDK_ISCSI_DEFAULT_NODEBASE); 638 if (opts->nodebase == NULL) { 639 SPDK_ERRLOG("strdup() failed for default nodebase\n"); 640 return -ENOMEM; 641 } 642 } 643 644 if (opts->MaxSessions == 0 || opts->MaxSessions > 65535) { 645 SPDK_ERRLOG("%d is invalid. MaxSessions must be more than 0 and no more than 65535\n", 646 opts->MaxSessions); 647 return -EINVAL; 648 } 649 650 if (opts->MaxConnectionsPerSession == 0 || opts->MaxConnectionsPerSession > 65535) { 651 SPDK_ERRLOG("%d is invalid. MaxConnectionsPerSession must be more than 0 and no more than 65535\n", 652 opts->MaxConnectionsPerSession); 653 return -EINVAL; 654 } 655 656 if (opts->MaxQueueDepth == 0 || opts->MaxQueueDepth > 256) { 657 SPDK_ERRLOG("%d is invalid. MaxQueueDepth must be more than 0 and no more than 256\n", 658 opts->MaxQueueDepth); 659 return -EINVAL; 660 } 661 662 if (opts->DefaultTime2Wait > 3600) { 663 SPDK_ERRLOG("%d is invalid. DefaultTime2Wait must be no more than 3600\n", 664 opts->DefaultTime2Wait); 665 return -EINVAL; 666 } 667 668 if (opts->DefaultTime2Retain > 3600) { 669 SPDK_ERRLOG("%d is invalid. DefaultTime2Retain must be no more than 3600\n", 670 opts->DefaultTime2Retain); 671 return -EINVAL; 672 } 673 674 if (opts->FirstBurstLength >= SPDK_ISCSI_MIN_FIRST_BURST_LENGTH) { 675 if (opts->FirstBurstLength > SPDK_ISCSI_MAX_BURST_LENGTH) { 676 SPDK_ERRLOG("FirstBurstLength %d shall not exceed MaxBurstLength %d\n", 677 opts->FirstBurstLength, SPDK_ISCSI_MAX_BURST_LENGTH); 678 return -EINVAL; 679 } 680 } else { 681 SPDK_ERRLOG("FirstBurstLength %d shall be no less than %d\n", 682 opts->FirstBurstLength, SPDK_ISCSI_MIN_FIRST_BURST_LENGTH); 683 return -EINVAL; 684 } 685 686 if (opts->ErrorRecoveryLevel > 2) { 687 SPDK_ERRLOG("ErrorRecoveryLevel %d is not supported.\n", opts->ErrorRecoveryLevel); 688 return -EINVAL; 689 } 690 691 if (opts->timeout < 0) { 692 SPDK_ERRLOG("%d is invalid. timeout must not be less than 0\n", opts->timeout); 693 return -EINVAL; 694 } 695 696 if (opts->nopininterval < 0 || opts->nopininterval > MAX_NOPININTERVAL) { 697 SPDK_ERRLOG("%d is invalid. nopinterval must be between 0 and %d\n", 698 opts->nopininterval, MAX_NOPININTERVAL); 699 return -EINVAL; 700 } 701 702 if (!iscsi_check_chap_params(opts->disable_chap, opts->require_chap, 703 opts->mutual_chap, opts->chap_group)) { 704 SPDK_ERRLOG("CHAP params in opts are illegal combination\n"); 705 return -EINVAL; 706 } 707 708 if (opts->MaxLargeDataInPerConnection == 0) { 709 SPDK_ERRLOG("0 is invalid. MaxLargeDataInPerConnection must be more than 0\n"); 710 return -EINVAL; 711 } 712 713 if (opts->MaxR2TPerConnection == 0) { 714 SPDK_ERRLOG("0 is invalid. MaxR2TPerConnection must be more than 0\n"); 715 return -EINVAL; 716 } 717 718 return 0; 719 } 720 721 static int 722 iscsi_parse_options(struct spdk_iscsi_opts **popts) 723 { 724 struct spdk_iscsi_opts *opts; 725 struct spdk_conf_section *sp; 726 int rc; 727 728 opts = iscsi_opts_alloc(); 729 if (!opts) { 730 SPDK_ERRLOG("iscsi_opts_alloc_failed() failed\n"); 731 return -ENOMEM; 732 } 733 734 /* Process parameters */ 735 SPDK_DEBUGLOG(iscsi, "iscsi_read_config_file_parmas\n"); 736 sp = spdk_conf_find_section(NULL, "iSCSI"); 737 if (sp != NULL) { 738 rc = iscsi_read_config_file_params(sp, opts); 739 if (rc != 0) { 740 free(opts); 741 SPDK_ERRLOG("iscsi_read_config_file_params() failed\n"); 742 return rc; 743 } 744 } 745 746 *popts = opts; 747 748 return 0; 749 } 750 751 static int 752 iscsi_set_global_params(struct spdk_iscsi_opts *opts) 753 { 754 int rc; 755 756 rc = iscsi_opts_verify(opts); 757 if (rc != 0) { 758 SPDK_ERRLOG("spdk_iscsi_opts_verify() failed\n"); 759 return rc; 760 } 761 762 if (opts->authfile != NULL) { 763 g_iscsi.authfile = strdup(opts->authfile); 764 if (!g_iscsi.authfile) { 765 SPDK_ERRLOG("failed to strdup for auth file %s\n", opts->authfile); 766 return -ENOMEM; 767 } 768 } 769 770 g_iscsi.nodebase = strdup(opts->nodebase); 771 if (!g_iscsi.nodebase) { 772 SPDK_ERRLOG("failed to strdup for nodebase %s\n", opts->nodebase); 773 return -ENOMEM; 774 } 775 776 g_iscsi.MaxSessions = opts->MaxSessions; 777 g_iscsi.MaxConnectionsPerSession = opts->MaxConnectionsPerSession; 778 g_iscsi.MaxQueueDepth = opts->MaxQueueDepth; 779 g_iscsi.DefaultTime2Wait = opts->DefaultTime2Wait; 780 g_iscsi.DefaultTime2Retain = opts->DefaultTime2Retain; 781 g_iscsi.FirstBurstLength = opts->FirstBurstLength; 782 g_iscsi.ImmediateData = opts->ImmediateData; 783 g_iscsi.AllowDuplicateIsid = opts->AllowDuplicateIsid; 784 g_iscsi.ErrorRecoveryLevel = opts->ErrorRecoveryLevel; 785 g_iscsi.timeout = opts->timeout; 786 g_iscsi.nopininterval = opts->nopininterval; 787 g_iscsi.disable_chap = opts->disable_chap; 788 g_iscsi.require_chap = opts->require_chap; 789 g_iscsi.mutual_chap = opts->mutual_chap; 790 g_iscsi.chap_group = opts->chap_group; 791 g_iscsi.MaxLargeDataInPerConnection = opts->MaxLargeDataInPerConnection; 792 g_iscsi.MaxR2TPerConnection = opts->MaxR2TPerConnection; 793 794 iscsi_log_globals(); 795 796 return 0; 797 } 798 799 int 800 iscsi_set_discovery_auth(bool disable_chap, bool require_chap, bool mutual_chap, 801 int32_t chap_group) 802 { 803 if (!iscsi_check_chap_params(disable_chap, require_chap, mutual_chap, 804 chap_group)) { 805 SPDK_ERRLOG("CHAP params are illegal combination\n"); 806 return -EINVAL; 807 } 808 809 pthread_mutex_lock(&g_iscsi.mutex); 810 g_iscsi.disable_chap = disable_chap; 811 g_iscsi.require_chap = require_chap; 812 g_iscsi.mutual_chap = mutual_chap; 813 g_iscsi.chap_group = chap_group; 814 pthread_mutex_unlock(&g_iscsi.mutex); 815 816 return 0; 817 } 818 819 int 820 iscsi_auth_group_add_secret(struct spdk_iscsi_auth_group *group, 821 const char *user, const char *secret, 822 const char *muser, const char *msecret) 823 { 824 struct spdk_iscsi_auth_secret *_secret; 825 size_t len; 826 827 if (user == NULL || secret == NULL) { 828 SPDK_ERRLOG("user and secret must be specified\n"); 829 return -EINVAL; 830 } 831 832 if (muser != NULL && msecret == NULL) { 833 SPDK_ERRLOG("msecret must be specified with muser\n"); 834 return -EINVAL; 835 } 836 837 TAILQ_FOREACH(_secret, &group->secret_head, tailq) { 838 if (strcmp(_secret->user, user) == 0) { 839 SPDK_ERRLOG("user for secret is duplicated\n"); 840 return -EEXIST; 841 } 842 } 843 844 _secret = calloc(1, sizeof(*_secret)); 845 if (_secret == NULL) { 846 SPDK_ERRLOG("calloc() failed for CHAP secret\n"); 847 return -ENOMEM; 848 } 849 850 len = strnlen(user, sizeof(_secret->user)); 851 if (len > sizeof(_secret->user) - 1) { 852 SPDK_ERRLOG("CHAP user longer than %zu characters: %s\n", 853 sizeof(_secret->user) - 1, user); 854 free(_secret); 855 return -EINVAL; 856 } 857 memcpy(_secret->user, user, len); 858 859 len = strnlen(secret, sizeof(_secret->secret)); 860 if (len > sizeof(_secret->secret) - 1) { 861 SPDK_ERRLOG("CHAP secret longer than %zu characters: %s\n", 862 sizeof(_secret->secret) - 1, secret); 863 free(_secret); 864 return -EINVAL; 865 } 866 memcpy(_secret->secret, secret, len); 867 868 if (muser != NULL) { 869 len = strnlen(muser, sizeof(_secret->muser)); 870 if (len > sizeof(_secret->muser) - 1) { 871 SPDK_ERRLOG("Mutual CHAP user longer than %zu characters: %s\n", 872 sizeof(_secret->muser) - 1, muser); 873 free(_secret); 874 return -EINVAL; 875 } 876 memcpy(_secret->muser, muser, len); 877 878 len = strnlen(msecret, sizeof(_secret->msecret)); 879 if (len > sizeof(_secret->msecret) - 1) { 880 SPDK_ERRLOG("Mutual CHAP secret longer than %zu characters: %s\n", 881 sizeof(_secret->msecret) - 1, msecret); 882 free(_secret); 883 return -EINVAL; 884 } 885 memcpy(_secret->msecret, msecret, len); 886 } 887 888 TAILQ_INSERT_TAIL(&group->secret_head, _secret, tailq); 889 return 0; 890 } 891 892 int 893 iscsi_auth_group_delete_secret(struct spdk_iscsi_auth_group *group, 894 const char *user) 895 { 896 struct spdk_iscsi_auth_secret *_secret; 897 898 if (user == NULL) { 899 SPDK_ERRLOG("user must be specified\n"); 900 return -EINVAL; 901 } 902 903 TAILQ_FOREACH(_secret, &group->secret_head, tailq) { 904 if (strcmp(_secret->user, user) == 0) { 905 break; 906 } 907 } 908 909 if (_secret == NULL) { 910 SPDK_ERRLOG("secret is not found\n"); 911 return -ENODEV; 912 } 913 914 TAILQ_REMOVE(&group->secret_head, _secret, tailq); 915 free(_secret); 916 917 return 0; 918 } 919 920 int 921 iscsi_add_auth_group(int32_t tag, struct spdk_iscsi_auth_group **_group) 922 { 923 struct spdk_iscsi_auth_group *group; 924 925 TAILQ_FOREACH(group, &g_iscsi.auth_group_head, tailq) { 926 if (group->tag == tag) { 927 SPDK_ERRLOG("Auth group (%d) already exists\n", tag); 928 return -EEXIST; 929 } 930 } 931 932 group = calloc(1, sizeof(*group)); 933 if (group == NULL) { 934 SPDK_ERRLOG("calloc() failed for auth group\n"); 935 return -ENOMEM; 936 } 937 938 TAILQ_INIT(&group->secret_head); 939 group->tag = tag; 940 941 TAILQ_INSERT_TAIL(&g_iscsi.auth_group_head, group, tailq); 942 943 *_group = group; 944 return 0; 945 } 946 947 void 948 iscsi_delete_auth_group(struct spdk_iscsi_auth_group *group) 949 { 950 struct spdk_iscsi_auth_secret *_secret, *tmp; 951 952 TAILQ_REMOVE(&g_iscsi.auth_group_head, group, tailq); 953 954 TAILQ_FOREACH_SAFE(_secret, &group->secret_head, tailq, tmp) { 955 TAILQ_REMOVE(&group->secret_head, _secret, tailq); 956 free(_secret); 957 } 958 free(group); 959 } 960 961 struct spdk_iscsi_auth_group * 962 iscsi_find_auth_group_by_tag(int32_t tag) 963 { 964 struct spdk_iscsi_auth_group *group; 965 966 TAILQ_FOREACH(group, &g_iscsi.auth_group_head, tailq) { 967 if (group->tag == tag) { 968 return group; 969 } 970 } 971 972 return NULL; 973 } 974 975 static void 976 iscsi_auth_groups_destroy(void) 977 { 978 struct spdk_iscsi_auth_group *group, *tmp; 979 980 TAILQ_FOREACH_SAFE(group, &g_iscsi.auth_group_head, tailq, tmp) { 981 iscsi_delete_auth_group(group); 982 } 983 } 984 985 static int 986 iscsi_parse_auth_group(struct spdk_conf_section *sp) 987 { 988 int rc; 989 int i; 990 int tag; 991 const char *val, *user, *secret, *muser, *msecret; 992 struct spdk_iscsi_auth_group *group = NULL; 993 994 val = spdk_conf_section_get_val(sp, "Comment"); 995 if (val != NULL) { 996 SPDK_DEBUGLOG(iscsi, "Comment %s\n", val); 997 } 998 999 tag = spdk_conf_section_get_num(sp); 1000 1001 rc = iscsi_add_auth_group(tag, &group); 1002 if (rc != 0) { 1003 SPDK_ERRLOG("Failed to add auth group\n"); 1004 return rc; 1005 } 1006 1007 for (i = 0; ; i++) { 1008 val = spdk_conf_section_get_nval(sp, "Auth", i); 1009 if (val == NULL) { 1010 break; 1011 } 1012 1013 user = spdk_conf_section_get_nmval(sp, "Auth", i, 0); 1014 secret = spdk_conf_section_get_nmval(sp, "Auth", i, 1); 1015 muser = spdk_conf_section_get_nmval(sp, "Auth", i, 2); 1016 msecret = spdk_conf_section_get_nmval(sp, "Auth", i, 3); 1017 1018 rc = iscsi_auth_group_add_secret(group, user, secret, muser, msecret); 1019 if (rc != 0) { 1020 SPDK_ERRLOG("Failed to add secret to auth group\n"); 1021 iscsi_delete_auth_group(group); 1022 return rc; 1023 } 1024 } 1025 1026 return 0; 1027 } 1028 1029 static int 1030 iscsi_parse_auth_info(void) 1031 { 1032 struct spdk_conf *config; 1033 struct spdk_conf_section *sp; 1034 int rc; 1035 1036 config = spdk_conf_allocate(); 1037 if (!config) { 1038 SPDK_ERRLOG("Failed to allocate config file\n"); 1039 return -ENOMEM; 1040 } 1041 1042 rc = spdk_conf_read(config, g_iscsi.authfile); 1043 if (rc != 0) { 1044 SPDK_INFOLOG(iscsi, "Failed to load auth file\n"); 1045 spdk_conf_free(config); 1046 return rc; 1047 } 1048 1049 sp = spdk_conf_first_section(config); 1050 while (sp != NULL) { 1051 if (spdk_conf_section_match_prefix(sp, "AuthGroup")) { 1052 if (spdk_conf_section_get_num(sp) == 0) { 1053 SPDK_ERRLOG("Group 0 is invalid\n"); 1054 iscsi_auth_groups_destroy(); 1055 spdk_conf_free(config); 1056 return -EINVAL; 1057 } 1058 1059 rc = iscsi_parse_auth_group(sp); 1060 if (rc != 0) { 1061 SPDK_ERRLOG("parse_auth_group() failed\n"); 1062 iscsi_auth_groups_destroy(); 1063 spdk_conf_free(config); 1064 return rc; 1065 } 1066 } 1067 sp = spdk_conf_next_section(sp); 1068 } 1069 1070 spdk_conf_free(config); 1071 return 0; 1072 } 1073 1074 static struct spdk_iscsi_auth_secret * 1075 iscsi_find_auth_secret(const char *authuser, int ag_tag) 1076 { 1077 struct spdk_iscsi_auth_group *group; 1078 struct spdk_iscsi_auth_secret *_secret; 1079 1080 TAILQ_FOREACH(group, &g_iscsi.auth_group_head, tailq) { 1081 if (group->tag == ag_tag) { 1082 TAILQ_FOREACH(_secret, &group->secret_head, tailq) { 1083 if (strcmp(_secret->user, authuser) == 0) { 1084 return _secret; 1085 } 1086 } 1087 } 1088 } 1089 1090 return NULL; 1091 } 1092 1093 int 1094 iscsi_chap_get_authinfo(struct iscsi_chap_auth *auth, const char *authuser, 1095 int ag_tag) 1096 { 1097 struct spdk_iscsi_auth_secret *_secret; 1098 1099 if (authuser == NULL) { 1100 return -EINVAL; 1101 } 1102 1103 if (auth->user[0] != '\0') { 1104 memset(auth->user, 0, sizeof(auth->user)); 1105 memset(auth->secret, 0, sizeof(auth->secret)); 1106 memset(auth->muser, 0, sizeof(auth->muser)); 1107 memset(auth->msecret, 0, sizeof(auth->msecret)); 1108 } 1109 1110 pthread_mutex_lock(&g_iscsi.mutex); 1111 1112 _secret = iscsi_find_auth_secret(authuser, ag_tag); 1113 if (_secret == NULL) { 1114 pthread_mutex_unlock(&g_iscsi.mutex); 1115 1116 SPDK_ERRLOG("CHAP secret is not found: user:%s, tag:%d\n", 1117 authuser, ag_tag); 1118 return -ENOENT; 1119 } 1120 1121 memcpy(auth->user, _secret->user, sizeof(auth->user)); 1122 memcpy(auth->secret, _secret->secret, sizeof(auth->secret)); 1123 1124 if (_secret->muser[0] != '\0') { 1125 memcpy(auth->muser, _secret->muser, sizeof(auth->muser)); 1126 memcpy(auth->msecret, _secret->msecret, sizeof(auth->msecret)); 1127 } 1128 1129 pthread_mutex_unlock(&g_iscsi.mutex); 1130 return 0; 1131 } 1132 1133 static int 1134 iscsi_initialize_global_params(void) 1135 { 1136 int rc; 1137 1138 if (!g_spdk_iscsi_opts) { 1139 rc = iscsi_parse_options(&g_spdk_iscsi_opts); 1140 if (rc != 0) { 1141 SPDK_ERRLOG("iscsi_parse_options() failed\n"); 1142 return rc; 1143 } 1144 } 1145 1146 rc = iscsi_set_global_params(g_spdk_iscsi_opts); 1147 if (rc != 0) { 1148 SPDK_ERRLOG("iscsi_set_global_params() failed\n"); 1149 } 1150 1151 iscsi_opts_free(g_spdk_iscsi_opts); 1152 g_spdk_iscsi_opts = NULL; 1153 1154 return rc; 1155 } 1156 1157 static void 1158 iscsi_init_complete(int rc) 1159 { 1160 spdk_iscsi_init_cb cb_fn = g_init_cb_fn; 1161 void *cb_arg = g_init_cb_arg; 1162 1163 g_init_cb_fn = NULL; 1164 g_init_cb_arg = NULL; 1165 1166 cb_fn(cb_arg, rc); 1167 } 1168 1169 static void 1170 iscsi_parse_configuration(void) 1171 { 1172 int rc; 1173 1174 rc = iscsi_parse_portal_grps(); 1175 if (rc < 0) { 1176 SPDK_ERRLOG("iscsi_parse_portal_grps() failed\n"); 1177 goto end; 1178 } 1179 1180 rc = iscsi_parse_init_grps(); 1181 if (rc < 0) { 1182 SPDK_ERRLOG("iscsi_parse_init_grps() failed\n"); 1183 goto end; 1184 } 1185 1186 rc = iscsi_parse_tgt_nodes(); 1187 if (rc < 0) { 1188 SPDK_ERRLOG("iscsi_parse_tgt_nodes() failed\n"); 1189 } 1190 1191 if (g_iscsi.authfile != NULL) { 1192 if (access(g_iscsi.authfile, R_OK) == 0) { 1193 rc = iscsi_parse_auth_info(); 1194 if (rc < 0) { 1195 SPDK_ERRLOG("iscsi_parse_auth_info() failed\n"); 1196 } 1197 } else { 1198 SPDK_INFOLOG(iscsi, "CHAP secret file is not found in the path %s\n", 1199 g_iscsi.authfile); 1200 } 1201 } 1202 1203 end: 1204 iscsi_init_complete(rc); 1205 } 1206 1207 static int 1208 iscsi_poll_group_poll(void *ctx) 1209 { 1210 struct spdk_iscsi_poll_group *group = ctx; 1211 struct spdk_iscsi_conn *conn, *tmp; 1212 int rc; 1213 1214 if (spdk_unlikely(STAILQ_EMPTY(&group->connections))) { 1215 return SPDK_POLLER_IDLE; 1216 } 1217 1218 rc = spdk_sock_group_poll(group->sock_group); 1219 if (rc < 0) { 1220 SPDK_ERRLOG("Failed to poll sock_group=%p\n", group->sock_group); 1221 } 1222 1223 STAILQ_FOREACH_SAFE(conn, &group->connections, pg_link, tmp) { 1224 if (conn->state == ISCSI_CONN_STATE_EXITING) { 1225 iscsi_conn_destruct(conn); 1226 } 1227 } 1228 1229 return rc != 0 ? SPDK_POLLER_BUSY : SPDK_POLLER_IDLE; 1230 } 1231 1232 static int 1233 iscsi_poll_group_handle_nop(void *ctx) 1234 { 1235 struct spdk_iscsi_poll_group *group = ctx; 1236 struct spdk_iscsi_conn *conn, *tmp; 1237 1238 STAILQ_FOREACH_SAFE(conn, &group->connections, pg_link, tmp) { 1239 iscsi_conn_handle_nop(conn); 1240 } 1241 1242 return SPDK_POLLER_BUSY; 1243 } 1244 1245 static int 1246 iscsi_poll_group_create(void *io_device, void *ctx_buf) 1247 { 1248 struct spdk_iscsi_poll_group *pg = ctx_buf; 1249 1250 STAILQ_INIT(&pg->connections); 1251 pg->sock_group = spdk_sock_group_create(NULL); 1252 assert(pg->sock_group != NULL); 1253 1254 pg->poller = SPDK_POLLER_REGISTER(iscsi_poll_group_poll, pg, 0); 1255 /* set the period to 1 sec */ 1256 pg->nop_poller = SPDK_POLLER_REGISTER(iscsi_poll_group_handle_nop, pg, 1000000); 1257 1258 return 0; 1259 } 1260 1261 static void 1262 iscsi_poll_group_destroy(void *io_device, void *ctx_buf) 1263 { 1264 struct spdk_iscsi_poll_group *pg = ctx_buf; 1265 struct spdk_io_channel *ch; 1266 struct spdk_thread *thread; 1267 1268 assert(pg->poller != NULL); 1269 assert(pg->sock_group != NULL); 1270 1271 spdk_sock_group_close(&pg->sock_group); 1272 spdk_poller_unregister(&pg->poller); 1273 spdk_poller_unregister(&pg->nop_poller); 1274 1275 ch = spdk_io_channel_from_ctx(pg); 1276 thread = spdk_io_channel_get_thread(ch); 1277 1278 assert(thread == spdk_get_thread()); 1279 1280 spdk_thread_exit(thread); 1281 } 1282 1283 static void 1284 _iscsi_init_thread_done(void *ctx) 1285 { 1286 struct spdk_iscsi_poll_group *pg = ctx; 1287 1288 TAILQ_INSERT_TAIL(&g_iscsi.poll_group_head, pg, link); 1289 if (--g_iscsi.refcnt == 0) { 1290 iscsi_parse_configuration(); 1291 } 1292 } 1293 1294 static void 1295 _iscsi_init_thread(void *ctx) 1296 { 1297 struct spdk_io_channel *ch; 1298 struct spdk_iscsi_poll_group *pg; 1299 1300 ch = spdk_get_io_channel(&g_iscsi); 1301 pg = spdk_io_channel_get_ctx(ch); 1302 1303 spdk_thread_send_msg(g_init_thread, _iscsi_init_thread_done, pg); 1304 } 1305 1306 static void 1307 initialize_iscsi_poll_group(void) 1308 { 1309 struct spdk_cpuset tmp_cpumask = {}; 1310 uint32_t i; 1311 char thread_name[32]; 1312 struct spdk_thread *thread; 1313 1314 spdk_io_device_register(&g_iscsi, iscsi_poll_group_create, iscsi_poll_group_destroy, 1315 sizeof(struct spdk_iscsi_poll_group), "iscsi_tgt"); 1316 1317 /* Create threads for CPU cores active for this application, and send a 1318 * message to each thread to create a poll group on it. 1319 */ 1320 g_init_thread = spdk_get_thread(); 1321 assert(g_init_thread != NULL); 1322 assert(g_iscsi.refcnt == 0); 1323 1324 SPDK_ENV_FOREACH_CORE(i) { 1325 spdk_cpuset_zero(&tmp_cpumask); 1326 spdk_cpuset_set_cpu(&tmp_cpumask, i, true); 1327 snprintf(thread_name, sizeof(thread_name), "iscsi_poll_group_%u", i); 1328 1329 thread = spdk_thread_create(thread_name, &tmp_cpumask); 1330 assert(thread != NULL); 1331 1332 g_iscsi.refcnt++; 1333 spdk_thread_send_msg(thread, _iscsi_init_thread, NULL); 1334 } 1335 } 1336 1337 static int 1338 iscsi_parse_globals(void) 1339 { 1340 int rc; 1341 1342 rc = iscsi_initialize_global_params(); 1343 if (rc != 0) { 1344 SPDK_ERRLOG("iscsi_initialize_iscsi_global_params() failed\n"); 1345 return rc; 1346 } 1347 1348 g_iscsi.session = calloc(1, sizeof(struct spdk_iscsi_sess *) * g_iscsi.MaxSessions); 1349 if (!g_iscsi.session) { 1350 SPDK_ERRLOG("calloc() failed for session array\n"); 1351 return -1; 1352 } 1353 1354 /* 1355 * For now, just support same number of total connections, rather 1356 * than MaxSessions * MaxConnectionsPerSession. After we add better 1357 * handling for low resource conditions from our various buffer 1358 * pools, we can bump this up to support more connections. 1359 */ 1360 g_iscsi.MaxConnections = g_iscsi.MaxSessions; 1361 1362 rc = iscsi_initialize_all_pools(); 1363 if (rc != 0) { 1364 SPDK_ERRLOG("initialize_all_pools() failed\n"); 1365 free(g_iscsi.session); 1366 g_iscsi.session = NULL; 1367 return -1; 1368 } 1369 1370 rc = initialize_iscsi_conns(); 1371 if (rc < 0) { 1372 SPDK_ERRLOG("initialize_iscsi_conns() failed\n"); 1373 free(g_iscsi.session); 1374 g_iscsi.session = NULL; 1375 return rc; 1376 } 1377 1378 initialize_iscsi_poll_group(); 1379 return 0; 1380 } 1381 1382 void 1383 spdk_iscsi_init(spdk_iscsi_init_cb cb_fn, void *cb_arg) 1384 { 1385 int rc; 1386 1387 assert(cb_fn != NULL); 1388 g_init_cb_fn = cb_fn; 1389 g_init_cb_arg = cb_arg; 1390 1391 rc = iscsi_parse_globals(); 1392 if (rc < 0) { 1393 SPDK_ERRLOG("iscsi_parse_globals() failed\n"); 1394 iscsi_init_complete(-1); 1395 } 1396 1397 /* 1398 * iscsi_parse_configuration() will be called as the callback to 1399 * spdk_initialize_iscsi_poll_group() and will complete iSCSI 1400 * subsystem initialization. 1401 */ 1402 } 1403 1404 void 1405 spdk_iscsi_fini(spdk_iscsi_fini_cb cb_fn, void *cb_arg) 1406 { 1407 g_fini_cb_fn = cb_fn; 1408 g_fini_cb_arg = cb_arg; 1409 1410 iscsi_portal_grp_close_all(); 1411 shutdown_iscsi_conns(); 1412 } 1413 1414 static void 1415 iscsi_fini_done(void *io_device) 1416 { 1417 free(g_iscsi.authfile); 1418 free(g_iscsi.nodebase); 1419 1420 pthread_mutex_destroy(&g_iscsi.mutex); 1421 g_fini_cb_fn(g_fini_cb_arg); 1422 } 1423 1424 static void 1425 _iscsi_fini_dev_unreg(struct spdk_io_channel_iter *i, int status) 1426 { 1427 iscsi_check_pools(); 1428 iscsi_free_pools(); 1429 free(g_iscsi.session); 1430 1431 assert(TAILQ_EMPTY(&g_iscsi.poll_group_head)); 1432 1433 iscsi_shutdown_tgt_nodes(); 1434 iscsi_init_grps_destroy(); 1435 iscsi_portal_grps_destroy(); 1436 iscsi_auth_groups_destroy(); 1437 1438 spdk_io_device_unregister(&g_iscsi, iscsi_fini_done); 1439 } 1440 1441 static void 1442 _iscsi_fini_thread(struct spdk_io_channel_iter *i) 1443 { 1444 struct spdk_io_channel *ch; 1445 struct spdk_iscsi_poll_group *pg; 1446 1447 ch = spdk_io_channel_iter_get_channel(i); 1448 pg = spdk_io_channel_get_ctx(ch); 1449 1450 pthread_mutex_lock(&g_iscsi.mutex); 1451 TAILQ_REMOVE(&g_iscsi.poll_group_head, pg, link); 1452 pthread_mutex_unlock(&g_iscsi.mutex); 1453 1454 spdk_put_io_channel(ch); 1455 1456 spdk_for_each_channel_continue(i, 0); 1457 } 1458 1459 void 1460 shutdown_iscsi_conns_done(void) 1461 { 1462 spdk_for_each_channel(&g_iscsi, _iscsi_fini_thread, NULL, _iscsi_fini_dev_unreg); 1463 } 1464 1465 void 1466 spdk_iscsi_config_text(FILE *fp) 1467 { 1468 iscsi_globals_config_text(fp); 1469 iscsi_portal_grps_config_text(fp); 1470 iscsi_init_grps_config_text(fp); 1471 iscsi_tgt_nodes_config_text(fp); 1472 } 1473 1474 void 1475 iscsi_opts_info_json(struct spdk_json_write_ctx *w) 1476 { 1477 spdk_json_write_object_begin(w); 1478 1479 if (g_iscsi.authfile != NULL) { 1480 spdk_json_write_named_string(w, "auth_file", g_iscsi.authfile); 1481 } 1482 spdk_json_write_named_string(w, "node_base", g_iscsi.nodebase); 1483 1484 spdk_json_write_named_uint32(w, "max_sessions", g_iscsi.MaxSessions); 1485 spdk_json_write_named_uint32(w, "max_connections_per_session", 1486 g_iscsi.MaxConnectionsPerSession); 1487 1488 spdk_json_write_named_uint32(w, "max_queue_depth", g_iscsi.MaxQueueDepth); 1489 1490 spdk_json_write_named_uint32(w, "default_time2wait", g_iscsi.DefaultTime2Wait); 1491 spdk_json_write_named_uint32(w, "default_time2retain", g_iscsi.DefaultTime2Retain); 1492 1493 spdk_json_write_named_uint32(w, "first_burst_length", g_iscsi.FirstBurstLength); 1494 1495 spdk_json_write_named_bool(w, "immediate_data", g_iscsi.ImmediateData); 1496 1497 spdk_json_write_named_bool(w, "allow_duplicated_isid", g_iscsi.AllowDuplicateIsid); 1498 1499 spdk_json_write_named_uint32(w, "error_recovery_level", g_iscsi.ErrorRecoveryLevel); 1500 1501 spdk_json_write_named_int32(w, "nop_timeout", g_iscsi.timeout); 1502 spdk_json_write_named_int32(w, "nop_in_interval", g_iscsi.nopininterval); 1503 1504 spdk_json_write_named_bool(w, "disable_chap", g_iscsi.disable_chap); 1505 spdk_json_write_named_bool(w, "require_chap", g_iscsi.require_chap); 1506 spdk_json_write_named_bool(w, "mutual_chap", g_iscsi.mutual_chap); 1507 spdk_json_write_named_int32(w, "chap_group", g_iscsi.chap_group); 1508 1509 spdk_json_write_named_uint32(w, "max_large_datain_per_connection", 1510 g_iscsi.MaxLargeDataInPerConnection); 1511 spdk_json_write_named_uint32(w, "max_r2t_per_connection", 1512 g_iscsi.MaxR2TPerConnection); 1513 1514 spdk_json_write_object_end(w); 1515 } 1516 1517 static void 1518 iscsi_auth_group_info_json(struct spdk_iscsi_auth_group *group, 1519 struct spdk_json_write_ctx *w) 1520 { 1521 struct spdk_iscsi_auth_secret *_secret; 1522 1523 spdk_json_write_object_begin(w); 1524 1525 spdk_json_write_named_int32(w, "tag", group->tag); 1526 1527 spdk_json_write_named_array_begin(w, "secrets"); 1528 TAILQ_FOREACH(_secret, &group->secret_head, tailq) { 1529 spdk_json_write_object_begin(w); 1530 1531 spdk_json_write_named_string(w, "user", _secret->user); 1532 spdk_json_write_named_string(w, "secret", _secret->secret); 1533 1534 if (_secret->muser[0] != '\0') { 1535 spdk_json_write_named_string(w, "muser", _secret->muser); 1536 spdk_json_write_named_string(w, "msecret", _secret->msecret); 1537 } 1538 1539 spdk_json_write_object_end(w); 1540 } 1541 spdk_json_write_array_end(w); 1542 1543 spdk_json_write_object_end(w); 1544 } 1545 1546 static void 1547 iscsi_auth_group_config_json(struct spdk_iscsi_auth_group *group, 1548 struct spdk_json_write_ctx *w) 1549 { 1550 spdk_json_write_object_begin(w); 1551 1552 spdk_json_write_named_string(w, "method", "iscsi_create_auth_group"); 1553 1554 spdk_json_write_name(w, "params"); 1555 iscsi_auth_group_info_json(group, w); 1556 1557 spdk_json_write_object_end(w); 1558 } 1559 1560 void 1561 iscsi_auth_groups_info_json(struct spdk_json_write_ctx *w) 1562 { 1563 struct spdk_iscsi_auth_group *group; 1564 1565 TAILQ_FOREACH(group, &g_iscsi.auth_group_head, tailq) { 1566 iscsi_auth_group_info_json(group, w); 1567 } 1568 } 1569 1570 static void 1571 iscsi_auth_groups_config_json(struct spdk_json_write_ctx *w) 1572 { 1573 struct spdk_iscsi_auth_group *group; 1574 1575 TAILQ_FOREACH(group, &g_iscsi.auth_group_head, tailq) { 1576 iscsi_auth_group_config_json(group, w); 1577 } 1578 } 1579 1580 static void 1581 iscsi_opts_config_json(struct spdk_json_write_ctx *w) 1582 { 1583 spdk_json_write_object_begin(w); 1584 1585 spdk_json_write_named_string(w, "method", "iscsi_set_options"); 1586 1587 spdk_json_write_name(w, "params"); 1588 iscsi_opts_info_json(w); 1589 1590 spdk_json_write_object_end(w); 1591 } 1592 1593 void 1594 spdk_iscsi_config_json(struct spdk_json_write_ctx *w) 1595 { 1596 spdk_json_write_array_begin(w); 1597 iscsi_opts_config_json(w); 1598 iscsi_portal_grps_config_json(w); 1599 iscsi_init_grps_config_json(w); 1600 iscsi_tgt_nodes_config_json(w); 1601 iscsi_auth_groups_config_json(w); 1602 spdk_json_write_array_end(w); 1603 } 1604 1605 SPDK_LOG_REGISTER_COMPONENT(iscsi) 1606