iscsi: Add an iscsi library.

Change-Id: I28f3f4723a66f845eb478a6873d7aedb8f5409b8
Signed-off-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Ben Walker 2016-08-02 09:34:45 -07:00
parent d3090c8455
commit d29384bf97
25 changed files with 13588 additions and 4 deletions

View File

@ -37,13 +37,13 @@ To build SPDK, some dependencies must be installed.
Fedora/CentOS:
sudo dnf install -y gcc libpciaccess-devel CUnit-devel libaio-devel
sudo dnf install -y gcc libpciaccess-devel CUnit-devel libaio-devel openssl-devel
# Additional dependencies for NVMf:
sudo dnf install -y libibverbs-devel librdmacm-devel
Ubuntu/Debian:
sudo apt-get install -y gcc libpciaccess-dev make libcunit1-dev libaio-dev
sudo apt-get install -y gcc libpciaccess-dev make libcunit1-dev libaio-dev libssl-dev
# Additional dependencies for NVMf:
sudo apt-get install -y libibverbs-dev librdmacm-dev
@ -53,6 +53,7 @@ FreeBSD:
- libpciaccess
- gmake
- cunit
- openssl
Additionally, [DPDK](http://dpdk.org/doc/quick-start) is required.

View File

@ -34,8 +34,12 @@
SPDK_ROOT_DIR := $(abspath $(CURDIR)/..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
DIRS-y += bdev conf copy cunit event json jsonrpc log memory \
net rpc trace util nvme nvmf scsi ioat
DIRS-y += bdev conf copy cunit event json jsonrpc \
log memory net rpc trace util nvme nvmf scsi ioat
ifeq ($(OS),Linux)
DIRS-y += iscsi
endif
.PHONY: all clean $(DIRS-y)

44
lib/iscsi/Makefile Normal file
View File

@ -0,0 +1,44 @@
#
# BSD LICENSE
#
# 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.
#
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
CFLAGS += $(DPDK_INC) -I$(SPDK_ROOT_DIR)/lib
C_SRCS = acceptor.c conn.c crc32c.c \
init_grp.c iscsi.c md5.c param.c portal_grp.c \
tgt_node.c iscsi_subsystem.c \
iscsi_rpc.c task.c
LIBNAME = iscsi
include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk

114
lib/iscsi/acceptor.c Normal file
View File

@ -0,0 +1,114 @@
/*-
* 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.
*/
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <rte_config.h>
#include <rte_lcore.h>
#include <rte_cycles.h>
#include <rte_timer.h>
#include "spdk/log.h"
#include "spdk/net.h"
#include "iscsi/acceptor.h"
#include "iscsi/conn.h"
#include "iscsi/portal_grp.h"
#define ACCEPT_TIMEOUT (rte_get_timer_hz() >> 10) /* ~1ms */
static struct rte_timer g_acceptor_timer;
/*! \file
*/
static void
spdk_iscsi_portal_accept(struct spdk_iscsi_portal *portal)
{
int rc, sock;
if (portal->sock < 0) {
return;
}
while (1) {
rc = spdk_sock_accept(portal->sock);
if (rc >= 0) {
sock = rc;
rc = spdk_iscsi_conn_construct(portal, sock);
if (rc < 0) {
close(sock);
SPDK_ERRLOG("spdk_iscsi_connection_construct() failed\n");
break;
}
} else {
if (errno != EAGAIN && errno != EWOULDBLOCK) {
SPDK_ERRLOG("accept error(%d): %s\n", errno, strerror(errno));
}
break;
}
}
}
static void
spdk_acceptor(struct rte_timer *timer, void *arg)
{
struct spdk_iscsi_globals *iscsi = arg;
struct spdk_iscsi_portal_grp *portal_group;
struct spdk_iscsi_portal *portal;
TAILQ_FOREACH(portal_group, &iscsi->pg_head, tailq) {
TAILQ_FOREACH(portal, &portal_group->head, tailq) {
spdk_iscsi_portal_accept(portal);
}
}
}
void
spdk_iscsi_acceptor_start(void)
{
rte_timer_init(&g_acceptor_timer);
rte_timer_reset(&g_acceptor_timer, ACCEPT_TIMEOUT, PERIODICAL,
rte_lcore_id(), spdk_acceptor, &g_spdk_iscsi);
}
void
spdk_iscsi_acceptor_stop(void)
{
rte_timer_stop_sync(&g_acceptor_timer);
}

41
lib/iscsi/acceptor.h Normal file
View File

@ -0,0 +1,41 @@
/*-
* 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.
*/
#ifndef SPDK_ACCEPTOR_H_
#define SPDK_ACCEPTOR_H_
void spdk_iscsi_acceptor_start(void);
void spdk_iscsi_acceptor_stop(void);
#endif /* SPDK_ACCEPTOR_H_ */

1382
lib/iscsi/conn.c Normal file

File diff suppressed because it is too large Load Diff

182
lib/iscsi/conn.h Normal file
View File

@ -0,0 +1,182 @@
/*-
* 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.
*/
#ifndef SPDK_ISCSI_CONN_H
#define SPDK_ISCSI_CONN_H
#include <stdbool.h>
#include <stdint.h>
#include <rte_timer.h>
#include "iscsi/iscsi.h"
#include "spdk/queue.h"
#include "spdk/event.h"
/*
* MAX_CONNECTION_PARAMS: The numbers of the params in conn_param_table
* MAX_SESSION_PARAMS: The numbers of the params in sess_param_table
*/
#define MAX_CONNECTION_PARAMS 14
#define MAX_SESSION_PARAMS 19
#define MAX_ADDRBUF 64
#define MAX_INITIATOR_ADDR (MAX_ADDRBUF)
#define MAX_TARGET_ADDR (MAX_ADDRBUF)
#define OWNER_ISCSI_CONN 0x1
#define OBJECT_ISCSI_PDU 0x1
#define OBJECT_ISCSI_TASK 0x2
#define TRACE_GROUP_ISCSI 0x1
#define TRACE_READ_FROM_SOCKET_DONE SPDK_TPOINT_ID(TRACE_GROUP_ISCSI, 0x0)
#define TRACE_FLUSH_WRITEBUF_START SPDK_TPOINT_ID(TRACE_GROUP_ISCSI, 0x1)
#define TRACE_FLUSH_WRITEBUF_DONE SPDK_TPOINT_ID(TRACE_GROUP_ISCSI, 0x2)
#define TRACE_READ_PDU SPDK_TPOINT_ID(TRACE_GROUP_ISCSI, 0x3)
#define TRACE_ISCSI_TASK_DONE SPDK_TPOINT_ID(TRACE_GROUP_ISCSI, 0x4)
#define TRACE_ISCSI_TASK_QUEUE SPDK_TPOINT_ID(TRACE_GROUP_ISCSI, 0x5)
#define TRACE_ISCSI_CONN_ACTIVE SPDK_TPOINT_ID(TRACE_GROUP_ISCSI, 0x6)
#define TRACE_ISCSI_CONN_IDLE SPDK_TPOINT_ID(TRACE_GROUP_ISCSI, 0x7)
struct spdk_iscsi_conn {
int id;
int is_valid;
int is_idle;
/*
* All fields below this point are reinitialized each time the
* connection object is allocated. Make sure to update the
* SPDK_ISCSI_CONNECTION_MEMSET() macro if changing which fields
* are initialized when allocated.
*/
struct spdk_iscsi_portal *portal;
int sock;
struct spdk_iscsi_sess *sess;
enum iscsi_connection_state state;
int login_phase;
uint64_t last_flush;
uint64_t last_fill;
uint64_t last_nopin;
/* Timer used to destroy connection after logout if initiator does
* not close the connection.
*/
struct rte_timer logout_timer;
/* Timer used to wait for connection to close
*/
struct rte_timer shutdown_timer;
struct spdk_iscsi_pdu *pdu_in_progress;
TAILQ_HEAD(, spdk_iscsi_pdu) write_pdu_list;
TAILQ_HEAD(, spdk_iscsi_pdu) snack_pdu_list;
int pending_r2t;
struct spdk_iscsi_task *outstanding_r2t_tasks[DEFAULT_MAXR2T];
uint16_t cid;
/* IP address */
char initiator_addr[MAX_INITIATOR_ADDR];
char target_addr[MAX_TARGET_ADDR];
/* Initiator/Target port binds */
char initiator_name[MAX_INITIATOR_NAME];
struct spdk_scsi_port *initiator_port;
char target_short_name[MAX_TARGET_NAME];
struct spdk_scsi_port *target_port;
struct spdk_iscsi_tgt_node *target;
struct spdk_scsi_dev *dev;
/* for fast access */
int header_digest;
int data_digest;
int full_feature;
struct iscsi_param *params;
bool sess_param_state_negotiated[MAX_SESSION_PARAMS];
bool conn_param_state_negotiated[MAX_CONNECTION_PARAMS];
struct iscsi_chap_auth auth;
int authenticated;
int req_auth;
int req_mutual;
uint64_t last_activity_tsc;
uint32_t pending_task_cnt;
uint32_t data_out_cnt;
uint32_t data_in_cnt;
bool pending_activate_event;
int timeout;
uint64_t nopininterval;
bool nop_outstanding;
/*
* This is the maximum data segment length that iscsi target can send
* to the initiator on this connection. Not to be confused with the
* maximum data segment length that initiators can send to iscsi target, which
* is statically defined as SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH.
*/
int MaxRecvDataSegmentLength;
uint32_t StatSN;
uint32_t exp_statsn;
uint32_t ttt; /* target transfer tag*/
char *partial_text_parameter;
STAILQ_ENTRY(spdk_iscsi_conn) link;
struct spdk_poller poller;
TAILQ_HEAD(queued_r2t_tasks, spdk_iscsi_task) queued_r2t_tasks;
TAILQ_HEAD(active_r2t_tasks, spdk_iscsi_task) active_r2t_tasks;
TAILQ_HEAD(queued_datain_tasks, spdk_iscsi_task) queued_datain_tasks;
};
int spdk_initialize_iscsi_conns(void);
void spdk_shutdown_iscsi_conns(void);
int spdk_iscsi_conn_construct(struct spdk_iscsi_portal *portal, int sock);
void spdk_iscsi_conn_destruct(struct spdk_iscsi_conn *conn);
void spdk_iscsi_conn_logout(struct spdk_iscsi_conn *conn);
int spdk_iscsi_drop_conns(struct spdk_iscsi_conn *conn,
const char *conn_match, int drop_all);
void spdk_iscsi_conn_set_min_per_core(int count);
void spdk_iscsi_set_min_conn_idle_interval(int interval_in_us);
int spdk_iscsi_conn_read_data(struct spdk_iscsi_conn *conn, int len,
void *buf);
#endif /* SPDK_ISCSI_CONN_H */

136
lib/iscsi/crc32c.c Normal file
View File

@ -0,0 +1,136 @@
/*-
* 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.
*/
#include <inttypes.h>
#include <stdint.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <sys/uio.h>
#include "iscsi/iscsi.h"
#include "iscsi/crc32c.h"
#ifndef USE_ISAL
#define SPDK_USE_CRC32C_TABLE
#endif
#ifdef SPDK_USE_CRC32C_TABLE
static uint32_t spdk_crc32c_table[256];
__attribute__((constructor)) static void
spdk_init_crc32c(void)
{
int i, j;
uint32_t val;
for (i = 0; i < 256; i++) {
val = i;
for (j = 0; j < 8; j++) {
if (val & 1) {
val = (val >> 1) ^ SPDK_CRC32C_POLYNOMIAL_REFLECT;
} else {
val = (val >> 1);
}
}
spdk_crc32c_table[i] = val;
}
}
#endif /* SPDK_USE_CRC32C_TABLE */
#ifndef USE_ISAL
uint32_t
spdk_update_crc32c(const uint8_t *buf, size_t len, uint32_t crc)
{
size_t s;
#ifndef SPDK_USE_CRC32C_TABLE
int i;
uint32_t val;
#endif /* SPDK_USE_CRC32C_TABLE */
for (s = 0; s < len; s++) {
#ifdef SPDK_USE_CRC32C_TABLE
crc = (crc >> 8) ^ spdk_crc32c_table[(crc ^ buf[s]) & 0xff];
#else
val = buf[s];
for (i = 0; i < 8; i++) {
if ((crc ^ val) & 1) {
crc = (crc >> 1) ^ SPDK_CRC32C_POLYNOMIAL_REFLECT;
} else {
crc = (crc >> 1);
}
val = val >> 1;
}
#endif /* SPDK_USE_CRC32C_TABLE */
}
return crc;
}
#endif /* USE_ISAL */
uint32_t
spdk_fixup_crc32c(size_t total, uint32_t crc)
{
uint8_t padding[ISCSI_ALIGNMENT];
size_t pad_length;
size_t rest;
if (total == 0)
return crc;
rest = total % ISCSI_ALIGNMENT;
if (rest != 0) {
pad_length = ISCSI_ALIGNMENT;
pad_length -= rest;
if (pad_length > 0 && pad_length < sizeof padding) {
memset(padding, 0, sizeof padding);
crc = spdk_update_crc32c(padding, pad_length, crc);
}
}
return crc;
}
uint32_t
spdk_crc32c(const uint8_t *buf, size_t len)
{
uint32_t crc32c;
crc32c = SPDK_CRC32C_INITIAL;
crc32c = spdk_update_crc32c(buf, len, crc32c);
if ((len % ISCSI_ALIGNMENT) != 0) {
crc32c = spdk_fixup_crc32c(len, crc32c);
}
crc32c = crc32c ^ SPDK_CRC32C_XOR;
return crc32c;
}

56
lib/iscsi/crc32c.h Normal file
View File

@ -0,0 +1,56 @@
/*-
* 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.
*/
#ifndef SPDK_CRC32C_H
#define SPDK_CRC32C_H
#include <stdint.h>
#include <stddef.h>
#include <sys/uio.h>
#define SPDK_CRC32C_INITIAL 0xffffffffUL
#define SPDK_CRC32C_XOR 0xffffffffUL
#define SPDK_CRC32C_POLYNOMIAL 0x1edc6f41UL
#define SPDK_CRC32C_POLYNOMIAL_REFLECT 0x82f63b78UL
#ifdef USE_ISAL
uint32_t crc32_iscsi(const uint8_t *buf, size_t len, uint32_t crc);
#define spdk_update_crc32c(a,b,c) crc32_iscsi(a,b,c)
#else
uint32_t spdk_update_crc32c(const uint8_t *buf, size_t len, uint32_t crc);
#endif
uint32_t spdk_fixup_crc32c(size_t total, uint32_t crc);
uint32_t spdk_crc32c(const uint8_t *buf, size_t len);
#endif /* SPDK_CRC32C_H */

393
lib/iscsi/init_grp.c Normal file
View File

@ -0,0 +1,393 @@
/*-
* 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.
*/
#include <inttypes.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <poll.h>
#include <pthread.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <rte_debug.h>
#include "spdk/log.h"
#include "spdk/conf.h"
#include "spdk/net.h"
#include "iscsi/iscsi.h"
#include "iscsi/tgt_node.h"
#include "iscsi/conn.h"
#include "iscsi/init_grp.h"
/* Read spdk iscsi target's config file and create initiator group */
int
spdk_iscsi_init_grp_create_from_configfile(struct spdk_conf_section *sp)
{
int i, rc = 0;
const char *val = NULL;
int num_initiator_names;
int num_initiator_masks;
char **initiators = NULL, **netmasks = NULL;
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "add initiator group %d\n", sp->num);
val = spdk_conf_section_get_val(sp, "Comment");
if (val != NULL) {
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Comment %s\n", val);
}
/* counts number of definitions */
for (i = 0; ; i++) {
val = spdk_conf_section_get_nval(sp, "InitiatorName", i);
if (val == NULL)
break;
}
if (i == 0) {
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "num_initiator_names = 0\n");
goto cleanup;
}
num_initiator_names = i;
if (num_initiator_names > MAX_INITIATOR) {
SPDK_ERRLOG("%d > MAX_INITIATOR\n", num_initiator_names);
return -1;
}
for (i = 0; ; i++) {
val = spdk_conf_section_get_nval(sp, "Netmask", i);
if (val == NULL)
break;
}
if (i == 0) {
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "num_initiator_mask = 0\n");
goto cleanup;
}
num_initiator_masks = i;
if (num_initiator_masks > MAX_NETMASK) {
SPDK_ERRLOG("%d > MAX_NETMASK\n", num_initiator_masks);
return -1;
}
initiators = calloc(num_initiator_names, sizeof(char *));
if (!initiators) {
perror("initiators");
return -1;
}
for (i = 0; i < num_initiator_names; i++) {
val = spdk_conf_section_get_nval(sp, "InitiatorName", i);
if (!val) {
SPDK_ERRLOG("InitiatorName %d not found\n", i);
rc = -EINVAL;
goto cleanup;
}
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "InitiatorName %s\n", val);
initiators[i] = strdup(val);
if (!initiators[i]) {
perror("initiator name copy");
rc = -ENOMEM;
goto cleanup;
}
}
netmasks = calloc(num_initiator_masks, sizeof(char *));
if (!netmasks) {
perror("netmasks");
rc = -ENOMEM;
goto cleanup;
}
for (i = 0; i < num_initiator_masks; i++) {
val = spdk_conf_section_get_nval(sp, "Netmask", i);
if (!val) {
SPDK_ERRLOG("Netmask %d not found\n", i);
rc = -EINVAL;
goto cleanup;
}
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Netmask %s\n", val);
netmasks[i] = strdup(val);
if (!netmasks[i]) {
perror("initiator netmask copy");
rc = -ENOMEM;
goto cleanup;
}
}
rc = spdk_iscsi_init_grp_create_from_initiator_list(sp->num,
num_initiator_names, initiators, num_initiator_masks, netmasks);
if (rc < 0) {
goto cleanup;
}
return rc;
cleanup:
if (initiators) {
for (i = 0; i < num_initiator_names; i++) {
if (initiators[i]) {
free(initiators[i]);
}
}
free(initiators);
}
if (netmasks) {
for (i = 0; i < num_initiator_masks; i++) {
if (netmasks[i]) {
free(netmasks[i]);
}
}
free(netmasks);
}
return rc;
}
/*
* Create initiator group from list of initiator ip/hostnames and netmasks
* The initiator hostname/netmask lists are allocated by the caller on the
* heap. Freed later by common initiator_group_destroy() code
*/
int
spdk_iscsi_init_grp_create_from_initiator_list(int tag,
int num_initiator_names,
char **initiator_names,
int num_initiator_masks,
char **initiator_masks)
{
int i, rc = 0;
struct spdk_iscsi_init_grp *ig = NULL;
/* Make sure there are no duplicate initiator group tags */
if (spdk_iscsi_init_grp_find_by_tag(tag)) {
SPDK_ERRLOG("initiator group creation failed. duplicate initiator group tag (%d)\n", tag);
rc = -EEXIST;
goto cleanup;
}
if (num_initiator_names > MAX_INITIATOR) {
SPDK_ERRLOG("%d > MAX_INITIATOR\n", num_initiator_names);
rc = -1;
goto cleanup;
}
if (num_initiator_masks > MAX_NETMASK) {
SPDK_ERRLOG("%d > MAX_NETMASK\n", num_initiator_masks);
rc = -1;
goto cleanup;
}
SPDK_TRACELOG(SPDK_TRACE_DEBUG,
"add initiator group (from initiator list) tag=%d, #initiators=%d, #masks=%d\n",
tag, num_initiator_names, num_initiator_masks);
ig = malloc(sizeof(*ig));
if (!ig) {
SPDK_ERRLOG("initiator group malloc error (%d)\n", tag);
rc = -ENOMEM;
goto cleanup;
}
memset(ig, 0, sizeof(*ig));
ig->ref = 0;
ig->tag = tag;
ig->ninitiators = num_initiator_names;
ig->nnetmasks = num_initiator_masks;
ig->initiators = initiator_names;
for (i = 0; i < num_initiator_names; i++)
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "InitiatorName %s\n",
ig->initiators[i]);
ig->netmasks = initiator_masks;
for (i = 0; i < num_initiator_masks; i++)
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Netmask %s\n",
ig->netmasks[i]);
ig->state = GROUP_INIT;
spdk_iscsi_init_grp_register(ig);
return 0;
cleanup:
free(ig);
return rc;
}
void
spdk_iscsi_init_grp_destroy(struct spdk_iscsi_init_grp *ig)
{
int i;
if (!ig) {
return;
}
for (i = 0; i < ig->ninitiators; i++) {
free(ig->initiators[i]);
}
for (i = 0; i < ig->nnetmasks; i++) {
free(ig->netmasks[i]);
}
free(ig->initiators);
free(ig->netmasks);
free(ig);
};
struct spdk_iscsi_init_grp *
spdk_iscsi_init_grp_find_by_tag(int tag)
{
struct spdk_iscsi_init_grp *ig;
TAILQ_FOREACH(ig, &g_spdk_iscsi.ig_head, tailq) {
if (ig->tag == tag) {
return ig;
}
}
return NULL;
}
void
spdk_iscsi_init_grp_destroy_by_tag(int tag)
{
spdk_iscsi_init_grp_destroy(spdk_iscsi_init_grp_find_by_tag(tag));
}
void
spdk_iscsi_init_grp_register(struct spdk_iscsi_init_grp *ig)
{
RTE_VERIFY(ig != NULL);
pthread_mutex_lock(&g_spdk_iscsi.mutex);
ig->state = GROUP_READY;
TAILQ_INSERT_TAIL(&g_spdk_iscsi.ig_head, ig, tailq);
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
}
int
spdk_iscsi_init_grp_array_create(void)
{
struct spdk_conf_section *sp;
int rc;
TAILQ_INIT(&g_spdk_iscsi.ig_head);
sp = spdk_conf_first_section(NULL);
while (sp != NULL) {
if (spdk_conf_section_match_prefix(sp, "InitiatorGroup")) {
if (sp->num == 0) {
SPDK_ERRLOG("Group 0 is invalid\n");
return -1;
}
rc = spdk_iscsi_init_grp_create_from_configfile(sp);
if (rc < 0) {
SPDK_ERRLOG("add_initiator_group() failed\n");
return -1;
}
}
sp = spdk_conf_next_section(sp);
}
return 0;
}
void
spdk_iscsi_init_grp_array_destroy(void)
{
struct spdk_iscsi_init_grp *ig, *tmp;
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_iscsi_init_grp_array_destroy\n");
pthread_mutex_lock(&g_spdk_iscsi.mutex);
TAILQ_FOREACH_SAFE(ig, &g_spdk_iscsi.ig_head, tailq, tmp) {
ig->state = GROUP_DESTROY;
TAILQ_REMOVE(&g_spdk_iscsi.ig_head, ig, tailq);
spdk_iscsi_init_grp_destroy(ig);
}
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
}
static inline void
spdk_initiator_group_unregister(struct spdk_iscsi_init_grp *ig)
{
struct spdk_iscsi_init_grp *initiator_group;
struct spdk_iscsi_init_grp *initiator_group_tmp;
RTE_VERIFY(ig != NULL);
pthread_mutex_lock(&g_spdk_iscsi.mutex);
TAILQ_FOREACH_SAFE(initiator_group, &g_spdk_iscsi.ig_head, tailq, initiator_group_tmp) {
if (ig->tag == initiator_group->tag)
TAILQ_REMOVE(&g_spdk_iscsi.ig_head, initiator_group, tailq);
}
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
}
int
spdk_iscsi_init_grp_deletable(int tag)
{
int ret = 0;
struct spdk_iscsi_init_grp *ig;
pthread_mutex_lock(&g_spdk_iscsi.mutex);
ig = spdk_iscsi_init_grp_find_by_tag(tag);
if (ig == NULL) {
ret = -1;
goto out;
}
if (ig->state != GROUP_READY) {
ret = -1;
goto out;
}
if (ig->ref == 0) {
ret = 0;
goto out;
}
out:
if (ret == 0)
ig->state = GROUP_DESTROY;
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
return ret;
}
void
spdk_iscsi_init_grp_release(struct spdk_iscsi_init_grp *ig)
{
spdk_initiator_group_unregister(ig);
pthread_mutex_lock(&g_spdk_iscsi.mutex);
spdk_iscsi_init_grp_destroy(ig);
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
}

76
lib/iscsi/init_grp.h Normal file
View File

@ -0,0 +1,76 @@
/*-
* 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.
*/
#ifndef SPDK_INIT_GRP_H
#define SPDK_INIT_GRP_H
#include "spdk/conf.h"
enum group_state {
GROUP_INIT = 0x0,
GROUP_READY = 0x1,
GROUP_DESTROY = 0x2,
};
struct spdk_iscsi_init_grp {
int ninitiators;
char **initiators;
int nnetmasks;
char **netmasks;
int ref;
int tag;
enum group_state state;
TAILQ_ENTRY(spdk_iscsi_init_grp) tailq;
};
/* SPDK iSCSI Initiator Group management API */
int spdk_iscsi_init_grp_create_from_configfile(struct spdk_conf_section *sp);
int spdk_iscsi_init_grp_create_from_initiator_list(int tag,
int num_initiator_names, char **initiator_names,
int num_initiator_masks, char **initiator_masks);
void spdk_iscsi_init_grp_destroy(struct spdk_iscsi_init_grp *ig);
void spdk_iscsi_init_grp_destroy_by_tag(int tag);
void spdk_iscsi_init_grp_release(struct spdk_iscsi_init_grp *ig);
struct spdk_iscsi_init_grp *spdk_iscsi_init_grp_find_by_tag(int tag);
void spdk_iscsi_init_grp_register(struct spdk_iscsi_init_grp *ig);
int spdk_iscsi_init_grp_array_create(void);
void spdk_iscsi_init_grp_array_destroy(void);
int spdk_iscsi_init_grp_deletable(int tag);
#endif // SPDK_INIT_GRP_H

4693
lib/iscsi/iscsi.c Normal file

File diff suppressed because it is too large Load Diff

907
lib/iscsi/iscsi.h Normal file
View File

@ -0,0 +1,907 @@
/*-
* 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.
*/
#ifndef SPDK_ISCSI_H
#define SPDK_ISCSI_H
#include <stdint.h>
#include <pthread.h>
#include <sys/mman.h>
#include <sys/uio.h>
#include <stdbool.h>
#include "spdk/bdev.h"
#include "iscsi/param.h"
#include "iscsi/tgt_node.h"
#include "spdk/assert.h"
#define SPDK_ISCSI_BUILD_ETC "/usr/local/etc/spdk"
#define SPDK_ISCSI_DEFAULT_CONFIG SPDK_ISCSI_BUILD_ETC "/iscsi.conf"
#define SPDK_ISCSI_DEFAULT_AUTHFILE SPDK_ISCSI_BUILD_ETC "/auth.conf"
#define SPDK_ISCSI_DEFAULT_NODEBASE "iqn.2013-10.com.intel.spdk"
extern uint64_t g_flush_timeout;
#define DEFAULT_MAXR2T 4
#define MAX_INITIATOR_NAME 256
#define MAX_TARGET_NAME 256
#define MAX_ISCSI_NAME 256
#define MAX_PORTAL 1024
#define MAX_INITIATOR 256
#define MAX_NETMASK 256
#define MAX_PORTAL_GROUP 4096
#define MAX_INITIATOR_GROUP 4096
#define MAX_ISCSI_TARGET_NODE 4096
#define MAX_SESSIONS 1024
#define MAX_ISCSI_CONNECTIONS MAX_SESSIONS
#define MAX_FIRSTBURSTLENGTH 16777215
#define DEFAULT_PORT 3260
#define DEFAULT_MAX_SESSIONS 128
#define DEFAULT_MAX_CONNECTIONS_PER_SESSION 2
#define DEFAULT_MAXOUTSTANDINGR2T 1
#define DEFAULT_DEFAULTTIME2WAIT 2
#define DEFAULT_DEFAULTTIME2RETAIN 20
#define DEFAULT_FIRSTBURSTLENGTH 8192
#define DEFAULT_INITIALR2T 1
#define DEFAULT_IMMEDIATEDATA 1
#define DEFAULT_DATAPDUINORDER 1
#define DEFAULT_DATASEQUENCEINORDER 1
#define DEFAULT_ERRORRECOVERYLEVEL 0
#define DEFAULT_TIMEOUT 60
#define MAX_NOPININTERVAL 60
#define DEFAULT_NOPININTERVAL 30
#define DEFAULT_FLUSH_TIMEOUT 8
/*
* SPDK iSCSI target currently only supports 64KB as the maximum data segment length
* it can receive from initiators. Other values may work, but no guarantees.
*/
#define SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH 65536
/*
* SPDK iSCSI target will only send a maximum of SPDK_BDEV_LARGE_RBUF_MAX_SIZE data segments, even if the
* connection can support more.
*/
#define SPDK_ISCSI_MAX_SEND_DATA_SEGMENT_LENGTH SPDK_BDEV_LARGE_RBUF_MAX_SIZE
/*
* Defines maximum number of data out buffers each connection can have in
* use at any given time.
*/
#define MAX_DATA_OUT_PER_CONNECTION 16
/*
* Defines maximum number of data in buffers each connection can have in
* use at any given time. An "extra data in buffer" means any buffer after
* the first for the iSCSI I/O command. So this limit does not affect I/O
* smaller than SPDK_ISCSI_MAX_SEND_DATA_SEGMENT_LENGTH.
*/
#define MAX_EXTRA_DATAIN_PER_CONNECTION 64
#define NUM_PDU_PER_CONNECTION (2 * (SPDK_ISCSI_MAX_QUEUE_DEPTH + MAX_EXTRA_DATAIN_PER_CONNECTION + 8))
#define SPDK_ISCSI_MAX_BURST_LENGTH \
(SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH * MAX_DATA_OUT_PER_CONNECTION)
#define SPDK_ISCSI_FIRST_BURST_LENGTH 8192
/** Defines how long we should wait for a TCP close after responding to a
* logout request, before terminating the connection ourselves.
*/
#define ISCSI_LOGOUT_TIMEOUT 5 /* in seconds */
#define ISCSI_BHS_LEN 48
#define ISCSI_DIGEST_LEN 4
#define ISCSI_ALIGNMENT 4
/* support version - RFC3720(10.12.4) */
#define ISCSI_VERSION 0x00
#define ISCSI_ALIGN(SIZE) \
(((SIZE) + (ISCSI_ALIGNMENT - 1)) & ~(ISCSI_ALIGNMENT - 1))
/* for authentication key (non encoded 1024bytes) RFC3720(5.1/11.1.4) */
#define ISCSI_TEXT_MAX_VAL_LEN 8192
/*
* RFC 3720 5.1
* If not otherwise specified, the maximum length of a simple-value
* (not its encoded representation) is 255 bytes, not including the delimiter
* (comma or zero byte).
*/
#define ISCSI_TEXT_MAX_SIMPLE_VAL_LEN 255
#define ISCSI_TEXT_MAX_KEY_LEN 63
/* according to RFC1982 */
#define SN32_CMPMAX (((uint32_t)1U) << (32 - 1))
#define SN32_LT(S1,S2) \
(((uint32_t)(S1) != (uint32_t)(S2)) \
&& (((uint32_t)(S1) < (uint32_t)(S2) \
&& ((uint32_t)(S2) - (uint32_t)(S1) < SN32_CMPMAX)) \
|| ((uint32_t)(S1) > (uint32_t)(S2) \
&& ((uint32_t)(S1) - (uint32_t)(S2) > SN32_CMPMAX))))
#define SN32_GT(S1,S2) \
(((uint32_t)(S1) != (uint32_t)(S2)) \
&& (((uint32_t)(S1) < (uint32_t)(S2) \
&& ((uint32_t)(S2) - (uint32_t)(S1) > SN32_CMPMAX)) \
|| ((uint32_t)(S1) > (uint32_t)(S2) \
&& ((uint32_t)(S1) - (uint32_t)(S2) < SN32_CMPMAX))))
enum iscsi_op {
/* Initiator opcodes */
ISCSI_OP_NOPOUT = 0x00,
ISCSI_OP_SCSI = 0x01,
ISCSI_OP_TASK = 0x02,
ISCSI_OP_LOGIN = 0x03,
ISCSI_OP_TEXT = 0x04,
ISCSI_OP_SCSI_DATAOUT = 0x05,
ISCSI_OP_LOGOUT = 0x06,
ISCSI_OP_SNACK = 0x10,
ISCSI_OP_VENDOR_1C = 0x1c,
ISCSI_OP_VENDOR_1D = 0x1d,
ISCSI_OP_VENDOR_1E = 0x1e,
/* Target opcodes */
ISCSI_OP_NOPIN = 0x20,
ISCSI_OP_SCSI_RSP = 0x21,
ISCSI_OP_TASK_RSP = 0x22,
ISCSI_OP_LOGIN_RSP = 0x23,
ISCSI_OP_TEXT_RSP = 0x24,
ISCSI_OP_SCSI_DATAIN = 0x25,
ISCSI_OP_LOGOUT_RSP = 0x26,
ISCSI_OP_R2T = 0x31,
ISCSI_OP_ASYNC = 0x32,
ISCSI_OP_VENDOR_3C = 0x3c,
ISCSI_OP_VENDOR_3D = 0x3d,
ISCSI_OP_VENDOR_3E = 0x3e,
ISCSI_OP_REJECT = 0x3f,
};
enum iscsi_task_func {
ISCSI_TASK_FUNC_ABORT_TASK = 1,
ISCSI_TASK_FUNC_ABORT_TASK_SET = 2,
ISCSI_TASK_FUNC_CLEAR_ACA = 3,
ISCSI_TASK_FUNC_CLEAR_TASK_SET = 4,
ISCSI_TASK_FUNC_LOGICAL_UNIT_RESET = 5,
ISCSI_TASK_FUNC_TARGET_WARM_RESET = 6,
ISCSI_TASK_FUNC_TARGET_COLD_RESET = 7,
ISCSI_TASK_FUNC_TASK_REASSIGN = 8,
};
enum iscsi_task_func_resp {
ISCSI_TASK_FUNC_RESP_COMPLETE = 0,
ISCSI_TASK_FUNC_RESP_TASK_NOT_EXIST = 1,
ISCSI_TASK_FUNC_RESP_LUN_NOT_EXIST = 2,
ISCSI_TASK_FUNC_RESP_TASK_STILL_ALLEGIANT = 3,
ISCSI_TASK_FUNC_RESP_REASSIGNMENT_NOT_SUPPORTED = 4,
ISCSI_TASK_FUNC_RESP_FUNC_NOT_SUPPORTED = 5,
ISCSI_TASK_FUNC_RESP_AUTHORIZATION_FAILED = 6,
ISCSI_TASK_FUNC_REJECTED = 255
};
struct iscsi_bhs {
uint8_t opcode : 6;
uint8_t immediate : 1;
uint8_t reserved : 1;
uint8_t flags;
uint8_t rsv[2];
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint64_t lun;
uint32_t itt;
uint32_t ttt;
uint32_t stat_sn;
uint32_t exp_stat_sn;
uint32_t max_stat_sn;
uint8_t res3[12];
};
SPDK_STATIC_ASSERT(sizeof(struct iscsi_bhs) == ISCSI_BHS_LEN, "ISCSI_BHS_LEN mismatch");
struct iscsi_bhs_async {
uint8_t opcode : 6; /* opcode = 0x32 */
uint8_t reserved : 2;
uint8_t flags;
uint8_t res[2];
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint64_t lun;
uint32_t ffffffff;
uint32_t res3;
uint32_t stat_sn;
uint32_t exp_cmd_sn;
uint32_t max_cmd_sn;
uint8_t async_event;
uint8_t async_vcode;
uint16_t param1;
uint16_t param2;
uint16_t param3;
uint8_t res4[4];
};
struct iscsi_bhs_login_req {
uint8_t opcode : 6; /* opcode = 0x03 */
uint8_t immediate : 1;
uint8_t reserved : 1;
uint8_t flags;
uint8_t version_max;
uint8_t version_min;
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint8_t isid[6];
uint16_t tsih;
uint32_t itt;
uint16_t cid;
uint16_t res2;
uint32_t cmd_sn;
uint32_t exp_stat_sn;
uint8_t res3[16];
};
struct iscsi_bhs_login_rsp {
uint8_t opcode : 6; /* opcode = 0x23 */
uint8_t reserved : 2;
uint8_t flags;
uint8_t version_max;
uint8_t version_act;
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint8_t isid[6];
uint16_t tsih;
uint32_t itt;
uint32_t res2;
uint32_t stat_sn;
uint32_t exp_cmd_sn;
uint32_t max_cmd_sn;
uint8_t status_class;
uint8_t status_detail;
uint8_t res3[10];
};
struct iscsi_bhs_logout_req {
uint8_t opcode : 6; /* opcode = 0x06 */
uint8_t immediate : 1;
uint8_t reserved : 1;
uint8_t reason;
uint8_t res[2];
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint8_t res2[8];
uint32_t itt;
uint16_t cid;
uint16_t res3;
uint32_t cmd_sn;
uint32_t exp_stat_sn;
uint8_t res4[16];
};
struct iscsi_bhs_logout_resp {
uint8_t opcode : 6; /* opcode = 0x26 */
uint8_t reserved : 2;
uint8_t flags;
uint8_t response;
uint8_t res;
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint8_t res2[8];
uint32_t itt;
uint32_t res3;
uint32_t stat_sn;
uint32_t exp_cmd_sn;
uint32_t max_cmd_sn;
uint32_t res4;
uint16_t time_2_wait;
uint16_t time_2_retain;
uint32_t res5;
};
struct iscsi_bhs_nop_in {
uint8_t opcode : 6; /* opcode = 0x20 */
uint8_t reserved : 2;
uint8_t flags;
uint8_t res[2];
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint64_t lun;
uint32_t itt;
uint32_t ttt;
uint32_t stat_sn;
uint32_t exp_cmd_sn;
uint32_t max_cmd_sn;
uint8_t res3[12];
};
struct iscsi_bhs_nop_out {
uint8_t opcode : 6; /* opcode = 0x00 */
uint8_t immediate : 1;
uint8_t reserved : 1;
uint8_t flags;
uint8_t res[2];
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint64_t lun;
uint32_t itt;
uint32_t ttt;
uint32_t cmd_sn;
uint32_t exp_stat_sn;
uint8_t res4[16];
};
struct iscsi_bhs_r2t {
uint8_t opcode : 6; /* opcode = 0x31 */
uint8_t reserved : 2;
uint8_t flags;
uint8_t rsv[2];
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint64_t lun;
uint32_t itt;
uint32_t ttt;
uint32_t stat_sn;
uint32_t exp_cmd_sn;
uint32_t max_cmd_sn;
uint32_t r2t_sn;
uint32_t buffer_offset;
uint32_t desired_xfer_len;
};
struct iscsi_bhs_reject {
uint8_t opcode : 6; /* opcode = 0x3f */
uint8_t reserved : 2;
uint8_t flags;
uint8_t reason;
uint8_t res;
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint8_t res2[8];
uint32_t ffffffff;
uint32_t res3;
uint32_t stat_sn;
uint32_t exp_cmd_sn;
uint32_t max_cmd_sn;
uint32_t data_sn;
uint8_t res4[8];
};
struct iscsi_bhs_scsi_req {
uint8_t opcode : 6; /* opcode = 0x01 */
uint8_t immediate : 1;
uint8_t reserved : 1;
uint8_t attribute : 3;
uint8_t reserved2 : 2;
uint8_t write : 1;
uint8_t read : 1;
uint8_t final : 1;
uint8_t res[2];
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint64_t lun;
uint32_t itt;
uint32_t expected_data_xfer_len;
uint32_t cmd_sn;
uint32_t exp_stat_sn;
uint8_t cdb[16];
};
struct iscsi_bhs_scsi_resp {
uint8_t opcode : 6; /* opcode = 0x21 */
uint8_t reserved : 2;
uint8_t flags;
uint8_t response;
uint8_t status;
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint8_t res4[8];
uint32_t itt;
uint32_t snacktag;
uint32_t stat_sn;
uint32_t exp_cmd_sn;
uint32_t max_cmd_sn;
uint32_t exp_data_sn;
uint32_t bi_read_res_cnt;
uint32_t res_cnt;
};
struct iscsi_bhs_data_in {
uint8_t opcode : 6; /* opcode = 0x05 */
uint8_t reserved : 2;
uint8_t flags;
uint8_t res;
uint8_t status;
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint64_t lun;
uint32_t itt;
uint32_t ttt;
uint32_t stat_sn;
uint32_t exp_cmd_sn;
uint32_t max_cmd_sn;
uint32_t data_sn;
uint32_t buffer_offset;
uint32_t res_cnt;
};
struct iscsi_bhs_data_out {
uint8_t opcode : 6; /* opcode = 0x25 */
uint8_t reserved : 2;
uint8_t flags;
uint8_t res[2];
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint64_t lun;
uint32_t itt;
uint32_t ttt;
uint32_t res3;
uint32_t exp_stat_sn;
uint32_t res4;
uint32_t data_sn;
uint32_t buffer_offset;
uint32_t res5;
};
struct iscsi_bhs_snack_req {
uint8_t opcode : 6; /* opcode = 0x10 */
uint8_t reserved : 2;
uint8_t flags;
uint8_t res[2];
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint64_t lun;
uint32_t itt;
uint32_t ttt;
uint32_t res5;
uint32_t exp_stat_sn;
uint8_t res6[8];
uint32_t beg_run;
uint32_t run_len;
};
struct iscsi_bhs_task_req {
uint8_t opcode : 6; /* opcode = 0x02 */
uint8_t immediate : 1;
uint8_t reserved : 1;
uint8_t flags;
uint8_t res[2];
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint64_t lun;
uint32_t itt;
uint32_t ref_task_tag;
uint32_t cmd_sn;
uint32_t exp_stat_sn;
uint32_t ref_cmd_sn;
uint32_t exp_data_sn;
uint8_t res5[8];
};
struct iscsi_bhs_task_resp {
uint8_t opcode : 6; /* opcode = 0x22 */
uint8_t reserved : 2;
uint8_t flags;
uint8_t response;
uint8_t res;
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint8_t res2[8];
uint32_t itt;
uint32_t res3;
uint32_t stat_sn;
uint32_t exp_cmd_sn;
uint32_t max_cmd_sn;
uint8_t res4[12];
};
struct iscsi_bhs_text_req {
uint8_t opcode : 6; /* opcode = 0x04 */
uint8_t immediate : 1;
uint8_t reserved : 1;
uint8_t flags;
uint8_t res[2];
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint64_t lun;
uint32_t itt;
uint32_t ttt;
uint32_t cmd_sn;
uint32_t exp_stat_sn;
uint8_t res3[16];
};
struct iscsi_bhs_text_resp {
uint8_t opcode : 6; /* opcode = 0x24 */
uint8_t reserved : 2;
uint8_t flags;
uint8_t res[2];
uint8_t total_ahs_len;
uint8_t data_segment_len[3];
uint64_t lun;
uint32_t itt;
uint32_t ttt;
uint32_t stat_sn;
uint32_t exp_cmd_sn;
uint32_t max_cmd_sn;
uint8_t res4[12];
};
/* generic flags */
#define ISCSI_FLAG_FINAL 0x80
/* login flags */
#define ISCSI_LOGIN_TRANSIT 0x80
#define ISCSI_LOGIN_CONTINUE 0x40
#define ISCSI_LOGIN_CURRENT_STAGE_MASK 0x0c
#define ISCSI_LOGIN_CURRENT_STAGE_0 0x04
#define ISCSI_LOGIN_CURRENT_STAGE_1 0x08
#define ISCSI_LOGIN_CURRENT_STAGE_3 0x0c
#define ISCSI_LOGIN_NEXT_STAGE_MASK 0x03
#define ISCSI_LOGIN_NEXT_STAGE_0 0x01
#define ISCSI_LOGIN_NEXT_STAGE_1 0x02
#define ISCSI_LOGIN_NEXT_STAGE_3 0x03
/* text flags */
#define ISCSI_TEXT_CONTINUE 0x40
/* logout flags */
#define ISCSI_LOGOUT_REASON_MASK 0x7f
/* datain flags */
#define ISCSI_DATAIN_ACKNOLWEDGE 0x40
#define ISCSI_DATAIN_OVERFLOW 0x04
#define ISCSI_DATAIN_UNDERFLOW 0x02
#define ISCSI_DATAIN_STATUS 0x01
/* SCSI resp flags */
#define ISCSI_SCSI_BIDI_OVERFLOW 0x10
#define ISCSI_SCSI_BIDI_UNDERFLOW 0x08
#define ISCSI_SCSI_OVERFLOW 0x04
#define ISCSI_SCSI_UNDERFLOW 0x02
/* SCSI task flags */
#define ISCSI_TASK_FUNCTION_MASK 0x7f
/* Reason for Reject */
#define ISCSI_REASON_RESERVED 0x1
#define ISCSI_REASON_DATA_DIGEST_ERROR 0x2
#define ISCSI_REASON_DATA_SNACK_REJECT 0x3
#define ISCSI_REASON_PROTOCOL_ERROR 0x4
#define ISCSI_REASON_CMD_NOT_SUPPORTED 0x5
#define ISCSI_REASON_IMM_CMD_REJECT 0x6
#define ISCSI_REASON_TASK_IN_PROGRESS 0x7
#define ISCSI_REASON_INVALID_SNACK 0x8
#define ISCSI_REASON_INVALID_PDU_FIELD 0x9
#define ISCSI_REASON_LONG_OPERATION_REJECT 0xa
#define ISCSI_REASON_NEGOTIATION_RESET 0xb
#define ISCSI_REASON_WAIT_FOR_RESET 0xc
#define ISCSI_FLAG_SNACK_TYPE_DATA 0
#define ISCSI_FLAG_SNACK_TYPE_R2T 0
#define ISCSI_FLAG_SNACK_TYPE_STATUS 1
#define ISCSI_FLAG_SNACK_TYPE_DATA_ACK 2
#define ISCSI_FLAG_SNACK_TYPE_RDATA 3
#define ISCSI_FLAG_SNACK_TYPE_MASK 0x0F /* 4 bits */
/* For spdk_iscsi_login_in related function use, we need to avoid the conflict
* with other errors
* */
#define SPDK_ISCSI_LOGIN_ERROR_RESPONSE -1000
#define SPDK_ISCSI_LOGIN_ERROR_PARAMETER -1001
#define SPDK_ISCSI_PARAMETER_EXCHANGE_NOT_ONCE -1002
struct iscsi_ahs {
/* 0-3 */
uint8_t ahs_len[2];
uint8_t ahs_type;
uint8_t ahs_specific1;
/* 4-x */
uint8_t ahs_specific2[];
};
#define ISCSI_AHS_LEN 60
struct spdk_mobj {
struct rte_mempool *mp;
void *buf;
size_t len;
uint64_t reserved; /* do not use */
};
struct spdk_iscsi_pdu {
struct iscsi_bhs bhs;
struct iscsi_ahs *ahs;
struct spdk_mobj *mobj;
uint8_t *data_buf;
uint8_t *data;
uint8_t header_digest[ISCSI_DIGEST_LEN];
uint8_t data_digest[ISCSI_DIGEST_LEN];
size_t data_segment_len;
int bhs_valid_bytes;
int ahs_valid_bytes;
int data_valid_bytes;
int hdigest_valid_bytes;
int ddigest_valid_bytes;
int ref;
int data_ref;
struct spdk_iscsi_task *task; /* data tied to a task buffer */
uint32_t cmd_sn;
uint32_t writev_offset;
TAILQ_ENTRY(spdk_iscsi_pdu) tailq;
/*
* 60 bytes of AHS should suffice for now.
* This should always be at the end of PDU data structure.
* we need to not zero this out when doing memory clear.
*/
uint8_t ahs_data[ISCSI_AHS_LEN];
};
enum iscsi_connection_state {
ISCSI_CONN_STATE_INVALID = 0,
ISCSI_CONN_STATE_RUNNING = 1,
ISCSI_CONN_STATE_LOGGED_OUT = 2,
ISCSI_CONN_STATE_EXITING = 3,
};
enum iscsi_chap_phase {
ISCSI_CHAP_PHASE_NONE = 0,
ISCSI_CHAP_PHASE_WAIT_A = 1,
ISCSI_CHAP_PHASE_WAIT_NR = 2,
ISCSI_CHAP_PHASE_END = 3,
};
enum session_type {
SESSION_TYPE_INVALID = 0,
SESSION_TYPE_NORMAL = 1,
SESSION_TYPE_DISCOVERY = 2,
};
#define ISCSI_CHAP_CHALLENGE_LEN 1024
struct iscsi_chap_auth {
enum iscsi_chap_phase chap_phase;
char *user;
char *secret;
char *muser;
char *msecret;
uint8_t chap_id[1];
uint8_t chap_mid[1];
int chap_challenge_len;
uint8_t chap_challenge[ISCSI_CHAP_CHALLENGE_LEN];
int chap_mchallenge_len;
uint8_t chap_mchallenge[ISCSI_CHAP_CHALLENGE_LEN];
};
struct spdk_iscsi_sess {
uint32_t connections;
struct spdk_iscsi_conn **conns;
struct spdk_scsi_port initiator_port;
int tag;
uint64_t isid;
uint16_t tsih;
struct spdk_iscsi_tgt_node *target;
int queue_depth;
struct iscsi_param *params;
enum session_type session_type;
uint32_t MaxConnections;
uint32_t MaxOutstandingR2T;
uint32_t DefaultTime2Wait;
uint32_t DefaultTime2Retain;
uint32_t FirstBurstLength;
uint32_t MaxBurstLength;
uint32_t InitialR2T;
uint32_t ImmediateData;
uint32_t DataPDUInOrder;
uint32_t DataSequenceInOrder;
uint32_t ErrorRecoveryLevel;
uint32_t ExpCmdSN;
uint32_t MaxCmdSN;
uint32_t current_text_itt;
};
struct spdk_iscsi_globals {
char *authfile;
char *nodebase;
pthread_mutex_t mutex;
TAILQ_HEAD(, spdk_iscsi_portal_grp) pg_head;
TAILQ_HEAD(, spdk_iscsi_init_grp) ig_head;
int ntargets;
struct spdk_iscsi_tgt_node *target[MAX_ISCSI_TARGET_NODE];
int timeout;
int nopininterval;
int no_discovery_auth;
int req_discovery_auth;
int req_discovery_auth_mutual;
int discovery_auth_group;
uint32_t MaxSessions;
uint32_t MaxConnectionsPerSession;
uint32_t MaxConnections;
uint32_t MaxOutstandingR2T;
uint32_t DefaultTime2Wait;
uint32_t DefaultTime2Retain;
uint32_t FirstBurstLength;
uint32_t MaxBurstLength;
uint32_t MaxRecvDataSegmentLength;
uint32_t InitialR2T;
uint32_t ImmediateData;
uint32_t DataPDUInOrder;
uint32_t DataSequenceInOrder;
uint32_t ErrorRecoveryLevel;
uint32_t AllowDuplicateIsid;
struct rte_mempool *pdu_pool;
struct rte_mempool *pdu_immediate_data_pool;
struct rte_mempool *pdu_data_out_pool;
struct rte_mempool *session_pool;
struct rte_mempool *task_pool;
struct spdk_iscsi_sess **session;
};
#define ISCSI_BHS_LOGIN_GET_TBIT(X) (!!(X & ISCSI_LOGIN_TRANSIT))
#define ISCSI_BHS_LOGIN_GET_CBIT(X) (!!(X & ISCSI_LOGIN_CONTINUE))
#define ISCSI_BHS_LOGIN_GET_CSG(X) ((X & ISCSI_LOGIN_CURRENT_STAGE_MASK) >> 2)
#define ISCSI_BHS_LOGIN_GET_NSG(X) (X & ISCSI_LOGIN_NEXT_STAGE_MASK)
#define ISCSI_SECURITY_NEGOTIATION_PHASE 0
#define ISCSI_OPERATIONAL_NEGOTIATION_PHASE 1
#define ISCSI_NSG_RESERVED_CODE 2
#define ISCSI_FULL_FEATURE_PHASE 3
#define ISCSI_CLASS_SUCCESS 0x00
#define ISCSI_CLASS_REDIRECT 0x01
#define ISCSI_CLASS_INITIATOR_ERROR 0x02
#define ISCSI_CLASS_TARGET_ERROR 0x03
/* Class (Success) detailed info: 0 */
#define ISCSI_LOGIN_ACCEPT 0x00
/* Class (Redirection) detailed info: 1 */
#define ISCSI_LOGIN_TARGET_TEMPORARILY_MOVED 0x01
#define ISCSI_LOGIN_TARGET_PERMANENTLY_MOVED 0x02
/* Class(Initiator Error) detailed info: 2 */
#define ISCSI_LOGIN_INITIATOR_ERROR 0x00
#define ISCSI_LOGIN_AUTHENT_FAIL 0x01
#define ISCSI_LOGIN_AUTHORIZATION_FAIL 0x02
#define ISCSI_LOGIN_TARGET_NOT_FOUND 0x03
#define ISCSI_LOGIN_TARGET_REMOVED 0x04
#define ISCSI_LOGIN_UNSUPPORTED_VERSION 0x05
#define ISCSI_LOGIN_TOO_MANY_CONNECTIONS 0x06
#define ISCSI_LOGIN_MISSING_PARMS 0x07
#define ISCSI_LOGIN_CONN_ADD_FAIL 0x08
#define ISCSI_LOGIN_NOT_SUPPORTED_SESSION_TYPE 0x09
#define ISCSI_LOGIN_NO_SESSION 0x0a
#define ISCSI_LOGIN_INVALID_LOGIN_REQUEST 0x0b
/* Class(Target Error) detailed info: 3 */
#define ISCSI_LOGIN_STATUS_TARGET_ERROR 0x00
#define ISCSI_LOGIN_STATUS_SERVICE_UNAVAILABLE 0x01
#define ISCSI_LOGIN_STATUS_NO_RESOURCES 0x02
enum spdk_error_codes {
SPDK_SUCCESS = 0,
SPDK_ISCSI_CONNECTION_FATAL = -1,
SPDK_PDU_FATAL = -2,
};
#define DGET24(B) \
((( (uint32_t) *((uint8_t *)(B)+0)) << 16) \
| (((uint32_t) *((uint8_t *)(B)+1)) << 8) \
| (((uint32_t) *((uint8_t *)(B)+2)) << 0))
#define DSET24(B,D) \
(((*((uint8_t *)(B)+0)) = (uint8_t)((uint32_t)(D) >> 16)), \
((*((uint8_t *)(B)+1)) = (uint8_t)((uint32_t)(D) >> 8)), \
((*((uint8_t *)(B)+2)) = (uint8_t)((uint32_t)(D) >> 0)))
#define xstrdup(s) (s ? strdup(s) : (char *)NULL)
extern struct spdk_iscsi_globals g_spdk_iscsi;
struct spdk_iscsi_task;
int spdk_iscsi_send_nopin(struct spdk_iscsi_conn *conn);
void spdk_iscsi_task_response(struct spdk_iscsi_conn *conn,
struct spdk_iscsi_task *task);
int spdk_iscsi_execute(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu);
int spdk_iscsi_build_iovecs(struct spdk_iscsi_conn *conn,
struct iovec *iovec, struct spdk_iscsi_pdu *pdu);
int
spdk_iscsi_read_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu **_pdu);
void spdk_iscsi_task_mgmt_response(struct spdk_iscsi_conn *conn,
struct spdk_iscsi_task *task);
int spdk_iscsi_conn_params_init(struct iscsi_param **params);
int spdk_iscsi_sess_params_init(struct iscsi_param **params);
void spdk_free_sess(struct spdk_iscsi_sess *sess);
void spdk_clear_all_transfer_task(struct spdk_iscsi_conn *conn,
struct spdk_scsi_lun *lun);
void spdk_del_connection_queued_task(void *tailq, struct spdk_scsi_lun *lun);
void spdk_del_transfer_task(struct spdk_iscsi_conn *conn, uint32_t CmdSN);
bool spdk_iscsi_is_deferred_free_pdu(struct spdk_iscsi_pdu *pdu);
void spdk_iscsi_shutdown(void);
int spdk_iscsi_negotiate_params(struct spdk_iscsi_conn *conn,
struct iscsi_param *params, uint8_t *data,
int alloc_len, int data_len);
int spdk_iscsi_copy_param2var(struct spdk_iscsi_conn *conn);
void process_task_completion(spdk_event_t event);
void process_task_mgmt_completion(spdk_event_t event);
/* Memory management */
void spdk_put_pdu(struct spdk_iscsi_pdu *pdu);
struct spdk_iscsi_pdu *spdk_get_pdu(void);
int spdk_iscsi_conn_handle_queued_datain(struct spdk_iscsi_conn *conn);
static inline int
spdk_get_immediate_data_buffer_size(void)
{
/*
* Specify enough extra space in addition to FirstBurstLength to
* account for a header digest, data digest and additional header
* segments (AHS). These are not normally used but they do not
* take up much space and we need to make sure the worst-case scenario
* can be satisified by the size returned here.
*/
return g_spdk_iscsi.FirstBurstLength +
ISCSI_DIGEST_LEN + /* data digest */
ISCSI_DIGEST_LEN + /* header digest */
8 + /* bidirectional AHS */
52; /* extended CDB AHS (for a 64-byte CDB) */
}
static inline int
spdk_get_data_out_buffer_size(void)
{
return g_spdk_iscsi.MaxRecvDataSegmentLength;
}
#endif /* SPDK_ISCSI_H */

929
lib/iscsi/iscsi_rpc.c Normal file
View File

@ -0,0 +1,929 @@
/*-
* 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.
*/
#include "iscsi/iscsi.h"
#include "iscsi/conn.h"
#include "iscsi/tgt_node.h"
#include "iscsi/portal_grp.h"
#include "iscsi/init_grp.h"
#include "spdk/log.h"
#include "spdk/rpc.h"
extern struct spdk_iscsi_conn *g_conns_array; // TODO: move this to an internal iSCSI header
static void
spdk_rpc_get_initiator_groups(struct spdk_jsonrpc_server_conn *conn,
const struct spdk_json_val *params,
const struct spdk_json_val *id)
{
struct spdk_json_write_ctx *w;
struct spdk_iscsi_init_grp *ig;
int i;
if (params != NULL) {
spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"get_initiator_groups requires no parameters");
return;
}
if (id == NULL) {
return;
}
w = spdk_jsonrpc_begin_result(conn, id);
spdk_json_write_array_begin(w);
TAILQ_FOREACH(ig, &g_spdk_iscsi.ig_head, tailq) {
spdk_json_write_object_begin(w);
spdk_json_write_name(w, "initiators");
spdk_json_write_array_begin(w);
for (i = 0; i < ig->ninitiators; i++) {
spdk_json_write_string(w, ig->initiators[i]);
}
spdk_json_write_array_end(w);
spdk_json_write_name(w, "tag");
spdk_json_write_int32(w, ig->tag);
spdk_json_write_name(w, "netmasks");
spdk_json_write_array_begin(w);
for (i = 0; i < ig->nnetmasks; i++) {
spdk_json_write_string(w, ig->netmasks[i]);
}
spdk_json_write_array_end(w);
spdk_json_write_object_end(w);
}
spdk_json_write_array_end(w);
spdk_jsonrpc_end_result(conn, w);
}
SPDK_RPC_REGISTER("get_initiator_groups", spdk_rpc_get_initiator_groups)
struct rpc_initiator_list {
size_t num_initiators;
char *initiators[MAX_INITIATOR];
};
static int
decode_rpc_initiator_list(const struct spdk_json_val *val, void *out)
{
struct rpc_initiator_list *list = out;
return spdk_json_decode_array(val, spdk_json_decode_string, list->initiators, MAX_INITIATOR,
&list->num_initiators, sizeof(char *));
}
static void
free_rpc_initiator_list(struct rpc_initiator_list *list)
{
size_t i;
for (i = 0; i < list->num_initiators; i++) {
free(list->initiators[i]);
}
}
struct rpc_netmask_list {
size_t num_netmasks;
char *netmasks[MAX_NETMASK];
};
static int
decode_rpc_netmask_list(const struct spdk_json_val *val, void *out)
{
struct rpc_netmask_list *list = out;
return spdk_json_decode_array(val, spdk_json_decode_string, list->netmasks, MAX_NETMASK,
&list->num_netmasks, sizeof(char *));
}
static void
free_rpc_netmask_list(struct rpc_netmask_list *list)
{
size_t i;
for (i = 0; i < list->num_netmasks; i++) {
free(list->netmasks[i]);
}
}
struct rpc_initiator_group {
int32_t tag;
struct rpc_initiator_list initiator_list;
struct rpc_netmask_list netmask_list;
};
static void
free_rpc_initiator_group(struct rpc_initiator_group *ig)
{
free_rpc_initiator_list(&ig->initiator_list);
free_rpc_netmask_list(&ig->netmask_list);
}
static const struct spdk_json_object_decoder rpc_initiator_group_decoders[] = {
{"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32},
{"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list},
{"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list},
};
static void
spdk_rpc_add_initiator_group(struct spdk_jsonrpc_server_conn *conn,
const struct spdk_json_val *params,
const struct spdk_json_val *id)
{
struct rpc_initiator_group req = {};
size_t i;
char **initiators = NULL, **netmasks = NULL;
struct spdk_json_write_ctx *w;
if (spdk_json_decode_object(params, rpc_initiator_group_decoders,
sizeof(rpc_initiator_group_decoders) / sizeof(*rpc_initiator_group_decoders), &req)) {
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_json_decode_object failed\n");
goto invalid;
}
if (req.initiator_list.num_initiators == 0 ||
req.netmask_list.num_netmasks == 0) {
goto invalid;
}
initiators = calloc(req.initiator_list.num_initiators, sizeof(char *));
if (initiators == NULL) {
goto invalid;
}
for (i = 0; i < req.initiator_list.num_initiators; i++) {
initiators[i] = strdup(req.initiator_list.initiators[i]);
if (initiators[i] == NULL) {
goto invalid;
}
}
netmasks = calloc(req.netmask_list.num_netmasks, sizeof(char *));
if (netmasks == NULL) {
goto invalid;
}
for (i = 0; i < req.netmask_list.num_netmasks; i++) {
netmasks[i] = strdup(req.netmask_list.netmasks[i]);
if (netmasks[i] == NULL) {
goto invalid;
}
}
if (spdk_iscsi_init_grp_create_from_initiator_list(req.tag,
req.initiator_list.num_initiators,
initiators,
req.netmask_list.num_netmasks,
netmasks)) {
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "create_from_initiator_list failed\n");
goto invalid;
}
free_rpc_initiator_group(&req);
if (id == NULL) {
return;
}
w = spdk_jsonrpc_begin_result(conn, id);
spdk_json_write_bool(w, true);
spdk_jsonrpc_end_result(conn, w);
return;
invalid:
spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
if (initiators) {
for (i = 0; i < req.initiator_list.num_initiators; i++) {
free(initiators[i]);
}
free(initiators);
}
if (netmasks) {
for (i = 0; i < req.netmask_list.num_netmasks; i++) {
free(netmasks[i]);
}
free(netmasks);
}
free_rpc_initiator_group(&req);
}
SPDK_RPC_REGISTER("add_initiator_group", spdk_rpc_add_initiator_group)
struct rpc_delete_initiator_group {
int32_t tag;
};
static const struct spdk_json_object_decoder rpc_delete_initiator_group_decoders[] = {
{"tag", offsetof(struct rpc_delete_initiator_group, tag), spdk_json_decode_int32},
};
static void
spdk_rpc_delete_initiator_group(struct spdk_jsonrpc_server_conn *conn,
const struct spdk_json_val *params,
const struct spdk_json_val *id)
{
struct rpc_delete_initiator_group req = {};
struct spdk_json_write_ctx *w;
struct spdk_iscsi_init_grp *ig;
if (spdk_json_decode_object(params, rpc_delete_initiator_group_decoders,
sizeof(rpc_delete_initiator_group_decoders) / sizeof(*rpc_delete_initiator_group_decoders),
&req)) {
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_json_decode_object failed\n");
goto invalid;
}
if (spdk_iscsi_init_grp_deletable(req.tag)) {
goto invalid;
}
ig = spdk_iscsi_init_grp_find_by_tag(req.tag);
if (!ig) {
goto invalid;
}
spdk_iscsi_tgt_node_delete_map(NULL, ig);
spdk_iscsi_init_grp_release(ig);
if (id == NULL) {
return;
}
w = spdk_jsonrpc_begin_result(conn, id);
spdk_json_write_bool(w, true);
spdk_jsonrpc_end_result(conn, w);
return;
invalid:
spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
}
SPDK_RPC_REGISTER("delete_initiator_group", spdk_rpc_delete_initiator_group)
static void
spdk_rpc_get_target_nodes(struct spdk_jsonrpc_server_conn *conn,
const struct spdk_json_val *params,
const struct spdk_json_val *id)
{
struct spdk_iscsi_globals *iscsi = &g_spdk_iscsi;
struct spdk_json_write_ctx *w;
size_t tgt_idx;
int i;
if (params != NULL) {
spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"get_target_nodes requires no parameters");
return;
}
if (id == NULL) {
return;
}
w = spdk_jsonrpc_begin_result(conn, id);
spdk_json_write_array_begin(w);
for (tgt_idx = 0 ; tgt_idx < MAX_ISCSI_TARGET_NODE; tgt_idx++) {
struct spdk_iscsi_tgt_node *tgtnode = iscsi->target[tgt_idx];
if (tgtnode == NULL) {
continue;
}
spdk_json_write_object_begin(w);
spdk_json_write_name(w, "name");
spdk_json_write_string(w, tgtnode->name);
if (tgtnode->alias) {
spdk_json_write_name(w, "alias_name");
spdk_json_write_string(w, tgtnode->alias);
}
/*
* TODO: combine portal_group_tags and initiator_group_tags into an array
* of objects (needs rpc script changes to match)
*/
spdk_json_write_name(w, "portal_group_tags");
spdk_json_write_array_begin(w);
for (i = 0; i < tgtnode->maxmap; i++) {
spdk_json_write_int32(w, tgtnode->map[i].pg->tag);
}
spdk_json_write_array_end(w);
spdk_json_write_name(w, "initiator_group_tags");
spdk_json_write_array_begin(w);
for (i = 0; i < tgtnode->maxmap; i++) {
spdk_json_write_int32(w, tgtnode->map[i].ig->tag);
}
spdk_json_write_array_end(w);
/*
* TODO: combine lun_names and lun_ids into an array of objects
*/
spdk_json_write_name(w, "lun_names");
spdk_json_write_array_begin(w);
for (i = 0; i < tgtnode->dev->maxlun; i++) {
if (tgtnode->dev->lun[i]) {
spdk_json_write_string(w, tgtnode->dev->lun[i]->name);
}
}
spdk_json_write_array_end(w);
spdk_json_write_name(w, "lun_ids");
spdk_json_write_array_begin(w);
for (i = 0; i < tgtnode->dev->maxlun; i++) {
if (tgtnode->dev->lun[i]) {
spdk_json_write_int32(w, tgtnode->dev->lun[i]->id);
}
}
spdk_json_write_array_end(w);
spdk_json_write_name(w, "queue_depth");
spdk_json_write_int32(w, tgtnode->queue_depth);
/*
* TODO: convert these to bool
*/
spdk_json_write_name(w, "chap_disabled");
spdk_json_write_int32(w, tgtnode->auth_chap_disabled);
spdk_json_write_name(w, "chap_required");
spdk_json_write_int32(w, tgtnode->auth_chap_required);
spdk_json_write_name(w, "chap_mutual");
spdk_json_write_int32(w, tgtnode->auth_chap_mutual);
spdk_json_write_name(w, "chap_auth_group");
spdk_json_write_int32(w, tgtnode->auth_group);
spdk_json_write_object_end(w);
}
spdk_json_write_array_end(w);
spdk_jsonrpc_end_result(conn, w);
}
SPDK_RPC_REGISTER("get_target_nodes", spdk_rpc_get_target_nodes)
struct rpc_pg_tags {
size_t num_tags;
int32_t tags[MAX_TARGET_MAP];
};
static int
decode_rpc_pg_tags(const struct spdk_json_val *val, void *out)
{
struct rpc_pg_tags *pg_tags = out;
return spdk_json_decode_array(val, spdk_json_decode_int32, pg_tags->tags, MAX_TARGET_MAP,
&pg_tags->num_tags, sizeof(int32_t));
}
struct rpc_ig_tags {
size_t num_tags;
int32_t tags[MAX_TARGET_MAP];
};
static int
decode_rpc_ig_tags(const struct spdk_json_val *val, void *out)
{
struct rpc_ig_tags *ig_tags = out;
return spdk_json_decode_array(val, spdk_json_decode_int32, ig_tags->tags, MAX_TARGET_MAP,
&ig_tags->num_tags, sizeof(int32_t));
}
#define RPC_CONSTRUCT_TARGET_NODE_MAX_LUN 64
struct rpc_lun_names {
size_t num_names;
char *names[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN];
};
static int
decode_rpc_lun_names(const struct spdk_json_val *val, void *out)
{
struct rpc_lun_names *lun_names = out;
return spdk_json_decode_array(val, spdk_json_decode_string, lun_names->names,
RPC_CONSTRUCT_TARGET_NODE_MAX_LUN,
&lun_names->num_names, sizeof(char *));
}
static void
free_rpc_lun_names(struct rpc_lun_names *r)
{
size_t i;
for (i = 0; i < r->num_names; i++) {
free(r->names[i]);
}
}
struct rpc_lun_ids {
size_t num_ids;
int32_t ids[RPC_CONSTRUCT_TARGET_NODE_MAX_LUN];
};
static int
decode_rpc_lun_ids(const struct spdk_json_val *val, void *out)
{
struct rpc_lun_ids *lun_ids = out;
return spdk_json_decode_array(val, spdk_json_decode_int32, lun_ids->ids,
RPC_CONSTRUCT_TARGET_NODE_MAX_LUN,
&lun_ids->num_ids, sizeof(int32_t));
}
struct rpc_target_node {
char *name;
char *alias_name;
struct rpc_pg_tags pg_tags;
struct rpc_ig_tags ig_tags;
struct rpc_lun_names lun_names;
struct rpc_lun_ids lun_ids;
int32_t queue_depth;
int32_t chap_disabled;
int32_t chap_required;
int32_t chap_mutual;
int32_t chap_auth_group;
};
static void
free_rpc_target_node(struct rpc_target_node *req)
{
free_rpc_lun_names(&req->lun_names);
}
static const struct spdk_json_object_decoder rpc_target_node_decoders[] = {
{"name", offsetof(struct rpc_target_node, name), spdk_json_decode_string},
{"alias_name", offsetof(struct rpc_target_node, alias_name), spdk_json_decode_string},
{"pg_tags", offsetof(struct rpc_target_node, pg_tags), decode_rpc_pg_tags},
{"ig_tags", offsetof(struct rpc_target_node, ig_tags), decode_rpc_ig_tags},
{"lun_names", offsetof(struct rpc_target_node, lun_names), decode_rpc_lun_names},
{"lun_ids", offsetof(struct rpc_target_node, lun_ids), decode_rpc_lun_ids},
{"queue_depth", offsetof(struct rpc_target_node, queue_depth), spdk_json_decode_int32},
{"chap_disabled", offsetof(struct rpc_target_node, chap_disabled), spdk_json_decode_int32},
{"chap_required", offsetof(struct rpc_target_node, chap_required), spdk_json_decode_int32},
{"chap_mutual", offsetof(struct rpc_target_node, chap_mutual), spdk_json_decode_int32},
{"chap_auth_group", offsetof(struct rpc_target_node, chap_auth_group), spdk_json_decode_int32},
};
static void
spdk_rpc_construct_target_node(struct spdk_jsonrpc_server_conn *conn,
const struct spdk_json_val *params,
const struct spdk_json_val *id)
{
struct rpc_target_node req = {};
struct spdk_json_write_ctx *w;
struct spdk_iscsi_tgt_node *target;
if (spdk_json_decode_object(params, rpc_target_node_decoders,
sizeof(rpc_target_node_decoders) / sizeof(*rpc_target_node_decoders),
&req)) {
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_json_decode_object failed\n");
goto invalid;
}
if (req.pg_tags.num_tags != req.ig_tags.num_tags) {
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "pg_tags/ig_tags count mismatch\n");
goto invalid;
}
if (req.lun_names.num_names != req.lun_ids.num_ids) {
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "lun_names/lun_ids count mismatch\n");
goto invalid;
}
/*
* Use default parameters in a few places:
* index = -1 : automatically pick an index for the new target node
* alias = NULL
* 0, 0 = disable header/data digests
*/
target = spdk_iscsi_tgt_node_construct(-1, req.name, req.alias_name,
req.pg_tags.tags,
req.ig_tags.tags,
req.pg_tags.num_tags,
req.lun_names.names,
req.lun_ids.ids,
req.lun_names.num_names,
req.queue_depth,
req.chap_disabled,
req.chap_required,
req.chap_mutual,
req.chap_auth_group,
0, 0);
if (target == NULL) {
goto invalid;
}
free_rpc_target_node(&req);
if (id == NULL) {
return;
}
w = spdk_jsonrpc_begin_result(conn, id);
spdk_json_write_bool(w, true);
spdk_jsonrpc_end_result(conn, w);
return;
invalid:
spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
free_rpc_target_node(&req);
}
SPDK_RPC_REGISTER("construct_target_node", spdk_rpc_construct_target_node)
struct rpc_delete_target_node {
char *name;
};
static void
free_rpc_delete_target_node(struct rpc_delete_target_node *r)
{
free(r->name);
}
static const struct spdk_json_object_decoder rpc_delete_target_node_decoders[] = {
{"name", offsetof(struct rpc_delete_target_node, name), spdk_json_decode_string},
};
static void
spdk_rpc_delete_target_node(struct spdk_jsonrpc_server_conn *conn,
const struct spdk_json_val *params,
const struct spdk_json_val *id)
{
struct rpc_delete_target_node req = {};
struct spdk_json_write_ctx *w;
if (spdk_json_decode_object(params, rpc_delete_target_node_decoders,
sizeof(rpc_delete_target_node_decoders) / sizeof(*rpc_delete_target_node_decoders),
&req)) {
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_json_decode_object failed\n");
goto invalid;
}
if (req.name == NULL) {
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "missing name param\n");
goto invalid;
}
if (spdk_iscsi_shutdown_tgt_node_by_name(req.name)) {
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "shutdown_tgt_node_by_name failed\n");
goto invalid;
}
free_rpc_delete_target_node(&req);
if (id == NULL) {
return;
}
w = spdk_jsonrpc_begin_result(conn, id);
spdk_json_write_bool(w, true);
spdk_jsonrpc_end_result(conn, w);
return;
invalid:
spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
free_rpc_delete_target_node(&req);
}
SPDK_RPC_REGISTER("delete_target_node", spdk_rpc_delete_target_node)
static void
spdk_rpc_get_portal_groups(struct spdk_jsonrpc_server_conn *conn,
const struct spdk_json_val *params,
const struct spdk_json_val *id)
{
struct spdk_json_write_ctx *w;
struct spdk_iscsi_portal_grp *pg;
struct spdk_iscsi_portal *portal;
if (params != NULL) {
spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"get_portal_groups requires no parameters");
return;
}
if (id == NULL) {
return;
}
w = spdk_jsonrpc_begin_result(conn, id);
spdk_json_write_array_begin(w);
TAILQ_FOREACH(pg, &g_spdk_iscsi.pg_head, tailq) {
spdk_json_write_object_begin(w);
spdk_json_write_name(w, "portals");
spdk_json_write_array_begin(w);
TAILQ_FOREACH(portal, &pg->head, tailq) {
spdk_json_write_object_begin(w);
spdk_json_write_name(w, "host");
spdk_json_write_string(w, portal->host);
spdk_json_write_name(w, "port");
spdk_json_write_string(w, portal->port);
spdk_json_write_object_end(w);
}
spdk_json_write_array_end(w);
spdk_json_write_name(w, "tag");
spdk_json_write_int32(w, pg->tag);
spdk_json_write_object_end(w);
}
spdk_json_write_array_end(w);
spdk_jsonrpc_end_result(conn, w);
}
SPDK_RPC_REGISTER("get_portal_groups", spdk_rpc_get_portal_groups)
struct rpc_portal {
char *host;
char *port;
};
struct rpc_portal_list {
size_t num_portals;
struct rpc_portal portals[MAX_PORTAL];
};
struct rpc_portal_group {
int32_t tag;
struct rpc_portal_list portal_list;
};
static void
free_rpc_portal(struct rpc_portal *portal)
{
free(portal->host);
portal->host = NULL;
free(portal->port);
portal->port = NULL;
}
static void
free_rpc_portal_list(struct rpc_portal_list *pl)
{
size_t i;
for (i = 0; i < pl->num_portals; i++) {
free_rpc_portal(&pl->portals[i]);
}
pl->num_portals = 0;
}
static void
free_rpc_portal_group(struct rpc_portal_group *pg)
{
free_rpc_portal_list(&pg->portal_list);
}
static const struct spdk_json_object_decoder rpc_portal_decoders[] = {
{"host", offsetof(struct rpc_portal, host), spdk_json_decode_string},
{"port", offsetof(struct rpc_portal, port), spdk_json_decode_string},
};
static int
decode_rpc_portal(const struct spdk_json_val *val, void *out)
{
struct rpc_portal *portal = out;
return spdk_json_decode_object(val, rpc_portal_decoders,
sizeof(rpc_portal_decoders) / sizeof(*rpc_portal_decoders),
portal);
}
static int
decode_rpc_portal_list(const struct spdk_json_val *val, void *out)
{
struct rpc_portal_list *list = out;
return spdk_json_decode_array(val, decode_rpc_portal, list->portals, MAX_PORTAL, &list->num_portals,
sizeof(struct rpc_portal));
}
static const struct spdk_json_object_decoder rpc_portal_group_decoders[] = {
{"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32},
{"portals", offsetof(struct rpc_portal_group, portal_list), decode_rpc_portal_list},
};
static void
spdk_rpc_add_portal_group(struct spdk_jsonrpc_server_conn *conn,
const struct spdk_json_val *params,
const struct spdk_json_val *id)
{
struct rpc_portal_group req = {};
struct spdk_iscsi_portal *portal_list[MAX_PORTAL] = {};
struct spdk_json_write_ctx *w;
size_t i;
if (spdk_json_decode_object(params, rpc_portal_group_decoders,
sizeof(rpc_portal_group_decoders) / sizeof(*rpc_portal_group_decoders),
&req)) {
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_json_decode_object failed\n");
goto invalid;
}
for (i = 0; i < req.portal_list.num_portals; i++) {
portal_list[i] = spdk_iscsi_portal_create(req.portal_list.portals[i].host,
req.portal_list.portals[i].port, 0);
if (portal_list[i] == NULL) {
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "portal_list allocation failed\n");
goto invalid;
}
}
if (spdk_iscsi_portal_grp_create_from_portal_list(req.tag, portal_list,
req.portal_list.num_portals)) {
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "create_from_portal_list failed\n");
goto invalid;
}
/*
* Leave the host and port strings allocated here and don't call free_rpc_portal_group(),
* because the pointers are inserted directly into the portal group list.
*/
if (id == NULL) {
return;
}
w = spdk_jsonrpc_begin_result(conn, id);
spdk_json_write_bool(w, true);
spdk_jsonrpc_end_result(conn, w);
return;
invalid:
spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
for (i = 0; i < req.portal_list.num_portals; i++) {
spdk_iscsi_portal_destroy(portal_list[i]);
}
free_rpc_portal_group(&req);
}
SPDK_RPC_REGISTER("add_portal_group", spdk_rpc_add_portal_group)
struct rpc_delete_portal_group {
int32_t tag;
};
static const struct spdk_json_object_decoder rpc_delete_portal_group_decoders[] = {
{"tag", offsetof(struct rpc_delete_portal_group, tag), spdk_json_decode_int32},
};
static void
spdk_rpc_delete_portal_group(struct spdk_jsonrpc_server_conn *conn,
const struct spdk_json_val *params,
const struct spdk_json_val *id)
{
struct rpc_delete_portal_group req = {};
struct spdk_json_write_ctx *w;
struct spdk_iscsi_portal_grp *pg;
if (spdk_json_decode_object(params, rpc_delete_portal_group_decoders,
sizeof(rpc_delete_portal_group_decoders) / sizeof(*rpc_delete_portal_group_decoders),
&req)) {
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_json_decode_object failed\n");
goto invalid;
}
if (spdk_iscsi_portal_grp_deletable(req.tag)) {
goto invalid;
}
pg = spdk_iscsi_portal_grp_find_by_tag(req.tag);
if (!pg) {
goto invalid;
}
spdk_iscsi_tgt_node_delete_map(pg, NULL);
spdk_iscsi_portal_grp_release(pg);
if (id == NULL) {
return;
}
w = spdk_jsonrpc_begin_result(conn, id);
spdk_json_write_bool(w, true);
spdk_jsonrpc_end_result(conn, w);
return;
invalid:
spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
}
SPDK_RPC_REGISTER("delete_portal_group", spdk_rpc_delete_portal_group)
static void
spdk_rpc_get_iscsi_connections(struct spdk_jsonrpc_server_conn *conn,
const struct spdk_json_val *params,
const struct spdk_json_val *id)
{
struct spdk_json_write_ctx *w;
struct spdk_iscsi_conn *conns = g_conns_array;
int i;
uint16_t tsih;
if (params != NULL) {
spdk_jsonrpc_send_error_response(conn, id, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
"get_iscsi_connections requires no parameters");
return;
}
if (id == NULL) {
return;
}
w = spdk_jsonrpc_begin_result(conn, id);
spdk_json_write_array_begin(w);
for (i = 0; i < MAX_ISCSI_CONNECTIONS; i++) {
struct spdk_iscsi_conn *c = &conns[i];
if (!c->is_valid) {
continue;
}
spdk_json_write_object_begin(w);
spdk_json_write_name(w, "id");
spdk_json_write_int32(w, c->id);
spdk_json_write_name(w, "cid");
spdk_json_write_int32(w, c->cid);
/*
* If we try to return data for a connection that has not
* logged in yet, the session will not be set. So in this
* case, return -1 for the tsih rather than segfaulting
* on the null c->sess.
*/
if (c->sess == NULL) {
tsih = -1;
} else {
tsih = c->sess->tsih;
}
spdk_json_write_name(w, "tsih");
spdk_json_write_int32(w, tsih);
spdk_json_write_name(w, "is_idle");
spdk_json_write_int32(w, c->is_idle);
spdk_json_write_name(w, "lcore_id");
spdk_json_write_int32(w, c->poller.lcore);
spdk_json_write_name(w, "initiator_addr");
spdk_json_write_string(w, c->initiator_addr);
spdk_json_write_name(w, "target_addr");
spdk_json_write_string(w, c->target_addr);
spdk_json_write_name(w, "target_node_name");
spdk_json_write_string(w, c->target_short_name);
spdk_json_write_object_end(w);
}
spdk_json_write_array_end(w);
spdk_jsonrpc_end_result(conn, w);
}
SPDK_RPC_REGISTER("get_iscsi_connections", spdk_rpc_get_iscsi_connections)

1025
lib/iscsi/iscsi_subsystem.c Normal file

File diff suppressed because it is too large Load Diff

73
lib/iscsi/md5.c Normal file
View File

@ -0,0 +1,73 @@
/*-
* 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.
*/
#include <inttypes.h>
#include <stdint.h>
#include <stddef.h>
#include <openssl/md5.h>
#include "iscsi/md5.h"
int spdk_md5init(struct spdk_md5ctx *md5ctx)
{
int rc;
if (md5ctx == NULL)
return -1;
rc = MD5_Init(&md5ctx->md5ctx);
return rc;
}
int spdk_md5final(void *md5, struct spdk_md5ctx *md5ctx)
{
int rc;
if (md5ctx == NULL || md5 == NULL)
return -1;
rc = MD5_Final(md5, &md5ctx->md5ctx);
return rc;
}
int spdk_md5update(struct spdk_md5ctx *md5ctx, const void *data, size_t len)
{
int rc;
if (md5ctx == NULL)
return -1;
if (data == NULL || len <= 0)
return 0;
rc = MD5_Update(&md5ctx->md5ctx, data, len);
return rc;
}

52
lib/iscsi/md5.h Normal file
View File

@ -0,0 +1,52 @@
/*-
* 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.
*/
#ifndef SPDK_MD5_H
#define SPDK_MD5_H
#include <stddef.h>
#include <openssl/md5.h>
#define SPDK_MD5DIGEST_LEN MD5_DIGEST_LENGTH
struct spdk_md5ctx {
MD5_CTX md5ctx;
};
int spdk_md5init(struct spdk_md5ctx *md5ctx);
int spdk_md5final(void *md5, struct spdk_md5ctx *md5ctx);
int spdk_md5update(struct spdk_md5ctx *md5ctx, const void *data, size_t len);
#endif /* SPDK_MD5_H */

1185
lib/iscsi/param.c Normal file

File diff suppressed because it is too large Load Diff

84
lib/iscsi/param.h Normal file
View File

@ -0,0 +1,84 @@
/*-
* 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.
*/
#ifndef SPDK_ISCSI_PARAM_H
#define SPDK_ISCSI_PARAM_H
#include <stdint.h>
enum iscsi_param_type {
ISPT_INVALID = -1,
ISPT_NOTSPECIFIED = 0,
ISPT_LIST,
ISPT_NUMERICAL_MIN,
ISPT_NUMERICAL_MAX,
ISPT_NUMERICAL_DECLARATIVE,
ISPT_DECLARATIVE,
ISPT_BOOLEAN_OR,
ISPT_BOOLEAN_AND,
};
struct iscsi_param {
struct iscsi_param *next;
char *key;
char *val;
char *list;
int type;
int state_index;
};
void
spdk_iscsi_param_free(struct iscsi_param *params);
struct iscsi_param *
spdk_iscsi_param_find(struct iscsi_param *params, const char *key);
int
spdk_iscsi_param_del(struct iscsi_param **params, const char *key);
int
spdk_iscsi_param_add(struct iscsi_param **params, const char *key,
const char *val, const char *list, int type);
int
spdk_iscsi_param_set(struct iscsi_param *params, const char *key,
const char *val);
int
spdk_iscsi_param_set_int(struct iscsi_param *params, const char *key, uint32_t val);
int
spdk_iscsi_parse_params(struct iscsi_param **params, const uint8_t *data,
int len, bool cbit_enabled, char **partial_parameter);
char *
spdk_iscsi_param_get_val(struct iscsi_param *params, const char *key);
int
spdk_iscsi_param_eq_val(struct iscsi_param *params, const char *key,
const char *val);
#endif /* SPDK_ISCSI_PARAM_H */

642
lib/iscsi/portal_grp.c Normal file
View File

@ -0,0 +1,642 @@
/*-
* 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.
*/
#include <inttypes.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <poll.h>
#include <pthread.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <rte_debug.h>
#include "spdk/log.h"
#include "spdk/conf.h"
#include "spdk/net.h"
#include "iscsi/iscsi.h"
#include "iscsi/tgt_node.h"
#include "iscsi/conn.h"
#include "iscsi/portal_grp.h"
#define PORTNUMSTRLEN 32
static int
spdk_iscsi_portal_grp_open(struct spdk_iscsi_portal_grp *pg);
/* Assumes caller allocated host and port strings on the heap */
struct spdk_iscsi_portal *
spdk_iscsi_portal_create(char *host, char *port, uint64_t cpumask)
{
struct spdk_iscsi_portal *p = NULL;
RTE_VERIFY(host != NULL);
RTE_VERIFY(port != NULL);
p = malloc(sizeof(*p));
if (!p) {
SPDK_ERRLOG("portal malloc error (%s, %s)\n", host, port);
return NULL;
}
p->host = host;
p->port = port;
p->cpumask = cpumask;
p->sock = -1;
p->group = NULL; /* set at a later time by caller */
return p;
}
void
spdk_iscsi_portal_destroy(struct spdk_iscsi_portal *p)
{
RTE_VERIFY(p != NULL);
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_iscsi_portal_destroy\n");
free(p->host);
free(p->port);
free(p);
}
static int
spdk_iscsi_portal_create_from_configline(const char *portalstring,
struct spdk_iscsi_portal **ip,
int dry_run)
{
char *host = NULL, *port = NULL;
const char *cpumask_str;
uint64_t cpumask = 0;
int n, len;
const char *p, *q;
if (portalstring == NULL) {
SPDK_ERRLOG("portal error\n");
goto error_out;
}
if (portalstring[0] == '[') {
/* IPv6 */
p = strchr(portalstring + 1, ']');
if (p == NULL) {
SPDK_ERRLOG("portal error\n");
goto error_out;
}
p++;
n = p - portalstring;
if (!dry_run) {
host = malloc(n + 1);
if (!host) {
perror("host");
goto error_out;
}
memcpy(host, portalstring, n);
host[n] = '\0';
}
if (p[0] == '\0') {
if (!dry_run) {
port = malloc(PORTNUMSTRLEN);
if (!port) {
perror("port");
goto error_out;
}
snprintf(port, PORTNUMSTRLEN, "%d", DEFAULT_PORT);
}
} else {
if (p[0] != ':') {
SPDK_ERRLOG("portal error\n");
goto error_out;
}
if (!dry_run) {
q = strchr(portalstring, '@');
if (q == NULL) {
q = portalstring + strlen(portalstring);
}
len = q - p - 1;
port = malloc(len + 1);
if (!port) {
perror("port");
goto error_out;
}
memset(port, 0, len + 1);
memcpy(port, p + 1, len);
}
}
} else {
/* IPv4 */
p = strchr(portalstring, ':');
if (p == NULL) {
p = portalstring + strlen(portalstring);
}
n = p - portalstring;
if (!dry_run) {
host = malloc(n + 1);
if (!host) {
perror("host");
goto error_out;
}
memcpy(host, portalstring, n);
host[n] = '\0';
}
if (p[0] == '\0') {
if (!dry_run) {
port = malloc(PORTNUMSTRLEN);
if (!port) {
perror("port");
goto error_out;
}
snprintf(port, PORTNUMSTRLEN, "%d", DEFAULT_PORT);
}
} else {
if (p[0] != ':') {
SPDK_ERRLOG("portal error\n");
goto error_out;
}
if (!dry_run) {
q = strchr(portalstring, '@');
if (q == NULL) {
q = portalstring + strlen(portalstring);
}
if (q == p) {
SPDK_ERRLOG("no port specified\n");
goto error_out;
}
len = q - p - 1;
port = malloc(len + 1);
if (!port) {
perror("port");
goto error_out;
}
memset(port, 0, len + 1);
memcpy(port, p + 1, len);
}
}
}
p = strchr(portalstring, '@');
if (p != NULL) {
cpumask_str = p + 1;
if (spdk_app_parse_core_mask(cpumask_str, &cpumask)) {
SPDK_ERRLOG("invalid portal cpumask %s\n", cpumask_str);
goto error_out;
}
if ((cpumask & spdk_app_get_core_mask()) != cpumask) {
SPDK_ERRLOG("portal cpumask %s not a subset of "
"reactor mask %jx\n", cpumask_str,
spdk_app_get_core_mask());
goto error_out;
}
} else {
cpumask = spdk_app_get_core_mask();
}
if (!dry_run) {
*ip = spdk_iscsi_portal_create(host, port, cpumask);
if (!*ip) {
goto error_out;
}
}
return 0;
error_out:
if (host != NULL)
free(host);
if (port != NULL)
free(port);
return -1;
}
struct spdk_iscsi_portal_grp *
spdk_iscsi_portal_grp_create(int tag)
{
struct spdk_iscsi_portal_grp *pg = malloc(sizeof(*pg));
if (!pg) {
SPDK_ERRLOG("portal group malloc error (%d)\n", tag);
return NULL;
}
/* Make sure there are no duplicate portal group tags */
if (spdk_iscsi_portal_grp_find_by_tag(tag)) {
SPDK_ERRLOG("portal group creation failed. duplicate portal group tag (%d)\n", tag);
free(pg);
return NULL;
}
pg->state = GROUP_INIT;
pg->ref = 0;
pg->tag = tag;
TAILQ_INIT(&pg->head);
return pg;
}
void
spdk_iscsi_portal_grp_destroy(struct spdk_iscsi_portal_grp *pg)
{
struct spdk_iscsi_portal *p;
RTE_VERIFY(pg != NULL);
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_iscsi_portal_grp_destroy\n");
while (!TAILQ_EMPTY(&pg->head)) {
p = TAILQ_FIRST(&pg->head);
TAILQ_REMOVE(&pg->head, p, tailq);
spdk_iscsi_portal_destroy(p);
}
free(pg);
}
static void
spdk_iscsi_portal_grp_register(struct spdk_iscsi_portal_grp *pg)
{
RTE_VERIFY(pg != NULL);
RTE_VERIFY(!TAILQ_EMPTY(&pg->head));
pthread_mutex_lock(&g_spdk_iscsi.mutex);
pg->state = GROUP_READY;
TAILQ_INSERT_TAIL(&g_spdk_iscsi.pg_head, pg, tailq);
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
}
int
spdk_iscsi_portal_grp_create_from_portal_list(int tag,
struct spdk_iscsi_portal **portal_list,
int num_portals)
{
int i = 0, count = 0, port, sock;
struct spdk_iscsi_portal_grp *pg;
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "add portal group (from portal list) %d\n", tag);
if (num_portals > MAX_PORTAL) {
SPDK_ERRLOG("%d > MAX_PORTAL\n", num_portals);
goto error_out;
}
pg = spdk_iscsi_portal_grp_create(tag);
if (!pg) {
SPDK_ERRLOG("portal group creation error (%d)\n", tag);
goto error_out;
}
for (i = 0; i < num_portals; i++) {
struct spdk_iscsi_portal *p = portal_list[i];
SPDK_TRACELOG(SPDK_TRACE_DEBUG,
"RIndex=%d, Host=%s, Port=%s, Tag=%d\n",
i, p->host, p->port, tag);
port = (int)strtol(p->port, NULL, 0);
sock = spdk_sock_listen(p->host, port);
if (sock < 0) {
SPDK_ERRLOG("listen error %.64s:%d\n", p->host, port);
spdk_iscsi_portal_destroy(p);
count++;
continue;
}
p->sock = sock;
spdk_iscsi_portal_grp_add_portal(pg, p);
}
/* if listening is failed on all the ports,
* then do not register the portal group. */
if (count == num_portals) {
spdk_iscsi_portal_grp_destroy(pg);
goto error_out;
}
/* Add portal group to the end of the pg list */
spdk_iscsi_portal_grp_register(pg);
return 0;
error_out:
return -1;
}
int
spdk_iscsi_portal_grp_create_from_configfile(struct spdk_conf_section *sp)
{
struct spdk_iscsi_portal_grp *pg;
struct spdk_iscsi_portal *p;
const char *val;
char *label, *portal;
int portals = 0, i = 0, rc = 0;
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "add portal group (from config file) %d\n",
sp->num);
val = spdk_conf_section_get_val(sp, "Comment");
if (val != NULL) {
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Comment %s\n", val);
}
/* counts number of definitions */
for (i = 0; ; i++) {
/*
* label is no longer used, but we keep it in the config
* file definition so that we do not break existing config
* files.
*/
label = spdk_conf_section_get_nmval(sp, "Portal", i, 0);
portal = spdk_conf_section_get_nmval(sp, "Portal", i, 1);
if (label == NULL || portal == NULL)
break;
rc = spdk_iscsi_portal_create_from_configline(portal, &p, 1);
if (rc < 0) {
SPDK_ERRLOG("parse portal error (%s)\n", portal);
goto error_out;
}
}
portals = i;
if (portals > MAX_PORTAL) {
SPDK_ERRLOG("%d > MAX_PORTAL\n", portals);
goto error_out;
}
pg = spdk_iscsi_portal_grp_create(sp->num);
if (!pg) {
SPDK_ERRLOG("portal group malloc error (%s)\n", sp->name);
goto error_out;
}
for (i = 0; i < portals; i++) {
label = spdk_conf_section_get_nmval(sp, "Portal", i, 0);
portal = spdk_conf_section_get_nmval(sp, "Portal", i, 1);
if (label == NULL || portal == NULL) {
spdk_iscsi_portal_grp_destroy(pg);
SPDK_ERRLOG("portal error\n");
goto error_out;
}
rc = spdk_iscsi_portal_create_from_configline(portal, &p, 0);
if (rc < 0) {
spdk_iscsi_portal_grp_destroy(pg);
SPDK_ERRLOG("parse portal error (%s)\n", portal);
goto error_out;
}
SPDK_TRACELOG(SPDK_TRACE_DEBUG,
"RIndex=%d, Host=%s, Port=%s, Tag=%d\n",
i, p->host, p->port, sp->num);
spdk_iscsi_portal_grp_add_portal(pg, p);
}
/* Add portal group to the end of the pg list */
spdk_iscsi_portal_grp_register(pg);
return 0;
error_out:
return -1;
}
void
spdk_iscsi_portal_grp_add_portal(struct spdk_iscsi_portal_grp *pg,
struct spdk_iscsi_portal *p)
{
RTE_VERIFY(pg != NULL);
RTE_VERIFY(p != NULL);
p->group = pg;
TAILQ_INSERT_TAIL(&pg->head, p, tailq);
}
struct spdk_iscsi_portal_grp *
spdk_iscsi_portal_grp_find_by_tag(int tag)
{
struct spdk_iscsi_portal_grp *pg;
TAILQ_FOREACH(pg, &g_spdk_iscsi.pg_head, tailq) {
if (pg->tag == tag) {
return pg;
}
}
return NULL;
}
int
spdk_iscsi_portal_grp_array_create(void)
{
int rc = 0;
struct spdk_conf_section *sp;
TAILQ_INIT(&g_spdk_iscsi.pg_head);
sp = spdk_conf_first_section(NULL);
while (sp != NULL) {
if (spdk_conf_section_match_prefix(sp, "PortalGroup")) {
if (sp->num == 0) {
SPDK_ERRLOG("Group 0 is invalid\n");
return -1;
}
/* Build portal group from cfg section PortalGroup */
rc = spdk_iscsi_portal_grp_create_from_configfile(sp);
if (rc < 0) {
SPDK_ERRLOG("parse_portal_group() failed\n");
return -1;
}
}
sp = spdk_conf_next_section(sp);
}
return 0;
}
void
spdk_iscsi_portal_grp_array_destroy(void)
{
struct spdk_iscsi_portal_grp *pg, *tmp;
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_iscsi_portal_grp_array_destroy\n");
pthread_mutex_lock(&g_spdk_iscsi.mutex);
TAILQ_FOREACH_SAFE(pg, &g_spdk_iscsi.pg_head, tailq, tmp) {
pg->state = GROUP_DESTROY;
TAILQ_REMOVE(&g_spdk_iscsi.pg_head, pg, tailq);
spdk_iscsi_portal_grp_destroy(pg);
}
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
}
static int
spdk_iscsi_portal_grp_open(struct spdk_iscsi_portal_grp *pg)
{
struct spdk_iscsi_portal *p;
int port;
int sock;
TAILQ_FOREACH(p, &pg->head, tailq) {
if (p->sock < 0) {
SPDK_TRACELOG(SPDK_TRACE_NET, "open host %s, port %s, tag %d\n",
p->host, p->port, pg->tag);
port = (int)strtol(p->port, NULL, 0);
sock = spdk_sock_listen(p->host, port);
if (sock < 0) {
SPDK_ERRLOG("listen error %.64s:%d\n", p->host, port);
return -1;
}
p->sock = sock;
}
}
return 0;
}
int
spdk_iscsi_portal_grp_open_all(void)
{
struct spdk_iscsi_portal_grp *pg;
int rc;
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_iscsi_portal_grp_open_all\n");
pthread_mutex_lock(&g_spdk_iscsi.mutex);
TAILQ_FOREACH(pg, &g_spdk_iscsi.pg_head, tailq) {
rc = spdk_iscsi_portal_grp_open(pg);
if (rc < 0) {
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
return -1;
}
}
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
return 0;
}
static int
spdk_iscsi_portal_grp_close(struct spdk_iscsi_portal_grp *pg)
{
struct spdk_iscsi_portal *p;
TAILQ_FOREACH(p, &pg->head, tailq) {
if (p->sock >= 0) {
SPDK_TRACELOG(SPDK_TRACE_NET, "close host %s, port %s, tag %d\n",
p->host, p->port, pg->tag);
close(p->sock);
p->sock = -1;
}
}
return 0;
}
int
spdk_iscsi_portal_grp_close_all(void)
{
struct spdk_iscsi_portal_grp *pg;
int rc;
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "spdk_iscsi_portal_grp_close_all\n");
pthread_mutex_lock(&g_spdk_iscsi.mutex);
TAILQ_FOREACH(pg, &g_spdk_iscsi.pg_head, tailq) {
rc = spdk_iscsi_portal_grp_close(pg);
if (rc < 0) {
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
return -1;
}
}
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
return 0;
}
static inline void
spdk_iscsi_portal_grp_unregister(struct spdk_iscsi_portal_grp *pg)
{
struct spdk_iscsi_portal_grp *portal_group;
struct spdk_iscsi_portal_grp *portal_group_tmp;
RTE_VERIFY(pg != NULL);
RTE_VERIFY(!TAILQ_EMPTY(&pg->head));
pthread_mutex_lock(&g_spdk_iscsi.mutex);
TAILQ_FOREACH_SAFE(portal_group, &g_spdk_iscsi.pg_head, tailq, portal_group_tmp) {
if (portal_group->tag == pg->tag)
TAILQ_REMOVE(&g_spdk_iscsi.pg_head, portal_group, tailq);
}
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
}
int
spdk_iscsi_portal_grp_deletable(int tag)
{
int ret = 0;
struct spdk_iscsi_portal_grp *pg;
pthread_mutex_lock(&g_spdk_iscsi.mutex);
pg = spdk_iscsi_portal_grp_find_by_tag(tag);
if (pg == NULL) {
ret = -1;
goto out;
}
if (pg->state != GROUP_READY) {
ret = -1;
goto out;
}
if (pg->ref == 0) {
ret = 0;
goto out;
}
out:
if (ret == 0)
pg->state = GROUP_DESTROY;
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
return ret;
}
void
spdk_iscsi_portal_grp_release(struct spdk_iscsi_portal_grp *pg)
{
spdk_iscsi_portal_grp_close(pg);
spdk_iscsi_portal_grp_unregister(pg);
pthread_mutex_lock(&g_spdk_iscsi.mutex);
spdk_iscsi_portal_grp_destroy(pg);
pthread_mutex_unlock(&g_spdk_iscsi.mutex);
}
SPDK_LOG_REGISTER_TRACE_FLAG("net", SPDK_TRACE_NET)

87
lib/iscsi/portal_grp.h Normal file
View File

@ -0,0 +1,87 @@
/*-
* 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.
*/
#ifndef SPDK_PORTAL_GRP_H
#define SPDK_PORTAL_GRP_H
#include "iscsi/init_grp.h"
struct spdk_iscsi_portal {
struct spdk_iscsi_portal_grp *group;
char *host;
char *port;
int sock;
uint64_t cpumask;
TAILQ_ENTRY(spdk_iscsi_portal) tailq;
};
struct spdk_iscsi_portal_grp {
int ref;
int tag;
enum group_state state;
TAILQ_ENTRY(spdk_iscsi_portal_grp) tailq;
TAILQ_HEAD(, spdk_iscsi_portal) head;
};
/* SPDK iSCSI Portal Group management API */
struct spdk_iscsi_portal *spdk_iscsi_portal_create(char *host, char *port,
uint64_t cpumask);
void spdk_iscsi_portal_destroy(struct spdk_iscsi_portal *p);
struct spdk_iscsi_portal_grp *spdk_iscsi_portal_grp_create(int tag);
int spdk_iscsi_portal_grp_create_from_configfile(struct spdk_conf_section *sp);
int spdk_iscsi_portal_grp_create_from_portal_list(int tag,
struct spdk_iscsi_portal **portal_list,
int num_portals);
void spdk_iscsi_portal_grp_destroy(struct spdk_iscsi_portal_grp *pg);
void spdk_iscsi_portal_grp_destroy_by_tag(int tag);
void spdk_iscsi_portal_grp_release(struct spdk_iscsi_portal_grp *pg);
void spdk_iscsi_portal_grp_add_portal(struct spdk_iscsi_portal_grp *pg,
struct spdk_iscsi_portal *p);
void spdk_iscsi_portal_grp_delete_portal(struct spdk_iscsi_portal_grp *pg,
struct spdk_iscsi_portal *p);
int spdk_iscsi_portal_grp_array_create(void);
void spdk_iscsi_portal_grp_array_destroy(void);
struct spdk_iscsi_portal_grp *spdk_iscsi_portal_grp_find_by_tag(int tag);
int spdk_iscsi_portal_grp_open_all(void);
int spdk_iscsi_portal_grp_close_all(void);
int spdk_iscsi_portal_grp_deletable(int tag);
#endif // SPDK_PORTAL_GRP_H

67
lib/iscsi/task.c Normal file
View File

@ -0,0 +1,67 @@
/*-
* 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.
*/
#include <rte_config.h>
#include <rte_mempool.h>
#include "spdk/log.h"
#include "iscsi/task.h"
static void
spdk_iscsi_task_free(struct spdk_scsi_task *task)
{
spdk_iscsi_task_disassociate_pdu((struct spdk_iscsi_task *)task);
rte_mempool_put(g_spdk_iscsi.task_pool, (void *)task);
}
struct spdk_iscsi_task *
spdk_iscsi_task_get(uint32_t *owner_task_ctr, struct spdk_iscsi_task *parent)
{
struct spdk_iscsi_task *task;
int rc;
rc = rte_mempool_get(g_spdk_iscsi.task_pool, (void **)&task);
if ((rc < 0) || !task) {
SPDK_ERRLOG("Unable to get task\n");
rte_panic("no memory\n");
}
memset(task, 0, sizeof(*task));
spdk_scsi_task_construct((struct spdk_scsi_task *)task, owner_task_ctr,
(struct spdk_scsi_task *)parent);
task->scsi.free_fn = spdk_iscsi_task_free;
return task;
}

158
lib/iscsi/task.h Normal file
View File

@ -0,0 +1,158 @@
/*-
* 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.
*/
#ifndef SPDK_ISCSI_TASK_H
#define SPDK_ISCSI_TASK_H
#include "iscsi/iscsi.h"
#include "spdk/scsi.h"
struct spdk_iscsi_task {
struct spdk_scsi_task scsi;
struct spdk_iscsi_pdu *pdu;
uint32_t outstanding_r2t;
/*
* Tracks the current offset of large read io.
*/
uint32_t current_datain_offset;
/*
* next_expected_r2t_offset is used when we receive
* the DataOUT PDU.
*/
uint32_t next_expected_r2t_offset;
/*
* Tracks the length of the R2T that is in progress.
* Used to check that an R2T burst does not exceed
* MaxBurstLength.
*/
uint32_t current_r2t_length;
/*
* next_r2t_offset is used when we are sending the
* R2T packet to keep track of next offset of r2t.
*/
uint32_t next_r2t_offset;
uint32_t R2TSN;
uint32_t r2t_datasn; /* record next datasn for a r2tsn*/
uint32_t acked_r2tsn; /* next r2tsn to be acked */
uint32_t datain_datasn;
uint32_t acked_data_sn; /* next expected datain datasn */
uint32_t ttt;
TAILQ_ENTRY(spdk_iscsi_task) link;
};
static inline void
spdk_iscsi_task_put(struct spdk_iscsi_task *task)
{
spdk_put_task(&task->scsi);
}
static inline struct spdk_iscsi_pdu *
spdk_iscsi_task_get_pdu(struct spdk_iscsi_task *task)
{
return task->pdu;
}
static inline void
spdk_iscsi_task_set_pdu(struct spdk_iscsi_task *task, struct spdk_iscsi_pdu *pdu)
{
task->pdu = pdu;
}
static inline struct iscsi_bhs *
spdk_iscsi_task_get_bhs(struct spdk_iscsi_task *task)
{
return &spdk_iscsi_task_get_pdu(task)->bhs;
}
static inline void
spdk_iscsi_task_associate_pdu(struct spdk_iscsi_task *task, struct spdk_iscsi_pdu *pdu)
{
spdk_iscsi_task_set_pdu(task, pdu);
pdu->ref++;
}
static inline void
spdk_iscsi_task_disassociate_pdu(struct spdk_iscsi_task *task)
{
if (spdk_iscsi_task_get_pdu(task)) {
spdk_put_pdu(spdk_iscsi_task_get_pdu(task));
spdk_iscsi_task_set_pdu(task, NULL);
}
}
static inline int
spdk_iscsi_task_is_immediate(struct spdk_iscsi_task *task)
{
struct iscsi_bhs_scsi_req *scsi_req;
scsi_req = (struct iscsi_bhs_scsi_req *)spdk_iscsi_task_get_bhs(task);
return (scsi_req->immediate == 1);
}
static inline int
spdk_iscsi_task_is_read(struct spdk_iscsi_task *task)
{
struct iscsi_bhs_scsi_req *scsi_req;
scsi_req = (struct iscsi_bhs_scsi_req *)spdk_iscsi_task_get_bhs(task);
return (scsi_req->read == 1);
}
static inline uint32_t
spdk_iscsi_task_get_cmdsn(struct spdk_iscsi_task *task)
{
return spdk_iscsi_task_get_pdu(task)->cmd_sn;
}
struct spdk_iscsi_task *spdk_iscsi_task_get(uint32_t *owner_task_ctr,
struct spdk_iscsi_task *parent);
static inline struct spdk_iscsi_task *
spdk_iscsi_task_get_primary(struct spdk_iscsi_task *task)
{
struct spdk_scsi_task *scsi_task;
struct spdk_scsi_task *scsi_primary_task;
scsi_task = &task->scsi;
scsi_primary_task = spdk_scsi_task_get_primary(scsi_task);
return (struct spdk_iscsi_task *)scsi_primary_task;
}
#endif /* SPDK_ISCSI_TASK_H */

1142
lib/iscsi/tgt_node.c Normal file

File diff suppressed because it is too large Load Diff

111
lib/iscsi/tgt_node.h Normal file
View File

@ -0,0 +1,111 @@
/*-
* 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.
*/
#ifndef SPDK_ISCSI_TGT_NODE_H_
#define SPDK_ISCSI_TGT_NODE_H_
#include <pthread.h>
#include <libaio.h>
#include <time.h>
#include "spdk/scsi.h"
struct spdk_iscsi_conn;
#define SPDK_ISCSI_MAX_QUEUE_DEPTH 64
#define MAX_TARGET_MAP 256
#define SPDK_TN_TAG_MAX 0x0000ffff
struct spdk_iscsi_tgt_node_map {
struct spdk_iscsi_portal_grp *pg;
struct spdk_iscsi_init_grp *ig;
};
struct spdk_iscsi_tgt_node {
int num;
char *name;
char *alias;
pthread_mutex_t mutex;
int auth_chap_disabled;
int auth_chap_required;
int auth_chap_mutual;
int auth_group;
int header_digest;
int data_digest;
int queue_depth;
struct spdk_scsi_dev *dev;
int maxmap;
struct spdk_iscsi_tgt_node_map map[MAX_TARGET_MAP];
};
int spdk_iscsi_init_tgt_nodes(void);
int spdk_iscsi_shutdown_tgt_nodes(void);
int spdk_iscsi_shutdown_tgt_node_by_name(const char *target_name);
int spdk_iscsi_send_tgts(struct spdk_iscsi_conn *conn, const char *iiqn,
const char *iaddr, const char *tiqn, uint8_t *data, int alloc_len,
int data_len);
struct spdk_iscsi_init_grp *
spdk_iscsi_find_init_grp(int tag);
/* This typedef exists to work around an astyle 2.05 bug.
* Remove it when astyle is fixed.
*/
typedef struct spdk_iscsi_tgt_node _spdk_iscsi_tgt_node;
_spdk_iscsi_tgt_node *
spdk_iscsi_tgt_node_construct(int target_index,
const char *name, const char *alias,
int *pg_tag_list, int *ig_tag_list, uint16_t num_maps,
char *lun_name_list[], int *lun_id_list, int num_luns,
int queue_depth,
int no_auth_chap, int auth_chap, int auth_chap_mutual, int auth_group,
int header_digest, int data_digest);
int spdk_iscsi_tgt_node_access(struct spdk_iscsi_conn *conn,
struct spdk_iscsi_tgt_node *target, const char *iqn,
const char *addr);
struct spdk_iscsi_tgt_node *spdk_iscsi_find_tgt_node(const char *target_name);
int spdk_iscsi_tgt_node_reset(struct spdk_iscsi_tgt_node *target,
uint64_t lun);
int spdk_iscsi_tgt_node_cleanup_luns(struct spdk_iscsi_conn *conn,
struct spdk_iscsi_tgt_node *target);
void spdk_iscsi_tgt_node_delete_map(struct spdk_iscsi_portal_grp *portal_group,
struct spdk_iscsi_init_grp *initiator_group);
#endif /* SPDK_ISCSI_TGT_NODE_H_ */