iscsi: Add an iscsi library.
Change-Id: I28f3f4723a66f845eb478a6873d7aedb8f5409b8 Signed-off-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
d3090c8455
commit
d29384bf97
@ -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.
|
||||
|
||||
|
@ -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
44
lib/iscsi/Makefile
Normal 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
114
lib/iscsi/acceptor.c
Normal 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
41
lib/iscsi/acceptor.h
Normal 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
1382
lib/iscsi/conn.c
Normal file
File diff suppressed because it is too large
Load Diff
182
lib/iscsi/conn.h
Normal file
182
lib/iscsi/conn.h
Normal 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
136
lib/iscsi/crc32c.c
Normal 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
56
lib/iscsi/crc32c.h
Normal 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
393
lib/iscsi/init_grp.c
Normal 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
76
lib/iscsi/init_grp.h
Normal 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
4693
lib/iscsi/iscsi.c
Normal file
File diff suppressed because it is too large
Load Diff
907
lib/iscsi/iscsi.h
Normal file
907
lib/iscsi/iscsi.h
Normal 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
929
lib/iscsi/iscsi_rpc.c
Normal 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
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
73
lib/iscsi/md5.c
Normal 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
52
lib/iscsi/md5.h
Normal 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
1185
lib/iscsi/param.c
Normal file
File diff suppressed because it is too large
Load Diff
84
lib/iscsi/param.h
Normal file
84
lib/iscsi/param.h
Normal 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
642
lib/iscsi/portal_grp.c
Normal 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
87
lib/iscsi/portal_grp.h
Normal 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
67
lib/iscsi/task.c
Normal 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
158
lib/iscsi/task.h
Normal 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
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
111
lib/iscsi/tgt_node.h
Normal 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_ */
|
Loading…
Reference in New Issue
Block a user