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 37 #include <rte_config.h> 38 #include <rte_mempool.h> 39 #include <rte_version.h> 40 41 #include "iscsi/iscsi.h" 42 #include "iscsi/init_grp.h" 43 #include "iscsi/portal_grp.h" 44 #include "iscsi/acceptor.h" 45 #include "iscsi/conn.h" 46 #include "iscsi/task.h" 47 48 #include "spdk/env.h" 49 50 #include "spdk_internal/event.h" 51 #include "spdk_internal/log.h" 52 53 #define ISCSI_CONFIG_TMPL \ 54 "[iSCSI]\n" \ 55 " # node name (not include optional part)\n" \ 56 " # Users can optionally change this to fit their environment.\n" \ 57 " NodeBase \"%s\"\n" \ 58 "\n" \ 59 " # files\n" \ 60 " AuthFile %s\n" \ 61 "\n" \ 62 " # socket I/O timeout sec. (polling is infinity)\n" \ 63 " Timeout %d\n" \ 64 "\n" \ 65 " # authentication information for discovery session\n" \ 66 " DiscoveryAuthMethod %s\n" \ 67 " DiscoveryAuthGroup %s\n" \ 68 "\n" \ 69 " MaxSessions %d\n" \ 70 " MaxConnectionsPerSession %d\n" \ 71 " MaxConnections %d\n" \ 72 " MaxOutstandingR2T %d\n" \ 73 "\n" \ 74 " # iSCSI initial parameters negotiate with initiators\n" \ 75 " # NOTE: incorrect values might crash\n" \ 76 " DefaultTime2Wait %d\n" \ 77 " DefaultTime2Retain %d\n" \ 78 "\n" \ 79 " ImmediateData %s\n" \ 80 " DataPDUInOrder %s\n" \ 81 " DataSequenceInOrder %s\n" \ 82 " ErrorRecoveryLevel %d\n" \ 83 "\n" \ 84 " # Defines whether iSCSI target will enable configuration via RPC\n" \ 85 " # RpcConfiguration Yes\n" \ 86 "\n" 87 88 static void 89 spdk_iscsi_config_dump_section(FILE *fp) 90 { 91 const char *authmethod = "None"; 92 char authgroup[32] = "None"; 93 94 if (NULL == fp) 95 return; 96 97 if (g_spdk_iscsi.req_discovery_auth) 98 authmethod = "CHAP"; 99 else if (g_spdk_iscsi.req_discovery_auth_mutual) 100 authmethod = "CHAP Mutual"; 101 else if (!g_spdk_iscsi.no_discovery_auth) 102 authmethod = "Auto"; 103 104 if (g_spdk_iscsi.discovery_auth_group) 105 snprintf(authgroup, sizeof(authgroup), "AuthGroup%d", g_spdk_iscsi.discovery_auth_group); 106 107 fprintf(fp, ISCSI_CONFIG_TMPL, 108 g_spdk_iscsi.nodebase, g_spdk_iscsi.authfile, 109 g_spdk_iscsi.timeout, authmethod, authgroup, 110 g_spdk_iscsi.MaxSessions, g_spdk_iscsi.MaxConnectionsPerSession, 111 g_spdk_iscsi.MaxConnections, g_spdk_iscsi.MaxOutstandingR2T, 112 g_spdk_iscsi.DefaultTime2Wait, g_spdk_iscsi.DefaultTime2Retain, 113 (g_spdk_iscsi.ImmediateData == 1) ? "Yes" : "No", 114 (g_spdk_iscsi.DataPDUInOrder == 1) ? "Yes" : "No", 115 (g_spdk_iscsi.DataSequenceInOrder == 1) ? "Yes" : "No", 116 g_spdk_iscsi.ErrorRecoveryLevel); 117 } 118 119 120 /* Portal groups */ 121 static const char *portal_group_section = \ 122 "\n" 123 "# Users must change the PortalGroup section(s) to match the IP addresses\n" 124 "# for their environment.\n" 125 "# PortalGroup sections define which TCP ports the iSCSI server will use\n" 126 "# to listen for incoming connections. These are also used to determine\n" 127 "# which targets are accessible over each portal group.\n"; 128 129 #define PORTAL_GROUP_TMPL \ 130 "[PortalGroup%d]\n" \ 131 " Comment \"Portal%d\"\n" 132 133 #define PORTAL_TMPL \ 134 " Portal DA1 %s:%s\n" 135 136 static void 137 spdk_iscsi_config_dump_portal_groups(FILE *fp) 138 { 139 struct spdk_iscsi_portal *p = NULL; 140 struct spdk_iscsi_portal_grp *pg = NULL; 141 142 /* Create portal group section */ 143 fprintf(fp, "%s", portal_group_section); 144 145 /* Dump portal groups */ 146 TAILQ_FOREACH(pg, &g_spdk_iscsi.pg_head, tailq) { 147 if (NULL == pg) continue; 148 fprintf(fp, PORTAL_GROUP_TMPL, pg->tag, pg->tag); 149 /* Dump portals */ 150 TAILQ_FOREACH(p, &pg->head, tailq) { 151 if (NULL == p) continue; 152 fprintf(fp, PORTAL_TMPL, p->host, p->port); 153 } 154 } 155 } 156 157 /* Initiator Groups */ 158 static const char *initiator_group_section = \ 159 "\n" 160 "# Users must change the InitiatorGroup section(s) to match the IP\n" 161 "# addresses and initiator configuration in their environment.\n" 162 "# Netmask can be used to specify a single IP address or a range of IP addresses\n" 163 "# Netmask 192.168.1.20 <== single IP address\n" 164 "# Netmask 192.168.1.0/24 <== IP range 192.168.1.*\n"; 165 166 #define INITIATOR_GROUP_TMPL \ 167 "[InitiatorGroup%d]\n" \ 168 " Comment \"Initiator Group%d\"\n" 169 170 #define INITIATOR_TMPL \ 171 " InitiatorName " 172 173 #define NETMASK_TMPL \ 174 " Netmask " 175 176 static void 177 spdk_iscsi_config_dump_initiator_groups(FILE *fp) 178 { 179 int i; 180 struct spdk_iscsi_init_grp *ig; 181 182 /* Create initiator group section */ 183 fprintf(fp, "%s", initiator_group_section); 184 185 /* Dump initiator groups */ 186 TAILQ_FOREACH(ig, &g_spdk_iscsi.ig_head, tailq) { 187 if (NULL == ig) continue; 188 fprintf(fp, INITIATOR_GROUP_TMPL, ig->tag, ig->tag); 189 190 /* Dump initiators */ 191 fprintf(fp, INITIATOR_TMPL); 192 for (i = 0; i < ig->ninitiators; i++) 193 fprintf(fp, "%s ", ig->initiators[i]); 194 fprintf(fp, "\n"); 195 196 /* Dump netmasks */ 197 fprintf(fp, NETMASK_TMPL); 198 for (i = 0; i < ig->nnetmasks; i++) 199 fprintf(fp, "%s ", ig->netmasks[i]); 200 fprintf(fp, "\n"); 201 } 202 } 203 204 /* Target nodes */ 205 static const char *target_nodes_section = \ 206 "\n" 207 "# Users should change the TargetNode section(s) below to match the\n" 208 "# desired iSCSI target node configuration.\n" 209 "# TargetName, Mapping, LUN0 are minimum required\n"; 210 211 #define TARGET_NODE_TMPL \ 212 "[TargetNode%d]\n" \ 213 " Comment \"Target%d\"\n" \ 214 " TargetName %s\n" \ 215 " TargetAlias \"%s\"\n" 216 217 #define TARGET_NODE_PGIG_MAPPING_TMPL \ 218 " Mapping PortalGroup%d InitiatorGroup%d\n" 219 220 #define TARGET_NODE_AUTH_TMPL \ 221 " AuthMethod %s\n" \ 222 " AuthGroup %s\n" \ 223 " UseDigest %s\n" 224 225 #define TARGET_NODE_QD_TMPL \ 226 " QueueDepth %d\n\n" 227 228 #define TARGET_NODE_LUN_TMPL \ 229 " LUN%d %s\n" 230 231 static void 232 spdk_iscsi_config_dump_target_nodes(FILE *fp) 233 { 234 int t = 0, l = 0, m = 0; 235 struct spdk_scsi_dev *dev = NULL; 236 struct spdk_iscsi_tgt_node *target = NULL; 237 238 /* Create target nodes section */ 239 fprintf(fp, "%s", target_nodes_section); 240 241 for (t = 0; t < MAX_ISCSI_TARGET_NODE; t++) { 242 int idx; 243 const char *authmethod = "None"; 244 char authgroup[32] = "None"; 245 const char *usedigest = "Auto"; 246 247 target = g_spdk_iscsi.target[t]; 248 if (NULL == target) continue; 249 250 dev = target->dev; 251 if (NULL == dev) continue; 252 253 idx = target->num; 254 fprintf(fp, TARGET_NODE_TMPL, idx, idx, target->name, spdk_scsi_dev_get_name(dev)); 255 256 for (m = 0; m < target->maxmap; m++) { 257 if (NULL == target->map[m].pg) continue; 258 if (NULL == target->map[m].ig) continue; 259 260 fprintf(fp, TARGET_NODE_PGIG_MAPPING_TMPL, 261 target->map[m].pg->tag, 262 target->map[m].ig->tag); 263 } 264 265 if (target->auth_chap_disabled) 266 authmethod = "None"; 267 else if (!target->auth_chap_required) 268 authmethod = "Auto"; 269 else if (target->auth_chap_mutual) 270 authmethod = "CHAP Mutual"; 271 else 272 authmethod = "CHAP"; 273 274 if (target->auth_group > 0) 275 snprintf(authgroup, sizeof(authgroup), "AuthGroup%d", target->auth_group); 276 277 if (target->header_digest) 278 usedigest = "Header"; 279 else if (target->data_digest) 280 usedigest = "Data"; 281 282 fprintf(fp, TARGET_NODE_AUTH_TMPL, 283 authmethod, authgroup, usedigest); 284 285 for (l = 0; l < SPDK_SCSI_DEV_MAX_LUN; l++) { 286 struct spdk_scsi_lun *lun = spdk_scsi_dev_get_lun(dev, l); 287 288 if (!lun) { 289 continue; 290 } 291 292 fprintf(fp, TARGET_NODE_LUN_TMPL, 293 spdk_scsi_lun_get_id(lun), 294 spdk_scsi_lun_get_name(lun)); 295 } 296 297 fprintf(fp, TARGET_NODE_QD_TMPL, 298 target->queue_depth); 299 } 300 } 301 302 static void 303 spdk_mobj_ctor(struct rte_mempool *mp, __attribute__((unused)) void *arg, 304 void *_m, __attribute__((unused)) unsigned i) 305 { 306 struct spdk_mobj *m = _m; 307 uint64_t *phys_addr; 308 ptrdiff_t off; 309 310 m->mp = mp; 311 m->buf = (uint8_t *)m + sizeof(struct spdk_mobj); 312 m->buf = (void *)((unsigned long)((uint8_t *)m->buf + 512) & ~511UL); 313 off = (uint64_t)(uint8_t *)m->buf - (uint64_t)(uint8_t *)m; 314 315 /* 316 * we store the physical address in a 64bit unsigned integer 317 * right before the 512B aligned buffer area. 318 */ 319 phys_addr = (uint64_t *)m->buf - 1; 320 *phys_addr = rte_mempool_virt2phy(mp, m) + off; 321 } 322 323 #define PDU_POOL_SIZE(iscsi) (iscsi->MaxConnections * NUM_PDU_PER_CONNECTION) 324 #define IMMEDIATE_DATA_POOL_SIZE(iscsi) (iscsi->MaxConnections * 128) 325 #define DATA_OUT_POOL_SIZE(iscsi) (iscsi->MaxConnections * MAX_DATA_OUT_PER_CONNECTION) 326 327 static int spdk_iscsi_initialize_pdu_pool(void) 328 { 329 struct spdk_iscsi_globals *iscsi = &g_spdk_iscsi; 330 int imm_mobj_size = spdk_get_immediate_data_buffer_size() + 331 sizeof(struct spdk_mobj) + 512; 332 int dout_mobj_size = spdk_get_data_out_buffer_size() + 333 sizeof(struct spdk_mobj) + 512; 334 335 /* create PDU pool */ 336 iscsi->pdu_pool = rte_mempool_create("PDU_Pool", 337 PDU_POOL_SIZE(iscsi), 338 sizeof(struct spdk_iscsi_pdu), 339 256, 0, 340 NULL, NULL, NULL, NULL, 341 SOCKET_ID_ANY, 0); 342 if (!iscsi->pdu_pool) { 343 SPDK_ERRLOG("create PDU pool failed\n"); 344 return -1; 345 } 346 347 iscsi->pdu_immediate_data_pool = 348 rte_mempool_create("PDU_immediate_data_Pool", 349 IMMEDIATE_DATA_POOL_SIZE(iscsi), 350 imm_mobj_size, 351 0, 0, NULL, NULL, 352 spdk_mobj_ctor, NULL, 353 rte_socket_id(), 0); 354 if (!iscsi->pdu_immediate_data_pool) { 355 SPDK_ERRLOG("create PDU 8k pool failed\n"); 356 return -1; 357 } 358 359 iscsi->pdu_data_out_pool = rte_mempool_create("PDU_data_out_Pool", 360 DATA_OUT_POOL_SIZE(iscsi), 361 dout_mobj_size, 362 0, 0, NULL, NULL, 363 spdk_mobj_ctor, NULL, 364 rte_socket_id(), 0); 365 if (!iscsi->pdu_data_out_pool) { 366 SPDK_ERRLOG("create PDU 64k pool failed\n"); 367 return -1; 368 } 369 370 return 0; 371 } 372 373 static void spdk_iscsi_sess_ctor(struct rte_mempool *pool, void *arg, 374 void *session_buf, unsigned index) 375 { 376 struct spdk_iscsi_globals *iscsi = arg; 377 struct spdk_iscsi_sess *sess = session_buf; 378 379 iscsi->session[index] = sess; 380 381 /* tsih 0 is reserved, so start tsih values at 1. */ 382 sess->tsih = index + 1; 383 } 384 385 #define DEFAULT_TASK_POOL_SIZE 32768 386 387 static int 388 spdk_iscsi_initialize_task_pool(void) 389 { 390 struct spdk_iscsi_globals *iscsi = &g_spdk_iscsi; 391 392 /* create scsi_task pool */ 393 iscsi->task_pool = rte_mempool_create("SCSI_TASK_Pool", 394 DEFAULT_TASK_POOL_SIZE, 395 sizeof(struct spdk_iscsi_task), 396 128, 0, 397 NULL, NULL, NULL, NULL, 398 SOCKET_ID_ANY, 0); 399 if (!iscsi->task_pool) { 400 SPDK_ERRLOG("create task pool failed\n"); 401 return -1; 402 } 403 404 return 0; 405 } 406 407 #define SESSION_POOL_SIZE(iscsi) (iscsi->MaxSessions) 408 static int spdk_iscsi_initialize_session_pool(void) 409 { 410 struct spdk_iscsi_globals *iscsi = &g_spdk_iscsi; 411 412 iscsi->session_pool = rte_mempool_create("Session_Pool", 413 SESSION_POOL_SIZE(iscsi), 414 sizeof(struct spdk_iscsi_sess), 415 0, 0, 416 NULL, NULL, 417 spdk_iscsi_sess_ctor, iscsi, 418 SOCKET_ID_ANY, 0); 419 if (!iscsi->session_pool) { 420 SPDK_ERRLOG("create session pool failed\n"); 421 return -1; 422 } 423 424 return 0; 425 } 426 427 static int 428 spdk_iscsi_initialize_all_pools(void) 429 { 430 if (spdk_iscsi_initialize_pdu_pool() != 0) { 431 return -1; 432 } 433 434 if (spdk_iscsi_initialize_session_pool() != 0) { 435 return -1; 436 } 437 438 if (spdk_iscsi_initialize_task_pool() != 0) { 439 return -1; 440 } 441 442 return 0; 443 } 444 445 /* 446 * Wrapper to provide rte_mempool_avail_count() on older DPDK versions. 447 * Drop this if the minimum DPDK version is raised to at least 16.07. 448 */ 449 #if RTE_VERSION < RTE_VERSION_NUM(16, 7, 0, 1) 450 static unsigned rte_mempool_avail_count(const struct rte_mempool *pool) 451 { 452 return rte_mempool_count(pool); 453 } 454 #endif 455 456 static int 457 spdk_iscsi_check_pool(struct rte_mempool *pool, uint32_t count) 458 { 459 if (rte_mempool_avail_count(pool) != count) { 460 SPDK_ERRLOG("rte_mempool_avail_count(%s) == %d, should be %d\n", 461 pool->name, rte_mempool_avail_count(pool), count); 462 return -1; 463 } else { 464 return 0; 465 } 466 } 467 468 static int 469 spdk_iscsi_check_pools(void) 470 { 471 int rc = 0; 472 struct spdk_iscsi_globals *iscsi = &g_spdk_iscsi; 473 474 rc += spdk_iscsi_check_pool(iscsi->pdu_pool, PDU_POOL_SIZE(iscsi)); 475 rc += spdk_iscsi_check_pool(iscsi->session_pool, SESSION_POOL_SIZE(iscsi)); 476 rc += spdk_iscsi_check_pool(iscsi->pdu_immediate_data_pool, IMMEDIATE_DATA_POOL_SIZE(iscsi)); 477 rc += spdk_iscsi_check_pool(iscsi->pdu_data_out_pool, DATA_OUT_POOL_SIZE(iscsi)); 478 /* TODO: check the task_pool on exit */ 479 480 if (rc == 0) { 481 return 0; 482 } else { 483 return -1; 484 } 485 } 486 487 static void 488 spdk_iscsi_free_pools(void) 489 { 490 struct spdk_iscsi_globals *iscsi = &g_spdk_iscsi; 491 492 rte_mempool_free(iscsi->pdu_pool); 493 rte_mempool_free(iscsi->session_pool); 494 rte_mempool_free(iscsi->pdu_immediate_data_pool); 495 rte_mempool_free(iscsi->pdu_data_out_pool); 496 rte_mempool_free(iscsi->task_pool); 497 } 498 499 void spdk_put_pdu(struct spdk_iscsi_pdu *pdu) 500 { 501 if (!pdu) 502 return; 503 504 pdu->ref--; 505 506 if (pdu->ref < 0) { 507 SPDK_ERRLOG("Negative PDU refcount: %p\n", pdu); 508 pdu->ref = 0; 509 } 510 511 if (pdu->ref == 0) { 512 if (pdu->mobj) 513 rte_mempool_put(pdu->mobj->mp, (void *)pdu->mobj); 514 515 if (pdu->data && !pdu->data_from_mempool) 516 free(pdu->data); 517 518 rte_mempool_put(g_spdk_iscsi.pdu_pool, (void *)pdu); 519 } 520 } 521 522 struct spdk_iscsi_pdu *spdk_get_pdu(void) 523 { 524 struct spdk_iscsi_pdu *pdu; 525 int rc; 526 527 rc = rte_mempool_get(g_spdk_iscsi.pdu_pool, (void **)&pdu); 528 if ((rc < 0) || !pdu) { 529 SPDK_ERRLOG("Unable to get PDU\n"); 530 abort(); 531 } 532 533 /* we do not want to zero out the last part of the structure reserved for AHS and sense data */ 534 memset(pdu, 0, offsetof(struct spdk_iscsi_pdu, ahs)); 535 pdu->ref = 1; 536 537 return pdu; 538 } 539 540 static int 541 spdk_iscsi_app_read_parameters(void) 542 { 543 struct spdk_conf_section *sp; 544 const char *ag_tag; 545 const char *val; 546 int ag_tag_i; 547 int MaxSessions; 548 int MaxConnectionsPerSession; 549 int DefaultTime2Wait; 550 int DefaultTime2Retain; 551 int InitialR2T; 552 int ImmediateData; 553 int DataPDUInOrder; 554 int DataSequenceInOrder; 555 int ErrorRecoveryLevel; 556 int timeout; 557 int nopininterval; 558 int rc; 559 int i; 560 int AllowDuplicateIsid; 561 int min_conn_per_core = 0; 562 int conn_idle_interval = 0; 563 unsigned long flush_timeout = 0; 564 565 /* Process parameters */ 566 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_iscsi_app_read_parameters\n"); 567 sp = spdk_conf_find_section(NULL, "iSCSI"); 568 if (sp == NULL) { 569 SPDK_ERRLOG("iSCSI config section not found.\n"); 570 return -1; 571 } 572 573 val = spdk_conf_section_get_val(sp, "Comment"); 574 if (val != NULL) { 575 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Comment %s\n", val); 576 } 577 578 val = spdk_conf_section_get_val(sp, "AuthFile"); 579 if (val == NULL) { 580 val = SPDK_ISCSI_DEFAULT_AUTHFILE; 581 } 582 583 g_spdk_iscsi.authfile = strdup(val); 584 if (!g_spdk_iscsi.authfile) { 585 perror("authfile"); 586 return -ENOMEM; 587 } 588 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "AuthFile %s\n", g_spdk_iscsi.authfile); 589 590 /* ISCSI Global */ 591 val = spdk_conf_section_get_val(sp, "NodeBase"); 592 if (val == NULL) { 593 val = SPDK_ISCSI_DEFAULT_NODEBASE; 594 } 595 596 g_spdk_iscsi.nodebase = strdup(val); 597 if (!g_spdk_iscsi.nodebase) { 598 perror("nodebase"); 599 free(g_spdk_iscsi.authfile); 600 return -ENOMEM; 601 } 602 603 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "NodeBase %s\n", 604 g_spdk_iscsi.nodebase); 605 606 MaxSessions = spdk_conf_section_get_intval(sp, "MaxSessions"); 607 if (MaxSessions < 1) { 608 MaxSessions = DEFAULT_MAX_SESSIONS; 609 } else if (MaxSessions > 0xffff) { 610 /* limited to 16bits - RFC3720(12.2) */ 611 SPDK_ERRLOG("over 65535 sessions are not supported\n"); 612 return -1; 613 } 614 g_spdk_iscsi.MaxSessions = MaxSessions; 615 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "MaxSessions %d\n", g_spdk_iscsi.MaxSessions); 616 617 g_spdk_iscsi.session = spdk_dma_zmalloc(sizeof(void *) * g_spdk_iscsi.MaxSessions, 0, NULL); 618 if (!g_spdk_iscsi.session) { 619 perror("Unable to allocate session pointer array\n"); 620 return -1; 621 } 622 623 MaxConnectionsPerSession = spdk_conf_section_get_intval(sp, "MaxConnectionsPerSession"); 624 if (MaxConnectionsPerSession < 1) { 625 MaxConnectionsPerSession = DEFAULT_MAX_CONNECTIONS_PER_SESSION; 626 } 627 g_spdk_iscsi.MaxConnectionsPerSession = MaxConnectionsPerSession; 628 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "MaxConnectionsPerSession %d\n", 629 g_spdk_iscsi.MaxConnectionsPerSession); 630 631 if (MaxConnectionsPerSession > 0xffff) { 632 SPDK_ERRLOG("over 65535 connections are not supported\n"); 633 return -1; 634 } 635 636 /* 637 * For now, just support same number of total connections, rather 638 * than MaxSessions * MaxConnectionsPerSession. After we add better 639 * handling for low resource conditions from our various buffer 640 * pools, we can bump this up to support more connections. 641 */ 642 g_spdk_iscsi.MaxConnections = g_spdk_iscsi.MaxSessions; 643 644 DefaultTime2Wait = spdk_conf_section_get_intval(sp, "DefaultTime2Wait"); 645 if (DefaultTime2Wait < 0) { 646 DefaultTime2Wait = DEFAULT_DEFAULTTIME2WAIT; 647 } 648 g_spdk_iscsi.DefaultTime2Wait = DefaultTime2Wait; 649 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "DefaultTime2Wait %d\n", 650 g_spdk_iscsi.DefaultTime2Wait); 651 652 DefaultTime2Retain = spdk_conf_section_get_intval(sp, "DefaultTime2Retain"); 653 if (DefaultTime2Retain < 0) { 654 DefaultTime2Retain = DEFAULT_DEFAULTTIME2RETAIN; 655 } 656 g_spdk_iscsi.DefaultTime2Retain = DefaultTime2Retain; 657 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "DefaultTime2Retain %d\n", 658 g_spdk_iscsi.DefaultTime2Retain); 659 660 /* check size limit - RFC3720(12.15, 12.16, 12.17) */ 661 if (g_spdk_iscsi.MaxOutstandingR2T > 65535) { 662 SPDK_ERRLOG("MaxOutstandingR2T(%d) > 65535\n", g_spdk_iscsi.MaxOutstandingR2T); 663 return -1; 664 } 665 if (g_spdk_iscsi.DefaultTime2Wait > 3600) { 666 SPDK_ERRLOG("DefaultTime2Wait(%d) > 3600\n", g_spdk_iscsi.DefaultTime2Wait); 667 return -1; 668 } 669 if (g_spdk_iscsi.DefaultTime2Retain > 3600) { 670 SPDK_ERRLOG("DefaultTime2Retain(%d) > 3600\n", g_spdk_iscsi.DefaultTime2Retain); 671 return -1; 672 } 673 674 g_spdk_iscsi.FirstBurstLength = SPDK_ISCSI_FIRST_BURST_LENGTH; 675 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "FirstBurstLength %d\n", 676 g_spdk_iscsi.FirstBurstLength); 677 678 g_spdk_iscsi.MaxBurstLength = SPDK_ISCSI_MAX_BURST_LENGTH; 679 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "MaxBurstLength %d\n", 680 g_spdk_iscsi.MaxBurstLength); 681 682 g_spdk_iscsi.MaxRecvDataSegmentLength = SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH; 683 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "MaxRecvDataSegmentLength %d\n", 684 g_spdk_iscsi.MaxRecvDataSegmentLength); 685 686 /* check size limit (up to 24bits - RFC3720(12.12)) */ 687 if (g_spdk_iscsi.MaxBurstLength < 512) { 688 SPDK_ERRLOG("MaxBurstLength(%d) < 512\n", g_spdk_iscsi.MaxBurstLength); 689 return -1; 690 } 691 if (g_spdk_iscsi.FirstBurstLength < 512) { 692 SPDK_ERRLOG("FirstBurstLength(%d) < 512\n", g_spdk_iscsi.FirstBurstLength); 693 return -1; 694 } 695 if (g_spdk_iscsi.FirstBurstLength > g_spdk_iscsi.MaxBurstLength) { 696 SPDK_ERRLOG("FirstBurstLength(%d) > MaxBurstLength(%d)\n", 697 g_spdk_iscsi.FirstBurstLength, g_spdk_iscsi.MaxBurstLength); 698 return -1; 699 } 700 if (g_spdk_iscsi.MaxBurstLength > 0x00ffffff) { 701 SPDK_ERRLOG("MaxBurstLength(%d) > 0x00ffffff\n", g_spdk_iscsi.MaxBurstLength); 702 return -1; 703 } 704 705 val = spdk_conf_section_get_val(sp, "InitialR2T"); 706 if (val == NULL) { 707 InitialR2T = DEFAULT_INITIALR2T; 708 } else if (strcasecmp(val, "Yes") == 0) { 709 InitialR2T = 1; 710 } else if (strcasecmp(val, "No") == 0) { 711 #if 0 712 InitialR2T = 0; 713 #else 714 SPDK_ERRLOG("not supported value %s\n", val); 715 return -1; 716 #endif 717 } else { 718 SPDK_ERRLOG("unknown value %s\n", val); 719 return -1; 720 } 721 g_spdk_iscsi.InitialR2T = InitialR2T; 722 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "InitialR2T %s\n", 723 g_spdk_iscsi.InitialR2T ? "Yes" : "No"); 724 725 val = spdk_conf_section_get_val(sp, "ImmediateData"); 726 if (val == NULL) { 727 ImmediateData = DEFAULT_IMMEDIATEDATA; 728 } else if (strcasecmp(val, "Yes") == 0) { 729 ImmediateData = 1; 730 } else if (strcasecmp(val, "No") == 0) { 731 ImmediateData = 0; 732 } else { 733 SPDK_ERRLOG("unknown value %s\n", val); 734 return -1; 735 } 736 g_spdk_iscsi.ImmediateData = ImmediateData; 737 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "ImmediateData %s\n", 738 g_spdk_iscsi.ImmediateData ? "Yes" : "No"); 739 740 val = spdk_conf_section_get_val(sp, "DataPDUInOrder"); 741 if (val == NULL) { 742 DataPDUInOrder = DEFAULT_DATAPDUINORDER; 743 } else if (strcasecmp(val, "Yes") == 0) { 744 DataPDUInOrder = 1; 745 } else if (strcasecmp(val, "No") == 0) { 746 #if 0 747 DataPDUInOrder = 0; 748 #else 749 SPDK_ERRLOG("not supported value %s\n", val); 750 return -1; 751 #endif 752 } else { 753 SPDK_ERRLOG("unknown value %s\n", val); 754 return -1; 755 } 756 g_spdk_iscsi.DataPDUInOrder = DataPDUInOrder; 757 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "DataPDUInOrder %s\n", 758 g_spdk_iscsi.DataPDUInOrder ? "Yes" : "No"); 759 760 /* This option is only for test. 761 * If AllowDuplicateIsid is enabled, it allows different connections carrying 762 * TSIH=0 login the target within the same session. 763 */ 764 val = spdk_conf_section_get_val(sp, "AllowDuplicateIsid"); 765 if (val == NULL) { 766 AllowDuplicateIsid = 0; 767 } else if (strcasecmp(val, "Yes") == 0) { 768 AllowDuplicateIsid = 1; 769 } else if (strcasecmp(val, "No") == 0) { 770 AllowDuplicateIsid = 0; 771 } else { 772 SPDK_ERRLOG("unknown value %s\n", val); 773 return -1; 774 } 775 g_spdk_iscsi.AllowDuplicateIsid = AllowDuplicateIsid; 776 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "AllowDuplicateIsid %s\n", 777 g_spdk_iscsi.AllowDuplicateIsid ? "Yes" : "No"); 778 779 val = spdk_conf_section_get_val(sp, "DataSequenceInOrder"); 780 if (val == NULL) { 781 DataSequenceInOrder = DEFAULT_DATASEQUENCEINORDER; 782 } else if (strcasecmp(val, "Yes") == 0) { 783 DataSequenceInOrder = 1; 784 } else if (strcasecmp(val, "No") == 0) { 785 #if 0 786 DataSequenceInOrder = 0; 787 #else 788 SPDK_ERRLOG("not supported value %s\n", val); 789 return -1; 790 #endif 791 } else { 792 SPDK_ERRLOG("unknown value %s\n", val); 793 return -1; 794 } 795 g_spdk_iscsi.DataSequenceInOrder = DataSequenceInOrder; 796 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "DataSequenceInOrder %s\n", 797 g_spdk_iscsi.DataSequenceInOrder ? "Yes" : "No"); 798 799 ErrorRecoveryLevel = spdk_conf_section_get_intval(sp, "ErrorRecoveryLevel"); 800 if (ErrorRecoveryLevel < 0) { 801 ErrorRecoveryLevel = DEFAULT_ERRORRECOVERYLEVEL; 802 } else if (ErrorRecoveryLevel > 2) { 803 SPDK_ERRLOG("ErrorRecoveryLevel %d not supported,\n", ErrorRecoveryLevel); 804 return -1; 805 } 806 g_spdk_iscsi.ErrorRecoveryLevel = ErrorRecoveryLevel; 807 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "ErrorRecoveryLevel %d\n", 808 g_spdk_iscsi.ErrorRecoveryLevel); 809 810 timeout = spdk_conf_section_get_intval(sp, "Timeout"); 811 if (timeout < 0) { 812 timeout = DEFAULT_TIMEOUT; 813 } 814 g_spdk_iscsi.timeout = timeout; 815 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Timeout %d\n", 816 g_spdk_iscsi.timeout); 817 818 val = spdk_conf_section_get_val(sp, "FlushTimeout"); 819 if (val) { 820 flush_timeout = strtoul(val, NULL, 10); 821 } 822 if (flush_timeout == 0) { 823 flush_timeout = DEFAULT_FLUSH_TIMEOUT; 824 } 825 g_spdk_iscsi.flush_timeout = flush_timeout * (spdk_get_ticks_hz() >> 20); 826 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "FlushTimeout %"PRIu64"\n", g_spdk_iscsi.flush_timeout); 827 828 nopininterval = spdk_conf_section_get_intval(sp, "NopInInterval"); 829 if (nopininterval < 0) { 830 nopininterval = DEFAULT_NOPININTERVAL; 831 } 832 if (nopininterval > MAX_NOPININTERVAL) { 833 SPDK_ERRLOG("%d NopInInterval too big, using %d instead.\n", 834 nopininterval, DEFAULT_NOPININTERVAL); 835 nopininterval = DEFAULT_NOPININTERVAL; 836 } 837 838 g_spdk_iscsi.nopininterval = nopininterval; 839 SPDK_TRACELOG(SPDK_TRACE_DEBUG, "NopInInterval %d\n", 840 g_spdk_iscsi.nopininterval); 841 842 val = spdk_conf_section_get_val(sp, "DiscoveryAuthMethod"); 843 if (val == NULL) { 844 g_spdk_iscsi.no_discovery_auth = 0; 845 g_spdk_iscsi.req_discovery_auth = 0; 846 g_spdk_iscsi.req_discovery_auth_mutual = 0; 847 } else { 848 g_spdk_iscsi.no_discovery_auth = 0; 849 for (i = 0; ; i++) { 850 val = spdk_conf_section_get_nmval(sp, "DiscoveryAuthMethod", 0, i); 851 if (val == NULL) 852 break; 853 if (strcasecmp(val, "CHAP") == 0) { 854 g_spdk_iscsi.req_discovery_auth = 1; 855 } else if (strcasecmp(val, "Mutual") == 0) { 856 g_spdk_iscsi.req_discovery_auth_mutual = 1; 857 } else if (strcasecmp(val, "Auto") == 0) { 858 g_spdk_iscsi.req_discovery_auth = 0; 859 g_spdk_iscsi.req_discovery_auth_mutual = 0; 860 } else if (strcasecmp(val, "None") == 0) { 861 g_spdk_iscsi.no_discovery_auth = 1; 862 g_spdk_iscsi.req_discovery_auth = 0; 863 g_spdk_iscsi.req_discovery_auth_mutual = 0; 864 } else { 865 SPDK_ERRLOG("unknown auth\n"); 866 return -1; 867 } 868 } 869 if (g_spdk_iscsi.req_discovery_auth_mutual && !g_spdk_iscsi.req_discovery_auth) { 870 SPDK_ERRLOG("Mutual but not CHAP\n"); 871 return -1; 872 } 873 } 874 if (g_spdk_iscsi.no_discovery_auth != 0) { 875 SPDK_TRACELOG(SPDK_TRACE_DEBUG, 876 "DiscoveryAuthMethod None\n"); 877 } else if (g_spdk_iscsi.req_discovery_auth == 0) { 878 SPDK_TRACELOG(SPDK_TRACE_DEBUG, 879 "DiscoveryAuthMethod Auto\n"); 880 } else { 881 SPDK_TRACELOG(SPDK_TRACE_DEBUG, 882 "DiscoveryAuthMethod %s %s\n", 883 g_spdk_iscsi.req_discovery_auth ? "CHAP" : "", 884 g_spdk_iscsi.req_discovery_auth_mutual ? "Mutual" : ""); 885 } 886 887 val = spdk_conf_section_get_val(sp, "DiscoveryAuthGroup"); 888 if (val == NULL) { 889 g_spdk_iscsi.discovery_auth_group = 0; 890 } else { 891 ag_tag = val; 892 if (strcasecmp(ag_tag, "None") == 0) { 893 ag_tag_i = 0; 894 } else { 895 if (strncasecmp(ag_tag, "AuthGroup", 896 strlen("AuthGroup")) != 0 897 || sscanf(ag_tag, "%*[^0-9]%d", &ag_tag_i) != 1) { 898 SPDK_ERRLOG("auth group error\n"); 899 return -1; 900 } 901 if (ag_tag_i == 0) { 902 SPDK_ERRLOG("invalid auth group %d\n", ag_tag_i); 903 return -1; 904 } 905 } 906 g_spdk_iscsi.discovery_auth_group = ag_tag_i; 907 } 908 if (g_spdk_iscsi.discovery_auth_group == 0) { 909 SPDK_TRACELOG(SPDK_TRACE_DEBUG, 910 "DiscoveryAuthGroup None\n"); 911 } else { 912 SPDK_TRACELOG(SPDK_TRACE_DEBUG, 913 "DiscoveryAuthGroup AuthGroup%d\n", 914 g_spdk_iscsi.discovery_auth_group); 915 } 916 917 min_conn_per_core = spdk_conf_section_get_intval(sp, "MinConnectionsPerCore"); 918 if (min_conn_per_core >= 0) 919 spdk_iscsi_conn_set_min_per_core(min_conn_per_core); 920 921 conn_idle_interval = spdk_conf_section_get_intval(sp, "MinConnectionIdleInterval"); 922 if (conn_idle_interval > 0) 923 spdk_iscsi_set_min_conn_idle_interval(conn_idle_interval); 924 925 /* portal groups */ 926 rc = spdk_iscsi_portal_grp_array_create(); 927 if (rc < 0) { 928 SPDK_ERRLOG("spdk_iscsi_portal_grp_array_create() failed\n"); 929 return -1; 930 } 931 932 /* initiator groups */ 933 rc = spdk_iscsi_init_grp_array_create(); 934 if (rc < 0) { 935 SPDK_ERRLOG("spdk_iscsi_init_grp_array_create() failed\n"); 936 return -1; 937 } 938 939 rc = pthread_mutex_init(&g_spdk_iscsi.mutex, NULL); 940 if (rc != 0) { 941 SPDK_ERRLOG("mutex_init() failed\n"); 942 return -1; 943 } 944 945 return 0; 946 } 947 948 static void 949 spdk_iscsi_setup(void *arg1, void *arg2) 950 { 951 int rc; 952 953 /* open portals */ 954 rc = spdk_iscsi_portal_grp_open_all(); 955 if (rc < 0) { 956 SPDK_ERRLOG("spdk_iscsi_portal_grp_open_all() failed\n"); 957 return; 958 } 959 960 spdk_iscsi_acceptor_start(); 961 } 962 963 int 964 spdk_iscsi_init(void) 965 { 966 int rc; 967 968 rc = spdk_iscsi_app_read_parameters(); 969 if (rc < 0) { 970 SPDK_ERRLOG("spdk_iscsi_app_read_parameters() failed\n"); 971 return -1; 972 } 973 974 rc = spdk_iscsi_initialize_all_pools(); 975 if (rc != 0) { 976 SPDK_ERRLOG("spdk_initialize_all_pools() failed\n"); 977 return -1; 978 } 979 980 rc = spdk_iscsi_init_tgt_nodes(); 981 if (rc < 0) { 982 SPDK_ERRLOG("spdk_iscsi_init_tgt_nodes() failed\n"); 983 return -1; 984 } 985 986 rc = spdk_initialize_iscsi_conns(); 987 if (rc < 0) { 988 SPDK_ERRLOG("spdk_initialize_iscsi_conns() failed\n"); 989 return -1; 990 } 991 992 /* 993 * Defer creation of listening sockets until the reactor has started. 994 */ 995 spdk_event_call(spdk_event_allocate(spdk_env_get_current_core(), spdk_iscsi_setup, NULL, NULL)); 996 997 return 0; 998 } 999 1000 int 1001 spdk_iscsi_fini(void) 1002 { 1003 int rc; 1004 1005 rc = spdk_iscsi_check_pools(); 1006 spdk_iscsi_free_pools(); 1007 1008 spdk_iscsi_shutdown_tgt_nodes(); 1009 spdk_iscsi_init_grp_array_destroy(); 1010 spdk_iscsi_portal_grp_array_destroy(); 1011 free(g_spdk_iscsi.authfile); 1012 free(g_spdk_iscsi.nodebase); 1013 1014 pthread_mutex_destroy(&g_spdk_iscsi.mutex); 1015 1016 return rc; 1017 } 1018 1019 void 1020 spdk_iscsi_config_text(FILE *fp) 1021 { 1022 spdk_iscsi_config_dump_section(fp); 1023 spdk_iscsi_config_dump_portal_groups(fp); 1024 spdk_iscsi_config_dump_initiator_groups(fp); 1025 spdk_iscsi_config_dump_target_nodes(fp); 1026 } 1027 1028 SPDK_LOG_REGISTER_TRACE_FLAG("iscsi", SPDK_TRACE_ISCSI) 1029