2016-08-02 16:34:45 +00:00
|
|
|
/*-
|
|
|
|
* BSD LICENSE
|
|
|
|
*
|
|
|
|
* Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
|
|
|
|
* Copyright (c) Intel Corporation.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
*
|
|
|
|
* * Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
* the documentation and/or other materials provided with the
|
|
|
|
* distribution.
|
|
|
|
* * Neither the name of Intel Corporation nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2017-05-02 18:18:25 +00:00
|
|
|
#include "spdk/stdinc.h"
|
2017-12-08 08:12:30 +00:00
|
|
|
#include "spdk/env.h"
|
2017-12-18 04:29:37 +00:00
|
|
|
#include "spdk/string.h"
|
2018-02-14 02:26:10 +00:00
|
|
|
#include "spdk/sock.h"
|
2018-03-16 01:56:36 +00:00
|
|
|
#include "spdk/likely.h"
|
2016-10-03 21:40:06 +00:00
|
|
|
|
2016-08-02 16:34:45 +00:00
|
|
|
#include "iscsi/iscsi.h"
|
|
|
|
#include "iscsi/init_grp.h"
|
|
|
|
#include "iscsi/portal_grp.h"
|
|
|
|
#include "iscsi/conn.h"
|
|
|
|
#include "iscsi/task.h"
|
2016-08-17 20:35:18 +00:00
|
|
|
|
2017-01-04 23:45:29 +00:00
|
|
|
#include "spdk_internal/event.h"
|
2016-11-07 22:10:28 +00:00
|
|
|
#include "spdk_internal/log.h"
|
2016-08-02 16:34:45 +00:00
|
|
|
|
2018-05-14 23:24:19 +00:00
|
|
|
struct spdk_iscsi_opts *g_spdk_iscsi_opts = NULL;
|
|
|
|
|
2018-02-22 02:26:00 +00:00
|
|
|
static spdk_iscsi_init_cb g_init_cb_fn = NULL;
|
|
|
|
static void *g_init_cb_arg = NULL;
|
|
|
|
|
2017-11-10 17:02:00 +00:00
|
|
|
static spdk_iscsi_fini_cb g_fini_cb_fn;
|
|
|
|
static void *g_fini_cb_arg;
|
|
|
|
|
2016-08-02 16:34:45 +00:00
|
|
|
#define ISCSI_CONFIG_TMPL \
|
|
|
|
"[iSCSI]\n" \
|
|
|
|
" # node name (not include optional part)\n" \
|
|
|
|
" # Users can optionally change this to fit their environment.\n" \
|
|
|
|
" NodeBase \"%s\"\n" \
|
|
|
|
"\n" \
|
|
|
|
" # files\n" \
|
|
|
|
" AuthFile %s\n" \
|
|
|
|
"\n" \
|
|
|
|
" # socket I/O timeout sec. (polling is infinity)\n" \
|
|
|
|
" Timeout %d\n" \
|
|
|
|
"\n" \
|
|
|
|
" # authentication information for discovery session\n" \
|
|
|
|
" DiscoveryAuthMethod %s\n" \
|
|
|
|
" DiscoveryAuthGroup %s\n" \
|
|
|
|
"\n" \
|
|
|
|
" MaxSessions %d\n" \
|
|
|
|
" MaxConnectionsPerSession %d\n" \
|
|
|
|
" MaxConnections %d\n" \
|
2017-11-22 05:58:25 +00:00
|
|
|
" MaxQueueDepth %d\n" \
|
2016-08-02 16:34:45 +00:00
|
|
|
"\n" \
|
|
|
|
" # iSCSI initial parameters negotiate with initiators\n" \
|
|
|
|
" # NOTE: incorrect values might crash\n" \
|
|
|
|
" DefaultTime2Wait %d\n" \
|
|
|
|
" DefaultTime2Retain %d\n" \
|
|
|
|
"\n" \
|
2018-08-10 18:27:02 +00:00
|
|
|
" FirstBurstLength %d\n" \
|
2016-08-02 16:34:45 +00:00
|
|
|
" ImmediateData %s\n" \
|
|
|
|
" ErrorRecoveryLevel %d\n" \
|
|
|
|
"\n"
|
|
|
|
|
|
|
|
static void
|
2018-05-07 23:33:15 +00:00
|
|
|
spdk_iscsi_globals_config_text(FILE *fp)
|
2016-08-02 16:34:45 +00:00
|
|
|
{
|
2016-08-08 17:59:49 +00:00
|
|
|
const char *authmethod = "None";
|
2016-08-02 16:34:45 +00:00
|
|
|
char authgroup[32] = "None";
|
|
|
|
|
2017-12-07 23:23:48 +00:00
|
|
|
if (NULL == fp) {
|
2016-08-02 16:34:45 +00:00
|
|
|
return;
|
2017-12-07 23:23:48 +00:00
|
|
|
}
|
2016-08-02 16:34:45 +00:00
|
|
|
|
2018-08-22 01:29:23 +00:00
|
|
|
if (g_spdk_iscsi.require_chap) {
|
2016-08-08 17:59:49 +00:00
|
|
|
authmethod = "CHAP";
|
2018-08-22 01:29:23 +00:00
|
|
|
} else if (g_spdk_iscsi.mutual_chap) {
|
2016-08-08 17:59:49 +00:00
|
|
|
authmethod = "CHAP Mutual";
|
2018-08-22 01:29:23 +00:00
|
|
|
} else if (!g_spdk_iscsi.disable_chap) {
|
2016-08-08 17:59:49 +00:00
|
|
|
authmethod = "Auto";
|
2017-12-07 23:23:48 +00:00
|
|
|
}
|
2016-08-02 16:34:45 +00:00
|
|
|
|
2018-08-22 01:29:23 +00:00
|
|
|
if (g_spdk_iscsi.chap_group) {
|
|
|
|
snprintf(authgroup, sizeof(authgroup), "AuthGroup%d", g_spdk_iscsi.chap_group);
|
2017-12-07 23:23:48 +00:00
|
|
|
}
|
2016-08-02 16:34:45 +00:00
|
|
|
|
|
|
|
fprintf(fp, ISCSI_CONFIG_TMPL,
|
|
|
|
g_spdk_iscsi.nodebase, g_spdk_iscsi.authfile,
|
|
|
|
g_spdk_iscsi.timeout, authmethod, authgroup,
|
|
|
|
g_spdk_iscsi.MaxSessions, g_spdk_iscsi.MaxConnectionsPerSession,
|
2017-10-26 01:26:01 +00:00
|
|
|
g_spdk_iscsi.MaxConnections,
|
2017-11-22 05:58:25 +00:00
|
|
|
g_spdk_iscsi.MaxQueueDepth,
|
2016-08-02 16:34:45 +00:00
|
|
|
g_spdk_iscsi.DefaultTime2Wait, g_spdk_iscsi.DefaultTime2Retain,
|
2018-08-10 18:27:02 +00:00
|
|
|
g_spdk_iscsi.FirstBurstLength,
|
2018-03-12 09:38:53 +00:00
|
|
|
(g_spdk_iscsi.ImmediateData) ? "Yes" : "No",
|
2016-08-02 16:34:45 +00:00
|
|
|
g_spdk_iscsi.ErrorRecoveryLevel);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-12-08 08:12:30 +00:00
|
|
|
spdk_mobj_ctor(struct spdk_mempool *mp, __attribute__((unused)) void *arg,
|
2016-08-02 16:34:45 +00:00
|
|
|
void *_m, __attribute__((unused)) unsigned i)
|
|
|
|
{
|
|
|
|
struct spdk_mobj *m = _m;
|
|
|
|
uint64_t *phys_addr;
|
2016-09-29 20:23:56 +00:00
|
|
|
ptrdiff_t off;
|
2016-08-02 16:34:45 +00:00
|
|
|
|
|
|
|
m->mp = mp;
|
|
|
|
m->buf = (uint8_t *)m + sizeof(struct spdk_mobj);
|
|
|
|
m->buf = (void *)((unsigned long)((uint8_t *)m->buf + 512) & ~511UL);
|
|
|
|
off = (uint64_t)(uint8_t *)m->buf - (uint64_t)(uint8_t *)m;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* we store the physical address in a 64bit unsigned integer
|
|
|
|
* right before the 512B aligned buffer area.
|
|
|
|
*/
|
|
|
|
phys_addr = (uint64_t *)m->buf - 1;
|
2017-12-08 08:12:30 +00:00
|
|
|
*phys_addr = spdk_vtophys(m) + off;
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
|
|
|
|
2017-11-22 05:58:25 +00:00
|
|
|
#define NUM_PDU_PER_CONNECTION(iscsi) (2 * (iscsi->MaxQueueDepth + MAX_LARGE_DATAIN_PER_CONNECTION + 8))
|
|
|
|
#define PDU_POOL_SIZE(iscsi) (iscsi->MaxConnections * NUM_PDU_PER_CONNECTION(iscsi))
|
2016-08-02 16:34:45 +00:00
|
|
|
#define IMMEDIATE_DATA_POOL_SIZE(iscsi) (iscsi->MaxConnections * 128)
|
|
|
|
#define DATA_OUT_POOL_SIZE(iscsi) (iscsi->MaxConnections * MAX_DATA_OUT_PER_CONNECTION)
|
|
|
|
|
|
|
|
static int spdk_iscsi_initialize_pdu_pool(void)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_globals *iscsi = &g_spdk_iscsi;
|
|
|
|
int imm_mobj_size = spdk_get_immediate_data_buffer_size() +
|
|
|
|
sizeof(struct spdk_mobj) + 512;
|
|
|
|
int dout_mobj_size = spdk_get_data_out_buffer_size() +
|
|
|
|
sizeof(struct spdk_mobj) + 512;
|
|
|
|
|
|
|
|
/* create PDU pool */
|
2017-12-08 08:12:30 +00:00
|
|
|
iscsi->pdu_pool = spdk_mempool_create("PDU_Pool",
|
|
|
|
PDU_POOL_SIZE(iscsi),
|
|
|
|
sizeof(struct spdk_iscsi_pdu),
|
|
|
|
256, SPDK_ENV_SOCKET_ID_ANY);
|
2016-08-02 16:34:45 +00:00
|
|
|
if (!iscsi->pdu_pool) {
|
|
|
|
SPDK_ERRLOG("create PDU pool failed\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-12-08 08:12:30 +00:00
|
|
|
iscsi->pdu_immediate_data_pool = spdk_mempool_create_ctor("PDU_immediate_data_Pool",
|
|
|
|
IMMEDIATE_DATA_POOL_SIZE(iscsi),
|
|
|
|
imm_mobj_size, 0,
|
|
|
|
spdk_env_get_socket_id(spdk_env_get_current_core()),
|
|
|
|
spdk_mobj_ctor, NULL);
|
2016-08-02 16:34:45 +00:00
|
|
|
if (!iscsi->pdu_immediate_data_pool) {
|
2018-08-10 18:27:02 +00:00
|
|
|
SPDK_ERRLOG("create PDU immediate data pool failed\n");
|
2016-08-02 16:34:45 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-12-08 08:12:30 +00:00
|
|
|
iscsi->pdu_data_out_pool = spdk_mempool_create_ctor("PDU_data_out_Pool",
|
2016-08-02 16:34:45 +00:00
|
|
|
DATA_OUT_POOL_SIZE(iscsi),
|
2018-03-20 07:49:53 +00:00
|
|
|
dout_mobj_size, 256,
|
2017-12-08 08:12:30 +00:00
|
|
|
spdk_env_get_socket_id(spdk_env_get_current_core()),
|
|
|
|
spdk_mobj_ctor, NULL);
|
2016-08-02 16:34:45 +00:00
|
|
|
if (!iscsi->pdu_data_out_pool) {
|
2018-08-10 18:27:02 +00:00
|
|
|
SPDK_ERRLOG("create PDU data out pool failed\n");
|
2016-08-02 16:34:45 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-12-08 08:12:30 +00:00
|
|
|
static void spdk_iscsi_sess_ctor(struct spdk_mempool *pool, void *arg,
|
2016-08-02 16:34:45 +00:00
|
|
|
void *session_buf, unsigned index)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_globals *iscsi = arg;
|
|
|
|
struct spdk_iscsi_sess *sess = session_buf;
|
|
|
|
|
|
|
|
iscsi->session[index] = sess;
|
|
|
|
|
|
|
|
/* tsih 0 is reserved, so start tsih values at 1. */
|
|
|
|
sess->tsih = index + 1;
|
|
|
|
}
|
|
|
|
|
iscsi: fix the run out of task pool issue
When performed limitation iSCSI tests, 128 target nodes with 1
connection for each target node, for IO bigger than 256KiB iSCSI
target will report run of out task pool issue sometimes. When
all the iSCSI parameters with default values, each connection
will consume maximum 189 tasks, we hardcoded the task pool with
16384, so 189 * 128 connection will exceed 16384. Increase the
default number from 16384 to 32768 will fix the issue.
With 1MiB block size and queue depth with 128 for each connection,
there will be 64 outstanding iSCSI commands in the iSCSI target,
for Writes, the maximum R2T number is 4, so the maximum tasks for
the 4 R2T is (1 + 16) * 4 = 68, 8KiB for the first burst task, 16
for the data segment. For Reads, the maximum 64 data in segment can
be used as 4 iSCSI Read commands. The rest 56 iSCSI commands will
cost 56 tasks, so the total number is 56 + 64 + 68 = 188, 1 additional
task for NOP task.
Change-Id: I945871cbe3076139f08c2ef647af2d9c84601dcb
Signed-off-by: Changpeng Liu <changpeng.liu@intel.com>
2017-02-23 02:18:30 +00:00
|
|
|
#define DEFAULT_TASK_POOL_SIZE 32768
|
2016-08-02 16:34:45 +00:00
|
|
|
|
|
|
|
static int
|
|
|
|
spdk_iscsi_initialize_task_pool(void)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_globals *iscsi = &g_spdk_iscsi;
|
|
|
|
|
|
|
|
/* create scsi_task pool */
|
2017-12-06 04:41:52 +00:00
|
|
|
iscsi->task_pool = spdk_mempool_create("SCSI_TASK_Pool",
|
|
|
|
DEFAULT_TASK_POOL_SIZE,
|
|
|
|
sizeof(struct spdk_iscsi_task),
|
2017-12-08 08:12:30 +00:00
|
|
|
128, SPDK_ENV_SOCKET_ID_ANY);
|
2016-08-02 16:34:45 +00:00
|
|
|
if (!iscsi->task_pool) {
|
|
|
|
SPDK_ERRLOG("create task pool failed\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define SESSION_POOL_SIZE(iscsi) (iscsi->MaxSessions)
|
|
|
|
static int spdk_iscsi_initialize_session_pool(void)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_globals *iscsi = &g_spdk_iscsi;
|
|
|
|
|
2017-12-08 08:12:30 +00:00
|
|
|
iscsi->session_pool = spdk_mempool_create_ctor("Session_Pool",
|
2016-08-02 16:34:45 +00:00
|
|
|
SESSION_POOL_SIZE(iscsi),
|
2017-12-08 08:12:30 +00:00
|
|
|
sizeof(struct spdk_iscsi_sess), 0,
|
|
|
|
SPDK_ENV_SOCKET_ID_ANY,
|
|
|
|
spdk_iscsi_sess_ctor, iscsi);
|
2016-08-02 16:34:45 +00:00
|
|
|
if (!iscsi->session_pool) {
|
|
|
|
SPDK_ERRLOG("create session pool failed\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
spdk_iscsi_initialize_all_pools(void)
|
|
|
|
{
|
|
|
|
if (spdk_iscsi_initialize_pdu_pool() != 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (spdk_iscsi_initialize_session_pool() != 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (spdk_iscsi_initialize_task_pool() != 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-10-06 14:17:38 +00:00
|
|
|
static void
|
2017-12-08 08:12:30 +00:00
|
|
|
spdk_iscsi_check_pool(struct spdk_mempool *pool, size_t count)
|
2016-08-02 16:34:45 +00:00
|
|
|
{
|
2017-12-08 08:12:30 +00:00
|
|
|
if (spdk_mempool_count(pool) != count) {
|
|
|
|
SPDK_ERRLOG("spdk_mempool_count(%s) == %zu, should be %zu\n",
|
|
|
|
spdk_mempool_get_name(pool), spdk_mempool_count(pool), count);
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-06 14:17:38 +00:00
|
|
|
static void
|
2017-05-24 23:10:00 +00:00
|
|
|
spdk_iscsi_check_pools(void)
|
2016-08-02 16:34:45 +00:00
|
|
|
{
|
|
|
|
struct spdk_iscsi_globals *iscsi = &g_spdk_iscsi;
|
|
|
|
|
2017-10-06 14:17:38 +00:00
|
|
|
spdk_iscsi_check_pool(iscsi->pdu_pool, PDU_POOL_SIZE(iscsi));
|
|
|
|
spdk_iscsi_check_pool(iscsi->session_pool, SESSION_POOL_SIZE(iscsi));
|
|
|
|
spdk_iscsi_check_pool(iscsi->pdu_immediate_data_pool, IMMEDIATE_DATA_POOL_SIZE(iscsi));
|
|
|
|
spdk_iscsi_check_pool(iscsi->pdu_data_out_pool, DATA_OUT_POOL_SIZE(iscsi));
|
2018-06-11 18:35:50 +00:00
|
|
|
spdk_iscsi_check_pool(iscsi->task_pool, DEFAULT_TASK_POOL_SIZE);
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
|
|
|
|
2017-05-24 23:10:00 +00:00
|
|
|
static void
|
|
|
|
spdk_iscsi_free_pools(void)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_globals *iscsi = &g_spdk_iscsi;
|
|
|
|
|
2017-12-08 08:12:30 +00:00
|
|
|
spdk_mempool_free(iscsi->pdu_pool);
|
|
|
|
spdk_mempool_free(iscsi->session_pool);
|
|
|
|
spdk_mempool_free(iscsi->pdu_immediate_data_pool);
|
|
|
|
spdk_mempool_free(iscsi->pdu_data_out_pool);
|
2017-12-06 04:41:52 +00:00
|
|
|
spdk_mempool_free(iscsi->task_pool);
|
2017-05-24 23:10:00 +00:00
|
|
|
}
|
|
|
|
|
2016-08-02 16:34:45 +00:00
|
|
|
void spdk_put_pdu(struct spdk_iscsi_pdu *pdu)
|
|
|
|
{
|
2017-12-07 23:23:48 +00:00
|
|
|
if (!pdu) {
|
2016-08-02 16:34:45 +00:00
|
|
|
return;
|
2017-12-07 23:23:48 +00:00
|
|
|
}
|
2016-08-02 16:34:45 +00:00
|
|
|
|
|
|
|
pdu->ref--;
|
|
|
|
|
|
|
|
if (pdu->ref < 0) {
|
|
|
|
SPDK_ERRLOG("Negative PDU refcount: %p\n", pdu);
|
|
|
|
pdu->ref = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pdu->ref == 0) {
|
2017-12-07 23:23:48 +00:00
|
|
|
if (pdu->mobj) {
|
2017-12-08 08:12:30 +00:00
|
|
|
spdk_mempool_put(pdu->mobj->mp, (void *)pdu->mobj);
|
2017-12-07 23:23:48 +00:00
|
|
|
}
|
2016-08-02 16:34:45 +00:00
|
|
|
|
2017-12-07 23:23:48 +00:00
|
|
|
if (pdu->data && !pdu->data_from_mempool) {
|
2016-08-02 16:34:45 +00:00
|
|
|
free(pdu->data);
|
2017-12-07 23:23:48 +00:00
|
|
|
}
|
2016-08-02 16:34:45 +00:00
|
|
|
|
2017-12-08 08:12:30 +00:00
|
|
|
spdk_mempool_put(g_spdk_iscsi.pdu_pool, (void *)pdu);
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-08 17:11:20 +00:00
|
|
|
struct spdk_iscsi_pdu *spdk_get_pdu(void)
|
2016-08-02 16:34:45 +00:00
|
|
|
{
|
|
|
|
struct spdk_iscsi_pdu *pdu;
|
|
|
|
|
2017-12-08 08:12:30 +00:00
|
|
|
pdu = spdk_mempool_get(g_spdk_iscsi.pdu_pool);
|
|
|
|
if (!pdu) {
|
2016-08-02 16:34:45 +00:00
|
|
|
SPDK_ERRLOG("Unable to get PDU\n");
|
2016-11-07 21:03:27 +00:00
|
|
|
abort();
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
|
|
|
|
2016-10-31 17:39:59 +00:00
|
|
|
/* we do not want to zero out the last part of the structure reserved for AHS and sense data */
|
2017-07-13 00:50:19 +00:00
|
|
|
memset(pdu, 0, offsetof(struct spdk_iscsi_pdu, ahs));
|
2016-08-02 16:34:45 +00:00
|
|
|
pdu->ref = 1;
|
|
|
|
|
|
|
|
return pdu;
|
|
|
|
}
|
|
|
|
|
2017-10-26 03:02:14 +00:00
|
|
|
static void
|
|
|
|
spdk_iscsi_log_globals(void)
|
|
|
|
{
|
2017-08-30 18:06:33 +00:00
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "AuthFile %s\n", g_spdk_iscsi.authfile);
|
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "NodeBase %s\n", g_spdk_iscsi.nodebase);
|
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "MaxSessions %d\n", g_spdk_iscsi.MaxSessions);
|
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "MaxConnectionsPerSession %d\n",
|
2017-10-26 03:02:14 +00:00
|
|
|
g_spdk_iscsi.MaxConnectionsPerSession);
|
2017-08-30 18:06:33 +00:00
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "MaxQueueDepth %d\n", g_spdk_iscsi.MaxQueueDepth);
|
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "DefaultTime2Wait %d\n",
|
2017-10-26 03:02:14 +00:00
|
|
|
g_spdk_iscsi.DefaultTime2Wait);
|
2017-08-30 18:06:33 +00:00
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "DefaultTime2Retain %d\n",
|
2017-10-26 03:02:14 +00:00
|
|
|
g_spdk_iscsi.DefaultTime2Retain);
|
2018-08-10 18:27:02 +00:00
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "FirstBurstLength %d\n",
|
|
|
|
g_spdk_iscsi.FirstBurstLength);
|
2017-08-30 18:06:33 +00:00
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "ImmediateData %s\n",
|
2017-10-26 03:02:14 +00:00
|
|
|
g_spdk_iscsi.ImmediateData ? "Yes" : "No");
|
2017-08-30 18:06:33 +00:00
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "AllowDuplicateIsid %s\n",
|
2017-10-26 03:02:14 +00:00
|
|
|
g_spdk_iscsi.AllowDuplicateIsid ? "Yes" : "No");
|
2017-08-30 18:06:33 +00:00
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "ErrorRecoveryLevel %d\n",
|
2017-10-26 03:02:14 +00:00
|
|
|
g_spdk_iscsi.ErrorRecoveryLevel);
|
2017-08-30 18:06:33 +00:00
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "Timeout %d\n", g_spdk_iscsi.timeout);
|
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "NopInInterval %d\n",
|
2017-10-26 03:02:14 +00:00
|
|
|
g_spdk_iscsi.nopininterval);
|
2018-08-22 01:29:23 +00:00
|
|
|
if (g_spdk_iscsi.disable_chap) {
|
2017-08-30 18:06:33 +00:00
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI,
|
2017-10-26 03:02:14 +00:00
|
|
|
"DiscoveryAuthMethod None\n");
|
2018-08-22 01:29:23 +00:00
|
|
|
} else if (!g_spdk_iscsi.require_chap) {
|
2017-08-30 18:06:33 +00:00
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI,
|
2017-10-26 03:02:14 +00:00
|
|
|
"DiscoveryAuthMethod Auto\n");
|
|
|
|
} else {
|
2017-08-30 18:06:33 +00:00
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI,
|
2017-10-26 03:02:14 +00:00
|
|
|
"DiscoveryAuthMethod %s %s\n",
|
2018-08-22 01:29:23 +00:00
|
|
|
g_spdk_iscsi.require_chap ? "CHAP" : "",
|
|
|
|
g_spdk_iscsi.mutual_chap ? "Mutual" : "");
|
2017-10-26 03:02:14 +00:00
|
|
|
}
|
|
|
|
|
2018-08-22 01:29:23 +00:00
|
|
|
if (g_spdk_iscsi.chap_group == 0) {
|
2017-08-30 18:06:33 +00:00
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI,
|
2017-10-26 03:02:14 +00:00
|
|
|
"DiscoveryAuthGroup None\n");
|
|
|
|
} else {
|
2017-08-30 18:06:33 +00:00
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI,
|
2017-10-26 03:02:14 +00:00
|
|
|
"DiscoveryAuthGroup AuthGroup%d\n",
|
2018-08-22 01:29:23 +00:00
|
|
|
g_spdk_iscsi.chap_group);
|
2017-10-26 03:02:14 +00:00
|
|
|
}
|
2018-01-24 06:57:10 +00:00
|
|
|
|
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "MinConnectionsPerCore%d\n",
|
|
|
|
spdk_iscsi_conn_get_min_per_core());
|
2017-10-26 03:02:14 +00:00
|
|
|
}
|
|
|
|
|
2017-10-26 03:09:05 +00:00
|
|
|
static void
|
2018-03-08 23:19:30 +00:00
|
|
|
spdk_iscsi_opts_init(struct spdk_iscsi_opts *opts)
|
|
|
|
{
|
|
|
|
opts->MaxSessions = DEFAULT_MAX_SESSIONS;
|
|
|
|
opts->MaxConnectionsPerSession = DEFAULT_MAX_CONNECTIONS_PER_SESSION;
|
|
|
|
opts->MaxQueueDepth = DEFAULT_MAX_QUEUE_DEPTH;
|
|
|
|
opts->DefaultTime2Wait = DEFAULT_DEFAULTTIME2WAIT;
|
|
|
|
opts->DefaultTime2Retain = DEFAULT_DEFAULTTIME2RETAIN;
|
2018-08-10 18:27:02 +00:00
|
|
|
opts->FirstBurstLength = DEFAULT_FIRSTBURSTLENGTH;
|
2018-03-08 23:19:30 +00:00
|
|
|
opts->ImmediateData = DEFAULT_IMMEDIATEDATA;
|
2018-03-12 09:38:53 +00:00
|
|
|
opts->AllowDuplicateIsid = false;
|
2018-03-08 23:19:30 +00:00
|
|
|
opts->ErrorRecoveryLevel = DEFAULT_ERRORRECOVERYLEVEL;
|
|
|
|
opts->timeout = DEFAULT_TIMEOUT;
|
|
|
|
opts->nopininterval = DEFAULT_NOPININTERVAL;
|
2018-08-22 01:29:23 +00:00
|
|
|
opts->disable_chap = false;
|
|
|
|
opts->require_chap = false;
|
|
|
|
opts->mutual_chap = false;
|
|
|
|
opts->chap_group = 0;
|
2018-05-04 02:32:43 +00:00
|
|
|
opts->authfile = NULL;
|
|
|
|
opts->nodebase = NULL;
|
2018-03-14 09:17:38 +00:00
|
|
|
opts->min_connections_per_core = DEFAULT_CONNECTIONS_PER_LCORE;
|
2018-03-08 23:19:30 +00:00
|
|
|
}
|
|
|
|
|
2018-05-14 23:24:19 +00:00
|
|
|
struct spdk_iscsi_opts *
|
|
|
|
spdk_iscsi_opts_alloc(void)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_opts *opts;
|
|
|
|
|
|
|
|
opts = calloc(1, sizeof(*opts));
|
|
|
|
if (!opts) {
|
|
|
|
SPDK_ERRLOG("calloc() failed for iscsi options\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
spdk_iscsi_opts_init(opts);
|
|
|
|
|
|
|
|
return opts;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-03-08 23:19:30 +00:00
|
|
|
spdk_iscsi_opts_free(struct spdk_iscsi_opts *opts)
|
|
|
|
{
|
|
|
|
free(opts->authfile);
|
|
|
|
free(opts->nodebase);
|
2018-05-14 23:24:19 +00:00
|
|
|
free(opts);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Deep copy of spdk_iscsi_opts */
|
|
|
|
struct spdk_iscsi_opts *
|
|
|
|
spdk_iscsi_opts_copy(struct spdk_iscsi_opts *src)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_opts *dst;
|
|
|
|
|
|
|
|
dst = calloc(1, sizeof(*dst));
|
|
|
|
if (!dst) {
|
|
|
|
SPDK_ERRLOG("calloc() failed for iscsi options\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src->authfile) {
|
|
|
|
dst->authfile = strdup(src->authfile);
|
|
|
|
if (!dst->authfile) {
|
|
|
|
free(dst);
|
|
|
|
SPDK_ERRLOG("failed to strdup for auth file %s\n", src->authfile);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src->nodebase) {
|
|
|
|
dst->nodebase = strdup(src->nodebase);
|
|
|
|
if (!dst->nodebase) {
|
|
|
|
free(dst->authfile);
|
|
|
|
free(dst);
|
|
|
|
SPDK_ERRLOG("failed to strdup for nodebase %s\n", src->nodebase);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dst->MaxSessions = src->MaxSessions;
|
|
|
|
dst->MaxConnectionsPerSession = src->MaxConnectionsPerSession;
|
|
|
|
dst->MaxQueueDepth = src->MaxQueueDepth;
|
|
|
|
dst->DefaultTime2Wait = src->DefaultTime2Wait;
|
|
|
|
dst->DefaultTime2Retain = src->DefaultTime2Retain;
|
2018-08-10 18:27:02 +00:00
|
|
|
dst->FirstBurstLength = src->FirstBurstLength;
|
2018-05-14 23:24:19 +00:00
|
|
|
dst->ImmediateData = src->ImmediateData;
|
|
|
|
dst->AllowDuplicateIsid = src->AllowDuplicateIsid;
|
|
|
|
dst->ErrorRecoveryLevel = src->ErrorRecoveryLevel;
|
|
|
|
dst->timeout = src->timeout;
|
|
|
|
dst->nopininterval = src->nopininterval;
|
2018-08-22 01:29:23 +00:00
|
|
|
dst->disable_chap = src->disable_chap;
|
|
|
|
dst->require_chap = src->require_chap;
|
|
|
|
dst->mutual_chap = src->mutual_chap;
|
|
|
|
dst->chap_group = src->chap_group;
|
2018-05-14 23:24:19 +00:00
|
|
|
dst->min_connections_per_core = src->min_connections_per_core;
|
|
|
|
|
|
|
|
return dst;
|
2018-03-08 23:19:30 +00:00
|
|
|
}
|
|
|
|
|
2018-05-04 02:32:43 +00:00
|
|
|
static int
|
2018-03-08 23:25:34 +00:00
|
|
|
spdk_iscsi_read_config_file_params(struct spdk_conf_section *sp,
|
|
|
|
struct spdk_iscsi_opts *opts)
|
2016-08-02 16:34:45 +00:00
|
|
|
{
|
|
|
|
const char *val;
|
|
|
|
int MaxSessions;
|
|
|
|
int MaxConnectionsPerSession;
|
2017-11-22 05:58:25 +00:00
|
|
|
int MaxQueueDepth;
|
2016-08-02 16:34:45 +00:00
|
|
|
int DefaultTime2Wait;
|
|
|
|
int DefaultTime2Retain;
|
2018-08-10 18:27:02 +00:00
|
|
|
int FirstBurstLength;
|
2016-08-02 16:34:45 +00:00
|
|
|
int ErrorRecoveryLevel;
|
|
|
|
int timeout;
|
|
|
|
int nopininterval;
|
|
|
|
int min_conn_per_core = 0;
|
2017-10-26 02:38:34 +00:00
|
|
|
const char *ag_tag;
|
|
|
|
int ag_tag_i;
|
2016-08-02 16:34:45 +00:00
|
|
|
|
|
|
|
val = spdk_conf_section_get_val(sp, "Comment");
|
|
|
|
if (val != NULL) {
|
2017-08-30 18:06:33 +00:00
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "Comment %s\n", val);
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
val = spdk_conf_section_get_val(sp, "AuthFile");
|
2017-10-26 01:25:52 +00:00
|
|
|
if (val != NULL) {
|
2018-03-08 23:19:30 +00:00
|
|
|
opts->authfile = strdup(val);
|
2018-05-04 02:32:43 +00:00
|
|
|
if (!opts->authfile) {
|
|
|
|
SPDK_ERRLOG("strdup() failed for AuthFile\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
val = spdk_conf_section_get_val(sp, "NodeBase");
|
2017-10-26 01:25:52 +00:00
|
|
|
if (val != NULL) {
|
2018-03-08 23:19:30 +00:00
|
|
|
opts->nodebase = strdup(val);
|
2018-05-04 02:32:43 +00:00
|
|
|
if (!opts->nodebase) {
|
|
|
|
free(opts->authfile);
|
|
|
|
SPDK_ERRLOG("strdup() failed for NodeBase\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MaxSessions = spdk_conf_section_get_intval(sp, "MaxSessions");
|
2017-10-26 01:25:52 +00:00
|
|
|
if (MaxSessions >= 0) {
|
2018-05-04 02:20:40 +00:00
|
|
|
opts->MaxSessions = MaxSessions;
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MaxConnectionsPerSession = spdk_conf_section_get_intval(sp, "MaxConnectionsPerSession");
|
2017-10-26 01:25:52 +00:00
|
|
|
if (MaxConnectionsPerSession >= 0) {
|
2018-05-04 02:20:40 +00:00
|
|
|
opts->MaxConnectionsPerSession = MaxConnectionsPerSession;
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
2017-11-22 05:58:25 +00:00
|
|
|
|
|
|
|
MaxQueueDepth = spdk_conf_section_get_intval(sp, "MaxQueueDepth");
|
|
|
|
if (MaxQueueDepth >= 0) {
|
2018-05-04 02:20:40 +00:00
|
|
|
opts->MaxQueueDepth = MaxQueueDepth;
|
2017-11-22 05:58:25 +00:00
|
|
|
}
|
|
|
|
|
2016-08-02 16:34:45 +00:00
|
|
|
DefaultTime2Wait = spdk_conf_section_get_intval(sp, "DefaultTime2Wait");
|
2017-10-26 01:25:52 +00:00
|
|
|
if (DefaultTime2Wait >= 0) {
|
2018-05-04 02:20:40 +00:00
|
|
|
opts->DefaultTime2Wait = DefaultTime2Wait;
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
2018-08-10 18:27:02 +00:00
|
|
|
|
2016-08-02 16:34:45 +00:00
|
|
|
DefaultTime2Retain = spdk_conf_section_get_intval(sp, "DefaultTime2Retain");
|
2017-10-26 01:25:52 +00:00
|
|
|
if (DefaultTime2Retain >= 0) {
|
2018-05-04 02:20:40 +00:00
|
|
|
opts->DefaultTime2Retain = DefaultTime2Retain;
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
2018-08-10 18:27:02 +00:00
|
|
|
|
|
|
|
FirstBurstLength = spdk_conf_section_get_intval(sp, "FirstBurstLength");
|
|
|
|
if (FirstBurstLength >= 0) {
|
|
|
|
opts->FirstBurstLength = FirstBurstLength;
|
|
|
|
}
|
|
|
|
|
2018-03-08 23:19:30 +00:00
|
|
|
opts->ImmediateData = spdk_conf_section_get_boolval(sp, "ImmediateData",
|
|
|
|
opts->ImmediateData);
|
2016-08-02 16:34:45 +00:00
|
|
|
|
|
|
|
/* This option is only for test.
|
|
|
|
* If AllowDuplicateIsid is enabled, it allows different connections carrying
|
|
|
|
* TSIH=0 login the target within the same session.
|
|
|
|
*/
|
2018-03-08 23:19:30 +00:00
|
|
|
opts->AllowDuplicateIsid = spdk_conf_section_get_boolval(sp, "AllowDuplicateIsid",
|
|
|
|
opts->AllowDuplicateIsid);
|
2017-10-26 13:01:08 +00:00
|
|
|
|
2016-08-02 16:34:45 +00:00
|
|
|
ErrorRecoveryLevel = spdk_conf_section_get_intval(sp, "ErrorRecoveryLevel");
|
2017-10-26 01:25:52 +00:00
|
|
|
if (ErrorRecoveryLevel >= 0) {
|
2018-05-04 02:20:40 +00:00
|
|
|
opts->ErrorRecoveryLevel = ErrorRecoveryLevel;
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
|
|
|
timeout = spdk_conf_section_get_intval(sp, "Timeout");
|
2017-10-26 01:25:52 +00:00
|
|
|
if (timeout >= 0) {
|
2018-03-08 23:19:30 +00:00
|
|
|
opts->timeout = timeout;
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
|
|
|
nopininterval = spdk_conf_section_get_intval(sp, "NopInInterval");
|
2017-10-26 01:25:52 +00:00
|
|
|
if (nopininterval >= 0) {
|
2018-05-04 02:20:40 +00:00
|
|
|
opts->nopininterval = nopininterval;
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
|
|
|
val = spdk_conf_section_get_val(sp, "DiscoveryAuthMethod");
|
2017-10-26 01:25:52 +00:00
|
|
|
if (val != NULL) {
|
2017-10-26 04:14:36 +00:00
|
|
|
if (strcasecmp(val, "CHAP") == 0) {
|
2018-08-22 01:29:23 +00:00
|
|
|
opts->disable_chap = false;
|
|
|
|
opts->require_chap = true;
|
|
|
|
opts->mutual_chap = false;
|
2017-10-26 04:14:36 +00:00
|
|
|
} else if (strcasecmp(val, "Mutual") == 0) {
|
2018-08-22 01:29:23 +00:00
|
|
|
opts->disable_chap = false;
|
|
|
|
opts->require_chap = true;
|
|
|
|
opts->mutual_chap = true;
|
2017-10-26 04:14:36 +00:00
|
|
|
} else if (strcasecmp(val, "Auto") == 0) {
|
2018-08-22 01:29:23 +00:00
|
|
|
opts->disable_chap = false;
|
|
|
|
opts->require_chap = false;
|
|
|
|
opts->mutual_chap = false;
|
2017-10-26 04:14:36 +00:00
|
|
|
} else if (strcasecmp(val, "None") == 0) {
|
2018-08-22 01:29:23 +00:00
|
|
|
opts->disable_chap = true;
|
|
|
|
opts->require_chap = false;
|
|
|
|
opts->mutual_chap = false;
|
2017-10-26 04:14:36 +00:00
|
|
|
} else {
|
|
|
|
SPDK_ERRLOG("unknown auth %s, ignoring\n", val);
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
2017-10-26 01:25:52 +00:00
|
|
|
}
|
2016-08-02 16:34:45 +00:00
|
|
|
val = spdk_conf_section_get_val(sp, "DiscoveryAuthGroup");
|
2017-10-26 01:25:52 +00:00
|
|
|
if (val != NULL) {
|
2016-08-02 16:34:45 +00:00
|
|
|
ag_tag = val;
|
|
|
|
if (strcasecmp(ag_tag, "None") == 0) {
|
2018-08-22 01:29:23 +00:00
|
|
|
opts->chap_group = 0;
|
2016-08-02 16:34:45 +00:00
|
|
|
} else {
|
|
|
|
if (strncasecmp(ag_tag, "AuthGroup",
|
|
|
|
strlen("AuthGroup")) != 0
|
2017-10-26 03:09:05 +00:00
|
|
|
|| sscanf(ag_tag, "%*[^0-9]%d", &ag_tag_i) != 1
|
|
|
|
|| ag_tag_i == 0) {
|
|
|
|
SPDK_ERRLOG("invalid auth group %s, ignoring\n", ag_tag);
|
|
|
|
} else {
|
2018-08-22 01:29:23 +00:00
|
|
|
opts->chap_group = ag_tag_i;
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
min_conn_per_core = spdk_conf_section_get_intval(sp, "MinConnectionsPerCore");
|
2017-12-07 23:23:48 +00:00
|
|
|
if (min_conn_per_core >= 0) {
|
2018-03-14 09:17:38 +00:00
|
|
|
opts->min_connections_per_core = min_conn_per_core;
|
2017-12-07 23:23:48 +00:00
|
|
|
}
|
2018-05-04 02:32:43 +00:00
|
|
|
|
|
|
|
return 0;
|
2017-10-26 02:38:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2018-05-04 02:20:40 +00:00
|
|
|
spdk_iscsi_opts_verify(struct spdk_iscsi_opts *opts)
|
2017-10-26 02:38:34 +00:00
|
|
|
{
|
2018-03-08 23:19:30 +00:00
|
|
|
if (!opts->authfile) {
|
2018-05-04 02:32:43 +00:00
|
|
|
opts->authfile = strdup(SPDK_ISCSI_DEFAULT_AUTHFILE);
|
|
|
|
if (opts->authfile == NULL) {
|
|
|
|
SPDK_ERRLOG("strdup() failed for default authfile\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
2018-03-08 23:19:30 +00:00
|
|
|
}
|
2017-10-26 02:38:34 +00:00
|
|
|
|
2018-03-08 23:19:30 +00:00
|
|
|
if (!opts->nodebase) {
|
2018-05-04 02:32:43 +00:00
|
|
|
opts->nodebase = strdup(SPDK_ISCSI_DEFAULT_NODEBASE);
|
|
|
|
if (opts->nodebase == NULL) {
|
|
|
|
SPDK_ERRLOG("strdup() failed for default nodebase\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
2018-03-08 23:19:30 +00:00
|
|
|
}
|
|
|
|
|
2018-05-04 02:20:40 +00:00
|
|
|
if (opts->MaxSessions == 0 || opts->MaxSessions > 65535) {
|
|
|
|
SPDK_ERRLOG("%d is invalid. MaxSessions must be more than 0 and no more than 65535\n",
|
|
|
|
opts->MaxSessions);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opts->MaxConnectionsPerSession == 0 || opts->MaxConnectionsPerSession > 65535) {
|
|
|
|
SPDK_ERRLOG("%d is invalid. MaxConnectionsPerSession must be more than 0 and no more than 65535\n",
|
|
|
|
opts->MaxConnectionsPerSession);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opts->MaxQueueDepth == 0 || opts->MaxQueueDepth > 256) {
|
|
|
|
SPDK_ERRLOG("%d is invalid. MaxQueueDepth must be more than 0 and no more than 256\n",
|
|
|
|
opts->MaxQueueDepth);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opts->DefaultTime2Wait > 3600) {
|
|
|
|
SPDK_ERRLOG("%d is invalid. DefaultTime2Wait must be no more than 3600\n",
|
|
|
|
opts->DefaultTime2Wait);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opts->DefaultTime2Retain > 3600) {
|
|
|
|
SPDK_ERRLOG("%d is invalid. DefaultTime2Retain must be no more than 3600\n",
|
|
|
|
opts->DefaultTime2Retain);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2018-08-10 18:27:02 +00:00
|
|
|
if (opts->FirstBurstLength >= SPDK_ISCSI_MIN_FIRST_BURST_LENGTH) {
|
|
|
|
if (opts->FirstBurstLength > SPDK_ISCSI_MAX_BURST_LENGTH) {
|
|
|
|
SPDK_ERRLOG("FirstBurstLength %d shall not exceed MaxBurstLength %d\n",
|
|
|
|
opts->FirstBurstLength, SPDK_ISCSI_MAX_BURST_LENGTH);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SPDK_ERRLOG("FirstBurstLength %d shall be no less than %d\n",
|
|
|
|
opts->FirstBurstLength, SPDK_ISCSI_MIN_FIRST_BURST_LENGTH);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2018-05-04 02:20:40 +00:00
|
|
|
if (opts->ErrorRecoveryLevel > 2) {
|
|
|
|
SPDK_ERRLOG("ErrorRecoveryLevel %d is not supported.\n", opts->ErrorRecoveryLevel);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opts->timeout < 0) {
|
|
|
|
SPDK_ERRLOG("%d is invalid. timeout must not be less than 0\n", opts->timeout);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opts->nopininterval < 0 || opts->nopininterval > MAX_NOPININTERVAL) {
|
|
|
|
SPDK_ERRLOG("%d is invalid. nopinterval must be between 0 and %d\n",
|
|
|
|
opts->nopininterval, MAX_NOPININTERVAL);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2018-08-22 01:29:23 +00:00
|
|
|
if (!spdk_iscsi_check_chap_params(opts->disable_chap, opts->require_chap,
|
|
|
|
opts->mutual_chap, opts->chap_group)) {
|
2018-03-09 00:06:58 +00:00
|
|
|
SPDK_ERRLOG("CHAP params in opts are illegal combination\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2018-05-04 02:20:40 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-05-14 23:24:19 +00:00
|
|
|
static int
|
|
|
|
spdk_iscsi_parse_options(struct spdk_iscsi_opts **popts)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_opts *opts;
|
|
|
|
struct spdk_conf_section *sp;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
opts = spdk_iscsi_opts_alloc();
|
|
|
|
if (!opts) {
|
|
|
|
SPDK_ERRLOG("spdk_iscsi_opts_alloc_failed() failed\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Process parameters */
|
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "spdk_iscsi_read_config_file_parmas\n");
|
|
|
|
sp = spdk_conf_find_section(NULL, "iSCSI");
|
|
|
|
if (sp != NULL) {
|
|
|
|
rc = spdk_iscsi_read_config_file_params(sp, opts);
|
|
|
|
if (rc != 0) {
|
|
|
|
free(opts);
|
|
|
|
SPDK_ERRLOG("spdk_iscsi_read_config_file_params() failed\n");
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*popts = opts;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-05-04 02:20:40 +00:00
|
|
|
static int
|
|
|
|
spdk_iscsi_set_global_params(struct spdk_iscsi_opts *opts)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
rc = spdk_iscsi_opts_verify(opts);
|
|
|
|
if (rc != 0) {
|
|
|
|
SPDK_ERRLOG("spdk_iscsi_opts_verify() failed\n");
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2018-03-08 23:19:30 +00:00
|
|
|
g_spdk_iscsi.authfile = strdup(opts->authfile);
|
2017-10-26 02:38:34 +00:00
|
|
|
if (!g_spdk_iscsi.authfile) {
|
2018-03-08 23:19:30 +00:00
|
|
|
SPDK_ERRLOG("failed to strdup for auth file %s\n", opts->authfile);
|
2017-10-26 02:38:34 +00:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
2018-03-08 23:19:30 +00:00
|
|
|
|
|
|
|
g_spdk_iscsi.nodebase = strdup(opts->nodebase);
|
2017-10-26 02:38:34 +00:00
|
|
|
if (!g_spdk_iscsi.nodebase) {
|
2018-03-08 23:19:30 +00:00
|
|
|
SPDK_ERRLOG("failed to strdup for nodebase %s\n", opts->nodebase);
|
2017-10-26 02:38:34 +00:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2018-03-08 23:19:30 +00:00
|
|
|
g_spdk_iscsi.MaxSessions = opts->MaxSessions;
|
|
|
|
g_spdk_iscsi.MaxConnectionsPerSession = opts->MaxConnectionsPerSession;
|
|
|
|
g_spdk_iscsi.MaxQueueDepth = opts->MaxQueueDepth;
|
|
|
|
g_spdk_iscsi.DefaultTime2Wait = opts->DefaultTime2Wait;
|
|
|
|
g_spdk_iscsi.DefaultTime2Retain = opts->DefaultTime2Retain;
|
2018-08-10 18:27:02 +00:00
|
|
|
g_spdk_iscsi.FirstBurstLength = opts->FirstBurstLength;
|
2018-03-08 23:19:30 +00:00
|
|
|
g_spdk_iscsi.ImmediateData = opts->ImmediateData;
|
|
|
|
g_spdk_iscsi.AllowDuplicateIsid = opts->AllowDuplicateIsid;
|
|
|
|
g_spdk_iscsi.ErrorRecoveryLevel = opts->ErrorRecoveryLevel;
|
|
|
|
g_spdk_iscsi.timeout = opts->timeout;
|
|
|
|
g_spdk_iscsi.nopininterval = opts->nopininterval;
|
2018-08-22 01:29:23 +00:00
|
|
|
g_spdk_iscsi.disable_chap = opts->disable_chap;
|
|
|
|
g_spdk_iscsi.require_chap = opts->require_chap;
|
|
|
|
g_spdk_iscsi.mutual_chap = opts->mutual_chap;
|
|
|
|
g_spdk_iscsi.chap_group = opts->chap_group;
|
2018-03-08 23:19:30 +00:00
|
|
|
|
2018-03-14 09:17:38 +00:00
|
|
|
spdk_iscsi_conn_set_min_per_core(opts->min_connections_per_core);
|
|
|
|
|
2018-05-04 01:57:04 +00:00
|
|
|
spdk_iscsi_log_globals();
|
2017-10-26 02:38:34 +00:00
|
|
|
|
2018-05-04 01:57:04 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2017-10-26 02:38:34 +00:00
|
|
|
|
2018-08-22 04:43:18 +00:00
|
|
|
int
|
|
|
|
spdk_iscsi_set_discovery_auth(bool disable_chap, bool require_chap, bool mutual_chap,
|
|
|
|
int32_t chap_group)
|
|
|
|
{
|
|
|
|
if (!spdk_iscsi_check_chap_params(disable_chap, require_chap, mutual_chap,
|
|
|
|
chap_group)) {
|
|
|
|
SPDK_ERRLOG("CHAP params are illegal combination\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pthread_mutex_lock(&g_spdk_iscsi.mutex);
|
|
|
|
g_spdk_iscsi.disable_chap = disable_chap;
|
|
|
|
g_spdk_iscsi.require_chap = require_chap;
|
|
|
|
g_spdk_iscsi.mutual_chap = mutual_chap;
|
|
|
|
g_spdk_iscsi.chap_group = chap_group;
|
|
|
|
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-08-09 03:16:11 +00:00
|
|
|
int
|
2018-08-20 01:32:30 +00:00
|
|
|
spdk_iscsi_auth_group_add_secret(struct spdk_iscsi_auth_group *group,
|
|
|
|
const char *user, const char *secret,
|
|
|
|
const char *muser, const char *msecret)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_auth_secret *_secret;
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
if (user == NULL || secret == NULL) {
|
|
|
|
SPDK_ERRLOG("user and secret must be specified\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (muser != NULL && msecret == NULL) {
|
|
|
|
SPDK_ERRLOG("msecret must be specified with muser\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
TAILQ_FOREACH(_secret, &group->secret_head, tailq) {
|
|
|
|
if (strcmp(_secret->user, user) == 0) {
|
|
|
|
SPDK_ERRLOG("user for secret is duplicated\n");
|
|
|
|
return -EEXIST;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_secret = calloc(1, sizeof(*_secret));
|
|
|
|
if (_secret == NULL) {
|
|
|
|
SPDK_ERRLOG("calloc() failed for CHAP secret\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
len = strnlen(user, sizeof(_secret->user));
|
|
|
|
if (len > sizeof(_secret->user) - 1) {
|
|
|
|
SPDK_ERRLOG("CHAP user longer than %zu characters: %s\n",
|
|
|
|
sizeof(_secret->user) - 1, user);
|
|
|
|
free(_secret);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
memcpy(_secret->user, user, len);
|
|
|
|
|
|
|
|
len = strnlen(secret, sizeof(_secret->secret));
|
|
|
|
if (len > sizeof(_secret->secret) - 1) {
|
|
|
|
SPDK_ERRLOG("CHAP secret longer than %zu characters: %s\n",
|
|
|
|
sizeof(_secret->secret) - 1, secret);
|
|
|
|
free(_secret);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
memcpy(_secret->secret, secret, len);
|
|
|
|
|
|
|
|
if (muser != NULL) {
|
|
|
|
len = strnlen(muser, sizeof(_secret->muser));
|
|
|
|
if (len > sizeof(_secret->muser) - 1) {
|
|
|
|
SPDK_ERRLOG("Mutual CHAP user longer than %zu characters: %s\n",
|
|
|
|
sizeof(_secret->muser) - 1, muser);
|
|
|
|
free(_secret);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
memcpy(_secret->muser, muser, len);
|
|
|
|
|
|
|
|
len = strnlen(msecret, sizeof(_secret->msecret));
|
|
|
|
if (len > sizeof(_secret->msecret) - 1) {
|
|
|
|
SPDK_ERRLOG("Mutual CHAP secret longer than %zu characters: %s\n",
|
|
|
|
sizeof(_secret->msecret) - 1, msecret);
|
|
|
|
free(_secret);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
memcpy(_secret->msecret, msecret, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
TAILQ_INSERT_TAIL(&group->secret_head, _secret, tailq);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-08-09 03:16:11 +00:00
|
|
|
int
|
2018-08-20 01:32:30 +00:00
|
|
|
spdk_iscsi_add_auth_group(int32_t tag, struct spdk_iscsi_auth_group **_group)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_auth_group *group;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(group, &g_spdk_iscsi.auth_group_head, tailq) {
|
|
|
|
if (group->tag == tag) {
|
|
|
|
SPDK_ERRLOG("Auth group (%d) already exists\n", tag);
|
|
|
|
return -EEXIST;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
group = calloc(1, sizeof(*group));
|
|
|
|
if (group == NULL) {
|
|
|
|
SPDK_ERRLOG("calloc() failed for auth group\n");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
TAILQ_INIT(&group->secret_head);
|
|
|
|
group->tag = tag;
|
|
|
|
|
|
|
|
TAILQ_INSERT_TAIL(&g_spdk_iscsi.auth_group_head, group, tailq);
|
|
|
|
|
|
|
|
*_group = group;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-08-09 03:16:11 +00:00
|
|
|
void
|
2018-08-20 01:32:30 +00:00
|
|
|
spdk_iscsi_delete_auth_group(struct spdk_iscsi_auth_group *group)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_auth_secret *_secret, *tmp;
|
|
|
|
|
|
|
|
TAILQ_REMOVE(&g_spdk_iscsi.auth_group_head, group, tailq);
|
|
|
|
|
|
|
|
TAILQ_FOREACH_SAFE(_secret, &group->secret_head, tailq, tmp) {
|
|
|
|
TAILQ_REMOVE(&group->secret_head, _secret, tailq);
|
|
|
|
free(_secret);
|
|
|
|
}
|
|
|
|
free(group);
|
|
|
|
}
|
|
|
|
|
2018-08-09 03:16:11 +00:00
|
|
|
struct spdk_iscsi_auth_group *
|
|
|
|
spdk_iscsi_find_auth_group_by_tag(int32_t tag)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_auth_group *group;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(group, &g_spdk_iscsi.auth_group_head, tailq) {
|
|
|
|
if (group->tag == tag) {
|
|
|
|
return group;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-08-20 01:32:30 +00:00
|
|
|
static void
|
|
|
|
spdk_iscsi_auth_groups_destroy(void)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_auth_group *group, *tmp;
|
|
|
|
|
|
|
|
TAILQ_FOREACH_SAFE(group, &g_spdk_iscsi.auth_group_head, tailq, tmp) {
|
|
|
|
spdk_iscsi_delete_auth_group(group);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
spdk_iscsi_parse_auth_group(struct spdk_conf_section *sp)
|
2018-08-20 00:27:21 +00:00
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
int i;
|
2018-08-20 01:32:30 +00:00
|
|
|
int tag;
|
|
|
|
const char *val, *user, *secret, *muser, *msecret;
|
|
|
|
struct spdk_iscsi_auth_group *group = NULL;
|
2018-08-20 00:27:21 +00:00
|
|
|
|
2018-08-20 01:32:30 +00:00
|
|
|
val = spdk_conf_section_get_val(sp, "Comment");
|
|
|
|
if (val != NULL) {
|
|
|
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "Comment %s\n", val);
|
|
|
|
}
|
|
|
|
|
|
|
|
tag = spdk_conf_section_get_num(sp);
|
|
|
|
|
|
|
|
rc = spdk_iscsi_add_auth_group(tag, &group);
|
|
|
|
if (rc != 0) {
|
|
|
|
SPDK_ERRLOG("Failed to add auth group\n");
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; ; i++) {
|
|
|
|
val = spdk_conf_section_get_nval(sp, "Auth", i);
|
|
|
|
if (val == NULL) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
user = spdk_conf_section_get_nmval(sp, "Auth", i, 0);
|
|
|
|
secret = spdk_conf_section_get_nmval(sp, "Auth", i, 1);
|
|
|
|
muser = spdk_conf_section_get_nmval(sp, "Auth", i, 2);
|
|
|
|
msecret = spdk_conf_section_get_nmval(sp, "Auth", i, 3);
|
|
|
|
|
|
|
|
rc = spdk_iscsi_auth_group_add_secret(group, user, secret, muser, msecret);
|
|
|
|
if (rc != 0) {
|
|
|
|
SPDK_ERRLOG("Failed to add secret to auth group\n");
|
|
|
|
spdk_iscsi_delete_auth_group(group);
|
|
|
|
return rc;
|
|
|
|
}
|
2018-08-20 00:27:21 +00:00
|
|
|
}
|
|
|
|
|
2018-08-20 01:32:30 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
spdk_iscsi_parse_auth_info(void)
|
|
|
|
{
|
|
|
|
struct spdk_conf *config;
|
|
|
|
struct spdk_conf_section *sp;
|
|
|
|
int rc;
|
|
|
|
|
2018-08-20 00:27:21 +00:00
|
|
|
config = spdk_conf_allocate();
|
2018-08-20 01:32:30 +00:00
|
|
|
if (!config) {
|
|
|
|
SPDK_ERRLOG("Failed to allocate config file\n");
|
|
|
|
return -ENOMEM;
|
2018-08-20 00:27:21 +00:00
|
|
|
}
|
|
|
|
|
2018-08-20 01:32:30 +00:00
|
|
|
rc = spdk_conf_read(config, g_spdk_iscsi.authfile);
|
|
|
|
if (rc != 0) {
|
|
|
|
SPDK_INFOLOG(SPDK_LOG_ISCSI, "Failed to load auth file\n");
|
2018-08-20 00:27:21 +00:00
|
|
|
spdk_conf_free(config);
|
2018-08-20 01:32:30 +00:00
|
|
|
return rc;
|
2018-08-20 00:27:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sp = spdk_conf_first_section(config);
|
|
|
|
while (sp != NULL) {
|
|
|
|
if (spdk_conf_section_match_prefix(sp, "AuthGroup")) {
|
2018-08-20 01:32:30 +00:00
|
|
|
if (spdk_conf_section_get_num(sp) == 0) {
|
2018-08-20 00:27:21 +00:00
|
|
|
SPDK_ERRLOG("Group 0 is invalid\n");
|
2018-08-20 01:32:30 +00:00
|
|
|
spdk_iscsi_auth_groups_destroy();
|
2018-08-20 00:27:21 +00:00
|
|
|
spdk_conf_free(config);
|
2018-08-20 01:32:30 +00:00
|
|
|
return -EINVAL;
|
2018-08-20 00:27:21 +00:00
|
|
|
}
|
|
|
|
|
2018-08-20 01:32:30 +00:00
|
|
|
rc = spdk_iscsi_parse_auth_group(sp);
|
|
|
|
if (rc != 0) {
|
|
|
|
SPDK_ERRLOG("parse_auth_group() failed\n");
|
|
|
|
spdk_iscsi_auth_groups_destroy();
|
|
|
|
spdk_conf_free(config);
|
|
|
|
return rc;
|
2018-08-20 00:27:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
sp = spdk_conf_next_section(sp);
|
|
|
|
}
|
|
|
|
|
|
|
|
spdk_conf_free(config);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-08-20 01:32:30 +00:00
|
|
|
static struct spdk_iscsi_auth_secret *
|
|
|
|
spdk_iscsi_find_auth_secret(const char *authuser, int ag_tag)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_auth_group *group;
|
|
|
|
struct spdk_iscsi_auth_secret *_secret;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(group, &g_spdk_iscsi.auth_group_head, tailq) {
|
|
|
|
if (group->tag == ag_tag) {
|
|
|
|
TAILQ_FOREACH(_secret, &group->secret_head, tailq) {
|
|
|
|
if (strcmp(_secret->user, authuser) == 0) {
|
|
|
|
return _secret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
spdk_iscsi_chap_get_authinfo(struct iscsi_chap_auth *auth, const char *authuser,
|
|
|
|
int ag_tag)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_auth_secret *_secret;
|
|
|
|
|
|
|
|
if (authuser == NULL) {
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (auth->user[0] != '\0') {
|
|
|
|
memset(auth->user, 0, sizeof(auth->user));
|
|
|
|
memset(auth->secret, 0, sizeof(auth->secret));
|
|
|
|
memset(auth->muser, 0, sizeof(auth->muser));
|
|
|
|
memset(auth->msecret, 0, sizeof(auth->msecret));
|
|
|
|
}
|
|
|
|
|
2018-08-09 03:16:11 +00:00
|
|
|
pthread_mutex_lock(&g_spdk_iscsi.mutex);
|
|
|
|
|
2018-08-20 01:32:30 +00:00
|
|
|
_secret = spdk_iscsi_find_auth_secret(authuser, ag_tag);
|
|
|
|
if (_secret == NULL) {
|
2018-08-09 03:16:11 +00:00
|
|
|
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
|
|
|
|
|
2018-08-20 01:32:30 +00:00
|
|
|
SPDK_ERRLOG("CHAP secret is not found: user:%s, tag:%d\n",
|
|
|
|
authuser, ag_tag);
|
|
|
|
return -ENOENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(auth->user, _secret->user, sizeof(auth->user));
|
|
|
|
memcpy(auth->secret, _secret->secret, sizeof(auth->secret));
|
|
|
|
|
|
|
|
if (_secret->muser[0] != '\0') {
|
|
|
|
memcpy(auth->muser, _secret->muser, sizeof(auth->muser));
|
|
|
|
memcpy(auth->msecret, _secret->msecret, sizeof(auth->msecret));
|
|
|
|
}
|
|
|
|
|
2018-08-09 03:16:11 +00:00
|
|
|
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
|
2018-08-20 01:32:30 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-05-04 01:57:04 +00:00
|
|
|
static int
|
|
|
|
spdk_iscsi_initialize_global_params(void)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
2018-05-14 23:24:19 +00:00
|
|
|
if (!g_spdk_iscsi_opts) {
|
|
|
|
rc = spdk_iscsi_parse_options(&g_spdk_iscsi_opts);
|
2018-05-04 02:32:43 +00:00
|
|
|
if (rc != 0) {
|
2018-05-14 23:24:19 +00:00
|
|
|
SPDK_ERRLOG("spdk_iscsi_parse_options() failed\n");
|
2018-05-04 02:32:43 +00:00
|
|
|
return rc;
|
|
|
|
}
|
2018-03-08 02:59:00 +00:00
|
|
|
}
|
|
|
|
|
2018-05-14 23:24:19 +00:00
|
|
|
rc = spdk_iscsi_set_global_params(g_spdk_iscsi_opts);
|
2018-05-04 01:57:04 +00:00
|
|
|
if (rc != 0) {
|
|
|
|
SPDK_ERRLOG("spdk_iscsi_set_global_params() failed\n");
|
|
|
|
}
|
2017-10-26 03:02:14 +00:00
|
|
|
|
2018-05-14 23:24:19 +00:00
|
|
|
spdk_iscsi_opts_free(g_spdk_iscsi_opts);
|
|
|
|
g_spdk_iscsi_opts = NULL;
|
|
|
|
|
2018-05-04 02:20:40 +00:00
|
|
|
return rc;
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
|
|
|
|
2018-02-22 02:26:00 +00:00
|
|
|
static void
|
|
|
|
spdk_iscsi_init_complete(int rc)
|
|
|
|
{
|
|
|
|
spdk_iscsi_init_cb cb_fn = g_init_cb_fn;
|
|
|
|
void *cb_arg = g_init_cb_arg;
|
|
|
|
|
|
|
|
g_init_cb_fn = NULL;
|
|
|
|
g_init_cb_arg = NULL;
|
|
|
|
|
|
|
|
cb_fn(cb_arg, rc);
|
|
|
|
}
|
|
|
|
|
2018-03-13 00:16:47 +00:00
|
|
|
static int
|
2018-02-13 05:09:49 +00:00
|
|
|
spdk_iscsi_poll_group_poll(void *ctx)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_poll_group *group = ctx;
|
|
|
|
struct spdk_iscsi_conn *conn, *tmp;
|
2018-02-14 02:26:10 +00:00
|
|
|
int rc;
|
|
|
|
|
2018-03-16 01:56:36 +00:00
|
|
|
if (spdk_unlikely(STAILQ_EMPTY(&group->connections))) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = spdk_sock_group_poll(group->sock_group);
|
|
|
|
if (rc < 0) {
|
|
|
|
SPDK_ERRLOG("Failed to poll sock_group=%p\n", group->sock_group);
|
2018-02-14 02:26:10 +00:00
|
|
|
}
|
2018-02-13 05:09:49 +00:00
|
|
|
|
|
|
|
STAILQ_FOREACH_SAFE(conn, &group->connections, link, tmp) {
|
2018-03-06 04:46:55 +00:00
|
|
|
if (conn->state == ISCSI_CONN_STATE_EXITING) {
|
|
|
|
spdk_iscsi_conn_destruct(conn);
|
|
|
|
}
|
2018-02-13 05:09:49 +00:00
|
|
|
}
|
2018-03-13 00:16:47 +00:00
|
|
|
|
|
|
|
return -1;
|
2018-02-13 05:09:49 +00:00
|
|
|
}
|
|
|
|
|
2018-03-13 00:16:47 +00:00
|
|
|
static int
|
2018-02-28 05:55:38 +00:00
|
|
|
spdk_iscsi_poll_group_handle_nop(void *ctx)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_poll_group *group = ctx;
|
|
|
|
struct spdk_iscsi_conn *conn, *tmp;
|
|
|
|
|
|
|
|
STAILQ_FOREACH_SAFE(conn, &group->connections, link, tmp) {
|
|
|
|
spdk_iscsi_conn_handle_nop(conn);
|
|
|
|
}
|
2018-03-13 00:16:47 +00:00
|
|
|
|
|
|
|
return -1;
|
2018-02-28 05:55:38 +00:00
|
|
|
}
|
|
|
|
|
2018-02-13 05:09:49 +00:00
|
|
|
static void
|
|
|
|
iscsi_create_poll_group(void *ctx)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_poll_group *pg;
|
|
|
|
|
2018-04-18 20:14:17 +00:00
|
|
|
assert(g_spdk_iscsi.poll_group != NULL);
|
2018-02-13 05:09:49 +00:00
|
|
|
pg = &g_spdk_iscsi.poll_group[spdk_env_get_current_core()];
|
|
|
|
pg->core = spdk_env_get_current_core();
|
|
|
|
|
|
|
|
STAILQ_INIT(&pg->connections);
|
2018-02-14 02:26:10 +00:00
|
|
|
pg->sock_group = spdk_sock_group_create();
|
|
|
|
assert(pg->sock_group != NULL);
|
|
|
|
|
2018-02-13 05:09:49 +00:00
|
|
|
pg->poller = spdk_poller_register(spdk_iscsi_poll_group_poll, pg, 0);
|
2018-02-28 05:55:38 +00:00
|
|
|
/* set the period to 1 sec */
|
|
|
|
pg->nop_poller = spdk_poller_register(spdk_iscsi_poll_group_handle_nop, pg, 1000000);
|
2018-02-13 05:09:49 +00:00
|
|
|
}
|
|
|
|
|
2018-02-26 15:30:05 +00:00
|
|
|
static void
|
|
|
|
iscsi_unregister_poll_group(void *ctx)
|
|
|
|
{
|
|
|
|
struct spdk_iscsi_poll_group *pg;
|
|
|
|
|
2018-04-18 20:14:17 +00:00
|
|
|
assert(g_spdk_iscsi.poll_group != NULL);
|
2018-02-26 15:30:05 +00:00
|
|
|
pg = &g_spdk_iscsi.poll_group[spdk_env_get_current_core()];
|
|
|
|
assert(pg->poller != NULL);
|
2018-02-14 02:26:10 +00:00
|
|
|
assert(pg->sock_group != NULL);
|
2018-02-26 15:30:05 +00:00
|
|
|
|
2018-02-14 02:26:10 +00:00
|
|
|
spdk_sock_group_close(&pg->sock_group);
|
2018-02-26 15:30:05 +00:00
|
|
|
spdk_poller_unregister(&pg->poller);
|
2018-02-28 05:55:38 +00:00
|
|
|
spdk_poller_unregister(&pg->nop_poller);
|
2018-02-26 15:30:05 +00:00
|
|
|
}
|
|
|
|
|
2018-02-13 05:09:49 +00:00
|
|
|
static void
|
2018-03-08 04:07:51 +00:00
|
|
|
spdk_initialize_iscsi_poll_group(spdk_thread_fn cpl)
|
2018-02-13 05:09:49 +00:00
|
|
|
{
|
|
|
|
size_t g_num_poll_groups = spdk_env_get_last_core() + 1;
|
|
|
|
|
|
|
|
g_spdk_iscsi.poll_group = calloc(g_num_poll_groups, sizeof(struct spdk_iscsi_poll_group));
|
|
|
|
if (!g_spdk_iscsi.poll_group) {
|
|
|
|
SPDK_ERRLOG("Failed to allocated iscsi poll group\n");
|
|
|
|
spdk_iscsi_init_complete(-1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Send a message to each thread and create a poll group */
|
2018-03-08 04:07:51 +00:00
|
|
|
spdk_for_each_thread(iscsi_create_poll_group, NULL, cpl);
|
2018-02-13 05:09:49 +00:00
|
|
|
}
|
|
|
|
|
2018-03-08 04:11:57 +00:00
|
|
|
static void
|
2018-05-04 01:57:04 +00:00
|
|
|
spdk_iscsi_parse_configuration(void *ctx)
|
2018-03-08 04:11:57 +00:00
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
2018-03-08 23:25:34 +00:00
|
|
|
rc = spdk_iscsi_parse_portal_grps();
|
2018-03-08 04:11:57 +00:00
|
|
|
if (rc < 0) {
|
2018-03-08 23:25:34 +00:00
|
|
|
SPDK_ERRLOG("spdk_iscsi_parse_portal_grps() failed\n");
|
2018-03-08 04:11:57 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2018-03-08 23:25:34 +00:00
|
|
|
rc = spdk_iscsi_parse_init_grps();
|
2018-03-08 04:11:57 +00:00
|
|
|
if (rc < 0) {
|
2018-03-08 23:25:34 +00:00
|
|
|
SPDK_ERRLOG("spdk_iscsi_parse_init_grps() failed\n");
|
2018-03-08 04:11:57 +00:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2018-03-08 23:25:34 +00:00
|
|
|
rc = spdk_iscsi_parse_tgt_nodes();
|
2018-03-08 04:11:57 +00:00
|
|
|
if (rc < 0) {
|
2018-03-08 23:25:34 +00:00
|
|
|
SPDK_ERRLOG("spdk_iscsi_parse_tgt_nodes() failed\n");
|
2018-03-08 04:11:57 +00:00
|
|
|
}
|
|
|
|
|
2018-08-20 01:32:30 +00:00
|
|
|
if (access(g_spdk_iscsi.authfile, R_OK) == 0) {
|
|
|
|
rc = spdk_iscsi_parse_auth_info();
|
|
|
|
if (rc < 0) {
|
|
|
|
SPDK_ERRLOG("spdk_iscsi_parse_auth_info() failed\n");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SPDK_INFOLOG(SPDK_LOG_ISCSI, "CHAP secret file is not found in the path %s\n",
|
|
|
|
g_spdk_iscsi.authfile);
|
|
|
|
}
|
|
|
|
|
2018-03-08 04:11:57 +00:00
|
|
|
end:
|
|
|
|
spdk_iscsi_init_complete(rc);
|
|
|
|
}
|
|
|
|
|
2018-03-08 04:35:49 +00:00
|
|
|
static int
|
2018-05-04 01:57:04 +00:00
|
|
|
spdk_iscsi_parse_globals(void)
|
2016-08-02 16:34:45 +00:00
|
|
|
{
|
2017-06-14 22:59:16 +00:00
|
|
|
int rc;
|
2016-08-02 16:34:45 +00:00
|
|
|
|
2018-05-04 01:57:04 +00:00
|
|
|
rc = spdk_iscsi_initialize_global_params();
|
|
|
|
if (rc != 0) {
|
|
|
|
SPDK_ERRLOG("spdk_iscsi_initialize_iscsi_global_params() failed\n");
|
|
|
|
return rc;
|
|
|
|
}
|
2018-03-08 23:23:53 +00:00
|
|
|
|
2018-05-04 01:57:04 +00:00
|
|
|
g_spdk_iscsi.session = spdk_dma_zmalloc(sizeof(void *) * g_spdk_iscsi.MaxSessions, 0, NULL);
|
|
|
|
if (!g_spdk_iscsi.session) {
|
|
|
|
SPDK_ERRLOG("spdk_dma_zmalloc() failed for session array\n");
|
|
|
|
return -1;
|
2018-03-08 23:23:53 +00:00
|
|
|
}
|
|
|
|
|
2018-05-04 01:57:04 +00:00
|
|
|
/*
|
|
|
|
* For now, just support same number of total connections, rather
|
|
|
|
* than MaxSessions * MaxConnectionsPerSession. After we add better
|
|
|
|
* handling for low resource conditions from our various buffer
|
|
|
|
* pools, we can bump this up to support more connections.
|
|
|
|
*/
|
|
|
|
g_spdk_iscsi.MaxConnections = g_spdk_iscsi.MaxSessions;
|
|
|
|
|
|
|
|
rc = spdk_iscsi_initialize_all_pools();
|
2018-03-08 23:23:53 +00:00
|
|
|
if (rc != 0) {
|
2018-05-04 01:57:04 +00:00
|
|
|
SPDK_ERRLOG("spdk_initialize_all_pools() failed\n");
|
|
|
|
return -1;
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
|
|
|
|
2018-03-08 03:57:27 +00:00
|
|
|
rc = spdk_initialize_iscsi_conns();
|
|
|
|
if (rc < 0) {
|
|
|
|
SPDK_ERRLOG("spdk_initialize_iscsi_conns() failed\n");
|
2018-03-08 04:35:49 +00:00
|
|
|
return rc;
|
2018-03-08 03:57:27 +00:00
|
|
|
}
|
|
|
|
|
2018-05-04 01:57:04 +00:00
|
|
|
spdk_initialize_iscsi_poll_group(spdk_iscsi_parse_configuration);
|
2018-03-08 04:35:49 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
spdk_iscsi_init(spdk_iscsi_init_cb cb_fn, void *cb_arg)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
assert(cb_fn != NULL);
|
|
|
|
g_init_cb_fn = cb_fn;
|
|
|
|
g_init_cb_arg = cb_arg;
|
|
|
|
|
2018-05-04 01:57:04 +00:00
|
|
|
rc = spdk_iscsi_parse_globals();
|
2018-03-08 04:35:49 +00:00
|
|
|
if (rc < 0) {
|
|
|
|
SPDK_ERRLOG("spdk_iscsi_parse_globals() failed\n");
|
|
|
|
spdk_iscsi_init_complete(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* spdk_iscsi_parse_configuration() will be called as the callback to
|
|
|
|
* spdk_initialize_iscsi_poll_group() and will complete iSCSI
|
|
|
|
* subsystem initialization.
|
|
|
|
*/
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
|
|
|
|
2017-10-06 14:17:38 +00:00
|
|
|
void
|
2017-11-10 17:02:00 +00:00
|
|
|
spdk_iscsi_fini(spdk_iscsi_fini_cb cb_fn, void *cb_arg)
|
|
|
|
{
|
|
|
|
g_fini_cb_fn = cb_fn;
|
|
|
|
g_fini_cb_arg = cb_arg;
|
|
|
|
|
|
|
|
spdk_iscsi_portal_grp_close_all();
|
|
|
|
spdk_shutdown_iscsi_conns();
|
|
|
|
}
|
|
|
|
|
2018-02-26 15:30:05 +00:00
|
|
|
static void
|
|
|
|
spdk_iscsi_fini_done(void *arg)
|
2016-08-02 16:34:45 +00:00
|
|
|
{
|
2017-10-06 14:17:38 +00:00
|
|
|
spdk_iscsi_check_pools();
|
2017-05-24 23:10:00 +00:00
|
|
|
spdk_iscsi_free_pools();
|
2016-08-02 16:34:45 +00:00
|
|
|
|
|
|
|
spdk_iscsi_shutdown_tgt_nodes();
|
2018-03-08 23:25:34 +00:00
|
|
|
spdk_iscsi_init_grps_destroy();
|
|
|
|
spdk_iscsi_portal_grps_destroy();
|
2018-08-20 01:32:30 +00:00
|
|
|
spdk_iscsi_auth_groups_destroy();
|
2016-08-02 16:34:45 +00:00
|
|
|
free(g_spdk_iscsi.authfile);
|
|
|
|
free(g_spdk_iscsi.nodebase);
|
2018-02-13 05:09:49 +00:00
|
|
|
free(g_spdk_iscsi.poll_group);
|
2016-08-02 16:34:45 +00:00
|
|
|
|
|
|
|
pthread_mutex_destroy(&g_spdk_iscsi.mutex);
|
2017-11-10 17:02:00 +00:00
|
|
|
g_fini_cb_fn(g_fini_cb_arg);
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
|
|
|
|
2018-02-26 15:30:05 +00:00
|
|
|
void
|
|
|
|
spdk_shutdown_iscsi_conns_done(void)
|
|
|
|
{
|
2018-02-27 01:28:31 +00:00
|
|
|
if (g_spdk_iscsi.poll_group) {
|
|
|
|
spdk_for_each_thread(iscsi_unregister_poll_group, NULL, spdk_iscsi_fini_done);
|
|
|
|
} else {
|
|
|
|
spdk_iscsi_fini_done(NULL);
|
|
|
|
}
|
2018-02-26 15:30:05 +00:00
|
|
|
}
|
|
|
|
|
2017-06-13 17:38:16 +00:00
|
|
|
void
|
2016-08-02 16:34:45 +00:00
|
|
|
spdk_iscsi_config_text(FILE *fp)
|
|
|
|
{
|
2018-05-07 23:33:15 +00:00
|
|
|
spdk_iscsi_globals_config_text(fp);
|
2018-05-09 22:56:04 +00:00
|
|
|
spdk_iscsi_portal_grps_config_text(fp);
|
2018-05-09 22:55:12 +00:00
|
|
|
spdk_iscsi_init_grps_config_text(fp);
|
2018-05-04 07:20:02 +00:00
|
|
|
spdk_iscsi_tgt_nodes_config_text(fp);
|
2016-08-02 16:34:45 +00:00
|
|
|
}
|
|
|
|
|
2018-05-24 23:34:08 +00:00
|
|
|
void
|
|
|
|
spdk_iscsi_opts_info_json(struct spdk_json_write_ctx *w)
|
|
|
|
{
|
|
|
|
spdk_json_write_object_begin(w);
|
|
|
|
|
|
|
|
spdk_json_write_named_string(w, "auth_file", g_spdk_iscsi.authfile);
|
|
|
|
spdk_json_write_named_string(w, "node_base", g_spdk_iscsi.nodebase);
|
|
|
|
|
|
|
|
spdk_json_write_named_uint32(w, "max_sessions", g_spdk_iscsi.MaxSessions);
|
|
|
|
spdk_json_write_named_uint32(w, "max_connections_per_session",
|
|
|
|
g_spdk_iscsi.MaxConnectionsPerSession);
|
|
|
|
|
|
|
|
spdk_json_write_named_uint32(w, "max_queue_depth", g_spdk_iscsi.MaxQueueDepth);
|
|
|
|
|
|
|
|
spdk_json_write_named_uint32(w, "default_time2wait", g_spdk_iscsi.DefaultTime2Wait);
|
|
|
|
spdk_json_write_named_uint32(w, "default_time2retain", g_spdk_iscsi.DefaultTime2Retain);
|
|
|
|
|
2018-08-10 18:27:02 +00:00
|
|
|
spdk_json_write_named_uint32(w, "first_burst_length", g_spdk_iscsi.FirstBurstLength);
|
|
|
|
|
2018-05-24 23:34:08 +00:00
|
|
|
spdk_json_write_named_bool(w, "immediate_data", g_spdk_iscsi.ImmediateData);
|
|
|
|
|
|
|
|
spdk_json_write_named_bool(w, "allow_duplicated_isid", g_spdk_iscsi.AllowDuplicateIsid);
|
|
|
|
|
|
|
|
spdk_json_write_named_uint32(w, "error_recovery_level", g_spdk_iscsi.ErrorRecoveryLevel);
|
|
|
|
|
2018-07-17 17:44:22 +00:00
|
|
|
spdk_json_write_named_int32(w, "nop_timeout", g_spdk_iscsi.timeout);
|
2018-05-24 23:34:08 +00:00
|
|
|
spdk_json_write_named_int32(w, "nop_in_interval", g_spdk_iscsi.nopininterval);
|
|
|
|
|
2018-08-22 02:30:57 +00:00
|
|
|
spdk_json_write_named_bool(w, "disable_chap", g_spdk_iscsi.disable_chap);
|
|
|
|
spdk_json_write_named_bool(w, "require_chap", g_spdk_iscsi.require_chap);
|
|
|
|
spdk_json_write_named_bool(w, "mutual_chap", g_spdk_iscsi.mutual_chap);
|
|
|
|
spdk_json_write_named_int32(w, "chap_group", g_spdk_iscsi.chap_group);
|
2018-05-24 23:34:08 +00:00
|
|
|
|
2018-07-17 17:44:22 +00:00
|
|
|
spdk_json_write_named_uint32(w, "min_connections_per_core",
|
|
|
|
spdk_iscsi_conn_get_min_per_core());
|
2018-05-24 23:34:08 +00:00
|
|
|
|
|
|
|
spdk_json_write_object_end(w);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
spdk_iscsi_opts_config_json(struct spdk_json_write_ctx *w)
|
|
|
|
{
|
|
|
|
spdk_json_write_object_begin(w);
|
|
|
|
|
|
|
|
spdk_json_write_named_string(w, "method", "set_iscsi_options");
|
|
|
|
|
|
|
|
spdk_json_write_name(w, "params");
|
|
|
|
spdk_iscsi_opts_info_json(w);
|
|
|
|
|
|
|
|
spdk_json_write_object_end(w);
|
|
|
|
}
|
|
|
|
|
2018-05-07 23:33:15 +00:00
|
|
|
void
|
|
|
|
spdk_iscsi_config_json(struct spdk_json_write_ctx *w)
|
|
|
|
{
|
|
|
|
spdk_json_write_array_begin(w);
|
2018-05-24 23:34:08 +00:00
|
|
|
spdk_iscsi_opts_config_json(w);
|
2018-05-09 22:56:04 +00:00
|
|
|
spdk_iscsi_portal_grps_config_json(w);
|
2018-05-09 22:55:12 +00:00
|
|
|
spdk_iscsi_init_grps_config_json(w);
|
2018-05-07 23:33:15 +00:00
|
|
|
spdk_iscsi_tgt_nodes_config_json(w);
|
|
|
|
spdk_json_write_array_end(w);
|
|
|
|
}
|
|
|
|
|
2017-08-30 18:06:33 +00:00
|
|
|
SPDK_LOG_REGISTER_COMPONENT("iscsi", SPDK_LOG_ISCSI)
|