#ifndef _ISCSI_H
#define _ISCSI_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/scsi/scsi.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/socket.h>
#include <sys/kstat.h>
#include <sys/sunddi.h>
#include <sys/sunmdi.h>
#include <sys/mdi_impldefs.h>
#include <sys/time.h>
#include <sys/nvpair.h>
#include <sys/sdt.h>
#include <sys/iscsi_protocol.h>
#include <sys/scsi/adapters/iscsi_if.h>
#include <iscsiAuthClient.h>
#include <iscsi_stats.h>
#include <iscsi_thread.h>
#include <sys/idm/idm.h>
#include <sys/idm/idm_conn_sm.h>
#include <nvfile.h>
#include <inet/ip.h>
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define LOGIN_PDU_BUFFER_SIZE (16 * 1024)
extern boolean_t iscsi_conn_logging;
extern boolean_t iscsi_io_logging;
extern boolean_t iscsi_login_logging;
extern boolean_t iscsi_logging;
extern boolean_t iscsi_sess_logging;
#define ISCSI_CONN_LOG if (iscsi_conn_logging) cmn_err
#define ISCSI_IO_LOG if (iscsi_io_logging) cmn_err
#define ISCSI_LOGIN_LOG if (iscsi_login_logging) cmn_err
#define ISCSI_LOG if (iscsi_logging) cmn_err
#define ISCSI_SESS_LOG if (iscsi_sess_logging) cmn_err
#define ISCSI_SESS_IOTH_NAME_FORMAT "io_thrd_%d.%d"
#define ISCSI_SESS_WD_NAME_FORMAT "wd_thrd_%d.%d"
#define ISCSI_SESS_LOGIN_TASKQ_NAME_FORMAT "login_taskq_%d.%d"
#define ISCSI_SESS_ENUM_TASKQ_NAME_FORMAT "enum_taskq_%d.%d"
#define ISCSI_CONN_CN_TASKQ_NAME_FORMAT "conn_cn_taskq_%d.%d.%d"
#define ISCSI_CONN_RXTH_NAME_FORMAT "rx_thrd_%d.%d.%d"
#define ISCSI_CONN_TXTH_NAME_FORMAT "tx_thrd_%d.%d.%d"
#define ISCSI_MAX_IOVEC 5
#define ISCSI_DEFAULT_MAX_STORM_DELAY 32
#define ISCSI_SOCKET_SNDBUF_SIZE (256 * 1024)
#define ISCSI_SOCKET_RCVBUF_SIZE (256 * 1024)
#define ISCSI_TCP_NODELAY_DEFAULT 0
#define ISCSI_TCP_CNOTIFY_THRESHOLD_DEFAULT 2000
#define ISCSI_TCP_CABORT_THRESHOLD_DEFAULT 10000
#define ISCSI_TCP_ABORT_THRESHOLD_DEFAULT (30 * 1000)
#define ISNS_TCP_ABORT_THRESHOLD_DEFAULT (3 * 1000)
#define ISCSI_DEFAULT_RX_TIMEOUT_VALUE 60
#define ISCSI_DEFAULT_CONN_DEFAULT_LOGIN_MAX 180
#define ISCSI_DEFAULT_LOGIN_POLLING_DELAY 60
#define TARGET_PROP "target"
#define LUN_PROP "lun"
#define MDI_GUID "wwn"
#define NDI_GUID "client-guid"
#define ISCSI_SIG_CMD 0x11111111
#define ISCSI_SIG_LUN 0x22222222
#define ISCSI_SIG_CONN 0x33333333
#define ISCSI_SIG_SESS 0x44444444
#define ISCSI_SIG_HBA 0x55555555
#define SENDTARGETS_DISCOVERY "SENDTARGETS_DISCOVERY"
#define ISCSI_LUN_MASK_MSB 0x00003f00
#define ISCSI_LUN_MASK_LSB 0x000000ff
#define ISCSI_LUN_MASK (ISCSI_LUN_MASK_MSB | ISCSI_LUN_MASK_LSB)
#define ISCSI_LUN_BYTE_COPY(lun, report_lun_data) \
lun[0] = (report_lun_data & ISCSI_LUN_MASK_MSB) >> 8; \
lun[1] = (report_lun_data & ISCSI_LUN_MASK_LSB);
#define ISCSI_INITIAL_LOGIN_STAGE -1
typedef enum iscsi_status {
ISCSI_STATUS_SUCCESS = 0,
ISCSI_STATUS_INTERNAL_ERROR,
ISCSI_STATUS_ITT_TABLE_FULL,
ISCSI_STATUS_LOGIN_FAILED,
ISCSI_STATUS_NO_CONN_LOGGED_IN,
ISCSI_STATUS_TCP_TX_ERROR,
ISCSI_STATUS_TCP_RX_ERROR,
ISCSI_STATUS_RX_TIMEOUT,
ISCSI_STATUS_HEADER_DIGEST_ERROR,
ISCSI_STATUS_DATA_DIGEST_ERROR,
ISCSI_STATUS_ALLOC_FAILURE,
ISCSI_STATUS_CMD_FAILED,
ISCSI_STATUS_PROTOCOL_ERROR,
ISCSI_STATUS_VERSION_MISMATCH,
ISCSI_STATUS_NEGO_FAIL,
ISCSI_STATUS_AUTHENTICATION_FAILED,
ISCSI_STATUS_REDIRECTION_FAILED,
ISCSI_STATUS_USCSI_FAILED,
ISCSI_STATUS_DATA_OVERFLOW,
ISCSI_STATUS_SHUTDOWN,
ISCSI_STATUS_BUSY,
ISCSI_STATUS_LOGIN_TIMED_OUT,
ISCSI_STATUS_LOGIN_TPGT_NEGO_FAIL
} iscsi_status_t;
#define ISCSI_SUCCESS(status) (status == ISCSI_STATUS_SUCCESS)
#define ISCSI_SNA32_CHECK 2147483648UL
#define ISCSI_CMD_TABLE_SIZE 1024
extern pri_t minclsyspri;
extern ksema_t iscsid_config_semaphore;
extern kmutex_t iscsi_oid_mutex;
extern uint32_t iscsi_oid;
extern void *iscsi_state;
#define ISCSI_DEFAULT_NOP_DELAY 5
extern int iscsi_nop_delay;
#define ISCSI_DEFAULT_RX_WINDOW 20
extern int iscsi_rx_window;
#define ISCSI_DEFAULT_RX_MAX_WINDOW 180
extern int iscsi_rx_max_window;
#define ISCSI_BOOT_DEFAULT_MAX_DELAY 180
typedef struct iscsi_auth {
IscsiAuthStringBlock auth_recv_string_block;
IscsiAuthStringBlock auth_send_string_block;
IscsiAuthLargeBinary auth_recv_binary_block;
IscsiAuthLargeBinary auth_send_binary_block;
IscsiAuthClient auth_client_block;
int num_auth_buffers;
IscsiAuthBufferDesc auth_buffers[5];
int bidirectional_auth;
char username[iscsiAuthStringMaxLength];
uint8_t password[iscsiAuthStringMaxLength];
int password_length;
char username_in[iscsiAuthStringMaxLength];
uint8_t password_in[iscsiAuthStringMaxLength];
int password_length_in;
} iscsi_auth_t;
typedef struct iscsi_task {
void *t_arg;
boolean_t t_blocking;
uint32_t t_event_count;
} iscsi_task_t;
typedef enum iscsi_cmd_type {
ISCSI_CMD_TYPE_SCSI = 1,
ISCSI_CMD_TYPE_NOP,
ISCSI_CMD_TYPE_ABORT,
ISCSI_CMD_TYPE_RESET,
ISCSI_CMD_TYPE_LOGOUT,
ISCSI_CMD_TYPE_LOGIN,
ISCSI_CMD_TYPE_TEXT
} iscsi_cmd_type_t;
typedef enum iscsi_cmd_state {
ISCSI_CMD_STATE_FREE = 0,
ISCSI_CMD_STATE_PENDING,
ISCSI_CMD_STATE_ACTIVE,
ISCSI_CMD_STATE_ABORTING,
ISCSI_CMD_STATE_IDM_ABORTING,
ISCSI_CMD_STATE_COMPLETED,
ISCSI_CMD_STATE_MAX
} iscsi_cmd_state_t;
#ifdef ISCSI_CMD_SM_STRINGS
static const char *iscsi_cmd_state_names[ISCSI_CMD_STATE_MAX+1] = {
"ISCSI_CMD_STATE_FREE",
"ISCSI_CMD_STATE_PENDING",
"ISCSI_CMD_STATE_ACTIVE",
"ISCSI_CMD_STATE_ABORTING",
"ISCSI_CMD_STATE_IDM_ABORTING",
"ISCSI_CMD_STATE_COMPLETED",
"ISCSI_CMD_STATE_MAX"
};
#endif
typedef enum iscsi_cmd_event {
ISCSI_CMD_EVENT_E1 = 0,
ISCSI_CMD_EVENT_E2,
ISCSI_CMD_EVENT_E3,
ISCSI_CMD_EVENT_E4,
ISCSI_CMD_EVENT_E6,
ISCSI_CMD_EVENT_E7,
ISCSI_CMD_EVENT_E8,
ISCSI_CMD_EVENT_E9,
ISCSI_CMD_EVENT_E10,
ISCSI_CMD_EVENT_MAX
} iscsi_cmd_event_t;
#ifdef ISCSI_CMD_SM_STRINGS
static const char *iscsi_cmd_event_names[ISCSI_CMD_EVENT_MAX+1] = {
"ISCSI_CMD_EVENT_E1",
"ISCSI_CMD_EVENT_E2",
"ISCSI_CMD_EVENT_E3",
"ISCSI_CMD_EVENT_E4",
"ISCSI_CMD_EVENT_E6",
"ISCSI_CMD_EVENT_E7",
"ISCSI_CMD_EVENT_E8",
"ISCSI_CMD_EVENT_E9",
"ISCSI_CMD_EVENT_E10",
"ISCSI_CMD_EVENT_MAX"
};
#endif
typedef enum iscsi_cmd_text_stage {
ISCSI_CMD_TEXT_INITIAL_REQ = 0,
ISCSI_CMD_TEXT_CONTINUATION,
ISCSI_CMD_TEXT_FINAL_RSP
} iscsi_cmd_text_stage_t;
#define ISCSI_CMD_MISCFLAG_INTERNAL 0x1
#define ISCSI_CMD_MISCFLAG_FREE 0x2
#define ISCSI_CMD_MISCFLAG_STUCK 0x4
#define ISCSI_CMD_MISCFLAG_XARQ 0x8
#define ISCSI_CMD_MISCFLAG_SENT 0x10
#define ISCSI_CMD_MISCFLAG_FLUSH 0x20
#define ISCSI_CMD_SN_WRAP 0x80000000
#define ISCSI_CMD_PKT_STAT_INIT 0
typedef struct iscsi_cmd {
uint32_t cmd_sig;
struct iscsi_cmd *cmd_prev;
struct iscsi_cmd *cmd_next;
struct iscsi_conn *cmd_conn;
iscsi_cmd_type_t cmd_type;
iscsi_cmd_state_t cmd_state;
iscsi_cmd_state_t cmd_prev_state;
clock_t cmd_lbolt_pending;
clock_t cmd_lbolt_active;
clock_t cmd_lbolt_aborting;
clock_t cmd_lbolt_idm_aborting;
clock_t cmd_lbolt_timeout;
uint8_t cmd_misc_flags;
idm_task_t *cmd_itp;
union {
struct {
idm_buf_t *ibp_ibuf;
idm_buf_t *ibp_obuf;
struct scsi_pkt *pkt;
struct buf *bp;
int cmdlen;
int statuslen;
size_t data_transferred;
uint32_t lun;
struct iscsi_cmd *abort_icmdp;
struct iscsi_cmd *r2t_icmdp;
boolean_t r2t_more;
uint_t pkt_stat;
} scsi;
struct {
struct iscsi_cmd *icmdp;
} abort;
struct {
int level;
uint8_t response;
} reset;
struct {
int rsvd;
} nop;
struct {
struct iscsi_cmd *icmdp;
uint32_t offset;
uint32_t length;
} r2t;
struct {
int rvsd;
} login;
struct {
int rsvd;
} logout;
struct {
char *buf;
int buf_len;
uint32_t offset;
uint32_t data_len;
uint32_t total_rx_len;
uint32_t ttt;
uint8_t lun[8];
iscsi_cmd_text_stage_t stage;
} text;
} cmd_un;
struct iscsi_lun *cmd_lun;
uint32_t cmd_itt;
uint32_t cmd_ttt;
boolean_t cmd_crc_error_seen;
int cmd_result;
int cmd_completed;
kmutex_t cmd_mutex;
kcondvar_t cmd_completion;
idm_pdu_t cmd_pdu;
sm_audit_buf_t cmd_state_audit;
uint32_t cmd_sn;
} iscsi_cmd_t;
typedef struct iscsi_lun {
uint32_t lun_sig;
int lun_state;
struct iscsi_lun *lun_next;
struct iscsi_sess *lun_sess;
dev_info_t *lun_dip;
mdi_pathinfo_t *lun_pip;
uint16_t lun_num;
uint8_t lun_addr_type;
uint32_t lun_oid;
char *lun_guid;
int lun_guid_size;
char *lun_addr;
time_t lun_time_online;
uchar_t lun_cap;
uchar_t lun_vid[ISCSI_INQ_VID_BUF_LEN];
uchar_t lun_pid[ISCSI_INQ_PID_BUF_LEN];
uchar_t lun_type;
kmutex_t lun_mutex;
int lun_refcnt;
} iscsi_lun_t;
#define ISCSI_LUN_STATE_CLEAR 0
#define ISCSI_LUN_STATE_OFFLINE 1
#define ISCSI_LUN_STATE_ONLINE 2
#define ISCSI_LUN_STATE_INVALID 4
#define ISCSI_LUN_STATE_BUSY 8
#define ISCSI_LUN_CAP_RESET 0x01
#define ISCSI_SCSI_RESET_SENSE_CODE 0x29
#define ISCSI_SCSI_LUNCHANGED_CODE 0x3f
#define ISCSI_SCSI_LUNCHANGED_ASCQ 0x0e
typedef struct iscsi_queue {
iscsi_cmd_t *head;
iscsi_cmd_t *tail;
int count;
kmutex_t mutex;
} iscsi_queue_t;
#define ISCSI_CONN_DEFAULT_LOGIN_MIN 0
#define ISCSI_CONN_DEFAULT_LOGIN_REDIRECT 10
typedef struct iscsi_tunable_params {
int recv_login_rsp_timeout;
int conn_login_max;
int polling_login_delay;
} iscsi_tunable_params_t;
typedef union iscsi_sockaddr {
struct sockaddr sin;
struct sockaddr_in sin4;
struct sockaddr_in6 sin6;
} iscsi_sockaddr_t;
#define SIZEOF_SOCKADDR(so) ((so)->sa_family == AF_INET ? \
sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6))
typedef enum {
LOGIN_START,
LOGIN_READY,
LOGIN_TX,
LOGIN_RX,
LOGIN_ERROR,
LOGIN_DONE,
LOGIN_FFP,
LOGIN_MAX
} iscsi_login_state_t;
#ifdef ISCSI_LOGIN_STATE_NAMES
static const char *iscsi_login_state_names[LOGIN_MAX+1] = {
"LOGIN_START",
"LOGIN_READY",
"LOGIN_TX",
"LOGIN_RX",
"LOGIN_ERROR",
"LOGIN_DONE",
"LOGIN_FFP",
"LOGIN_MAX"
};
#endif
typedef enum iscsi_conn_state {
ISCSI_CONN_STATE_UNDEFINED = 0,
ISCSI_CONN_STATE_FREE,
ISCSI_CONN_STATE_IN_LOGIN,
ISCSI_CONN_STATE_LOGGED_IN,
ISCSI_CONN_STATE_IN_LOGOUT,
ISCSI_CONN_STATE_FAILED,
ISCSI_CONN_STATE_POLLING,
ISCSI_CONN_STATE_MAX
} iscsi_conn_state_t;
#ifdef ISCSI_ICS_NAMES
static const char *iscsi_ics_name[ISCSI_CONN_STATE_MAX+1] = {
"ISCSI_CONN_STATE_UNDEFINED",
"ISCSI_CONN_STATE_FREE",
"ISCSI_CONN_STATE_IN_LOGIN",
"ISCSI_CONN_STATE_LOGGED_IN",
"ISCSI_CONN_STATE_IN_LOGOUT",
"ISCSI_CONN_STATE_FAILED",
"ISCSI_CONN_STATE_POLLING",
"ISCSI_CONN_STATE_MAX"
};
#endif
#define ISCSI_CONN_STATE_FULL_FEATURE(state) \
((state == ISCSI_CONN_STATE_LOGGED_IN) || \
(state == ISCSI_CONN_STATE_IN_LOGOUT))
typedef struct iscsi_conn {
uint32_t conn_sig;
struct iscsi_conn *conn_next;
struct iscsi_sess *conn_sess;
iscsi_conn_state_t conn_state;
iscsi_conn_state_t conn_prev_state;
kmutex_t conn_state_mutex;
kcondvar_t conn_state_change;
boolean_t conn_state_destroy;
boolean_t conn_state_ffp;
boolean_t conn_state_idm_connected;
boolean_t conn_async_logout;
ddi_taskq_t *conn_cn_taskq;
idm_conn_t *conn_ic;
iscsi_sockaddr_t conn_base_addr;
iscsi_sockaddr_t conn_curr_addr;
boolean_t conn_bound;
iscsi_sockaddr_t conn_bound_addr;
uint32_t conn_cid;
uint32_t conn_oid;
int conn_current_stage;
int conn_next_stage;
int conn_partial_response;
iscsi_queue_t conn_queue_active;
iscsi_queue_t conn_queue_idm_aborting;
clock_t conn_rx_lbolt;
clock_t conn_nop_lbolt;
iscsi_thread_t *conn_tx_thread;
uint32_t conn_expstatsn;
uint32_t conn_laststatsn;
iscsi_login_params_t conn_params;
struct {
kstat_t *ks;
iscsi_conn_stats_t ks_data;
} stats;
kmutex_t conn_login_mutex;
kcondvar_t conn_login_cv;
iscsi_login_state_t conn_login_state;
iscsi_status_t conn_login_status;
iscsi_hdr_t conn_login_resp_hdr;
char *conn_login_data;
int conn_login_datalen;
int conn_login_max_data_length;
clock_t conn_login_min;
clock_t conn_login_max;
sm_audit_buf_t conn_state_audit;
iscsi_tunable_params_t conn_tunable_params;
boolean_t conn_timeout;
} iscsi_conn_t;
typedef enum iscsi_sess_state {
ISCSI_SESS_STATE_FREE = 0,
ISCSI_SESS_STATE_LOGGED_IN,
ISCSI_SESS_STATE_FAILED,
ISCSI_SESS_STATE_IN_FLUSH,
ISCSI_SESS_STATE_FLUSHED,
ISCSI_SESS_STATE_MAX
} iscsi_sess_state_t;
#ifdef ISCSI_SESS_SM_STRINGS
static const char *iscsi_sess_state_names[ISCSI_SESS_STATE_MAX+1] = {
"ISCSI_SESS_STATE_FREE",
"ISCSI_SESS_STATE_LOGGED_IN",
"ISCSI_SESS_STATE_FAILED",
"ISCSI_SESS_STATE_IN_FLUSH",
"ISCSI_SESS_STATE_FLUSHED",
"ISCSI_SESS_STATE_MAX"
};
#endif
#define ISCSI_SESS_STATE_FULL_FEATURE(state) \
((state == ISCSI_SESS_STATE_LOGGED_IN) || \
(state == ISCSI_SESS_STATE_IN_FLUSH))
typedef enum iscsi_sess_event {
ISCSI_SESS_EVENT_N1 = 0,
ISCSI_SESS_EVENT_N3,
ISCSI_SESS_EVENT_N5,
ISCSI_SESS_EVENT_N6,
ISCSI_SESS_EVENT_N7,
ISCSI_SESS_EVENT_MAX
} iscsi_sess_event_t;
#ifdef ISCSI_SESS_SM_STRINGS
static const char *iscsi_sess_event_names[ISCSI_SESS_EVENT_MAX+1] = {
"ISCSI_SESS_EVENT_N1",
"ISCSI_SESS_EVENT_N3",
"ISCSI_SESS_EVENT_N5",
"ISCSI_SESS_EVENT_N6",
"ISCSI_SESS_EVENT_N7",
"ISCSI_SESS_EVENT_MAX"
};
#endif
typedef enum iscsi_sess_type {
ISCSI_SESS_TYPE_NORMAL = 0,
ISCSI_SESS_TYPE_DISCOVERY
} iscsi_sess_type_t;
#define SESS_ABORT_TASK_MAX_THREADS 1
#define ISCSI_SUN_ISID_0 0x40
#define ISCSI_SUN_ISID_1 0x00
#define ISCSI_SUN_ISID_2 0x00
#define ISCSI_SUN_ISID_3 0x2A
#define ISCSI_SUN_ISID_4 0x00
#define ISCSI_SUN_ISID_5 0xFF
#define ISCSI_DEFAULT_SESS_BOUND B_FALSE
#define ISCSI_DEFAULT_SESS_NUM 1
typedef enum iscsi_enum_status {
ISCSI_SESS_ENUM_FREE = 0,
ISCSI_SESS_ENUM_INPROG,
ISCSI_SESS_ENUM_DONE
} iscsi_enum_status_t;
typedef enum iscsi_enum_result {
ISCSI_SESS_ENUM_COMPLETE = 0,
ISCSI_SESS_ENUM_PARTIAL,
ISCSI_SESS_ENUM_IOFAIL,
ISCSI_SESS_ENUM_SUBMITTED,
ISCSI_SESS_ENUM_SUBFAIL,
ISCSI_SESS_ENUM_GONE,
ISCSI_SESS_ENUM_TUR_FAIL
} iscsi_enum_result_t;
typedef struct iscsi_sess {
uint32_t sess_sig;
iscsi_sess_state_t sess_state;
iscsi_sess_state_t sess_prev_state;
clock_t sess_state_lbolt;
krwlock_t sess_state_rwlock;
uint32_t sess_target_oid;
uint32_t sess_oid;
struct iscsi_sess *sess_next;
struct iscsi_hba *sess_hba;
struct iscsi_lun *sess_lun_list;
krwlock_t sess_lun_list_rwlock;
struct iscsi_conn *sess_conn_list;
struct iscsi_conn *sess_conn_list_last_ptr;
struct iscsi_conn *sess_conn_act;
krwlock_t sess_conn_list_rwlock;
uint32_t sess_conn_next_cid;
clock_t sess_rx_lbolt;
clock_t sess_failure_lbolt;
int sess_storm_delay;
kmutex_t sess_cmdsn_mutex;
uint32_t sess_cmdsn;
uint32_t sess_expcmdsn;
uint32_t sess_maxcmdsn;
uint32_t sess_itt;
struct iscsi_cmd *sess_cmd_table[ISCSI_CMD_TABLE_SIZE];
int sess_cmd_table_count;
iscsi_queue_t sess_queue_pending;
iscsi_error_t sess_last_err;
iscsi_queue_t sess_queue_completion;
iscsi_login_params_t sess_params;
uchar_t sess_name[ISCSI_MAX_NAME_LEN];
int sess_name_length;
char sess_alias[ISCSI_MAX_NAME_LEN];
int sess_alias_length;
iSCSIDiscoveryMethod_t sess_discovered_by;
iscsi_sockaddr_t sess_discovered_addr;
uchar_t sess_isid[ISCSI_ISID_LEN];
uint16_t sess_tsid;
int sess_tpgt_conf;
int sess_tpgt_nego;
iscsi_auth_t sess_auth;
struct {
kstat_t *ks;
iscsi_sess_stats_t ks_data;
kstat_t *ks_io;
kstat_io_t ks_io_data;
kmutex_t ks_io_lock;
} stats;
iscsi_thread_t *sess_ic_thread;
boolean_t sess_window_open;
boolean_t sess_boot;
iscsi_sess_type_t sess_type;
ddi_taskq_t *sess_login_taskq;
iscsi_thread_t *sess_wd_thread;
sm_audit_buf_t sess_state_audit;
kmutex_t sess_reset_mutex;
boolean_t sess_reset_in_progress;
boolean_t sess_boot_nic_reset;
kmutex_t sess_enum_lock;
kcondvar_t sess_enum_cv;
iscsi_enum_status_t sess_enum_status;
iscsi_enum_result_t sess_enum_result;
uint32_t sess_enum_result_count;
ddi_taskq_t *sess_enum_taskq;
kmutex_t sess_state_wmutex;
kcondvar_t sess_state_wcv;
boolean_t sess_state_hasw;
volatile uint32_t sess_state_event_count;
} iscsi_sess_t;
typedef struct iscsi_sess_list {
iscsi_sess_t *session;
struct iscsi_sess_list *next;
} iscsi_sess_list_t;
typedef struct iscsi_cn_task {
idm_conn_t *ct_ic;
idm_client_notify_t ct_icn;
uintptr_t ct_data;
} iscsi_cn_task_t;
typedef struct iscsi_network {
void* (*socket)(int domain, int, int);
int (*bind)(void *, struct sockaddr *, int, int, int);
int (*connect)(void *, struct sockaddr *, int, int, int);
int (*listen)(void *, int);
void* (*accept)(void *, struct sockaddr *, int *);
int (*getsockname)(void *, struct sockaddr *, socklen_t *);
int (*getsockopt)(void *, int, int, void *, int *, int);
int (*setsockopt)(void *, int, int, void *, int);
int (*shutdown)(void *, int);
void (*close)(void *);
size_t (*poll)(void *, clock_t);
size_t (*sendmsg)(void *, struct msghdr *);
size_t (*recvmsg)(void *, struct msghdr *, int);
iscsi_status_t (*sendpdu)(void *, iscsi_hdr_t *, char *, int);
iscsi_status_t (*recvdata)(void *, iscsi_hdr_t *, char *,
int, int, int);
iscsi_status_t (*recvhdr)(void *, iscsi_hdr_t *, int, int, int);
struct {
int sndbuf;
int rcvbuf;
int nodelay;
int conn_notify_threshold;
int conn_abort_threshold;
int abort_threshold;
} tweaks;
} iscsi_network_t;
#define ISCSI_NET_HEADER_DIGEST 0x00000001
#define ISCSI_NET_DATA_DIGEST 0x00000002
extern iscsi_network_t *iscsi_net;
#define ISCSI_CONFIG_STORM_DELAY_DEFAULT 5
typedef struct iscsi_hba {
uint32_t hba_sig;
dev_info_t *hba_dip;
scsi_hba_tran_t *hba_tran;
ldi_ident_t hba_li;
struct iscsi_sess *hba_sess_list;
krwlock_t hba_sess_list_rwlock;
clock_t hba_config_lbolt;
int hba_config_storm_delay;
uchar_t hba_name[ISCSI_MAX_NAME_LEN];
int hba_name_length;
uchar_t hba_alias[ISCSI_MAX_NAME_LEN];
int hba_alias_length;
uchar_t hba_isid[ISCSI_ISID_LEN];
iscsi_login_params_t hba_params;
uint32_t hba_oid;
kmutex_t hba_discovery_events_mutex;
iSCSIDiscoveryMethod_t hba_discovery_events;
boolean_t hba_discovery_in_progress;
boolean_t hba_mpxio_enabled;
boolean_t hba_persistent_loaded;
ksema_t hba_sendtgts_semaphore;
struct {
kstat_t *ks;
iscsi_hba_stats_t ks_data;
} stats;
kmutex_t hba_service_lock;
kcondvar_t hba_service_cv;
uint32_t hba_service_status;
uint32_t hba_service_client_count;
iscsi_tunable_params_t hba_tunable_params;
boolean_t hba_service_status_overwrite;
} iscsi_hba_t;
idm_rx_pdu_cb_t iscsi_rx_scsi_rsp;
idm_rx_pdu_cb_t iscsi_rx_misc_pdu;
idm_rx_pdu_error_cb_t iscsi_rx_error_pdu;
idm_build_hdr_cb_t iscsi_build_hdr;
idm_task_cb_t iscsi_task_aborted;
idm_client_notify_cb_t iscsi_client_notify;
int iscsi_sna_lte(uint32_t n1, uint32_t n2);
char *iscsi_get_next_text(char *data, int data_length, char *curr_text);
void iscsi_ic_thread(iscsi_thread_t *thread, void *arg);
void iscsi_tx_thread(iscsi_thread_t *thread, void *arg);
void iscsi_wd_thread(iscsi_thread_t *thread, void *arg);
iscsi_status_t iscsi_tx_cmd(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
void iscsi_task_cleanup(int opcode, iscsi_cmd_t *icmdp);
void iscsi_handle_abort(void *arg);
iscsi_status_t iscsi_handle_reset(iscsi_sess_t *isp, int level,
iscsi_lun_t *ilp);
iscsi_status_t iscsi_handle_logout(iscsi_conn_t *icp);
iscsi_status_t iscsi_handle_passthru(iscsi_sess_t *isp, uint16_t lun,
struct uscsi_cmd *ucmdp);
iscsi_status_t iscsi_handle_text(iscsi_conn_t *icp,
char *buf, uint32_t buf_len, uint32_t data_len, uint32_t *rx_data_len);
void iscsi_iodone(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
uint32_t iscsi_crc32c(void *address, unsigned long length);
uint32_t iscsi_crc32c_continued(void *address, unsigned long length,
uint32_t crc);
void iscsi_init_queue(iscsi_queue_t *queue);
void iscsi_destroy_queue(iscsi_queue_t *queue);
void iscsi_enqueue_pending_cmd(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
void iscsi_dequeue_pending_cmd(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
void iscsi_enqueue_active_cmd(iscsi_conn_t *icp, iscsi_cmd_t *icmdp);
void iscsi_dequeue_active_cmd(iscsi_conn_t *icp, iscsi_cmd_t *icmdp);
void iscsi_enqueue_idm_aborting_cmd(iscsi_conn_t *icp, iscsi_cmd_t *icmdp);
void iscsi_dequeue_idm_aborting_cmd(iscsi_conn_t *icp, iscsi_cmd_t *icmdp);
void iscsi_enqueue_completed_cmd(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
iscsi_status_t iscsi_dequeue_cmd(iscsi_cmd_t **, iscsi_cmd_t **, iscsi_cmd_t *);
void iscsi_move_queue(iscsi_queue_t *src_queue, iscsi_queue_t *dst_queue);
void iscsi_enqueue_cmd_head(iscsi_cmd_t **, iscsi_cmd_t **,
iscsi_cmd_t *);
void iscsi_login_cb(void *arg);
iscsi_status_t iscsi_login_start(void *arg);
void iscsi_login_update_state(iscsi_conn_t *icp,
iscsi_login_state_t next_state);
void iscsi_login_update_state_locked(iscsi_conn_t *icp,
iscsi_login_state_t next_state);
boolean_t iscsi_hba_kstat_init(struct iscsi_hba *ihp);
boolean_t iscsi_hba_kstat_term(struct iscsi_hba *ihp);
boolean_t iscsi_sess_kstat_init(struct iscsi_sess *isp);
boolean_t iscsi_sess_kstat_term(struct iscsi_sess *isp);
boolean_t iscsi_conn_kstat_init(struct iscsi_conn *icp);
void iscsi_conn_kstat_term(struct iscsi_conn *icp);
void iscsi_net_init();
void iscsi_net_fini();
iscsi_status_t iscsi_net_interface(boolean_t reset);
iscsi_sess_t *iscsi_sess_create(iscsi_hba_t *ihp,
iSCSIDiscoveryMethod_t method, struct sockaddr *addr_dsc,
char *target_name, int tpgt, uchar_t isid_lsb,
iscsi_sess_type_t type, uint32_t *oid);
void iscsi_sess_online(void *arg);
int iscsi_sess_get(uint32_t oid, iscsi_hba_t *ihp, iscsi_sess_t **ispp);
iscsi_status_t iscsi_sess_destroy(iscsi_sess_t *isp);
void iscsi_sess_state_machine(iscsi_sess_t *isp, iscsi_sess_event_t event,
uint32_t event_count);
char *iscsi_sess_state_str(iscsi_sess_state_t state);
boolean_t iscsi_sess_set_auth(iscsi_sess_t *isp);
iscsi_status_t iscsi_sess_reserve_scsi_itt(iscsi_cmd_t *icmdp);
void iscsi_sess_release_scsi_itt(iscsi_cmd_t *icmdp);
iscsi_status_t iscsi_sess_reserve_itt(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
void iscsi_sess_release_itt(iscsi_sess_t *isp, iscsi_cmd_t *icmdp);
void iscsi_sess_redrive_io(iscsi_sess_t *isp);
int iscsi_sess_get_by_target(uint32_t target_oid, iscsi_hba_t *ihp,
iscsi_sess_t **ispp);
iscsi_enum_result_t iscsi_sess_enum_request(iscsi_sess_t *isp,
boolean_t wait, uint32_t event_count);
iscsi_enum_result_t iscsi_sess_enum_query(iscsi_sess_t *isp);
void iscsi_sess_enter_state_zone(iscsi_sess_t *isp);
void iscsi_sess_exit_state_zone(iscsi_sess_t *isp);
iscsi_status_t iscsi_conn_create(struct sockaddr *addr, iscsi_sess_t *isp,
iscsi_conn_t **icpp);
iscsi_status_t iscsi_conn_online(iscsi_conn_t *icp);
iscsi_status_t iscsi_conn_offline(iscsi_conn_t *icp);
iscsi_status_t iscsi_conn_destroy(iscsi_conn_t *icp);
void iscsi_conn_set_login_min_max(iscsi_conn_t *icp, int min, int max);
iscsi_status_t iscsi_conn_sync_params(iscsi_conn_t *icp);
void iscsi_conn_retry(iscsi_sess_t *isp, iscsi_conn_t *icp);
void iscsi_conn_update_state(iscsi_conn_t *icp, iscsi_conn_state_t next_state);
void iscsi_conn_update_state_locked(iscsi_conn_t *icp,
iscsi_conn_state_t next_state);
iscsi_status_t iscsi_lun_create(iscsi_sess_t *isp, uint16_t lun_num,
uint8_t lun_addr_type, struct scsi_inquiry *inq, char *guid);
void iscsi_lun_hold(iscsi_lun_t *ilp);
void iscsi_lun_rele(iscsi_lun_t *ilp);
iscsi_status_t iscsi_lun_destroy(iscsi_hba_t *ihp, iscsi_lun_t *ilp);
void iscsi_lun_online(iscsi_hba_t *ihp,
iscsi_lun_t *ilp);
iscsi_status_t iscsi_lun_offline(iscsi_hba_t *ihp,
iscsi_lun_t *ilp, boolean_t lun_free);
void iscsi_cmd_state_machine(iscsi_cmd_t *icmdp,
iscsi_cmd_event_t event, void *arg);
iscsi_cmd_t *iscsi_cmd_alloc(iscsi_conn_t *icp, int km_flags);
void iscsi_cmd_free(iscsi_cmd_t *icmdp);
void * iscsi_ioctl_copyin(caddr_t arg, int mode, size_t size);
int iscsi_ioctl_copyout(void *data, size_t size, caddr_t arg, int mode);
iscsi_conn_list_t *iscsi_ioctl_conn_oid_list_get_copyin(caddr_t, int);
int iscsi_ioctl_conn_oid_list_get_copyout(iscsi_conn_list_t *, caddr_t, int);
boolean_t iscsi_ioctl_conn_oid_list_get(iscsi_hba_t *ihp,
iscsi_conn_list_t *cl);
boolean_t iscsi_ioctl_conn_props_get(iscsi_hba_t *ihp, iscsi_conn_props_t *cp);
int iscsi_ioctl_sendtgts_get(iscsi_hba_t *ihp, iscsi_sendtgts_list_t *stl);
int iscsi_target_prop_mod(iscsi_hba_t *, iscsi_property_t *, int cmd);
int iscsi_set_params(iscsi_param_set_t *, iscsi_hba_t *, boolean_t);
int iscsi_get_persisted_param(uchar_t *, iscsi_param_get_t *,
iscsi_login_params_t *);
void iscsi_set_default_login_params(iscsi_login_params_t *params);
int iscsi_ioctl_get_config_sess(iscsi_hba_t *ihp,
iscsi_config_sess_t *ics);
int iscsi_ioctl_set_config_sess(iscsi_hba_t *ihp,
iscsi_config_sess_t *ics);
int iscsi_ioctl_set_tunable_param(iscsi_hba_t *ihp,
iscsi_tunable_object_t *tpss);
int iscsi_get_param(iscsi_login_params_t *params,
boolean_t valid_flag,
iscsi_param_get_t *ipgp);
boolean_t iscsid_init(iscsi_hba_t *ihp);
boolean_t iscsid_start(iscsi_hba_t *ihp);
boolean_t iscsid_stop(iscsi_hba_t *ihp);
void iscsid_fini();
void iscsid_props(iSCSIDiscoveryProperties_t *props);
boolean_t iscsid_enable_discovery(iscsi_hba_t *ihp,
iSCSIDiscoveryMethod_t idm, boolean_t poke);
boolean_t iscsid_disable_discovery(iscsi_hba_t *ihp,
iSCSIDiscoveryMethod_t idm);
void iscsid_poke_discovery(iscsi_hba_t *ihp, iSCSIDiscoveryMethod_t method);
void iscsid_do_sendtgts(entry_t *discovery_addr);
void iscsid_do_isns_query_one_server(
iscsi_hba_t *ihp, entry_t *isns_addr);
void iscsid_do_isns_query(iscsi_hba_t *ihp);
void iscsid_config_one(iscsi_hba_t *ihp,
char *name, boolean_t protect);
void iscsid_config_all(iscsi_hba_t *ihp, boolean_t protect);
void iscsid_unconfig_one(iscsi_hba_t *ihp, char *name);
void iscsid_unconfig_all(iscsi_hba_t *ihp);
void isns_scn_callback(void *arg);
boolean_t iscsid_del(iscsi_hba_t *ihp, char *target_name,
iSCSIDiscoveryMethod_t method, struct sockaddr *addr_dsc);
boolean_t iscsid_login_tgt(iscsi_hba_t *ihp, char *target_name,
iSCSIDiscoveryMethod_t method, struct sockaddr *addr_dsc);
void iscsid_addr_to_sockaddr(int src_insize, void *src_addr, int src_port,
struct sockaddr *dst_addr);
void iscsid_set_default_initiator_node_settings(iscsi_hba_t *ihp,
boolean_t minimal);
void iscsi_send_sysevent(iscsi_hba_t *ihp, char *eventcalss,
char *subclass, nvlist_t *np);
boolean_t iscsi_reconfig_boot_sess(iscsi_hba_t *ihp);
boolean_t iscsi_chk_bootlun_mpxio(iscsi_hba_t *ihp);
boolean_t iscsi_cmp_boot_ini_name(char *name);
boolean_t iscsi_cmp_boot_tgt_name(char *name);
boolean_t iscsi_client_request_service(iscsi_hba_t *ihp);
void iscsi_client_release_service(iscsi_hba_t *ihp);
extern void bcopy(const void *s1, void *s2, size_t n);
extern void bzero(void *s, size_t n);
#ifdef __cplusplus
}
#endif
#endif