summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/iscsi_if.h190
-rw-r--r--usr/Makefile2
-rw-r--r--usr/flashnode.c609
-rw-r--r--usr/flashnode.h127
-rw-r--r--usr/idbm.c179
-rw-r--r--usr/idbm.h7
-rw-r--r--usr/idbm_fields.h63
-rw-r--r--usr/iscsi_ipc.h13
-rw-r--r--usr/iscsi_sysfs.c234
-rw-r--r--usr/iscsi_sysfs.h17
-rw-r--r--usr/iscsiadm.c429
-rw-r--r--usr/netlink.c171
12 files changed, 2031 insertions, 10 deletions
diff --git a/include/iscsi_if.h b/include/iscsi_if.h
index dad9fd8..20f2bc2 100644
--- a/include/iscsi_if.h
+++ b/include/iscsi_if.h
@@ -68,8 +68,14 @@ enum iscsi_uevent_e {
ISCSI_UEVENT_PING = UEVENT_BASE + 22,
ISCSI_UEVENT_GET_CHAP = UEVENT_BASE + 23,
ISCSI_UEVENT_DELETE_CHAP = UEVENT_BASE + 24,
+ ISCSI_UEVENT_SET_FLASHNODE_PARAMS = UEVENT_BASE + 25,
+ ISCSI_UEVENT_NEW_FLASHNODE = UEVENT_BASE + 26,
+ ISCSI_UEVENT_DEL_FLASHNODE = UEVENT_BASE + 27,
+ ISCSI_UEVENT_LOGIN_FLASHNODE = UEVENT_BASE + 28,
+ ISCSI_UEVENT_LOGOUT_FLASHNODE = UEVENT_BASE + 29,
+ ISCSI_UEVENT_LOGOUT_FLASHNODE_SID = UEVENT_BASE + 30,
- ISCSI_UEVENT_MAX = ISCSI_UEVENT_DELETE_CHAP,
+ ISCSI_UEVENT_MAX = ISCSI_UEVENT_LOGOUT_FLASHNODE_SID,
/* up events */
ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1,
@@ -219,6 +225,31 @@ struct iscsi_uevent {
uint32_t host_no;
uint16_t chap_tbl_idx;
} delete_chap;
+ struct msg_set_flashnode_param {
+ uint32_t host_no;
+ uint32_t flashnode_idx;
+ uint32_t count;
+ } set_flashnode;
+ struct msg_new_flashnode {
+ uint32_t host_no;
+ uint32_t len;
+ } new_flashnode;
+ struct msg_del_flashnode {
+ uint32_t host_no;
+ uint32_t flashnode_idx;
+ } del_flashnode;
+ struct msg_login_flashnode {
+ uint32_t host_no;
+ uint32_t flashnode_idx;
+ } login_flashnode;
+ struct msg_logout_flashnode {
+ uint32_t host_no;
+ uint32_t flashnode_idx;
+ } logout_flashnode;
+ struct msg_logout_flashnode_sid {
+ uint32_t host_no;
+ uint32_t sid;
+ } logout_flashnode_sid;
} u;
union {
/* messages k -> u */
@@ -276,6 +307,9 @@ struct iscsi_uevent {
with each ping request */
uint32_t data_size;
} ping_comp;
+ struct msg_new_flashnode_ret {
+ uint32_t flashnode_idx;
+ } new_flashnode_ret;
} r;
} __attribute__ ((aligned (sizeof(uint64_t))));
@@ -283,6 +317,7 @@ enum iscsi_param_type {
ISCSI_PARAM, /* iscsi_param (session, conn, target, LU) */
ISCSI_HOST_PARAM, /* iscsi_host_param */
ISCSI_NET_PARAM, /* iscsi_net_param */
+ ISCSI_FLASHNODE_PARAM, /* iscsi_flashnode_param */
};
struct iscsi_iface_param_info {
@@ -502,6 +537,159 @@ enum iscsi_param {
#define ISCSI_TGT_RESET_TMO (1ULL << ISCSI_PARAM_TGT_RESET_TMO)
#define ISCSI_TARGET_ALIAS (1ULL << ISCSI_PARAM_TARGET_ALIAS)
+/* iSCSI Flash Target params */
+enum iscsi_flashnode_param {
+ ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6,
+ ISCSI_FLASHNODE_PORTAL_TYPE,
+ ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE,
+ ISCSI_FLASHNODE_DISCOVERY_SESS,
+ ISCSI_FLASHNODE_ENTRY_EN,
+ ISCSI_FLASHNODE_HDR_DGST_EN,
+ ISCSI_FLASHNODE_DATA_DGST_EN,
+ ISCSI_FLASHNODE_IMM_DATA_EN,
+ ISCSI_FLASHNODE_INITIAL_R2T_EN,
+ ISCSI_FLASHNODE_DATASEQ_INORDER,
+ ISCSI_FLASHNODE_PDU_INORDER,
+ ISCSI_FLASHNODE_CHAP_AUTH_EN,
+ ISCSI_FLASHNODE_SNACK_REQ_EN,
+ ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN,
+ ISCSI_FLASHNODE_BIDI_CHAP_EN,
+ /* make authentication for discovery sessions optional */
+ ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL,
+ ISCSI_FLASHNODE_ERL,
+ ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT,
+ ISCSI_FLASHNODE_TCP_NAGLE_DISABLE,
+ ISCSI_FLASHNODE_TCP_WSF_DISABLE,
+ ISCSI_FLASHNODE_TCP_TIMER_SCALE,
+ ISCSI_FLASHNODE_TCP_TIMESTAMP_EN,
+ ISCSI_FLASHNODE_IP_FRAG_DISABLE,
+ ISCSI_FLASHNODE_MAX_RECV_DLENGTH,
+ ISCSI_FLASHNODE_MAX_XMIT_DLENGTH,
+ ISCSI_FLASHNODE_FIRST_BURST,
+ ISCSI_FLASHNODE_DEF_TIME2WAIT,
+ ISCSI_FLASHNODE_DEF_TIME2RETAIN,
+ ISCSI_FLASHNODE_MAX_R2T,
+ ISCSI_FLASHNODE_KEEPALIVE_TMO,
+ ISCSI_FLASHNODE_ISID,
+ ISCSI_FLASHNODE_TSID,
+ ISCSI_FLASHNODE_PORT,
+ ISCSI_FLASHNODE_MAX_BURST,
+ ISCSI_FLASHNODE_DEF_TASKMGMT_TMO,
+ ISCSI_FLASHNODE_IPADDR,
+ ISCSI_FLASHNODE_ALIAS,
+ ISCSI_FLASHNODE_REDIRECT_IPADDR,
+ ISCSI_FLASHNODE_MAX_SEGMENT_SIZE,
+ ISCSI_FLASHNODE_LOCAL_PORT,
+ ISCSI_FLASHNODE_IPV4_TOS,
+ ISCSI_FLASHNODE_IPV6_TC,
+ ISCSI_FLASHNODE_IPV6_FLOW_LABEL,
+ ISCSI_FLASHNODE_NAME,
+ ISCSI_FLASHNODE_TPGT,
+ ISCSI_FLASHNODE_LINK_LOCAL_IPV6,
+ ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX,
+ ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE,
+ ISCSI_FLASHNODE_TCP_XMIT_WSF,
+ ISCSI_FLASHNODE_TCP_RECV_WSF,
+ ISCSI_FLASHNODE_CHAP_IN_IDX,
+ ISCSI_FLASHNODE_CHAP_OUT_IDX,
+ ISCSI_FLASHNODE_USERNAME,
+ ISCSI_FLASHNODE_USERNAME_IN,
+ ISCSI_FLASHNODE_PASSWORD,
+ ISCSI_FLASHNODE_PASSWORD_IN,
+ ISCSI_FLASHNODE_STATSN,
+ ISCSI_FLASHNODE_EXP_STATSN,
+ ISCSI_FLASHNODE_IS_BOOT_TGT,
+
+ ISCSI_FLASHNODE_MAX,
+};
+
+#define ISCSI_FNODE_IS_FW_ASSIGNED_IPV6 \
+ (1ULL << ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6)
+#define ISCSI_FNODE_PORTAL_TYPE (1ULL << ISCSI_FLASHNODE_PORTAL_TYPE)
+#define ISCSI_FNODE_AUTO_SND_TGT_DISABLE \
+ (1ULL << ISCSI_FLASHNODE_OPT_AUTO_SND_TGT_DISABLE)
+#define ISCSI_FNODE_DISCOVERY_SESS \
+ (1ULL << ISCSI_FLASHNODE_OPT_DISCOVERY_SESS)
+#define ISCSI_FNODE_ENTRY_EN (1ULL << ISCSI_FLASHNODE_ENTRY_EN)
+#define ISCSI_FNODE_HDR_DGST_EN (1ULL << ISCSI_FLASHNODE_HDR_DGST_EN)
+#define ISCSI_FNODE_DATA_DGST_EN (1ULL << ISCSI_FLASHNODE_DATA_DGST_EN)
+#define ISCSI_FNODE_IMM_DATA_EN (1ULL << ISCSI_FLASHNODE_IMM_DATA_EN)
+#define ISCSI_FNODE_INITIAL_R2T_EN (1ULL << ISCSI_FLASHNODE_INITIAL_R2T_EN)
+#define ISCSI_FNODE_DATASEQ_INORDER \
+ (1ULL << ISCSI_FLASHNODE_DATASEQ_INORDER)
+#define ISCSI_FNODE_PDU_INORDER (1ULL << ISCSI_FLASHNODE_PDU_INORDER)
+#define ISCSI_FNODE_CHAP_AUTH_EN (1ULL << ISCSI_FLASHNODE_CHAP_AUTH_EN)
+#define ISCSI_FNODE_SNACK_REQ_EN (1ULL << ISCSI_FLASHNODE_SNACK_REQ_EN)
+#define ISCSI_FNODE_DISCOVERY_LOGOUT_EN \
+ (1ULL << ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN)
+#define ISCSI_FNODE_BIDI_CHAP_EN (1ULL << ISCSI_FLASHNODE_BIDI_CHAP_EN)
+#define ISCSI_FNODE_DISCOVERY_AUTH_OPTIONAL \
+ (1ULL << ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL)
+#define ISCSI_FNODE_ERL (1ULL << ISCSI_FLASHNODE_ERL)
+#define ISCSI_FNODE_TCP_TIMESTAMP_STAT \
+ (1ULL << ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT)
+#define ISCSI_FNODE_TCP_NAGLE_DISABLE \
+ (1ULL << ISCSI_FLASHNODE_TCP_NAGLE_DISABLE)
+#define ISCSI_FNODE_TCP_WSF_DISABLE \
+ (1ULL << ISCSI_FLASHNODE_TCP_WSF_DISABLE)
+#define ISCSI_FNODE_TCP_TIMER_SCALE \
+ (1ULL << ISCSI_FLASHNODE_TCP_TIMER_SCALE)
+#define ISCSI_FNODE_TCP_TIMESTAMP_ENABLE \
+ (1ULL << ISCSI_FLASHNODE_TCP_TIMESTAMP_ENABLE)
+#define ISCSI_FNODE_IP_FRAG_DISABLE \
+ (1ULL << ISCSI_FLASHNODE_IP_FRAG_DISABLE)
+#define ISCSI_FNODE_MAX_RECV_DLENGTH \
+ (1ULL << ISCSI_FLASHNODE_MAX_RECV_DLENGTH)
+#define ISCSI_FNODE_MAX_XMIT_DLENGTH \
+ (1ULL << ISCSI_FLASHNODE_MAX_XMIT_DLENGTH)
+#define ISCSI_FNODE_FIRST_BURST (1ULL << ISCSI_FLASHNODE_FIRST_BURST)
+#define ISCSI_FNODE_DEF_TIME2WAIT (1ULL << ISCSI_FLASHNODE_DEF_TIME2WAIT)
+#define ISCSI_FNODE_DEF_TIME2RETAIN \
+ (1ULL << ISCSI_FLASHNODE_DEF_TIME2RETAIN)
+#define ISCSI_FNODE_MAX_R2T (1ULL << ISCSI_FLASHNODE_MAX_R2T)
+#define ISCSI_FNODE_KEEPALIVE_TMO (1ULL << ISCSI_FLASHNODE_KEEPALIVE_TMO)
+#define ISCSI_FNODE_ISID (1ULL << ISCSI_FLASHNODE_ISID)
+#define ISCSI_FNODE_TSID (1ULL << ISCSI_FLASHNODE_TSID)
+#define ISCSI_FNODE_PORT (1ULL << ISCSI_FLASHNODE_PORT)
+#define ISCSI_FNODE_MAX_BURST (1ULL << ISCSI_FLASHNODE_MAX_BURST)
+#define ISCSI_FNODE_DEF_TMF_TMO (1ULL << ISCSI_FLASHNODE_DEF_TMF_TMO)
+#define ISCSI_FNODE_IPADDR (1ULL << ISCSI_FLASHNODE_IPADDR)
+#define ISCSI_FNODE_ALIAS (1ULL << ISCSI_FLASHNODE_ALIAS)
+#define ISCSI_FNODE_REDIRECT_IPADDR \
+ (1ULL << ISCSI_FLASHNODE_REDIRECT_IPADDR)
+#define ISCSI_FNODE_MAX_SEGMENT_SIZE \
+ (1ULL << ISCSI_FLASHNODE_MAX_SEGMENT_SIZE)
+#define ISCSI_FNODE_LOCAL_PORT (1ULL << ISCSI_FLASHNODE_LOCAL_PORT)
+#define ISCSI_FNODE_IPV4_TOS (1ULL << ISCSI_FLASHNODE_IPV4_TOS)
+#define ISCSI_FNODE_IPV6_TC (1ULL << ISCSI_FLASHNODE_IPV6_TC)
+#define ISCSI_FNODE_IPV6_FLOW_LABEL \
+ (1ULL << ISCSI_FLASHNODE_IPV6_FLOW_LABEL)
+#define ISCSI_FNODE_NAME (1ULL << ISCSI_FLASHNODE_NAME)
+#define ISCSI_FNODE_TPGT (1ULL << ISCSI_FLASHNODE_TPGT)
+#define ISCSI_FNODE_LINK_LOCAL_IPV6 \
+ (1ULL << ISCSI_FLASHNODE_LINK_LOCAL_IPV6)
+#define ISCSI_FNODE_DISCOVERY_PARENT_IDX \
+ (1ULL << ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX)
+#define ISCSI_FNODE_DISCOVERY_PARENT_TYPE \
+ (1ULL << ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE)
+#define ISCSI_FNODE_TCP_XMIT_WSF (1ULL << ISCSI_FLASHNODE_TCP_XMIT_WSF)
+#define ISCSI_FNODE_TCP_RECV_WSF (1ULL << ISCSI_FLASHNODE_TCP_RECV_WSF)
+#define ISCSI_FNODE_CHAP_IN_IDX (1ULL << ISCSI_FLASHNODE_CHAP_IN_IDX)
+#define ISCSI_FNODE_CHAP_OUT_IDX (1ULL << ISCSI_FLASHNODE_CHAP_OUT_IDX)
+#define ISCSI_FNODE_USERNAME (1ULL << ISCSI_FLASHNODE_USERNAME)
+#define ISCSI_FNODE_USERNAME_IN (1ULL << ISCSI_FLASHNODE_USERNAME_IN)
+#define ISCSI_FNODE_PASSWORD (1ULL << ISCSI_FLASHNODE_PASSWORD)
+#define ISCSI_FNODE_PASSWORD_IN (1ULL << ISCSI_FLASHNODE_PASSWORD_IN)
+#define ISCSI_FNODE_STATSN (1ULL << ISCSI_FLASHNODE_STATSN)
+#define ISCSI_FNODE_EXP_STATSN (1ULL << ISCSI_FLASHNODE_EXP_STATSN)
+#define ISCSI_FNODE_IS_BOOT_TGT (1ULL << ISCSI_FLASHNODE_IS_BOOT_TGT)
+
+struct iscsi_flashnode_param_info {
+ uint32_t len; /* Actual length of the param */
+ uint16_t param; /* iscsi param value */
+ uint8_t value[0]; /* length sized value follows */
+} __attribute__((__packed__));
+
/* iSCSI HBA params */
enum iscsi_host_param {
ISCSI_HOST_PARAM_HWADDRESS,
diff --git a/usr/Makefile b/usr/Makefile
index 33b517c..3d8ee22 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -40,7 +40,7 @@ SYSDEPS_SRCS = $(wildcard ../utils/sysdeps/*.o)
ISCSI_LIB_SRCS = iscsi_util.o io.o auth.o iscsi_timer.o login.o log.o md5.o \
sha1.o iface.o idbm.o sysfs.o host.o session_info.o iscsi_sysfs.o \
iscsi_net_util.o iscsid_req.o transport.o iser.o cxgbi.o be2iscsi.o \
- initiator_common.o iscsi_err.o uip_mgmt_ipc.o \
+ initiator_common.o iscsi_err.o flashnode.o uip_mgmt_ipc.o \
$(IPC_OBJ) $(SYSDEPS_SRCS)
# core initiator files
INITIATOR_SRCS = initiator.o scsi.o actor.o event_poll.o mgmt_ipc.o kern_err_table.o
diff --git a/usr/flashnode.c b/usr/flashnode.c
new file mode 100644
index 0000000..da1392a
--- /dev/null
+++ b/usr/flashnode.c
@@ -0,0 +1,609 @@
+/*
+ * iSCSI flashnode helpers
+ *
+ * Copyright (C) 2013 QLogic Corporation.
+ * Maintained by open-iscsi@googlegroups.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * See the file COPYING included with this distribution for more details.
+ */
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <arpa/inet.h>
+
+#include "log.h"
+#include "idbm.h"
+#include "iscsi_util.h"
+#include "transport.h"
+#include "iscsi_sysfs.h"
+#include "list.h"
+#include "sysdeps.h"
+#include "idbm_fields.h"
+#include "iscsi_err.h"
+#include "iscsi_ipc.h"
+#include "iscsi_netlink.h"
+#include "flashnode.h"
+#include "iscsi_settings.h"
+
+char key[NAME_MAXVAL];
+
+char *to_key(const char *fmt)
+{
+ int i = 0;
+ memset(key, 0, sizeof(key));
+ sprintf(key, fmt, i);
+ return key;
+}
+
+int flashnode_info_print_flat(void *data, struct flashnode_rec *fnode,
+ uint32_t host_no, uint32_t flashnode_idx)
+{
+ printf("%s: [%d] ", fnode->transport_name, flashnode_idx);
+ if (!strlen((char *)fnode->conn[0].ipaddress))
+ printf("%s:", UNKNOWN_VALUE);
+ else if (strchr((char *)fnode->conn[0].ipaddress, '.'))
+ printf("%s:", fnode->conn[0].ipaddress);
+ else
+ printf("[%s]:", fnode->conn[0].ipaddress);
+
+ if (!fnode->conn[0].port)
+ printf("%s,", UNKNOWN_VALUE);
+ else
+ printf("%u,", fnode->conn[0].port);
+
+ printf("%u ", fnode->sess.tpgt);
+
+ if (!strlen(fnode->sess.targetname))
+ printf("%s\n", UNKNOWN_VALUE);
+ else
+ printf("%s\n", fnode->sess.targetname);
+
+ return 0;
+}
+
+static int flashnode_fill_isid(struct flashnode_rec *fnode, struct iovec *iov)
+{
+ struct iscsi_flashnode_param_info *fnode_param;
+ struct nlattr *attr;
+ int len;
+ uint8_t isid[6];
+
+ len = sizeof(struct iscsi_flashnode_param_info) + 6;
+ iov->iov_base = iscsi_nla_alloc(ISCSI_FLASHNODE_ISID, len);
+ if (!iov->iov_base)
+ return 1;
+
+ attr = iov->iov_base;
+ iov->iov_len = NLA_ALIGN(attr->nla_len);
+
+ fnode_param = (struct iscsi_flashnode_param_info *)ISCSI_NLA_DATA(attr);
+ fnode_param->param = ISCSI_FLASHNODE_ISID;
+ fnode_param->len = 6;
+
+ sscanf(fnode->sess.isid, "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
+ &isid[0], &isid[1], &isid[2], &isid[3], &isid[4], &isid[5]);
+
+ memcpy(fnode_param->value, isid, fnode_param->len);
+ return 0;
+}
+
+static int flashnode_fill_ipv4_addr(struct flashnode_rec *fnode,
+ struct iovec *iov, int param_type)
+{
+ struct iscsi_flashnode_param_info *fnode_param;
+ struct nlattr *attr;
+ int len;
+ int rc;
+
+ len = sizeof(struct iscsi_flashnode_param_info) + 4;
+ iov->iov_base = iscsi_nla_alloc(param_type, len);
+ if (!iov->iov_base)
+ return 1;
+
+ attr = iov->iov_base;
+ iov->iov_len = NLA_ALIGN(attr->nla_len);
+
+ fnode_param = (struct iscsi_flashnode_param_info *)ISCSI_NLA_DATA(attr);
+ fnode_param->param = param_type;
+ fnode_param->len = 4;
+
+ switch (param_type) {
+ case ISCSI_FLASHNODE_IPADDR:
+ rc = inet_pton(AF_INET, (char *)fnode->conn[0].ipaddress,
+ fnode_param->value);
+ break;
+ case ISCSI_FLASHNODE_REDIRECT_IPADDR:
+ rc = inet_pton(AF_INET, (char *)fnode->conn[0].redirect_ipaddr,
+ fnode_param->value);
+ break;
+ default:
+ goto free;
+ }
+
+ if (rc <= 0)
+ goto free;
+
+ return 0;
+
+free:
+ free(iov->iov_base);
+ iov->iov_base = NULL;
+ iov->iov_len = 0;
+ return 1;
+}
+
+static int flashnode_fill_ipv6_addr(struct flashnode_rec *fnode,
+ struct iovec *iov, int param_type)
+{
+ struct iscsi_flashnode_param_info *fnode_param;
+ struct nlattr *attr;
+ int len;
+ int rc;
+
+ len = sizeof(struct iscsi_flashnode_param_info) + 16;
+ iov->iov_base = iscsi_nla_alloc(param_type, len);
+ if (!iov->iov_base)
+ return 1;
+
+ attr = iov->iov_base;
+ iov->iov_len = NLA_ALIGN(attr->nla_len);
+
+ fnode_param = (struct iscsi_flashnode_param_info *)ISCSI_NLA_DATA(attr);
+ fnode_param->param = param_type;
+ fnode_param->len = 16;
+
+ switch (param_type) {
+ case ISCSI_FLASHNODE_IPADDR:
+ rc = inet_pton(AF_INET6, (char *)fnode->conn[0].ipaddress,
+ fnode_param->value);
+ break;
+ case ISCSI_FLASHNODE_REDIRECT_IPADDR:
+ rc = inet_pton(AF_INET6, (char *)fnode->conn[0].redirect_ipaddr,
+ fnode_param->value);
+ break;
+ case ISCSI_FLASHNODE_LINK_LOCAL_IPV6:
+ rc = inet_pton(AF_INET6, (char *)fnode->conn[0].link_local_ipv6,
+ fnode_param->value);
+ break;
+ default:
+ goto free;
+ }
+
+ if (rc <= 0)
+ goto free;
+
+ return 0;
+
+free:
+ free(iov->iov_base);
+ iov->iov_base = NULL;
+ iov->iov_len = 0;
+ return 1;
+}
+
+static int flashnode_fill_ipaddr(struct flashnode_rec *fnode, struct iovec *iov,
+ int param_type)
+{
+ int rc = 0;
+
+ if (!strncmp(fnode->sess.portal_type, "ipv4", 4))
+ rc = flashnode_fill_ipv4_addr(fnode, iov, param_type);
+ else
+ rc = flashnode_fill_ipv6_addr(fnode, iov, param_type);
+
+ return rc;
+}
+
+static int flashnode_fill_uint8(struct flashnode_rec *fnode, struct iovec *iov,
+ int param_type, uint8_t val)
+{
+ struct iscsi_flashnode_param_info *fnode_param;
+ struct nlattr *attr;
+ int len;
+
+ len = sizeof(struct iscsi_flashnode_param_info) + 1;
+ iov->iov_base = iscsi_nla_alloc(param_type, len);
+ if (!iov->iov_base)
+ return 1;
+
+ attr = iov->iov_base;
+ iov->iov_len = NLA_ALIGN(attr->nla_len);
+
+ fnode_param = (struct iscsi_flashnode_param_info *)ISCSI_NLA_DATA(attr);
+ fnode_param->param = param_type;
+ fnode_param->len = 1;
+ fnode_param->value[0] = val;
+ return 0;
+}
+
+static int flashnode_fill_uint16(struct flashnode_rec *fnode, struct iovec *iov,
+ int param_type, uint16_t val)
+{
+ struct iscsi_flashnode_param_info *fnode_param;
+ struct nlattr *attr;
+ int len;
+
+ len = sizeof(struct iscsi_flashnode_param_info) + 2;
+ iov->iov_base = iscsi_nla_alloc(param_type, len);
+ if (!iov->iov_base)
+ return 1;
+
+ attr = iov->iov_base;
+ iov->iov_len = NLA_ALIGN(attr->nla_len);
+
+ fnode_param = (struct iscsi_flashnode_param_info *)ISCSI_NLA_DATA(attr);
+ fnode_param->param = param_type;
+ fnode_param->len = 2;
+ memcpy(fnode_param->value, &val, fnode_param->len);
+ return 0;
+}
+
+static int flashnode_fill_uint32(struct flashnode_rec *fnode, struct iovec *iov,
+ int param_type, uint32_t val)
+{
+ struct iscsi_flashnode_param_info *fnode_param;
+ struct nlattr *attr;
+ int len;
+
+ len = sizeof(struct iscsi_flashnode_param_info) + 4;
+ iov->iov_base = iscsi_nla_alloc(param_type, len);
+ if (!iov->iov_base)
+ return 1;
+
+ attr = iov->iov_base;
+ iov->iov_len = NLA_ALIGN(attr->nla_len);
+
+ fnode_param = (struct iscsi_flashnode_param_info *)ISCSI_NLA_DATA(attr);
+ fnode_param->param = param_type;
+ fnode_param->len = 4;
+ memcpy(fnode_param->value, &val, fnode_param->len);
+ return 0;
+}
+
+static int flashnode_fill_str(struct flashnode_rec *fnode, struct iovec *iov,
+ int param_type, char *buf, int buflen)
+{
+ struct iscsi_flashnode_param_info *fnode_param;
+ struct nlattr *attr;
+ int len;
+
+ len = sizeof(struct iscsi_flashnode_param_info) + buflen;
+ iov->iov_base = iscsi_nla_alloc(param_type, len);
+ if (!iov->iov_base)
+ return 1;
+
+ attr = iov->iov_base;
+ iov->iov_len = NLA_ALIGN(attr->nla_len);
+
+ fnode_param = (struct iscsi_flashnode_param_info *)ISCSI_NLA_DATA(attr);
+ fnode_param->param = param_type;
+ fnode_param->len = buflen;
+ memcpy(fnode_param->value, buf, fnode_param->len);
+ return 0;
+}
+
+int flashnode_build_config(struct list_head *params,
+ struct flashnode_rec *fnode, struct iovec *iovs)
+{
+ struct user_param *param;
+ struct iovec *iov = NULL;
+ int count = 0;
+ int port = 3260;
+
+ /* start at 2, because 0 is for nlmsghdr and 1 for event */
+ iov = iovs + 2;
+
+ list_for_each_entry(param, params, list) {
+ if (!strcmp(param->name, FLASHNODE_SESS_AUTO_SND_TGT_DISABLE)) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE,
+ fnode->sess.auto_snd_tgt_disable))
+ count++;
+ } else if (!strcmp(param->name,
+ FLASHNODE_SESS_DISCOVERY_SESS)) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_DISCOVERY_SESS,
+ fnode->sess.discovery_session))
+ count++;
+ } else if (!strcmp(param->name, FLASHNODE_SESS_ENTRY_EN)) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_ENTRY_EN,
+ fnode->sess.entry_enable))
+ count++;
+ } else if (!strcmp(param->name, FLASHNODE_SESS_IMM_DATA_EN)) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_IMM_DATA_EN,
+ fnode->sess.immediate_data))
+ count++;
+ } else if (!strcmp(param->name,
+ FLASHNODE_SESS_INITIAL_R2T_EN)) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_INITIAL_R2T_EN,
+ fnode->sess.initial_r2t))
+ count++;
+ } else if (!strcmp(param->name,
+ FLASHNODE_SESS_DATASEQ_INORDER)) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_DATASEQ_INORDER,
+ fnode->sess.data_seq_in_order))
+ count++;
+ } else if (!strcmp(param->name, FLASHNODE_SESS_PDU_INORDER)) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_PDU_INORDER,
+ fnode->sess.data_pdu_in_order))
+ count++;
+ } else if (!strcmp(param->name, FLASHNODE_SESS_CHAP_AUTH_EN)) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_CHAP_AUTH_EN,
+ fnode->sess.chap_auth_en))
+ count++;
+ } else if (!strcmp(param->name,
+ FLASHNODE_SESS_DISCOVERY_LOGOUT_EN)) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN,
+ fnode->sess.discovery_logout_en))
+ count++;
+ } else if (!strcmp(param->name, FLASHNODE_SESS_BIDI_CHAP_EN )) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_BIDI_CHAP_EN,
+ fnode->sess.bidi_chap_en))
+ count++;
+ } else if (!strcmp(param->name,
+ FLASHNODE_SESS_DISCOVERY_AUTH_OPTIONAL)) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL,
+ fnode->sess.discovery_auth_optional))
+ count++;
+ } else if (!strcmp(param->name, FLASHNODE_SESS_ERL)) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_ERL,
+ fnode->sess.erl))
+ count++;
+ } else if (!strcmp(param->name,
+ FLASHNODE_SESS_DEF_TIME2WAIT)) {
+ if (!flashnode_fill_uint16(fnode, &iov[count],
+ ISCSI_FLASHNODE_DEF_TIME2WAIT,
+ fnode->sess.def_time2wait))
+ count++;
+ } else if (!strcmp(param->name,
+ FLASHNODE_SESS_DEF_TIME2RETAIN)) {
+ if (!flashnode_fill_uint16(fnode, &iov[count],
+ ISCSI_FLASHNODE_DEF_TIME2RETAIN,
+ fnode->sess.def_time2retain))
+ count++;
+ } else if (!strcmp(param->name, FLASHNODE_SESS_MAX_R2T)) {
+ if (!flashnode_fill_uint16(fnode, &iov[count],
+ ISCSI_FLASHNODE_MAX_R2T,
+ fnode->sess.max_outstanding_r2t))
+ count++;
+ } else if (!strcmp(param->name, FLASHNODE_SESS_TSID)) {
+ if (!flashnode_fill_uint16(fnode, &iov[count],
+ ISCSI_FLASHNODE_TSID,
+ fnode->sess.tsid))
+ count++;
+ } else if (!strcmp(param->name, FLASHNODE_SESS_MAX_BURST)) {
+ if (!flashnode_fill_uint32(fnode, &iov[count],
+ ISCSI_FLASHNODE_MAX_BURST,
+ fnode->sess.max_burst_len))
+ count++;
+ } else if (!strcmp(param->name,
+ FLASHNODE_SESS_DEF_TASKMGMT_TMO)) {
+ if (!flashnode_fill_uint16(fnode, &iov[count],
+ ISCSI_FLASHNODE_DEF_TASKMGMT_TMO,
+ fnode->sess.def_taskmgmt_tmo))
+ count++;
+ } else if (!strcmp(param->name, FLASHNODE_SESS_NAME)) {
+ if (!flashnode_fill_str(fnode, &iov[count],
+ ISCSI_FLASHNODE_NAME,
+ fnode->sess.targetname,
+ sizeof(fnode->sess.targetname)))
+ count++;
+ } else if (!strcmp(param->name, FLASHNODE_SESS_FIRST_BURST)) {
+ if (!flashnode_fill_uint32(fnode, &iov[count],
+ ISCSI_FLASHNODE_FIRST_BURST,
+ fnode->sess.first_burst_len))
+ count++;
+ } else if (!strcmp(param->name, FLASHNODE_SESS_ISID)) {
+ if (!flashnode_fill_isid(fnode, &iov[count]))
+ count++;
+ } else if (!strcmp(param->name, FLASHNODE_SESS_ALIAS)) {
+ if (!flashnode_fill_str(fnode, &iov[count],
+ ISCSI_FLASHNODE_ALIAS,
+ fnode->sess.targetalias,
+ sizeof(fnode->sess.targetalias)))
+ count++;
+ } else if (!strcmp(param->name, FLASHNODE_SESS_TPGT)) {
+ if (!flashnode_fill_uint16(fnode, &iov[count],
+ ISCSI_FLASHNODE_TPGT,
+ fnode->sess.tpgt))
+ count++;
+ } else if (!strcmp(param->name,
+ FLASHNODE_SESS_DISCOVERY_PARENT_IDX)) {
+ if (!flashnode_fill_uint16(fnode, &iov[count],
+ ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX,
+ fnode->sess.discovery_parent_idx))
+ count++;
+ } else if (!strcmp(param->name,
+ FLASHNODE_SESS_DISCOVERY_PARENT_TYPE)) {
+ if (!flashnode_fill_str(fnode, &iov[count],
+ ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE,
+ fnode->sess.discovery_parent_type,
+ sizeof(fnode->sess.discovery_parent_type)))
+ count++;
+ } else if (!strcmp(param->name, FLASHNODE_SESS_PORTAL_TYPE)) {
+ if (!flashnode_fill_str(fnode, &iov[count],
+ ISCSI_FLASHNODE_PORTAL_TYPE,
+ fnode->sess.portal_type,
+ sizeof(fnode->sess.portal_type)))
+ count++;
+ } else if (!strcmp(param->name, to_key(FLASHNODE_CONN_PORT))) {
+ if (fnode->conn[0].port)
+ port = fnode->conn[0].port;
+ if (!flashnode_fill_uint16(fnode, &iov[count],
+ ISCSI_FLASHNODE_PORT, port))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_IPADDR))) {
+ if (!flashnode_fill_ipaddr(fnode, &iov[count],
+ ISCSI_FLASHNODE_IPADDR))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_MAX_RECV_DLENGTH))) {
+ if (!flashnode_fill_uint32(fnode, &iov[count],
+ ISCSI_FLASHNODE_MAX_RECV_DLENGTH,
+ fnode->conn[0].max_recv_dlength))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_IS_FW_ASSIGNED_IPV6))) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6,
+ fnode->conn[0].is_fw_assigned_ipv6))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_HDR_DGST_EN))) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_HDR_DGST_EN,
+ fnode->conn[0].header_digest_en))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_DATA_DGST_EN))) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_DATA_DGST_EN,
+ fnode->conn[0].data_digest_en))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_SNACK_REQ_EN))) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_SNACK_REQ_EN,
+ fnode->conn[0].snack_req_en))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_TCP_TIMESTAMP_STAT))) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT,
+ fnode->conn[0].tcp_timestamp_stat))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_TCP_NAGLE_DISABLE))) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_TCP_NAGLE_DISABLE,
+ fnode->conn[0].tcp_nagle_disable))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_TCP_WSF_DISABLE))) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_TCP_WSF_DISABLE,
+ fnode->conn[0].tcp_wsf_disable))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_TCP_TIMER_SCALE))) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_TCP_TIMER_SCALE,
+ fnode->conn[0].tcp_timer_scale))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_TCP_TIMESTAMP_EN))) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_TCP_TIMESTAMP_EN,
+ fnode->conn[0].tcp_timestamp_en))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_IP_FRAG_DISABLE))) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_IP_FRAG_DISABLE,
+ fnode->conn[0].fragment_disable))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_MAX_XMIT_DLENGTH))) {
+ if (!flashnode_fill_uint32(fnode, &iov[count],
+ ISCSI_FLASHNODE_MAX_XMIT_DLENGTH,
+ fnode->conn[0].max_xmit_dlength))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_KEEPALIVE_TMO))) {
+ if (!flashnode_fill_uint16(fnode, &iov[count],
+ ISCSI_FLASHNODE_KEEPALIVE_TMO,
+ fnode->conn[0].keepalive_tmo))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_REDIRECT_IPADDR))) {
+ if (!flashnode_fill_ipaddr(fnode, &iov[count],
+ ISCSI_FLASHNODE_REDIRECT_IPADDR))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_MAX_SEGMENT_SIZE))) {
+ if (!flashnode_fill_uint32(fnode, &iov[count],
+ ISCSI_FLASHNODE_MAX_SEGMENT_SIZE,
+ fnode->conn[0].max_segment_size))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_LOCAL_PORT))) {
+ if (!flashnode_fill_uint16(fnode, &iov[count],
+ ISCSI_FLASHNODE_LOCAL_PORT,
+ fnode->conn[0].local_port))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_IPV4_TOS))) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_IPV4_TOS,
+ fnode->conn[0].ipv4_tos))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_IPV6_TC))) {
+ if (!flashnode_fill_uint8(fnode, &iov[count],
+ ISCSI_FLASHNODE_IPV6_TC,
+ fnode->conn[0].ipv6_traffic_class))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_IPV6_FLOW_LABEL))) {
+ if (!flashnode_fill_uint16(fnode, &iov[count],
+ ISCSI_FLASHNODE_IPV6_FLOW_LABEL,
+ fnode->conn[0].ipv6_flow_lbl))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_LINK_LOCAL_IPV6))) {
+ if (!flashnode_fill_ipv6_addr(fnode, &iov[count],
+ ISCSI_FLASHNODE_LINK_LOCAL_IPV6))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_TCP_XMIT_WSF))) {
+ if (!flashnode_fill_uint32(fnode, &iov[count],
+ ISCSI_FLASHNODE_TCP_XMIT_WSF,
+ fnode->conn[0].tcp_xmit_wsf))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_TCP_RECV_WSF))) {
+ if (!flashnode_fill_uint32(fnode, &iov[count],
+ ISCSI_FLASHNODE_TCP_RECV_WSF,
+ fnode->conn[0].tcp_recv_wsf))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_STATSN))) {
+ if (!flashnode_fill_uint32(fnode, &iov[count],
+ ISCSI_FLASHNODE_STATSN,
+ fnode->conn[0].stat_sn))
+ count++;
+ } else if (!strcmp(param->name,
+ to_key(FLASHNODE_CONN_EXP_STATSN))) {
+ if (!flashnode_fill_uint32(fnode, &iov[count],
+ ISCSI_FLASHNODE_EXP_STATSN,
+ fnode->conn[0].exp_stat_sn))
+ count++;
+ }
+ }
+
+ return count;
+}
diff --git a/usr/flashnode.h b/usr/flashnode.h
new file mode 100644
index 0000000..c1de9cc
--- /dev/null
+++ b/usr/flashnode.h
@@ -0,0 +1,127 @@
+/*
+ * iSCSI flashnode helpers
+ *
+ * Copyright (C) 2013 QLogic Corporation.
+ * Maintained by open-iscsi@googlegroups.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * See the file COPYING included with this distribution for more details.
+ */
+#ifndef FLASHNODE_H
+#define FLASHNODE_H
+#include <sys/types.h>
+#include <netdb.h>
+#include <net/if.h>
+
+#include "types.h"
+#include "config.h"
+#include "auth.h"
+
+typedef enum portal_type {
+ IPV4,
+ IPV6,
+} portal_type_e;
+
+typedef struct flashnode_sess_rec {
+ char targetname[TARGET_NAME_MAXLEN];
+ char targetalias[TARGET_NAME_MAXLEN];
+ char username[AUTH_STR_MAX_LEN];
+ char username_in[AUTH_STR_MAX_LEN];
+ char password[AUTH_STR_MAX_LEN];
+ char password_in[AUTH_STR_MAX_LEN];
+ /* indicates if discovery was done through iSNS discovery service
+ * or through sendTarget */
+ char discovery_parent_type[ISCSI_MAX_STR_LEN];
+ char isid[16];
+ char portal_type[5]; /* ipv4 or ipv6 */
+ unsigned first_burst_len;
+ unsigned max_burst_len;
+ uint16_t def_time2wait;
+ uint16_t def_time2retain;
+ uint16_t max_outstanding_r2t;
+ uint16_t tsid;
+ uint16_t def_taskmgmt_tmo;
+ uint16_t tpgt;
+ uint16_t chap_out_idx;
+ uint16_t chap_in_idx;
+ /* index of iSCSI discovery session if the entry is
+ * discovered by iSCSI discovery session
+ */
+ uint16_t discovery_parent_idx;
+ /* Firmware auto sendtarget discovery disable */
+ uint8_t auto_snd_tgt_disable;
+ uint8_t discovery_session;
+ /* indicates if this flashnode entry is enabled or disabled */
+ uint8_t entry_enable;
+ uint8_t immediate_data;
+ uint8_t initial_r2t;
+ uint8_t data_seq_in_order;
+ uint8_t data_pdu_in_order;
+ uint8_t chap_auth_en;
+ /* enables firmware to auto logout the discovery session on discovery
+ * completion
+ */
+ uint8_t discovery_logout_en;
+ uint8_t bidi_chap_en;
+ /* makes authentication for discovery session optional */
+ uint8_t discovery_auth_optional;
+ uint8_t erl;
+ uint8_t is_boot_target;
+} flashnode_sess_rec_t;
+
+typedef struct flashnode_conn_rec {
+ char ipaddress[NI_MAXHOST];
+ char redirect_ipaddr[NI_MAXHOST];
+ char link_local_ipv6[NI_MAXHOST];
+ unsigned max_recv_dlength;
+ unsigned max_xmit_dlength;
+ unsigned max_segment_size;
+ unsigned tcp_xmit_wsf;
+ unsigned tcp_recv_wsf;
+ uint32_t stat_sn;
+ uint32_t exp_stat_sn;
+ uint16_t keepalive_tmo;
+ uint16_t port;
+ uint16_t local_port;
+ uint16_t ipv6_flow_lbl;
+ /* Link local IPv6 address is assigned by firmware or driver */
+ uint8_t is_fw_assigned_ipv6;
+ uint8_t header_digest_en;
+ uint8_t data_digest_en;
+ uint8_t snack_req_en;
+ /* tcp timestamp negotiation status */
+ uint8_t tcp_timestamp_stat;
+ uint8_t tcp_nagle_disable;
+ /* tcp window scale factor */
+ uint8_t tcp_wsf_disable;
+ uint8_t tcp_timer_scale;
+ uint8_t tcp_timestamp_en;
+ uint8_t fragment_disable;
+ uint8_t ipv4_tos;
+ uint8_t ipv6_traffic_class;
+} flashnode_conn_rec_t;
+
+struct flashnode_rec {
+ struct list_head list;
+ char transport_name[ISCSI_TRANSPORT_NAME_MAXLEN];
+ flashnode_sess_rec_t sess;
+ flashnode_conn_rec_t conn[ISCSI_CONN_MAX];
+};
+
+extern int flashnode_info_print_flat(void *data, struct flashnode_rec *tgt,
+ uint32_t host_no, uint32_t flashnode_idx);
+extern int iscsi_logout_flashnode_sid(struct iscsi_transport *t,
+ uint32_t host_no, uint32_t sid);
+extern int flashnode_build_config(struct list_head *params,
+ struct flashnode_rec *flashnode,
+ struct iovec *iovs);
+#endif
diff --git a/usr/idbm.c b/usr/idbm.c
index 4d30aa9..bc06058 100644
--- a/usr/idbm.c
+++ b/usr/idbm.c
@@ -94,6 +94,17 @@ static struct idbm *db;
_n++; \
} while (0)
+#define __recinfo_uint32(_key, _info, _rec, _name, _show, _n, _mod) do { \
+ _info[_n].type = TYPE_UINT32; \
+ strlcpy(_info[_n].name, _key, NAME_MAXVAL); \
+ snprintf(_info[_n].value, VALUE_MAXVAL, "%d", _rec->_name); \
+ _info[_n].data = &_rec->_name; \
+ _info[_n].data_len = sizeof(_rec->_name); \
+ _info[_n].visible = _show; \
+ _info[_n].can_modify = _mod; \
+ _n++; \
+} while (0)
+
#define __recinfo_int_o2(_key,_info,_rec,_name,_show,_op0,_op1,_n, _mod) do { \
_info[_n].type = TYPE_INT_O; \
strlcpy(_info[_n].name, _key, NAME_MAXVAL); \
@@ -469,6 +480,158 @@ static void idbm_recinfo_host_chap(struct iscsi_chap_rec *r, recinfo_t *ri)
}
}
+void idbm_recinfo_flashnode(struct flashnode_rec *r, recinfo_t *ri)
+{
+ int num = 0;
+ int i;
+
+ __recinfo_uint8(FLASHNODE_SESS_AUTO_SND_TGT_DISABLE, ri, r,
+ sess.auto_snd_tgt_disable, IDBM_SHOW, num, 1);
+ __recinfo_uint8(FLASHNODE_SESS_DISCOVERY_SESS, ri, r,
+ sess.discovery_session, IDBM_SHOW, num, 1);
+ __recinfo_str(FLASHNODE_SESS_PORTAL_TYPE, ri, r, sess.portal_type,
+ IDBM_SHOW, num, 1);
+ __recinfo_uint8(FLASHNODE_SESS_ENTRY_EN, ri, r,
+ sess.entry_enable, IDBM_SHOW, num, 1);
+ __recinfo_uint8(FLASHNODE_SESS_IMM_DATA_EN, ri, r, sess.immediate_data,
+ IDBM_SHOW, num, 1);
+ __recinfo_uint8(FLASHNODE_SESS_INITIAL_R2T_EN, ri, r, sess.initial_r2t,
+ IDBM_SHOW, num, 1);
+ __recinfo_uint8(FLASHNODE_SESS_DATASEQ_INORDER, ri, r,
+ sess.data_seq_in_order, IDBM_SHOW, num, 1);
+ __recinfo_uint8(FLASHNODE_SESS_PDU_INORDER, ri, r,
+ sess.data_pdu_in_order, IDBM_SHOW, num, 1);
+ __recinfo_uint8(FLASHNODE_SESS_CHAP_AUTH_EN, ri, r, sess.chap_auth_en,
+ IDBM_SHOW, num, 1);
+ __recinfo_uint8(FLASHNODE_SESS_DISCOVERY_LOGOUT_EN, ri, r,
+ sess.discovery_logout_en, IDBM_SHOW, num, 1);
+ __recinfo_uint8(FLASHNODE_SESS_BIDI_CHAP_EN, ri, r, sess.bidi_chap_en,
+ IDBM_SHOW, num, 1);
+ __recinfo_uint8(FLASHNODE_SESS_DISCOVERY_AUTH_OPTIONAL, ri, r,
+ sess.discovery_auth_optional, IDBM_SHOW, num, 1);
+ __recinfo_uint8(FLASHNODE_SESS_ERL, ri, r, sess.erl, IDBM_SHOW, num, 1);
+ __recinfo_uint32(FLASHNODE_SESS_FIRST_BURST, ri, r,
+ sess.first_burst_len, IDBM_SHOW, num, 1);
+ __recinfo_uint16(FLASHNODE_SESS_DEF_TIME2WAIT, ri, r,
+ sess.def_time2wait, IDBM_SHOW, num, 1);
+ __recinfo_uint16(FLASHNODE_SESS_DEF_TIME2RETAIN, ri, r,
+ sess.def_time2retain, IDBM_SHOW, num, 1);
+ __recinfo_uint16(FLASHNODE_SESS_MAX_R2T, ri, r,
+ sess.max_outstanding_r2t, IDBM_SHOW, num, 1);
+ __recinfo_str(FLASHNODE_SESS_ISID, ri, r, sess.isid, IDBM_SHOW, num, 1);
+ __recinfo_uint16(FLASHNODE_SESS_TSID, ri, r, sess.tsid, IDBM_SHOW,
+ num, 1);
+ __recinfo_uint32(FLASHNODE_SESS_MAX_BURST, ri, r, sess.max_burst_len,
+ IDBM_SHOW, num, 1);
+ __recinfo_uint16(FLASHNODE_SESS_DEF_TASKMGMT_TMO, ri, r,
+ sess.def_taskmgmt_tmo, IDBM_SHOW, num, 1);
+ __recinfo_str(FLASHNODE_SESS_ALIAS, ri, r, sess.targetalias, IDBM_SHOW,
+ num, 1);
+ __recinfo_str(FLASHNODE_SESS_NAME, ri, r, sess.targetname, IDBM_SHOW,
+ num, 1);
+ __recinfo_uint16(FLASHNODE_SESS_DISCOVERY_PARENT_IDX, ri, r,
+ sess.discovery_parent_idx, IDBM_SHOW, num, 1);
+ __recinfo_str(FLASHNODE_SESS_DISCOVERY_PARENT_TYPE, ri, r,
+ sess.discovery_parent_type, IDBM_SHOW, num, 1);
+ __recinfo_uint16(FLASHNODE_SESS_TPGT, ri, r, sess.tpgt, IDBM_SHOW,
+ num, 1);
+ __recinfo_uint16(FLASHNODE_SESS_CHAP_OUT_IDX, ri, r, sess.chap_out_idx,
+ IDBM_SHOW, num, 1);
+ __recinfo_uint16(FLASHNODE_SESS_CHAP_IN_IDX, ri, r, sess.chap_in_idx,
+ IDBM_SHOW, num, 1);
+ __recinfo_str(FLASHNODE_SESS_USERNAME, ri, r, sess.username, IDBM_SHOW,
+ num, 1);
+ __recinfo_str(FLASHNODE_SESS_USERNAME_IN, ri, r, sess.username_in,
+ IDBM_SHOW, num, 1);
+ __recinfo_str(FLASHNODE_SESS_PASSWORD, ri, r, sess.password, IDBM_SHOW,
+ num, 1);
+ __recinfo_str(FLASHNODE_SESS_PASSWORD_IN, ri, r, sess.password_in,
+ IDBM_SHOW, num, 1);
+ __recinfo_uint8(FLASHNODE_SESS_IS_BOOT_TGT, ri, r, sess.is_boot_target,
+ IDBM_SHOW, num, 1);
+
+ for (i = 0; i < ISCSI_CONN_MAX; i++) {
+ char key[NAME_MAXVAL];
+
+ sprintf(key, FLASHNODE_CONN_IS_FW_ASSIGNED_IPV6, i);
+ __recinfo_uint8(key, ri, r, conn[i].is_fw_assigned_ipv6,
+ IDBM_SHOW, num, 1);
+ sprintf(key, FLASHNODE_CONN_HDR_DGST_EN, i);
+ __recinfo_uint8(key, ri, r, conn[i].header_digest_en, IDBM_SHOW,
+ num, 1);
+ sprintf(key, FLASHNODE_CONN_DATA_DGST_EN, i);
+ __recinfo_uint8(key, ri, r, conn[i].data_digest_en, IDBM_SHOW,
+ num, 1);
+ sprintf(key, FLASHNODE_CONN_SNACK_REQ_EN, i);
+ __recinfo_uint8(key, ri, r, conn[i].snack_req_en, IDBM_SHOW,
+ num, 1);
+ sprintf(key, FLASHNODE_CONN_TCP_TIMESTAMP_STAT, i);
+ __recinfo_uint8(key, ri, r, conn[i].tcp_timestamp_stat,
+ IDBM_SHOW, num, 1);
+ sprintf(key, FLASHNODE_CONN_TCP_NAGLE_DISABLE, i);
+ __recinfo_uint8(key, ri, r, conn[i].tcp_nagle_disable,
+ IDBM_SHOW, num, 1);
+ sprintf(key, FLASHNODE_CONN_TCP_WSF_DISABLE, i);
+ __recinfo_uint8(key, ri, r, conn[i].tcp_wsf_disable, IDBM_SHOW,
+ num, 1);
+ sprintf(key, FLASHNODE_CONN_TCP_TIMER_SCALE, i);
+ __recinfo_uint8(key, ri, r, conn[i].tcp_timer_scale, IDBM_SHOW,
+ num, 1);
+ sprintf(key, FLASHNODE_CONN_TCP_TIMESTAMP_EN, i);
+ __recinfo_uint8(key, ri, r, conn[i].tcp_timestamp_en,
+ IDBM_SHOW, num, 1);
+ sprintf(key, FLASHNODE_CONN_IP_FRAG_DISABLE, i);
+ __recinfo_uint8(key, ri, r, conn[i].fragment_disable, IDBM_SHOW,
+ num, 1);
+ sprintf(key, FLASHNODE_CONN_MAX_XMIT_DLENGTH, i);
+ __recinfo_uint32(key, ri, r, conn[i].max_xmit_dlength,
+ IDBM_SHOW, num, 1);
+ sprintf(key, FLASHNODE_CONN_MAX_RECV_DLENGTH, i);
+ __recinfo_uint32(key, ri, r, conn[i].max_recv_dlength,
+ IDBM_SHOW, num, 1);
+ sprintf(key, FLASHNODE_CONN_KEEPALIVE_TMO, i);
+ __recinfo_uint16(key, ri, r, conn[i].keepalive_tmo, IDBM_SHOW,
+ num, 1);
+ sprintf(key, FLASHNODE_CONN_PORT, i);
+ __recinfo_uint16(key, ri, r, conn[i].port, IDBM_SHOW, num, 1);
+ sprintf(key, FLASHNODE_CONN_IPADDR, i);
+ __recinfo_str(key, ri, r, conn[i].ipaddress, IDBM_SHOW, num, 1);
+ sprintf(key, FLASHNODE_CONN_REDIRECT_IPADDR, i);
+ __recinfo_str(key, ri, r, conn[i].redirect_ipaddr, IDBM_SHOW,
+ num, 1);
+ sprintf(key, FLASHNODE_CONN_MAX_SEGMENT_SIZE, i);
+ __recinfo_uint32(key, ri, r, conn[i].max_segment_size,
+ IDBM_SHOW, num, 1);
+ sprintf(key, FLASHNODE_CONN_LOCAL_PORT, i);
+ __recinfo_uint16(key, ri, r, conn[i].local_port, IDBM_SHOW,
+ num, 1);
+ sprintf(key, FLASHNODE_CONN_IPV4_TOS, i);
+ __recinfo_uint8(key, ri, r, conn[i].ipv4_tos, IDBM_SHOW,
+ num, 1);
+ sprintf(key, FLASHNODE_CONN_IPV6_TC, i);
+ __recinfo_uint8(key, ri, r, conn[i].ipv6_traffic_class,
+ IDBM_SHOW, num, 1);
+ sprintf(key, FLASHNODE_CONN_IPV6_FLOW_LABEL, i);
+ __recinfo_uint16(key, ri, r, conn[i].ipv6_flow_lbl, IDBM_SHOW,
+ num, 1);
+ sprintf(key, FLASHNODE_CONN_LINK_LOCAL_IPV6, i);
+ __recinfo_str(key, ri, r, conn[i].link_local_ipv6, IDBM_SHOW,
+ num, 1);
+ sprintf(key, FLASHNODE_CONN_TCP_XMIT_WSF, i);
+ __recinfo_uint32(key, ri, r, conn[i].tcp_xmit_wsf, IDBM_SHOW,
+ num, 1);
+ sprintf(key, FLASHNODE_CONN_TCP_RECV_WSF, i);
+ __recinfo_uint32(key, ri, r, conn[i].tcp_recv_wsf, IDBM_SHOW,
+ num, 1);
+ sprintf(key, FLASHNODE_CONN_STATSN, i);
+ __recinfo_uint32(key, ri, r, conn[i].stat_sn, IDBM_SHOW,
+ num, 1);
+ sprintf(key, FLASHNODE_CONN_EXP_STATSN, i);
+ __recinfo_uint32(key, ri, r, conn[i].exp_stat_sn, IDBM_SHOW,
+ num, 1);
+ }
+}
+
recinfo_t *idbm_recinfo_alloc(int max_keys)
{
recinfo_t *info;
@@ -502,6 +665,9 @@ void idbm_print(int type, void *rec, int show, FILE *f)
case IDBM_PRINT_TYPE_HOST_CHAP:
idbm_recinfo_host_chap((struct iscsi_chap_rec *)rec, info);
break;
+ case IDBM_PRINT_TYPE_FLASHNODE:
+ idbm_recinfo_flashnode((struct flashnode_rec *)rec, info);
+ break;
}
fprintf(f, "%s\n", ISCSI_BEGIN_REC);
@@ -629,6 +795,13 @@ setup_passwd_len:
*(uint16_t *)info[i].data =
strtoul(value, NULL, 10);
goto updated;
+ } else if (info[i].type == TYPE_UINT32) {
+ if (!info[i].data)
+ continue;
+
+ *(uint32_t *)info[i].data =
+ strtoul(value, NULL, 10);
+ goto updated;
} else if (info[i].type == TYPE_STR) {
if (!info[i].data)
continue;
@@ -880,6 +1053,12 @@ int idbm_print_host_chap_info(struct iscsi_chap_rec *chap)
return 0;
}
+int idbm_print_flashnode_info(struct flashnode_rec *fnode)
+{
+ idbm_print(IDBM_PRINT_TYPE_FLASHNODE, fnode, 1, stdout);
+ return 0;
+}
+
int idbm_print_node_flat(void *data, node_rec_t *rec)
{
if (strchr(rec->conn[0].address, '.'))
diff --git a/usr/idbm.h b/usr/idbm.h
index 245f046..5e4038d 100644
--- a/usr/idbm.h
+++ b/usr/idbm.h
@@ -27,6 +27,7 @@
#include "initiator.h"
#include "config.h"
#include "list.h"
+#include "flashnode.h"
#define NODE_CONFIG_DIR ISCSI_CONFIG_ROOT"nodes"
#define SLP_CONFIG_DIR ISCSI_CONFIG_ROOT"slp"
@@ -42,6 +43,7 @@
#define TYPE_STR 2
#define TYPE_UINT8 3
#define TYPE_UINT16 4
+#define TYPE_UINT32 5
#define MAX_KEYS 256 /* number of keys total(including CNX_MAX) */
#define NAME_MAXVAL 128 /* the maximum length of key name */
#define VALUE_MAXVAL 256 /* the maximum length of 223 bytes in the RFC. */
@@ -85,6 +87,7 @@ struct user_param {
struct list_head list;
char *name;
char *value;
+ int param;
};
typedef int (idbm_iface_op_fn)(void *data, node_rec_t *rec);
@@ -168,6 +171,7 @@ enum {
IDBM_PRINT_TYPE_NODE,
IDBM_PRINT_TYPE_IFACE,
IDBM_PRINT_TYPE_HOST_CHAP,
+ IDBM_PRINT_TYPE_FLASHNODE
};
extern void idbm_print(int type, void *rec, int show, FILE *f);
@@ -182,4 +186,7 @@ idbm_create_rec_from_boot_context(struct boot_context *context);
extern int idbm_print_host_chap_info(struct iscsi_chap_rec *chap);
+extern int idbm_print_flashnode_info(struct flashnode_rec *target);
+extern void idbm_recinfo_flashnode(struct flashnode_rec *r, recinfo_t *ri);
+
#endif /* IDBM_H */
diff --git a/usr/idbm_fields.h b/usr/idbm_fields.h
index 358d014..179dda8 100644
--- a/usr/idbm_fields.h
+++ b/usr/idbm_fields.h
@@ -126,4 +126,67 @@
#define HOST_AUTH_PASSWORD_IN "host.auth.password_in"
#define HOST_AUTH_PASSWORD_IN_LEN "host.auth.password_in_length"
+/* flash target session fields */
+#define FLASHNODE_SESS_AUTO_SND_TGT_DISABLE "flashnode.session.auto_snd_tgt_disable"
+#define FLASHNODE_SESS_DISCOVERY_SESS "flashnode.session.discovery_session"
+#define FLASHNODE_SESS_PORTAL_TYPE "flashnode.session.portal_type"
+#define FLASHNODE_SESS_ENTRY_EN "flashnode.session.entry_enable"
+#define FLASHNODE_SESS_IMM_DATA_EN "flashnode.session.immediate_data"
+#define FLASHNODE_SESS_INITIAL_R2T_EN "flashnode.session.initial_r2t"
+#define FLASHNODE_SESS_DATASEQ_INORDER "flashnode.session.data_seq_in_order"
+#define FLASHNODE_SESS_PDU_INORDER "flashnode.session.data_pdu_in_order"
+#define FLASHNODE_SESS_CHAP_AUTH_EN "flashnode.session.chap_auth_en"
+#define FLASHNODE_SESS_DISCOVERY_LOGOUT_EN "flashnode.session.discovery_logout_en"
+#define FLASHNODE_SESS_BIDI_CHAP_EN "flashnode.session.bidi_chap_en"
+#define FLASHNODE_SESS_DISCOVERY_AUTH_OPTIONAL "flashnode.session.discovery_auth_optional"
+#define FLASHNODE_SESS_ERL "flashnode.session.erl"
+#define FLASHNODE_SESS_FIRST_BURST "flashnode.session.first_burst_len"
+#define FLASHNODE_SESS_DEF_TIME2WAIT "flashnode.session.def_time2wait"
+#define FLASHNODE_SESS_DEF_TIME2RETAIN "flashnode.session.def_time2retain"
+#define FLASHNODE_SESS_MAX_R2T "flashnode.session.max_outstanding_r2t"
+#define FLASHNODE_SESS_ISID "flashnode.session.isid"
+#define FLASHNODE_SESS_TSID "flashnode.session.tsid"
+#define FLASHNODE_SESS_MAX_BURST "flashnode.session.max_burst_len"
+#define FLASHNODE_SESS_DEF_TASKMGMT_TMO "flashnode.session.def_taskmgmt_tmo"
+#define FLASHNODE_SESS_ALIAS "flashnode.session.targetalias"
+#define FLASHNODE_SESS_NAME "flashnode.session.targetname"
+#define FLASHNODE_SESS_TPGT "flashnode.session.tpgt"
+#define FLASHNODE_SESS_DISCOVERY_PARENT_IDX "flashnode.session.discovery_parent_idx"
+#define FLASHNODE_SESS_DISCOVERY_PARENT_TYPE "flashnode.session.discovery_parent_type"
+#define FLASHNODE_SESS_CHAP_OUT_IDX "flashnode.session.chap_out_idx"
+#define FLASHNODE_SESS_CHAP_IN_IDX "flashnode.session.chap_in_idx"
+#define FLASHNODE_SESS_USERNAME "flashnode.session.username"
+#define FLASHNODE_SESS_USERNAME_IN "flashnode.session.username_in"
+#define FLASHNODE_SESS_PASSWORD "flashnode.session.password"
+#define FLASHNODE_SESS_PASSWORD_IN "flashnode.session.password_in"
+#define FLASHNODE_SESS_IS_BOOT_TGT "flashnode.session.is_boot_target"
+
+/* flash target connection fields */
+#define FLASHNODE_CONN_IS_FW_ASSIGNED_IPV6 "flashnode.conn[%d].is_fw_assigned_ipv6"
+#define FLASHNODE_CONN_HDR_DGST_EN "flashnode.conn[%d].header_digest_en"
+#define FLASHNODE_CONN_DATA_DGST_EN "flashnode.conn[%d].data_digest_en"
+#define FLASHNODE_CONN_SNACK_REQ_EN "flashnode.conn[%d].snack_req_en"
+#define FLASHNODE_CONN_TCP_TIMESTAMP_STAT "flashnode.conn[%d].tcp_timestamp_stat"
+#define FLASHNODE_CONN_TCP_NAGLE_DISABLE "flashnode.conn[%d].tcp_nagle_disable"
+#define FLASHNODE_CONN_TCP_WSF_DISABLE "flashnode.conn[%d].tcp_wsf_disable"
+#define FLASHNODE_CONN_TCP_TIMER_SCALE "flashnode.conn[%d].tcp_timer_scale"
+#define FLASHNODE_CONN_TCP_TIMESTAMP_EN "flashnode.conn[%d].tcp_timestamp_en"
+#define FLASHNODE_CONN_IP_FRAG_DISABLE "flashnode.conn[%d].fragment_disable"
+#define FLASHNODE_CONN_MAX_RECV_DLENGTH "flashnode.conn[%d].max_recv_dlength"
+#define FLASHNODE_CONN_MAX_XMIT_DLENGTH "flashnode.conn[%d].max_xmit_dlength"
+#define FLASHNODE_CONN_KEEPALIVE_TMO "flashnode.conn[%d].keepalive_tmo"
+#define FLASHNODE_CONN_PORT "flashnode.conn[%d].port"
+#define FLASHNODE_CONN_IPADDR "flashnode.conn[%d].ipaddress"
+#define FLASHNODE_CONN_REDIRECT_IPADDR "flashnode.conn[%d].redirect_ipaddr"
+#define FLASHNODE_CONN_MAX_SEGMENT_SIZE "flashnode.conn[%d].max_segment_size"
+#define FLASHNODE_CONN_LOCAL_PORT "flashnode.conn[%d].local_port"
+#define FLASHNODE_CONN_IPV4_TOS "flashnode.conn[%d].ipv4_tos"
+#define FLASHNODE_CONN_IPV6_TC "flashnode.conn[%d].ipv6_traffic_class"
+#define FLASHNODE_CONN_IPV6_FLOW_LABEL "flashnode.conn[%d].ipv6_flow_label"
+#define FLASHNODE_CONN_LINK_LOCAL_IPV6 "flashnode.conn[%d].link_local_ipv6"
+#define FLASHNODE_CONN_TCP_XMIT_WSF "flashnode.conn[%d].tcp_xmit_wsf"
+#define FLASHNODE_CONN_TCP_RECV_WSF "flashnode.conn[%d].tcp_recv_wsf"
+#define FLASHNODE_CONN_STATSN "flashnode.conn[%d].statsn"
+#define FLASHNODE_CONN_EXP_STATSN "flashnode.conn[%d].exp_statsn"
+
#endif
diff --git a/usr/iscsi_ipc.h b/usr/iscsi_ipc.h
index db5f1f0..b6665cb 100644
--- a/usr/iscsi_ipc.h
+++ b/usr/iscsi_ipc.h
@@ -145,6 +145,19 @@ struct iscsi_ipc {
int (*delete_chap) (uint64_t transport_handle, uint32_t host_no,
uint16_t chap_tbl_idx);
+ int (*set_flash_node_params) (uint64_t transport_handle,
+ uint32_t host_no, uint32_t flashnode_idx,
+ struct iovec *iovs, uint32_t param_count);
+ int (*new_flash_node) (uint64_t transport_handle, uint32_t host_no,
+ void *value, uint32_t *flashnode_idx);
+ int (*del_flash_node) (uint64_t transport_handle, uint32_t host_no,
+ uint32_t flashnode_idx);
+ int (*login_flash_node) (uint64_t transport_handle, uint32_t host_no,
+ uint32_t flashnode_idx);
+ int (*logout_flash_node) (uint64_t transport_handle, uint32_t host_no,
+ uint32_t flashnode_idx);
+ int (*logout_flash_node_sid) (uint64_t transport_handle,
+ uint32_t host_no, uint32_t sid);
};
#endif /* ISCSI_IPC_H */
diff --git a/usr/iscsi_sysfs.c b/usr/iscsi_sysfs.c
index 4015b35..64a4ce7 100644
--- a/usr/iscsi_sysfs.c
+++ b/usr/iscsi_sysfs.c
@@ -29,6 +29,7 @@
#include "initiator.h"
#include "transport.h"
#include "idbm.h"
+#include "idbm_fields.h"
#include "version.h"
#include "iscsi_sysfs.h"
#include "sysdeps.h"
@@ -37,6 +38,7 @@
#include "session_info.h"
#include "host.h"
#include "iscsi_err.h"
+#include "flashnode.h"
/*
* TODO: remove the _DIR defines and search for subsys dirs like
@@ -45,18 +47,22 @@
#define ISCSI_TRANSPORT_DIR "/sys/class/iscsi_transport"
#define ISCSI_SESSION_DIR "/sys/class/iscsi_session"
#define ISCSI_HOST_DIR "/sys/class/iscsi_host"
+#define ISCSI_FLASHNODE_DIR "/sys/bus/iscsi_flashnode/devices"
#define ISCSI_SESSION_SUBSYS "iscsi_session"
#define ISCSI_CONN_SUBSYS "iscsi_connection"
#define ISCSI_HOST_SUBSYS "iscsi_host"
#define ISCSI_TRANSPORT_SUBSYS "iscsi_transport"
#define ISCSI_IFACE_SUBSYS "iscsi_iface"
+#define ISCSI_FLASHNODE_SUBSYS "iscsi_flashnode"
#define SCSI_HOST_SUBSYS "scsi_host"
#define SCSI_SUBSYS "scsi"
#define ISCSI_SESSION_ID "session%d"
#define ISCSI_CONN_ID "connection%d:0"
#define ISCSI_HOST_ID "host%d"
+#define ISCSI_FLASHNODE_SESS "flashnode_sess-%d:%d"
+#define ISCSI_FLASHNODE_CONN "flashnode_conn-%d:%d:0"
/*
* TODO: make this into a real API and check inputs better and add doc.
@@ -440,6 +446,234 @@ uint32_t iscsi_sysfs_get_host_no_from_hwinfo(struct iface_rec *iface, int *rc)
}
/*
+ * Read the flash node attributes based on host and flash node index.
+ */
+int iscsi_sysfs_get_flashnode_info(struct flashnode_rec *fnode,
+ uint32_t host_no,
+ uint32_t flashnode_idx)
+{
+ char sess_id[NAME_SIZE] = {'\0'};
+ char conn_id[NAME_SIZE] = {'\0'};
+ char fnode_path[PATH_SIZE] = {'\0'};
+ struct iscsi_transport *t;
+ int ret = 0;
+
+ t = iscsi_sysfs_get_transport_by_hba(host_no);
+ if (!t)
+ log_debug(7, "could not get transport name for host%d",
+ host_no);
+ else
+ strncpy(fnode->transport_name, t->name,
+ ISCSI_TRANSPORT_NAME_MAXLEN);
+
+ snprintf(sess_id, sizeof(sess_id), ISCSI_FLASHNODE_SESS, host_no,
+ flashnode_idx);
+
+ snprintf(fnode_path, sizeof(fnode_path), ISCSI_FLASHNODE_DIR"/%s",
+ sess_id);
+ if (access(fnode_path, F_OK) != 0)
+ return errno;
+
+ snprintf(conn_id, sizeof(conn_id), ISCSI_FLASHNODE_CONN, host_no,
+ flashnode_idx);
+
+ snprintf(fnode_path, sizeof(fnode_path), ISCSI_FLASHNODE_DIR"/%s",
+ conn_id);
+ if (access(fnode_path, F_OK) != 0)
+ return errno;
+
+
+ sysfs_get_uint8(conn_id, ISCSI_FLASHNODE_SUBSYS, "is_fw_assigned_ipv6",
+ &((fnode->conn[0]).is_fw_assigned_ipv6));
+ sysfs_get_str(sess_id, ISCSI_FLASHNODE_SUBSYS, "portal_type",
+ (fnode->sess).portal_type,
+ sizeof((fnode->sess).portal_type));
+ sysfs_get_uint8(sess_id, ISCSI_FLASHNODE_SUBSYS, "auto_snd_tgt_disable",
+ &((fnode->sess).auto_snd_tgt_disable));
+ sysfs_get_uint8(sess_id, ISCSI_FLASHNODE_SUBSYS, "discovery_session",
+ &((fnode->sess).discovery_session));
+ sysfs_get_uint8(sess_id, ISCSI_FLASHNODE_SUBSYS, "entry_enable",
+ &((fnode->sess).entry_enable));
+ sysfs_get_uint8(conn_id, ISCSI_FLASHNODE_SUBSYS, "header_digest",
+ &((fnode->conn[0]).header_digest_en));
+ sysfs_get_uint8(conn_id, ISCSI_FLASHNODE_SUBSYS, "data_digest",
+ &((fnode->conn[0]).data_digest_en));
+ sysfs_get_uint8(sess_id, ISCSI_FLASHNODE_SUBSYS, "immediate_data",
+ &((fnode->sess).immediate_data));
+ sysfs_get_uint8(sess_id, ISCSI_FLASHNODE_SUBSYS, "initial_r2t",
+ &((fnode->sess).initial_r2t));
+ sysfs_get_uint8(sess_id, ISCSI_FLASHNODE_SUBSYS, "data_seq_in_order",
+ &((fnode->sess).data_seq_in_order));
+ sysfs_get_uint8(sess_id, ISCSI_FLASHNODE_SUBSYS, "data_pdu_in_order",
+ &((fnode->sess).data_pdu_in_order));
+ sysfs_get_uint8(sess_id, ISCSI_FLASHNODE_SUBSYS, "chap_auth",
+ &((fnode->sess).chap_auth_en));
+ sysfs_get_uint8(conn_id, ISCSI_FLASHNODE_SUBSYS, "snack_req",
+ &((fnode->conn[0]).snack_req_en));
+ sysfs_get_uint8(sess_id, ISCSI_FLASHNODE_SUBSYS, "discovery_logout",
+ &((fnode->sess).discovery_logout_en));
+ sysfs_get_uint8(sess_id, ISCSI_FLASHNODE_SUBSYS, "bidi_chap",
+ &((fnode->sess).bidi_chap_en));
+ sysfs_get_uint8(sess_id, ISCSI_FLASHNODE_SUBSYS,
+ "discovery_auth_optional",
+ &((fnode->sess).discovery_auth_optional));
+ sysfs_get_uint8(sess_id, ISCSI_FLASHNODE_SUBSYS, "erl",
+ &((fnode->sess).erl));
+ sysfs_get_uint8(conn_id, ISCSI_FLASHNODE_SUBSYS, "tcp_timestamp_stat",
+ &((fnode->conn[0]).tcp_timestamp_stat));
+ sysfs_get_uint8(conn_id, ISCSI_FLASHNODE_SUBSYS, "tcp_nagle_disable",
+ &((fnode->conn[0]).tcp_nagle_disable));
+ sysfs_get_uint8(conn_id, ISCSI_FLASHNODE_SUBSYS, "tcp_wsf_disable",
+ &((fnode->conn[0]).tcp_wsf_disable));
+ sysfs_get_uint8(conn_id, ISCSI_FLASHNODE_SUBSYS, "tcp_timer_scale",
+ &((fnode->conn[0]).tcp_timer_scale));
+ sysfs_get_uint8(conn_id, ISCSI_FLASHNODE_SUBSYS, "tcp_timestamp_enable",
+ &((fnode->conn[0]).tcp_timestamp_en));
+ sysfs_get_uint8(conn_id, ISCSI_FLASHNODE_SUBSYS, "fragment_disable",
+ &((fnode->conn[0]).fragment_disable));
+ sysfs_get_uint(conn_id, ISCSI_FLASHNODE_SUBSYS, "max_recv_dlength",
+ &((fnode->conn[0]).max_recv_dlength));
+ sysfs_get_uint(conn_id, ISCSI_FLASHNODE_SUBSYS, "max_xmit_dlength",
+ &((fnode->conn[0]).max_xmit_dlength));
+ sysfs_get_uint(sess_id, ISCSI_FLASHNODE_SUBSYS, "first_burst_len",
+ &((fnode->sess).first_burst_len));
+ sysfs_get_uint16(sess_id, ISCSI_FLASHNODE_SUBSYS, "def_time2wait",
+ &((fnode->sess).def_time2wait));
+ sysfs_get_uint16(sess_id, ISCSI_FLASHNODE_SUBSYS, "def_time2retain",
+ &((fnode->sess).def_time2retain));
+ sysfs_get_uint16(sess_id, ISCSI_FLASHNODE_SUBSYS, "max_outstanding_r2t",
+ &((fnode->sess).max_outstanding_r2t));
+ sysfs_get_uint16(conn_id, ISCSI_FLASHNODE_SUBSYS, "keepalive_tmo",
+ &((fnode->conn[0]).keepalive_tmo));
+ sysfs_get_str(sess_id, ISCSI_FLASHNODE_SUBSYS, "isid",
+ (fnode->sess).isid, sizeof((fnode->sess).isid));
+ sysfs_get_uint16(sess_id, ISCSI_FLASHNODE_SUBSYS, "tsid",
+ &((fnode->sess).tsid));
+ sysfs_get_uint16(conn_id, ISCSI_FLASHNODE_SUBSYS, "port",
+ &((fnode->conn[0]).port));
+ sysfs_get_uint(sess_id, ISCSI_FLASHNODE_SUBSYS, "max_burst_len",
+ &((fnode->sess).max_burst_len));
+ sysfs_get_uint16(sess_id, ISCSI_FLASHNODE_SUBSYS, "def_taskmgmt_tmo",
+ &((fnode->sess).def_taskmgmt_tmo));
+ sysfs_get_str(sess_id, ISCSI_FLASHNODE_SUBSYS, "targetalias",
+ (fnode->sess).targetalias,
+ sizeof((fnode->sess).targetalias));
+ sysfs_get_str(conn_id, ISCSI_FLASHNODE_SUBSYS, "ipaddress",
+ (fnode->conn[0]).ipaddress,
+ sizeof((fnode->conn[0]).ipaddress));
+ sysfs_get_str(conn_id, ISCSI_FLASHNODE_SUBSYS, "redirect_ipaddr",
+ (fnode->conn[0]).redirect_ipaddr,
+ sizeof((fnode->conn[0]).redirect_ipaddr));
+ sysfs_get_uint(conn_id, ISCSI_FLASHNODE_SUBSYS, "max_segment_size",
+ &((fnode->conn[0]).max_segment_size));
+ sysfs_get_uint16(conn_id, ISCSI_FLASHNODE_SUBSYS, "local_port",
+ &((fnode->conn[0]).local_port));
+ sysfs_get_uint8(conn_id, ISCSI_FLASHNODE_SUBSYS, "ipv4_tos",
+ &((fnode->conn[0]).ipv4_tos));
+ sysfs_get_uint8(conn_id, ISCSI_FLASHNODE_SUBSYS, "ipv6_traffic_class",
+ &((fnode->conn[0]).ipv6_traffic_class));
+ sysfs_get_uint16(conn_id, ISCSI_FLASHNODE_SUBSYS, "ipv6_flow_label",
+ &((fnode->conn[0]).ipv6_flow_lbl));
+ sysfs_get_str(sess_id, ISCSI_FLASHNODE_SUBSYS, "targetname",
+ (fnode->sess).targetname,
+ sizeof((fnode->sess).targetname));
+ sysfs_get_str(conn_id, ISCSI_FLASHNODE_SUBSYS, "link_local_ipv6",
+ (fnode->conn[0]).link_local_ipv6,
+ sizeof((fnode->conn[0]).link_local_ipv6));
+ sysfs_get_uint16(sess_id, ISCSI_FLASHNODE_SUBSYS,
+ "discovery_parent_idx",
+ &((fnode->sess).discovery_parent_idx));
+ sysfs_get_str(sess_id, ISCSI_FLASHNODE_SUBSYS,
+ "discovery_parent_type",
+ (fnode->sess).discovery_parent_type,
+ sizeof((fnode->sess).discovery_parent_type));
+ sysfs_get_uint16(sess_id, ISCSI_FLASHNODE_SUBSYS, "tpgt",
+ &((fnode->sess).tpgt));
+ sysfs_get_uint(conn_id, ISCSI_FLASHNODE_SUBSYS, "tcp_xmit_wsf",
+ &((fnode->conn[0]).tcp_xmit_wsf));
+ sysfs_get_uint(conn_id, ISCSI_FLASHNODE_SUBSYS, "tcp_recv_wsf",
+ &((fnode->conn[0]).tcp_recv_wsf));
+ sysfs_get_uint16(sess_id, ISCSI_FLASHNODE_SUBSYS, "chap_out_idx",
+ &((fnode->sess).chap_out_idx));
+ sysfs_get_uint16(sess_id, ISCSI_FLASHNODE_SUBSYS, "chap_in_idx",
+ &((fnode->sess).chap_in_idx));
+ sysfs_get_str(sess_id, ISCSI_FLASHNODE_SUBSYS, "username",
+ (fnode->sess).username, sizeof((fnode->sess).username));
+ sysfs_get_str(sess_id, ISCSI_FLASHNODE_SUBSYS, "username_in",
+ (fnode->sess).username,
+ sizeof((fnode->sess).username_in));
+ sysfs_get_str(sess_id, ISCSI_FLASHNODE_SUBSYS, "password",
+ (fnode->sess).password, sizeof((fnode->sess).password));
+ sysfs_get_str(sess_id, ISCSI_FLASHNODE_SUBSYS, "password_in",
+ (fnode->sess).password,
+ sizeof((fnode->sess).password_in));
+ sysfs_get_uint(conn_id, ISCSI_FLASHNODE_SUBSYS, "statsn",
+ &((fnode->conn[0]).stat_sn));
+ sysfs_get_uint(conn_id, ISCSI_FLASHNODE_SUBSYS, "exp_statsn",
+ &((fnode->conn[0]).exp_stat_sn));
+ sysfs_get_uint8(sess_id, ISCSI_FLASHNODE_SUBSYS, "is_boot_target",
+ &((fnode->sess).is_boot_target));
+ return ret;
+}
+
+/*
+ * For each flash node of the given host, perform operation specified in fn.
+ */
+int iscsi_sysfs_for_each_flashnode(void *data, uint32_t host_no, int *nr_found,
+ iscsi_sysfs_flashnode_op_fn *fn)
+{
+ struct dirent **namelist;
+ int rc = 0, i, n;
+ struct flashnode_rec *fnode;
+ uint32_t flashnode_idx;
+ uint32_t hostno;
+
+ fnode = malloc(sizeof(*fnode));
+ if (!fnode)
+ return ISCSI_ERR_NOMEM;
+
+ n = scandir(ISCSI_FLASHNODE_DIR, &namelist, trans_filter, alphasort);
+ if (n <= 0)
+ goto free_fnode;
+
+ for (i = 0; i < n; i++) {
+ memset(fnode, 0, sizeof(*fnode));
+
+ if (!strncmp(namelist[i]->d_name, "flashnode_conn",
+ strlen("flashnode_conn")))
+ continue;
+
+ if (sscanf(namelist[i]->d_name, ISCSI_FLASHNODE_SESS,
+ &hostno, &flashnode_idx) != 2) {
+ log_error("Invalid iscsi target dir: %s",
+ namelist[i]->d_name);
+ break;
+ }
+
+ if (host_no != hostno)
+ continue;
+
+ rc = iscsi_sysfs_get_flashnode_info(fnode, host_no,
+ flashnode_idx);
+ if (rc)
+ break;
+
+ rc = fn(data, fnode, host_no, flashnode_idx);
+ if (rc != 0)
+ break;
+ (*nr_found)++;
+ }
+
+ for (i = 0; i < n; i++)
+ free(namelist[i]);
+ free(namelist);
+
+free_fnode:
+ free(fnode);
+ return rc;
+}
+
+/*
* Read in iface settings based on host and session values. If
* session is not passed in, then the ifacename will not be set. And
* if the session is not passed in then iname will only be set for
diff --git a/usr/iscsi_sysfs.h b/usr/iscsi_sysfs.h
index 2b15d78..d130d36 100644
--- a/usr/iscsi_sysfs.h
+++ b/usr/iscsi_sysfs.h
@@ -31,6 +31,7 @@ struct iscsi_conn;
struct iscsi_session_operational_config;
struct iscsi_conn_operational_config;
struct iscsi_auth_config;
+struct flashnode_rec;
#define SCSI_MAX_STATE_VALUE 32
@@ -42,6 +43,8 @@ extern int iscsi_sysfs_session_has_leadconn(uint32_t sid);
typedef int (iscsi_sysfs_session_op_fn)(void *, struct session_info *);
typedef int (iscsi_sysfs_host_op_fn)(void *, struct host_info *);
+typedef int (iscsi_sysfs_flashnode_op_fn)(void *, struct flashnode_rec *,
+ uint32_t, uint32_t);
typedef int (iscsi_sysfs_iface_op_fn)(void *, struct iface_rec *);
extern int iscsi_sysfs_for_each_iface_on_host(void *data, uint32_t host_no,
@@ -56,6 +59,20 @@ extern uint32_t iscsi_sysfs_get_host_no_from_hwinfo(struct iface_rec *iface,
int *rc);
extern uint32_t iscsi_sysfs_get_host_no_from_hwaddress(char *hwaddress, int *rc);
extern int iscsi_sysfs_get_hostinfo_by_host_no(struct host_info *hinfo);
+extern int iscsi_sysfs_for_each_flashnode(void *data, uint32_t host_no,
+ int *nr_found,
+ iscsi_sysfs_flashnode_op_fn *fn);
+extern int iscsi_sysfs_get_flashnode_info(struct flashnode_rec *fnode,
+ uint32_t host_no,
+ uint32_t flashnode_id);
+extern int iscsi_sysfs_update_flashnode_param(uint32_t host_no,
+ uint32_t flashnode_id,
+ char *name, char *val);
+extern int iscsi_sysfs_create_flashnode(uint32_t host_no, char *ipver);
+extern int iscsi_sysfs_del_flashnode(uint32_t host_no, uint32_t flashnode_id);
+extern int iscsi_sysfs_login_flashnode(uint32_t host_no, uint32_t flashnode_id);
+extern int iscsi_sysfs_logout_flashnode(uint32_t host_no,
+ uint32_t flashnode_id);
extern int iscsi_sysfs_get_sid_from_path(char *session);
extern char *iscsi_sysfs_get_blockdev_from_lun(int hostno, int target, int sid);
diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c
index 8f9de05..5a18522 100644
--- a/usr/iscsiadm.c
+++ b/usr/iscsiadm.c
@@ -53,6 +53,7 @@
#include "iscsi_err.h"
#include "iscsi_ipc.h"
#include "iscsi_timer.h"
+#include "flashnode.h"
static char program_name[] = "iscsiadm";
static char config_file[TARGET_NAME_MAXLEN];
@@ -67,7 +68,8 @@ enum iscsiadm_mode {
MODE_IFACE,
MODE_FW,
MODE_PING,
- MODE_CHAP
+ MODE_CHAP,
+ MODE_FLASHNODE
};
enum iscsiadm_op {
@@ -78,7 +80,9 @@ enum iscsiadm_op {
OP_SHOW = 0x8,
OP_NONPERSISTENT = 0x10,
OP_APPLY = 0x20,
- OP_APPLY_ALL = 0x40
+ OP_APPLY_ALL = 0x40,
+ OP_LOGIN = 0x80,
+ OP_LOGOUT = 0x100
};
static struct option const long_options[] =
@@ -111,9 +115,11 @@ static struct option const long_options[] =
{"packetsize", required_argument, NULL, 'b'},
{"count", required_argument, NULL, 'c'},
{"interval", required_argument, NULL, 'i'},
+ {"flashnode_idx", optional_argument, NULL, 'x'},
+ {"portal_type", optional_argument, NULL, 'A'},
{NULL, 0, NULL, 0},
};
-static char *short_options = "RlDVhm:a:b:c:C:p:P:T:H:i:I:U:k:L:d:r:n:v:o:sSt:u";
+static char *short_options = "RlDVhm:a:b:c:C:p:P:T:H:i:I:U:k:L:d:r:n:v:o:sSt:ux:A:";
static void usage(int status)
{
@@ -130,7 +136,7 @@ iscsiadm -m node [ -hV ] [ -d debug_level ] [ -P printlevel ] [ -L all,manual,au
iscsiadm -m session [ -hV ] [ -d debug_level ] [ -P printlevel] [ -r sessionid | sysfsdir [ -R | -u | -s ] [ -o operation ] [ -n name ] [ -v value ] ]\n\
iscsiadm -m iface [ -hV ] [ -d debug_level ] [ -P printlevel ] [ -I ifacename | -H hostno|MAC ] [ [ -o operation ] [ -n name ] [ -v value ] ] [ -C ping [ -a ip ] [ -b packetsize ] [ -c count ] [ -i interval ] ]\n\
iscsiadm -m fw [ -l ]\n\
-iscsiadm -m host [ -P printlevel ] [ -H hostno|MAC ] [ -C chap [ -o operation ] [ -v chap_tbl_idx ] ]\n\
+iscsiadm -m host [ -P printlevel ] [ -H hostno|MAC ] [ [ -C chap [ -o operation ] [ -v chap_tbl_idx ] ] | [ -C flashnode [ -o operation ] [ -A portal_type ] [ -x flashnode_idx ] [ -n name ] [ -v value ] ] ]\n\
iscsiadm -k priority\n");
}
exit(status);
@@ -155,6 +161,10 @@ str_to_op(char *str)
op = OP_APPLY;
else if (!strcmp("applyall", str))
op = OP_APPLY_ALL;
+ else if (!strcmp("login", str))
+ op = OP_LOGIN;
+ else if (!strcmp("logout", str))
+ op = OP_LOGOUT;
else
op = OP_NOOP;
@@ -195,6 +205,8 @@ str_to_submode(char *str)
sub_mode = MODE_PING;
else if (!strcmp("chap", str))
sub_mode = MODE_CHAP;
+ else if (!strcmp("flashnode", str))
+ sub_mode = MODE_FLASHNODE;
else
sub_mode = -1;
@@ -221,6 +233,21 @@ str_to_type(char *str)
return type;
}
+static int
+str_to_portal_type(char *str)
+{
+ int ptype;
+
+ if (!strcmp("ipv4", str))
+ ptype = IPV4;
+ else if (!strcmp("ipv6", str))
+ ptype = IPV6;
+ else
+ ptype = -1;
+
+ return ptype;
+}
+
static void kill_iscsid(int priority)
{
iscsiadm_req_t req;
@@ -582,6 +609,8 @@ static int iscsi_logout_matched_portal(void *data, struct list_head *list,
{
struct node_rec *pattern_rec = data;
struct iscsi_transport *t;
+ uint32_t host_no;
+ int rc = 0;
t = iscsi_sysfs_get_transport_by_sid(info->sid);
if (!t)
@@ -590,7 +619,19 @@ static int iscsi_logout_matched_portal(void *data, struct list_head *list,
if (!iscsi_match_session(pattern_rec, info))
return -1;
- return iscsi_logout_portal(info, list);
+ host_no = iscsi_sysfs_get_host_no_from_sid(info->sid, &rc);
+ if (rc) {
+ log_error("could not get host_no for session%d: %s.",
+ info->sid, iscsi_err_to_str(rc));
+ return -1;
+ }
+
+ if (!iscsi_sysfs_session_user_created(info->sid))
+ rc = iscsi_logout_flashnode_sid(t, host_no, info->sid);
+ else
+ rc = iscsi_logout_portal(info, list);
+
+ return rc;
}
static int rec_match_fn(void *data, node_rec_t *rec)
@@ -1438,6 +1479,360 @@ static int exec_host_chap_op(int op, int info_level, uint32_t host_no,
return rc;
}
+static int get_flashnode_info(uint32_t host_no, uint32_t flashnode_idx)
+{
+ struct flashnode_rec fnode;
+ int rc = 0;
+
+ memset(&fnode, 0, sizeof(fnode));
+ rc = iscsi_sysfs_get_flashnode_info(&fnode, host_no, flashnode_idx);
+ if (rc) {
+ log_error("Could not read info for flashnode %u of host %u, %s",
+ flashnode_idx, host_no, strerror(rc));
+ return rc;
+ }
+
+ idbm_print_flashnode_info(&fnode);
+ return rc;
+}
+
+static int list_flashnodes(int info_level, uint32_t host_no)
+{
+ int rc = 0;
+ int num_found = 0;
+
+ rc = iscsi_sysfs_for_each_flashnode(NULL, host_no, &num_found,
+ flashnode_info_print_flat);
+
+ if (!num_found) {
+ log_error("No flashnodes attached to host %u.", host_no);
+ rc = ISCSI_ERR_NO_OBJS_FOUND;
+ }
+
+ return rc;
+}
+
+int iscsi_set_flashnode_params(struct iscsi_transport *t, uint32_t host_no,
+ uint32_t flashnode_idx, struct list_head *params)
+{
+ struct flashnode_rec fnode;
+ recinfo_t *flashnode_info;
+ struct user_param *param;
+ struct iovec *iovs = NULL;
+ struct iovec *iov = NULL;
+ int fd, rc = 0;
+ int param_count = 0;
+ int param_used = 0;
+ int i;
+
+ flashnode_info = idbm_recinfo_alloc(MAX_KEYS);
+ if (!flashnode_info) {
+ log_error("Out of Memory.");
+ rc = ISCSI_ERR_NOMEM;
+ goto free_info_rec;
+ }
+
+ memset(&fnode, 0, sizeof(fnode));
+ rc = iscsi_sysfs_get_flashnode_info(&fnode, host_no, flashnode_idx);
+ if (rc) {
+ log_error("Could not read info for flashnode %u, %s",
+ flashnode_idx, strerror(rc));
+ goto free_info_rec;
+ }
+
+ idbm_recinfo_flashnode(&fnode, flashnode_info);
+
+ i = 0;
+ list_for_each_entry(param, params, list) {
+ param_count++;
+ rc = idbm_verify_param(flashnode_info, param->name);
+ if (rc)
+ goto free_info_rec;
+ }
+
+ list_for_each_entry(param, params, list) {
+ rc = idbm_rec_update_param(flashnode_info, param->name,
+ param->value, 0);
+ if (rc)
+ goto free_info_rec;
+ }
+
+ /* +2 for event and nlmsghdr */
+ param_count += 2;
+ iovs = calloc((param_count * sizeof(struct iovec)),
+ sizeof(char));
+ if (!iovs) {
+ log_error("Out of Memory.");
+ rc = ISCSI_ERR_NOMEM;
+ goto free_info_rec;
+ }
+
+ /* param_used gives actual number of iovecs used for flashnode */
+ param_used = flashnode_build_config(params, &fnode, iovs);
+ if (!param_used) {
+ log_error("Build flashnode config failed.");
+ rc = ISCSI_ERR;
+ goto free_iovec;
+ }
+
+ fd = ipc->ctldev_open();
+ if (fd < 0) {
+ log_error("Netlink open failed.");
+ rc = ISCSI_ERR_INTERNAL;
+ goto free_iovec;
+ }
+
+ log_info("Update flashnode %u.", flashnode_idx);
+ rc = ipc->set_flash_node_params(t->handle, host_no, flashnode_idx,
+ iovs, param_count);
+ if (rc < 0)
+ rc = ISCSI_ERR;
+
+
+ ipc->ctldev_close();
+
+free_iovec:
+ /* start at 2, because 0 is for nlmsghdr and 1 for event */
+ iov = iovs + 2;
+ for (i = 0; i < param_used; i++, iov++) {
+ if (iov->iov_base)
+ free(iov->iov_base);
+ }
+
+ free(iovs);
+
+free_info_rec:
+ if (flashnode_info)
+ free(flashnode_info);
+
+ return rc;
+}
+
+int iscsi_new_flashnode(struct iscsi_transport *t, uint32_t host_no, char *val,
+ uint32_t *flashnode_idx)
+{
+ int fd, rc = 0;
+
+ fd = ipc->ctldev_open();
+ if (fd < 0) {
+ log_error("Netlink open failed.");
+ rc = ISCSI_ERR_INTERNAL;
+ goto exit_new_flashnode;
+ }
+
+ log_info("Create new flashnode for host %u.", host_no);
+ rc = ipc->new_flash_node(t->handle, host_no, val, flashnode_idx);
+ if (rc < 0)
+ rc = ISCSI_ERR;
+
+ ipc->ctldev_close();
+
+exit_new_flashnode:
+ return rc;
+}
+
+int iscsi_del_flashnode(struct iscsi_transport *t, uint32_t host_no,
+ uint32_t flashnode_idx)
+{
+ int fd, rc = 0;
+
+ fd = ipc->ctldev_open();
+ if (fd < 0) {
+ log_error("Netlink open failed.");
+ rc = ISCSI_ERR_INTERNAL;
+ goto exit_del_flashnode;
+ }
+
+ log_info("Delete flashnode %u.", flashnode_idx);
+ rc = ipc->del_flash_node(t->handle, host_no, flashnode_idx);
+ if (rc < 0)
+ rc = ISCSI_ERR;
+
+ ipc->ctldev_close();
+
+exit_del_flashnode:
+ return rc;
+}
+
+int iscsi_login_flashnode(struct iscsi_transport *t, uint32_t host_no,
+ uint32_t flashnode_idx)
+{
+ int fd, rc = 0;
+
+ fd = ipc->ctldev_open();
+ if (fd < 0) {
+ log_error("Netlink open failed.");
+ rc = ISCSI_ERR_INTERNAL;
+ goto exit_login_flashnode;
+ }
+
+ log_info("Login to flashnode %u.", flashnode_idx);
+ rc = ipc->login_flash_node(t->handle, host_no, flashnode_idx);
+ if (rc == -EPERM)
+ rc = ISCSI_ERR_SESS_EXISTS;
+ else if (rc < 0)
+ rc = ISCSI_ERR_LOGIN;
+
+ ipc->ctldev_close();
+
+exit_login_flashnode:
+ return rc;
+}
+
+int iscsi_logout_flashnode(struct iscsi_transport *t, uint32_t host_no,
+ uint32_t flashnode_idx)
+{
+ int fd, rc = 0;
+
+ fd = ipc->ctldev_open();
+ if (fd < 0) {
+ log_error("Netlink open failed.");
+ rc = ISCSI_ERR_INTERNAL;
+ goto exit_logout;
+ }
+
+ log_info("Logout flashnode %u.", flashnode_idx);
+ rc = ipc->logout_flash_node(t->handle, host_no, flashnode_idx);
+ if (rc == -ESRCH)
+ rc = ISCSI_ERR_SESS_NOT_FOUND;
+ else if (rc < 0)
+ rc = ISCSI_ERR_LOGOUT;
+
+ ipc->ctldev_close();
+
+exit_logout:
+ return rc;
+}
+
+int iscsi_logout_flashnode_sid(struct iscsi_transport *t, uint32_t host_no,
+ uint32_t sid)
+{
+ int fd, rc = 0;
+
+ fd = ipc->ctldev_open();
+ if (fd < 0) {
+ log_error("Netlink open failed.");
+ rc = ISCSI_ERR_INTERNAL;
+ goto exit_logout_sid;
+ }
+
+ log_info("Logout sid %u.", sid);
+ rc = ipc->logout_flash_node_sid(t->handle, host_no, sid);
+ if (rc < 0) {
+ log_error("Logout of sid %u failed.", sid);
+ rc = ISCSI_ERR_LOGOUT;
+ } else {
+ log_info("Logout of sid %u successful.", sid);
+ }
+
+ ipc->ctldev_close();
+
+exit_logout_sid:
+ return rc;
+}
+
+static int exec_flashnode_op(int op, int info_level, uint32_t host_no,
+ uint32_t flashnode_idx, int type,
+ struct list_head *params)
+{
+ struct iscsi_transport *t = NULL;
+ int rc = ISCSI_SUCCESS;
+ char *portal_type;
+
+ if (op != OP_SHOW && op != OP_NOOP && op != OP_NEW &&
+ flashnode_idx == 0xffffffff) {
+ log_error("Invalid flashnode index");
+ rc = ISCSI_ERR_INVAL;
+ goto exit_flashnode_op;
+ }
+
+ t = iscsi_sysfs_get_transport_by_hba(host_no);
+ if (!t) {
+ log_error("Could not match hostno %u to transport.", host_no);
+ rc = ISCSI_ERR_TRANS_NOT_FOUND;
+ goto exit_flashnode_op;
+ }
+
+ switch (op) {
+ case OP_NOOP:
+ case OP_SHOW:
+ if (flashnode_idx == 0xffffffff)
+ rc = list_flashnodes(info_level, host_no);
+ else
+ rc = get_flashnode_info(host_no, flashnode_idx);
+ break;
+ case OP_NEW:
+ if (type == IPV4) {
+ portal_type = "ipv4";
+ } else if (type == IPV6) {
+ portal_type = "ipv6";
+ } else {
+ log_error("Invalid type mentioned for flashnode");
+ rc = ISCSI_ERR_INVAL;
+ goto exit_flashnode_op;
+ }
+ rc = iscsi_new_flashnode(t, host_no, portal_type,
+ &flashnode_idx);
+ if (!rc)
+ log_info("New flashnode for host %u added at index %u.",
+ host_no, flashnode_idx);
+ else
+ log_error("Creation of flashnode for host %u failed.",
+ host_no);
+ break;
+ case OP_DELETE:
+ rc = iscsi_del_flashnode(t, host_no, flashnode_idx);
+ if (!rc)
+ log_info("Flashnode %u of host %u deleted.",
+ flashnode_idx, host_no);
+ else
+ log_error("Deletion of flashnode %u of host %u failed.",
+ flashnode_idx, host_no);
+ break;
+ case OP_UPDATE:
+ rc = iscsi_set_flashnode_params(t, host_no, flashnode_idx,
+ params);
+ if (!rc)
+ log_info("Update for flashnode %u of host %u successful.",
+ flashnode_idx, host_no);
+ else
+ log_error("Update for flashnode %u of host %u failed.",
+ flashnode_idx, host_no);
+ break;
+ case OP_LOGIN:
+ rc = iscsi_login_flashnode(t, host_no, flashnode_idx);
+ if (!rc)
+ log_info("Login to flashnode %u of host %u successful.",
+ flashnode_idx, host_no);
+ else if (rc == ISCSI_ERR_SESS_EXISTS)
+ log_info("Flashnode %u of host %u already logged in.",
+ flashnode_idx, host_no);
+ else
+ log_error("Login to flashnode %u of host %u failed.",
+ flashnode_idx, host_no);
+ break;
+ case OP_LOGOUT:
+ rc = iscsi_logout_flashnode(t, host_no, flashnode_idx);
+ if (!rc)
+ log_info("Logout of flashnode %u of host %u successful.",
+ flashnode_idx, host_no);
+ else if (rc == ISCSI_ERR_SESS_NOT_FOUND)
+ log_info("Flashnode %u of host %u not logged in.",
+ flashnode_idx, host_no);
+ else
+ log_error("Logout of flashnode %u of host %u failed.",
+ flashnode_idx, host_no);
+ break;
+ default:
+ log_error("Invalid operation");
+ rc = ISCSI_ERR_INVAL;
+ break;
+ }
+
+exit_flashnode_op:
+ return rc;
+}
+
static int verify_iface_params(struct list_head *params, struct node_rec *rec)
{
struct user_param *param;
@@ -2403,6 +2798,7 @@ main(int argc, char **argv)
int tpgt = PORTAL_GROUP_TAG_UNKNOWN, killiscsid=-1, do_show=0;
int packet_size=32, ping_count=1, ping_interval=0;
int do_discover = 0, sub_mode = -1;
+ int flashnode_idx = -1, portal_type = -1;
struct sigaction sa_old;
struct sigaction sa_new;
struct list_head ifaces;
@@ -2551,11 +2947,19 @@ main(int argc, char **argv)
printf("%s version %s\n", program_name,
ISCSI_VERSION_STR);
return 0;
+ case 'x':
+ flashnode_idx = atoi(optarg);
+ break;
+ case 'A':
+ portal_type = str_to_portal_type(optarg);
+ break;
case 'h':
usage(0);
}
- if (name && value) {
+ if ((mode == MODE_IFACE ||
+ (mode == MODE_HOST && sub_mode == MODE_FLASHNODE)) &&
+ name && value) {
param = idbm_alloc_user_param(name, value);
if (!param) {
log_error("Cannot allocate memory for params.");
@@ -2603,7 +3007,7 @@ main(int argc, char **argv)
switch (mode) {
case MODE_HOST:
- if ((rc = verify_mode_params(argc, argv, "CHdmPov", 0))) {
+ if ((rc = verify_mode_params(argc, argv, "CHdmPotnvxA", 0))) {
log_error("host mode: option '-%c' is not "
"allowed/supported", rc);
rc = ISCSI_ERR_INVAL;
@@ -2621,6 +3025,17 @@ main(int argc, char **argv)
rc = exec_host_chap_op(op, info_level, host_no,
value);
break;
+ case MODE_FLASHNODE:
+ if (!host_no) {
+ log_error("FLASHNODE mode requires host no");
+ rc = ISCSI_ERR_INVAL;
+ break;
+ }
+
+ rc = exec_flashnode_op(op, info_level, host_no,
+ flashnode_idx,
+ portal_type, &params);
+ break;
default:
log_error("Invalid Sub Mode");
break;
diff --git a/usr/netlink.c b/usr/netlink.c
index c43f686..c07fe3c 100644
--- a/usr/netlink.c
+++ b/usr/netlink.c
@@ -1252,6 +1252,169 @@ static int kdelete_chap(uint64_t transport_handle, uint32_t host_no,
return rc;
}
+static int
+kset_flashnode_params(uint64_t transport_handle, uint32_t host_no,
+ uint32_t flashnode_idx, struct iovec *iovs,
+ uint32_t param_count)
+{
+ struct iscsi_uevent ev;
+ int rc, ev_len;
+ struct iovec *iov = iovs + 1;
+
+ log_debug(8, "in %s", __FUNCTION__);
+
+ ev_len = sizeof(ev);
+ ev.type = ISCSI_UEVENT_SET_FLASHNODE_PARAMS;
+ ev.transport_handle = transport_handle;
+ ev.u.set_flashnode.host_no = host_no;
+ ev.u.set_flashnode.flashnode_idx = flashnode_idx;
+ /* first two iovs for nlmsg hdr and ev */
+ ev.u.set_flashnode.count = param_count - 2;
+
+ iov->iov_base = &ev;
+ iov->iov_len = ev_len;
+ rc = __kipc_call(iovs, param_count);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
+static int
+knew_flashnode(uint64_t transport_handle, uint32_t host_no, void *value,
+ uint32_t *flashnode_idx)
+{
+ struct iscsi_uevent *ev;
+ char *param_str;
+ int rc, len;
+ struct iovec iov[2];
+
+ log_debug(7, "in %s", __FUNCTION__);
+
+ memset(setparam_buf, 0, NLM_SETPARAM_DEFAULT_MAX);
+ ev = (struct iscsi_uevent *)setparam_buf;
+ ev->type = ISCSI_UEVENT_NEW_FLASHNODE;
+ ev->transport_handle = transport_handle;
+ ev->u.new_flashnode.host_no = host_no;
+
+ param_str = setparam_buf + sizeof(*ev);
+ if (!strlen(value))
+ return 0;
+ sprintf(param_str, "%s", (char *)value);
+ len = strlen(param_str) + 1;
+ ev->u.new_flashnode.len = len;
+
+
+ iov[1].iov_base = ev;
+ iov[1].iov_len = sizeof(*ev) + len;
+ rc = __kipc_call(iov, 2);
+ if (rc < 0)
+ return rc;
+
+ *flashnode_idx = ev->r.new_flashnode_ret.flashnode_idx;
+ return 0;
+}
+
+static int
+kdel_flashnode(uint64_t transport_handle, uint32_t host_no,
+ uint32_t flashnode_idx)
+{
+ struct iscsi_uevent ev;
+ int rc;
+ struct iovec iov[2];
+
+ log_debug(7, "in %s", __FUNCTION__);
+
+ memset(&ev, 0, sizeof(struct iscsi_uevent));
+ ev.type = ISCSI_UEVENT_DEL_FLASHNODE;
+ ev.transport_handle = transport_handle;
+ ev.u.del_flashnode.host_no = host_no;
+ ev.u.del_flashnode.flashnode_idx = flashnode_idx;
+
+ iov[1].iov_base = &ev;
+ iov[1].iov_len = sizeof(ev);
+ rc = __kipc_call(iov, 2);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
+static int
+klogin_flashnode(uint64_t transport_handle, uint32_t host_no,
+ uint32_t flashnode_idx)
+{
+ struct iscsi_uevent ev;
+ int rc;
+ struct iovec iov[2];
+
+ log_debug(7, "in %s", __FUNCTION__);
+
+ memset(&ev, 0, sizeof(struct iscsi_uevent));
+ ev.type = ISCSI_UEVENT_LOGIN_FLASHNODE;
+ ev.transport_handle = transport_handle;
+ ev.u.login_flashnode.host_no = host_no;
+ ev.u.login_flashnode.flashnode_idx = flashnode_idx;
+
+ iov[1].iov_base = &ev;
+ iov[1].iov_len = sizeof(ev);
+ rc = __kipc_call(iov, 2);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
+static int
+klogout_flashnode(uint64_t transport_handle, uint32_t host_no,
+ uint32_t flashnode_idx)
+{
+ struct iscsi_uevent ev;
+ int rc;
+ struct iovec iov[2];
+
+ log_debug(7, "in %s", __FUNCTION__);
+
+ memset(&ev, 0, sizeof(struct iscsi_uevent));
+ ev.type = ISCSI_UEVENT_LOGOUT_FLASHNODE;
+ ev.transport_handle = transport_handle;
+ ev.u.logout_flashnode.host_no = host_no;
+ ev.u.logout_flashnode.flashnode_idx = flashnode_idx;
+
+ iov[1].iov_base = &ev;
+ iov[1].iov_len = sizeof(ev);
+ rc = __kipc_call(iov, 2);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
+static int
+klogout_flashnode_sid(uint64_t transport_handle, uint32_t host_no,
+ uint32_t sid)
+{
+ struct iscsi_uevent ev;
+ int rc;
+ struct iovec iov[2];
+
+ log_debug(7, "in %s", __FUNCTION__);
+
+ memset(&ev, 0, sizeof(struct iscsi_uevent));
+ ev.type = ISCSI_UEVENT_LOGOUT_FLASHNODE_SID;
+ ev.transport_handle = transport_handle;
+ ev.u.logout_flashnode_sid.host_no = host_no;
+ ev.u.logout_flashnode_sid.sid = sid;
+
+ iov[1].iov_base = &ev;
+ iov[1].iov_len = sizeof(ev);
+ rc = __kipc_call(iov, 2);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
static void drop_data(struct nlmsghdr *nlh)
{
int ev_size;
@@ -1296,10 +1459,10 @@ static int ctldev_handle(void)
ev->r.c_session_ret.sid);
return 0;
case ISCSI_KEVENT_DESTROY_SESSION:
+ drop_data(nlh);
if (!ipc_ev_clbk)
return 0;
- drop_data(nlh);
if (ipc_ev_clbk->destroy_session)
ipc_ev_clbk->destroy_session(ev->r.d_session.host_no,
ev->r.d_session.sid);
@@ -1543,6 +1706,12 @@ struct iscsi_ipc nl_ipc = {
.exec_ping = kexec_ping,
.get_chap = kget_chap,
.delete_chap = kdelete_chap,
+ .set_flash_node_params = kset_flashnode_params,
+ .new_flash_node = knew_flashnode,
+ .del_flash_node = kdel_flashnode,
+ .login_flash_node = klogin_flashnode,
+ .logout_flash_node = klogout_flashnode,
+ .logout_flash_node_sid = klogout_flashnode_sid,
};
struct iscsi_ipc *ipc = &nl_ipc;