Print this page
NEX-15582 libipmi doesn't support Get Chassis Status IPMI command
Reviewed by: Dan Fields <dan.fields@nexenta.com>
8963 default chunk size used by ipmi_fru_read() is too large for some SP's
Author: Rob Johnston <rob.johnston@joyent.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
8967 libipmi: add support for GET_CHASSIS_STATUS command
8974 fac_prov_ipmi should support binding by entity id and instance
8975 ipmi topo plugin should automatically enumerate sensors on nodes it enumerates
8976 ipmi enumerator should include FRU identity information in FMRI authority
8977 ipmi enumerator doesn't always enumerate nested entities
8978 Add topo facility method for controlling chassis ident indicator
Author: Rob Johnston <rob.johnston@joyent.com>
Reviewed by: Yuri Pankov <yuripv@icloud.com>
Reviewed by: Ben Sims <bensims@gmail.com>
Approved by: Dan McDonald <danmcd@joyent.com>
NEX-15955 Support for more than 255 iSCSI Targets
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
NEX-15955 Support for more than 255 iSCSI Targets
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
NEX-3746 Panic seen if iSCSI Initiator sends a SCSI Response packet to target
NEX-3777 COMSTAR iscsi/io test can panic the target running 5.0
NEX-3785 This is on 5.0 release and iSCSI target can panic while running iSCSI mpxio disable test
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
NEX-3177 enums and string arrays required to be in sync.
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
NEX-2359 iSCSI target connection handling is missing refcount audit information
SUP-776 iSCSI target portals not isolating IQNs on different subnets


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  25  * Copyright (c) 2017, Joyent, Inc.  All rights reserved.
  26  */
  27 
  28 #ifndef _ISCSIT_H_
  29 #define _ISCSIT_H_
  30 
  31 #include <sys/iscsit/iscsi_if.h>
  32 #include <sys/iscsit/iscsit_common.h>
  33 
  34 #include "iscsit_authclient.h"
  35 
  36 /*
  37  * For some reason iscsi_protocol.h lists the max version as "0x02" and the
  38  * min version as "0x00".  RFC3720 clearly states that the current version
  39  * number is 0x00 so that is what we will use.
  40  */
  41 #define ISCSIT_MIN_VERSION                      0x00
  42 #define ISCSIT_MAX_VERSION                      0x00
  43 #define ISCSIT_MAX_CONNECTIONS                  32 /* MC/S support  */
  44 #define ISCSIT_MAX_RECV_DATA_SEGMENT_LENGTH     (32*1024)
  45 #define ISCSIT_MAX_BURST_LENGTH                 (1024*1024)
  46 #define ISCSIT_MAX_FIRST_BURST_LENGTH           ISCSI_DEFAULT_FIRST_BURST_LENGTH
  47 #define ISCSIT_MAX_TIME2WAIT                    ISCSI_MAX_TIME2WAIT
  48 #define ISCSIT_MAX_TIME2RETAIN                  ISCSI_DEFAULT_TIME_TO_RETAIN
  49 #define ISCSIT_MAX_OUTSTANDING_R2T              ISCSI_DEFAULT_MAX_OUT_R2T
  50 #define ISCSIT_MAX_ERROR_RECOVERY_LEVEL         0
  51 #define ISCSIT_MAX_OUTSTANDING_UNEXPECTED_PDUS  0
  52 
  53 #define ISCSIT_DEFAULT_TPG      "iscsit-default-tpg"
  54 #define ISCSIT_DEFAULT_TPGT     1
  55 
  56 #define ISCSI_MAX_TSIH          0xffff
  57 #define ISCSI_UNSPEC_TSIH       0
  58 
  59 /* Max targets per system */
  60 #define ISCSIT_MAX_TARGETS      1024
  61 
  62 #define ISCSIT_MAX_WINDOW       1024
  63 #define ISCSIT_RXPDU_QUEUE_LEN  2048
  64 
  65 /*
  66  * MC/S: A timeout is maintained to recover from lost CmdSN (holes in the
  67  * CmdSN ordering). When the timeout is reached, the ExpCmdSN is advanced
  68  * past the hole to continue processing the queued commands. This value is
  69  * system-tunable (volatile rxpdu_queue_threshold) and should be in the
  70  * range from 5 to 30 seconds.
  71  */
  72 #define ISCSIT_RXPDU_QUEUE_THRESHOLD            5       /* 5 seconds */
  73 #define ISCSIT_RXPDU_QUEUE_MONITOR_INTERVAL     5       /* 5 seconds */
  74 
  75 /* Time in seconds to wait between calls to stmf_deregister_local_port */
  76 #define TGT_DEREG_RETRY_SECONDS 1
  77 
  78 #define ISCSIT_GLOBAL_LOCK(rw) rw_enter(&iscsit_global.global_rwlock, (rw))
  79 #define ISCSIT_GLOBAL_UNLOCK() rw_exit(&iscsit_global.global_rwlock)
  80 
  81 /* Circular buffer to hold the out-of-order PDUs in MC/S */


 107         iscsit_tpg_t    *tpgt_tpg;
 108         idm_refcnt_t    tpgt_refcnt;
 109         avl_node_t      tpgt_tgt_ln;
 110         list_node_t     tpgt_delete_ln;
 111         uint16_t        tpgt_tag;
 112         boolean_t       tpgt_needs_tpg_offline;
 113 } iscsit_tpgt_t;
 114 
 115 typedef struct {
 116         struct sockaddr_storage portal_addr;
 117         int                     portal_online;
 118         idm_refcnt_t            portal_refcnt;
 119         avl_node_t              portal_tpg_ln;
 120         iscsit_tpg_t            *portal_tpg;
 121         idm_svc_t               *portal_svc;
 122         boolean_t               portal_default;
 123         void                    *portal_isns;
 124 } iscsit_portal_t;
 125 
 126 















 127 /* Target states and events, update iscsit_ts_name table whenever modified */
 128 typedef enum {
 129         TS_UNDEFINED = 0,
 130         TS_CREATED,
 131         TS_ONLINING,
 132         TS_ONLINE,
 133         TS_STMF_ONLINE,
 134         TS_DELETING_NEED_OFFLINE,
 135         TS_OFFLINING,
 136         TS_OFFLINE,
 137         TS_STMF_OFFLINE,
 138         TS_DELETING_STMF_DEREG,
 139         TS_DELETING_STMF_DEREG_FAIL,
 140         TS_DELETING,
 141         TS_MAX_STATE
 142 } iscsit_tgt_state_t;
 143 
 144 #ifdef ISCSIT_TGT_SM_STRINGS
 145 static const char *iscsit_ts_name[TS_MAX_STATE+1] = {
 146         "TS_UNDEFINED",
 147         "TS_CREATED",
 148         "TS_ONLINING",
 149         "TS_ONLINE",
 150         "TS_STMF_ONLINE",
 151         "TS_DELETING_NEED_OFFLINE",
 152         "TS_OFFLINING",
 153         "TS_OFFLINE",
 154         "TS_STMF_OFFLINE",
 155         "TS_DELETING_STMF_DEREG",
 156         "TS_DELETING_STMF_DEREG_FAIL",
 157         "TS_DELETING",
 158         "TS_MAX_STATE"
 159 };
 160 #endif
 161 
















 162 typedef enum {
 163         TE_UNDEFINED = 0,
 164         TE_STMF_ONLINE_REQ,
 165         TE_ONLINE_SUCCESS,
 166         TE_ONLINE_FAIL,
 167         TE_STMF_ONLINE_COMPLETE_ACK,
 168         TE_STMF_OFFLINE_REQ,
 169         TE_OFFLINE_COMPLETE,
 170         TE_STMF_OFFLINE_COMPLETE_ACK,
 171         TE_DELETE,
 172         TE_STMF_DEREG_SUCCESS,
 173         TE_STMF_DEREG_FAIL,
 174         TE_STMF_DEREG_RETRY,
 175         TE_WAIT_REF_COMPLETE,
 176         TE_MAX_EVENT
 177 } iscsit_tgt_event_t;
 178 
 179 #ifdef ISCSIT_TGT_SM_STRINGS
 180 static const char *iscsit_te_name[TE_MAX_EVENT+1] = {
 181         "TE_UNDEFINED",
 182         "TE_STMF_ONLINE_REQ",
 183         "TE_ONLINE_SUCCESS",
 184         "TE_ONLINE_FAIL",
 185         "TE_STMF_ONLINE_COMPLETE_ACK",
 186         "TE_STMF_OFFLINE_REQ",
 187         "TE_OFFLINE_COMPLETE",
 188         "TE_STMF_OFFLINE_COMPLETE_ACK",
 189         "TE_DELETE",
 190         "TE_STMF_DEREG_SUCCESS",
 191         "TE_STMF_DEREG_FAIL",
 192         "TE_STMF_DEREG_RETRY",
 193         "TE_WAIT_REF_COMPLETE",
 194         "TE_MAX_EVENT"
 195 };
 196 #endif
 197 
 198 typedef struct {
 199         char                    *target_name;
 200         nvlist_t                *target_props;
 201         kmutex_t                target_mutex;
 202         idm_refcnt_t            target_refcnt;
 203         idm_refcnt_t            target_sess_refcnt;
 204         avl_tree_t              target_tpgt_list;
 205         avl_tree_t              target_sess_list;
 206         avl_node_t              target_global_ln;
 207         avl_node_t              target_global_deleted_ln;
 208         /* STMF lport == iSCSI target */
 209         scsi_devid_desc_t       *target_devid;
 210         stmf_local_port_t       *target_stmf_lport;
 211         uint8_t                 target_stmf_lport_registered;
 212 
 213         /* Target state */
 214         boolean_t               target_sm_busy;


 267  * this is a problem depends on how we use those state machines.  This
 268  * is what we should use them for:
 269  *
 270  * IDM Connection state machine - Decisions related to command processing
 271  * including whether a connection is in FFP
 272  *
 273  * Session state machine - Summarize the state of all available connections
 274  * for the purposes of ERL1, ERL2 and MC/S.  A session in LOGGED_IN state
 275  * should always have at least one FFP connection but there may be a brief
 276  * window where a session in ACTIVE might have one or more FFP connections
 277  * even though ACTIVE is not strictly an FFP state according to the RFC.
 278  *
 279  * Login state machine -- drive the login process, collect negotiated
 280  * parameters.  Another side effect of this approach is that we may get
 281  * the "notify ffp" callback from the IDM connection state machine before
 282  * the login state machine has actually transitioned to FFP state.
 283  */
 284 
 285 struct iscsit_conn_s;
 286 












 287 /* Update iscsit_ss_name table whenever session states are modified */
 288 typedef enum {
 289         SS_UNDEFINED = 0,
 290         SS_Q1_FREE,
 291         SS_Q2_ACTIVE,
 292         SS_Q3_LOGGED_IN,
 293         SS_Q4_FAILED,
 294         SS_Q5_CONTINUE,
 295         SS_Q6_DONE,
 296         SS_Q7_ERROR,
 297         /* Add new session states above SS_MAX_STATE */
 298         SS_MAX_STATE
 299 } iscsit_session_state_t;
 300 
 301 #ifdef ISCSIT_SESS_SM_STRINGS
 302 /* An array of state text values, for use in logging state transitions */
 303 static const char *iscsit_ss_name[SS_MAX_STATE+1] = {
 304         "SS_UNDEFINED",
 305         "SS_Q1_FREE",
 306         "SS_Q2_ACTIVE",
 307         "SS_Q3_LOGGED_IN",
 308         "SS_Q4_FAILED",
 309         "SS_Q5_CONTINUE",
 310         "SS_Q6_DONE",
 311         "SS_Q7_ERROR",
 312         "SS_MAX_STATE"
 313 };
 314 #endif
 315 















 316 /* Update iscsit_se_name table whenever session events are modified */
 317 typedef enum {
 318         SE_UNDEFINED = 0,
 319         SE_CONN_IN_LOGIN,       /* From login state machine */
 320         SE_CONN_LOGGED_IN,      /* FFP enabled client notification */
 321         SE_CONN_FFP_FAIL,       /* FFP disabled client notification */
 322         SE_CONN_FFP_DISABLE,    /* FFP disabled client notification */
 323         SE_CONN_FAIL,           /* Conn destroy client notification */
 324         SE_SESSION_CLOSE,       /* FFP disabled client notification */
 325         SE_SESSION_REINSTATE,   /* From login state machine */
 326         SE_SESSION_TIMEOUT,     /* Internal */
 327         SE_SESSION_CONTINUE,    /* From login state machine */
 328         SE_SESSION_CONTINUE_FAIL, /* From login state machine? */
 329         /* Add new events above SE_MAX_EVENT */
 330         SE_MAX_EVENT
 331 } iscsit_session_event_t;
 332 
 333 #ifdef ISCSIT_SESS_SM_STRINGS
 334 /* An array of event text values, for use in logging events */
 335 static const char *iscsit_se_name[SE_MAX_EVENT+1] = {
 336         "SE_UNDEFINED",
 337         "SE_CONN_IN_LOGIN",
 338         "SE_CONN_LOGGED_IN",
 339         "SE_CONN_FFP_FAIL",
 340         "SE_CONN_FFP_DISABLE",
 341         "SE_CONN_FAIL",
 342         "SE_SESSION_CLOSE",
 343         "SE_SESSION_REINSTATE",
 344         "SE_SESSION_TIMEOUT",
 345         "SE_SESSION_CONTINUE",
 346         "SE_SESSION_CONTINUE_FAIL",
 347         "SE_MAX_EVENT"
 348 };
 349 #endif
 350 
 351 /*
 352  * Set in ist_tgt after iscsit_tgt_unbind_sess to differentiate an unbound
 353  * session from a discovery session.
 354  */
 355 #define SESS_UNBOUND_FROM_TGT   -1
 356 
 357 typedef struct {
 358         stmf_scsi_session_t     *ist_stmf_sess;
 359         stmf_local_port_t       *ist_lport;
 360         iscsit_tgt_t            *ist_tgt;
 361         idm_refcnt_t            ist_refcnt;
 362         kmem_cache_t            *ist_task_cache;
 363         kmutex_t                ist_sn_mutex;
 364         kmutex_t                ist_mutex;
 365         kcondvar_t              ist_cv;
 366         iscsit_session_state_t  ist_state;
 367         iscsit_session_state_t  ist_last_state;


 372         list_t                  ist_events;
 373         int                     ist_conn_count;
 374         int                     ist_ffp_conn_count;
 375         struct iscsit_conn_s    *ist_failed_conn;
 376         timeout_id_t            ist_state_timeout;
 377         list_t                  ist_conn_list;
 378         avl_node_t              ist_tgt_ln;
 379         char                    *ist_initiator_name;
 380         char                    *ist_initiator_alias;
 381         char                    *ist_target_name;
 382         char                    *ist_target_alias;
 383         uint8_t                 ist_isid[ISCSI_ISID_LEN];
 384         uint16_t                ist_tsih;
 385         uint16_t                ist_tpgt_tag;
 386         uint32_t                ist_expcmdsn;
 387         uint32_t                ist_maxcmdsn;
 388         avl_tree_t              ist_task_list;
 389         iscsit_cbuf_t           *ist_rxpdu_queue;
 390 } iscsit_sess_t;
 391 













 392 /* Update iscsit_ils_name table whenever login states are modified */
 393 typedef enum {
 394         ILS_UNDEFINED = 0,
 395         ILS_LOGIN_INIT,
 396         ILS_LOGIN_WAITING,      /* Waiting for more login PDU's */
 397         ILS_LOGIN_PROCESSING,   /* Processing login request */
 398         ILS_LOGIN_RESPONDING,   /* Sending login response */
 399         ILS_LOGIN_RESPONDED,    /* Sent login response (no trans. to FFP) */
 400         ILS_LOGIN_FFP,          /* Sending last login PDU for final response */
 401         ILS_LOGIN_DONE,         /* Last login PDU sent (so we can free it) */
 402         ILS_LOGIN_ERROR,        /* Login error, login failed */
 403         /* Add new login states above ILS_MAX_STATE */
 404         ILS_MAX_STATE
 405 } iscsit_login_state_t;
 406 
 407 #ifdef ISCSIT_LOGIN_SM_STRINGS
 408 /* An array of login state text values, for use in logging login progress */
 409 static const char *iscsit_ils_name[ILS_MAX_STATE+1] = {
 410         "ILS_UNDEFINED",
 411         "ILS_LOGIN_INIT",
 412         "ILS_LOGIN_WAITING",
 413         "ILS_LOGIN_PROCESSING",
 414         "ILS_LOGIN_RESPONDING",
 415         "ILS_LOGIN_RESPONDED",
 416         "ILS_LOGIN_FFP",
 417         "ILS_LOGIN_DONE",
 418         "ILS_LOGIN_ERROR",
 419         "ILS_MAX_STATE"
 420 };
 421 #endif
 422 











 423 /* Update iscsit_ile_name table whenever login events are modified */
 424 typedef enum {
 425         ILE_UNDEFINED = 0,
 426         ILE_LOGIN_RCV,
 427         ILE_LOGIN_RESP_READY,
 428         ILE_LOGIN_FFP,
 429         ILE_LOGIN_RESP_COMPLETE,
 430         ILE_LOGIN_ERROR,
 431         ILE_LOGIN_CONN_ERROR,
 432         /* Add new login events above ILE_MAX_EVENT */
 433         ILE_MAX_EVENT
 434 } iscsit_login_event_t;
 435 
 436 #ifdef ISCSIT_LOGIN_SM_STRINGS
 437 /* An array of login event text values, for use in logging login events */
 438 static const char *iscsit_ile_name[ILE_MAX_EVENT+1] = {
 439         "ILE_UNDEFINED",
 440         "ILE_LOGIN_RCV",
 441         "ILE_LOGIN_RESP_READY",
 442         "ILE_LOGIN_FFP",
 443         "ILE_LOGIN_RESP_COMPLETE",
 444         "ILE_LOGIN_ERROR",
 445         "ILE_LOGIN_CONN_ERROR",
 446         "ILE_MAX_EVENT"
 447 };
 448 #endif
 449 
 450 typedef struct {
 451         uint32_t                op_initial_params_set:1,
 452                                 op_discovery_session:1,
 453                                 op_initial_r2t:1,
 454                                 op_immed_data:1,
 455                                 op_data_pdu_in_order:1,
 456                                 op_data_sequence_in_order:1,
 457                                 op_declarative_params_set:1;
 458         uint64_t                op_max_connections;
 459         uint64_t                op_max_recv_data_segment_length;
 460         uint64_t                op_max_burst_length;
 461         uint64_t                op_first_burst_length;
 462         uint64_t                op_default_time_2_wait;
 463         uint64_t                op_default_time_2_retain;
 464         uint64_t                op_max_outstanding_r2t;
 465         uint64_t                op_error_recovery_level;
 466 } iscsit_op_params_t;


 548         iscsit_conn_t           *it_ict;
 549         kmutex_t                it_mutex;
 550         idm_pdu_t               *it_tm_pdu;
 551         uint32_t                it_stmf_abort:1,
 552                                 it_aborted:1,
 553                                 it_active:1,
 554                                 it_tm_task:1,
 555                                 it_tm_responded:1;
 556         uint32_t                it_cmdsn;
 557         uint32_t                it_itt;
 558         uint32_t                it_ttt;
 559         avl_node_t              it_sess_ln;
 560 } iscsit_task_t;
 561 
 562 typedef struct iscsit_isns_cfg {
 563         kmutex_t                isns_mutex;
 564         boolean_t               isns_state;
 565         list_t                  isns_svrs;
 566 } iscsit_isns_cfg_t;
 567 









 568 /*
 569  * State values for the iscsit service
 570  */
 571 typedef enum {
 572         ISE_UNDEFINED = 0,
 573         ISE_DETACHED,
 574         ISE_DISABLED,
 575         ISE_ENABLING,
 576         ISE_ENABLED,
 577         ISE_BUSY,
 578         ISE_DISABLING
 579 } iscsit_service_enabled_t;
 580 
 581 
 582 typedef struct {
 583         iscsit_service_enabled_t        global_svc_state;
 584         dev_info_t                      *global_dip;
 585         ldi_ident_t                     global_li;
 586         nvlist_t                        *global_props;
 587         stmf_port_provider_t            *global_pp;
 588         stmf_dbuf_store_t               *global_dbuf_store;
 589         taskq_t                         *global_dispatch_taskq;
 590         idm_refcnt_t                    global_refcnt;
 591         avl_tree_t                      global_discovery_sessions;
 592         avl_tree_t                      global_target_list;
 593         list_t                          global_deleted_target_list;
 594         avl_tree_t                      global_tpg_list;
 595         avl_tree_t                      global_ini_list;
 596         iscsit_tpg_t                    *global_default_tpg;
 597         vmem_t                          *global_tsih_pool;
 598         iscsit_isns_cfg_t               global_isns_cfg;


 665 stmf_status_t
 666 iscsit_send_scsi_status(scsi_task_t *task, uint32_t ioflags);
 667 
 668 void
 669 iscsit_lport_task_free(scsi_task_t *task);
 670 
 671 stmf_status_t
 672 iscsit_abort(stmf_local_port_t *lport, int abort_cmd, void *arg,
 673     uint32_t flags);
 674 
 675 void
 676 iscsit_ctl(stmf_local_port_t *lport, int cmd, void *arg);
 677 
 678 /*
 679  * Connection functions
 680  */
 681 idm_status_t
 682 iscsit_conn_reinstate(iscsit_conn_t *existing_ict, iscsit_conn_t *ict);
 683 
 684 void
 685 iscsit_conn_destroy_done(iscsit_conn_t *ict);
 686 
 687 void
 688 iscsit_conn_set_auth(iscsit_conn_t *ict);
 689 
 690 void
 691 iscsit_conn_hold(iscsit_conn_t *ict);
 692 
 693 void
 694 iscsit_conn_rele(iscsit_conn_t *ict);
 695 
 696 void
 697 iscsit_conn_logout(iscsit_conn_t *ict);
 698 
 699 /*
 700  * Session functions
 701  */
 702 int
 703 iscsit_sess_avl_compare(const void *void_sess1, const void *void_sess2);
 704 
 705 iscsit_sess_t *
 706 iscsit_sess_create(iscsit_tgt_t *tgt, iscsit_conn_t *ict,
 707     uint32_t cmdsn, uint8_t *isid, uint16_t tag,




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  25  * Copyright (c) 2017, Joyent, Inc.  All rights reserved.
  26  */
  27 
  28 #ifndef _ISCSIT_H_
  29 #define _ISCSIT_H_
  30 
  31 #include <sys/iscsit/iscsi_if.h>
  32 #include <sys/iscsit/iscsit_common.h>
  33 
  34 #include "iscsit_authclient.h"
  35 
  36 /*
  37  * For some reason iscsi_protocol.h lists the max version as "0x02" and the
  38  * min version as "0x00".  RFC3720 clearly states that the current version
  39  * number is 0x00 so that is what we will use.
  40  */
  41 #define ISCSIT_MIN_VERSION                      0x00
  42 #define ISCSIT_MAX_VERSION                      0x00
  43 #define ISCSIT_MAX_CONNECTIONS                  32 /* MC/S support  */
  44 #define ISCSIT_MAX_RECV_DATA_SEGMENT_LENGTH     (32*1024)
  45 #define ISCSIT_MAX_BURST_LENGTH                 (1024*1024)
  46 #define ISCSIT_MAX_FIRST_BURST_LENGTH           ISCSI_DEFAULT_FIRST_BURST_LENGTH
  47 #define ISCSIT_MAX_TIME2WAIT                    ISCSI_MAX_TIME2WAIT
  48 #define ISCSIT_MAX_TIME2RETAIN                  ISCSI_DEFAULT_TIME_TO_RETAIN
  49 #define ISCSIT_MAX_OUTSTANDING_R2T              ISCSI_DEFAULT_MAX_OUT_R2T
  50 #define ISCSIT_MAX_ERROR_RECOVERY_LEVEL         0
  51 #define ISCSIT_MAX_OUTSTANDING_UNEXPECTED_PDUS  0
  52 
  53 #define ISCSIT_DEFAULT_TPG      "iscsit-default-tpg"
  54 #define ISCSIT_DEFAULT_TPGT     1
  55 
  56 #define ISCSI_MAX_TSIH          0xffff
  57 #define ISCSI_UNSPEC_TSIH       0
  58 



  59 #define ISCSIT_MAX_WINDOW       1024
  60 #define ISCSIT_RXPDU_QUEUE_LEN  2048
  61 
  62 /*
  63  * MC/S: A timeout is maintained to recover from lost CmdSN (holes in the
  64  * CmdSN ordering). When the timeout is reached, the ExpCmdSN is advanced
  65  * past the hole to continue processing the queued commands. This value is
  66  * system-tunable (volatile rxpdu_queue_threshold) and should be in the
  67  * range from 5 to 30 seconds.
  68  */
  69 #define ISCSIT_RXPDU_QUEUE_THRESHOLD            5       /* 5 seconds */
  70 #define ISCSIT_RXPDU_QUEUE_MONITOR_INTERVAL     5       /* 5 seconds */
  71 
  72 /* Time in seconds to wait between calls to stmf_deregister_local_port */
  73 #define TGT_DEREG_RETRY_SECONDS 1
  74 
  75 #define ISCSIT_GLOBAL_LOCK(rw) rw_enter(&iscsit_global.global_rwlock, (rw))
  76 #define ISCSIT_GLOBAL_UNLOCK() rw_exit(&iscsit_global.global_rwlock)
  77 
  78 /* Circular buffer to hold the out-of-order PDUs in MC/S */


 104         iscsit_tpg_t    *tpgt_tpg;
 105         idm_refcnt_t    tpgt_refcnt;
 106         avl_node_t      tpgt_tgt_ln;
 107         list_node_t     tpgt_delete_ln;
 108         uint16_t        tpgt_tag;
 109         boolean_t       tpgt_needs_tpg_offline;
 110 } iscsit_tpgt_t;
 111 
 112 typedef struct {
 113         struct sockaddr_storage portal_addr;
 114         int                     portal_online;
 115         idm_refcnt_t            portal_refcnt;
 116         avl_node_t              portal_tpg_ln;
 117         iscsit_tpg_t            *portal_tpg;
 118         idm_svc_t               *portal_svc;
 119         boolean_t               portal_default;
 120         void                    *portal_isns;
 121 } iscsit_portal_t;
 122 
 123 
 124 #define TGT_STATE_LIST() \
 125         item(TS_UNDEFINED) \
 126         item(TS_CREATED) \
 127         item(TS_ONLINING) \
 128         item(TS_ONLINE) \
 129         item(TS_STMF_ONLINE) \
 130         item(TS_DELETING_NEED_OFFLINE) \
 131         item(TS_OFFLINING) \
 132         item(TS_OFFLINE) \
 133         item(TS_STMF_OFFLINE) \
 134         item(TS_DELETING_STMF_DEREG) \
 135         item(TS_DELETING_STMF_DEREG_FAIL) \
 136         item(TS_DELETING) \
 137         item(TS_MAX_STATE)
 138 
 139 /* Target states and events, update iscsit_ts_name table whenever modified */
 140 typedef enum {
 141 #define item(a) a,
 142         TGT_STATE_LIST()
 143 #undef  item










 144 } iscsit_tgt_state_t;
 145 
 146 #ifdef ISCSIT_TGT_SM_STRINGS
 147 static const char *iscsit_ts_name[TS_MAX_STATE + 1] = {
 148 #define item(a) #a,
 149         TGT_STATE_LIST()
 150 #undef  item










 151 };
 152 #endif
 153 
 154 #define TGT_EVENT_LIST() \
 155         item(TE_UNDEFINED) \
 156         item(TE_STMF_ONLINE_REQ) \
 157         item(TE_ONLINE_SUCCESS) \
 158         item(TE_ONLINE_FAIL) \
 159         item(TE_STMF_ONLINE_COMPLETE_ACK) \
 160         item(TE_STMF_OFFLINE_REQ) \
 161         item(TE_OFFLINE_COMPLETE) \
 162         item(TE_STMF_OFFLINE_COMPLETE_ACK) \
 163         item(TE_DELETE) \
 164         item(TE_STMF_DEREG_SUCCESS) \
 165         item(TE_STMF_DEREG_FAIL) \
 166         item(TE_STMF_DEREG_RETRY) \
 167         item(TE_WAIT_REF_COMPLETE) \
 168         item(TE_MAX_EVENT)
 169 
 170 typedef enum {
 171 #define item(a) a,
 172         TGT_EVENT_LIST()
 173 #undef  item











 174 } iscsit_tgt_event_t;
 175 
 176 #ifdef ISCSIT_TGT_SM_STRINGS
 177 static const char *iscsit_te_name[TE_MAX_EVENT + 1] = {
 178 #define item(a) #a,
 179         TGT_EVENT_LIST()
 180 #undef  item











 181 };
 182 #endif
 183 
 184 typedef struct {
 185         char                    *target_name;
 186         nvlist_t                *target_props;
 187         kmutex_t                target_mutex;
 188         idm_refcnt_t            target_refcnt;
 189         idm_refcnt_t            target_sess_refcnt;
 190         avl_tree_t              target_tpgt_list;
 191         avl_tree_t              target_sess_list;
 192         avl_node_t              target_global_ln;
 193         avl_node_t              target_global_deleted_ln;
 194         /* STMF lport == iSCSI target */
 195         scsi_devid_desc_t       *target_devid;
 196         stmf_local_port_t       *target_stmf_lport;
 197         uint8_t                 target_stmf_lport_registered;
 198 
 199         /* Target state */
 200         boolean_t               target_sm_busy;


 253  * this is a problem depends on how we use those state machines.  This
 254  * is what we should use them for:
 255  *
 256  * IDM Connection state machine - Decisions related to command processing
 257  * including whether a connection is in FFP
 258  *
 259  * Session state machine - Summarize the state of all available connections
 260  * for the purposes of ERL1, ERL2 and MC/S.  A session in LOGGED_IN state
 261  * should always have at least one FFP connection but there may be a brief
 262  * window where a session in ACTIVE might have one or more FFP connections
 263  * even though ACTIVE is not strictly an FFP state according to the RFC.
 264  *
 265  * Login state machine -- drive the login process, collect negotiated
 266  * parameters.  Another side effect of this approach is that we may get
 267  * the "notify ffp" callback from the IDM connection state machine before
 268  * the login state machine has actually transitioned to FFP state.
 269  */
 270 
 271 struct iscsit_conn_s;
 272 
 273 /* Add new session states above SS_MAX_STATE */
 274 #define SESSION_STATE_LIST() \
 275         item(SS_UNDEFINED) \
 276         item(SS_Q1_FREE) \
 277         item(SS_Q2_ACTIVE) \
 278         item(SS_Q3_LOGGED_IN) \
 279         item(SS_Q4_FAILED) \
 280         item(SS_Q5_CONTINUE) \
 281         item(SS_Q6_DONE) \
 282         item(SS_Q7_ERROR) \
 283         item(SS_MAX_STATE)
 284 
 285 /* Update iscsit_ss_name table whenever session states are modified */
 286 typedef enum {
 287 #define item(a) a,
 288         SESSION_STATE_LIST()
 289 #undef  item







 290 } iscsit_session_state_t;
 291 
 292 #ifdef ISCSIT_SESS_SM_STRINGS
 293 /* An array of state text values, for use in logging state transitions */
 294 static const char *iscsit_ss_name[SS_MAX_STATE + 1] = {
 295 #define item(a) #a,
 296         SESSION_STATE_LIST()
 297 #undef  item






 298 };
 299 #endif
 300 
 301 /* Add new events above SE_MAX_EVENT */
 302 #define SESSION_EVENT_LIST() \
 303         item(SE_UNDEFINED) \
 304         item(SE_CONN_IN_LOGIN)  /* From login state machine */ \
 305         item(SE_CONN_LOGGED_IN) /* FFP enabled client notification */ \
 306         item(SE_CONN_FFP_FAIL)  /* FFP disabled client notification */ \
 307         item(SE_CONN_FFP_DISABLE) /* FFP disabled client notification */ \
 308         item(SE_CONN_FAIL) /* Conn destroy client notification */ \
 309         item(SE_SESSION_CLOSE)  /* FFP disabled client notification */ \
 310         item(SE_SESSION_REINSTATE) /* From login state machine */ \
 311         item(SE_SESSION_TIMEOUT) /* Internal */ \
 312         item(SE_SESSION_CONTINUE) /* From login state machine */ \
 313         item(SE_SESSION_CONTINUE_FAIL) /* From login state machine? */ \
 314         item(SE_MAX_EVENT)
 315 
 316 /* Update iscsit_se_name table whenever session events are modified */
 317 typedef enum {
 318 #define item(a) a,
 319         SESSION_EVENT_LIST()
 320 #undef  item










 321 } iscsit_session_event_t;
 322 
 323 #ifdef ISCSIT_SESS_SM_STRINGS
 324 /* An array of event text values, for use in logging events */
 325 static const char *iscsit_se_name[SE_MAX_EVENT + 1] = {
 326 #define item(a) #a,
 327         SESSION_EVENT_LIST()
 328 #undef  item









 329 };
 330 #endif
 331 
 332 /*
 333  * Set in ist_tgt after iscsit_tgt_unbind_sess to differentiate an unbound
 334  * session from a discovery session.
 335  */
 336 #define SESS_UNBOUND_FROM_TGT   -1
 337 
 338 typedef struct {
 339         stmf_scsi_session_t     *ist_stmf_sess;
 340         stmf_local_port_t       *ist_lport;
 341         iscsit_tgt_t            *ist_tgt;
 342         idm_refcnt_t            ist_refcnt;
 343         kmem_cache_t            *ist_task_cache;
 344         kmutex_t                ist_sn_mutex;
 345         kmutex_t                ist_mutex;
 346         kcondvar_t              ist_cv;
 347         iscsit_session_state_t  ist_state;
 348         iscsit_session_state_t  ist_last_state;


 353         list_t                  ist_events;
 354         int                     ist_conn_count;
 355         int                     ist_ffp_conn_count;
 356         struct iscsit_conn_s    *ist_failed_conn;
 357         timeout_id_t            ist_state_timeout;
 358         list_t                  ist_conn_list;
 359         avl_node_t              ist_tgt_ln;
 360         char                    *ist_initiator_name;
 361         char                    *ist_initiator_alias;
 362         char                    *ist_target_name;
 363         char                    *ist_target_alias;
 364         uint8_t                 ist_isid[ISCSI_ISID_LEN];
 365         uint16_t                ist_tsih;
 366         uint16_t                ist_tpgt_tag;
 367         uint32_t                ist_expcmdsn;
 368         uint32_t                ist_maxcmdsn;
 369         avl_tree_t              ist_task_list;
 370         iscsit_cbuf_t           *ist_rxpdu_queue;
 371 } iscsit_sess_t;
 372 
 373 /* Add new login states above ILS_MAX_STATE */
 374 #define LOGIN_STATE_LIST() \
 375         item(ILS_UNDEFINED) \
 376         item(ILS_LOGIN_INIT) \
 377         item(ILS_LOGIN_WAITING) /* Waiting for more login PDU's */ \
 378         item(ILS_LOGIN_PROCESSING) /* Processing login request */ \
 379         item(ILS_LOGIN_RESPONDING) /* Sending login response */ \
 380         item(ILS_LOGIN_RESPONDED) /* Sent login response (no trans. to FFP) */ \
 381         item(ILS_LOGIN_FFP) /* Sending last login PDU for final response */ \
 382         item(ILS_LOGIN_DONE) /* Last login PDU sent (so we can free it) */ \
 383         item(ILS_LOGIN_ERROR) /* Login error, login failed */ \
 384         item(ILS_MAX_STATE)
 385 
 386 /* Update iscsit_ils_name table whenever login states are modified */
 387 typedef enum {
 388 #define item(a) a,
 389         LOGIN_STATE_LIST()
 390 #undef  item








 391 } iscsit_login_state_t;
 392 
 393 #ifdef ISCSIT_LOGIN_SM_STRINGS
 394 /* An array of login state text values, for use in logging login progess */
 395 static const char *iscsit_ils_name[ILS_MAX_STATE + 1] = {
 396 #define item(a) #a,
 397         LOGIN_STATE_LIST()
 398 #undef  item







 399 };
 400 #endif
 401 
 402 /* Add new login events above ILE_MAX_EVENT */
 403 #define LOGIN_EVENT_LIST() \
 404         item(ILE_UNDEFINED) \
 405         item(ILE_LOGIN_RCV) \
 406         item(ILE_LOGIN_RESP_READY) \
 407         item(ILE_LOGIN_FFP) \
 408         item(ILE_LOGIN_RESP_COMPLETE) \
 409         item(ILE_LOGIN_ERROR) \
 410         item(ILE_LOGIN_CONN_ERROR) \
 411         item(ILE_MAX_EVENT)
 412 
 413 /* Update iscsit_ile_name table whenever login events are modified */
 414 typedef enum {
 415 #define item(a) a,
 416         LOGIN_EVENT_LIST()
 417 #undef  item






 418 } iscsit_login_event_t;
 419 
 420 #ifdef ISCSIT_LOGIN_SM_STRINGS
 421 /* An array of login event text values, for use in loggin login events */
 422 static const char *iscsit_ile_name[ILE_MAX_EVENT + 1] = {
 423 #define item(a) #a,
 424         LOGIN_EVENT_LIST()
 425 #undef  item





 426 };
 427 #endif
 428 
 429 typedef struct {
 430         uint32_t                op_initial_params_set:1,
 431                                 op_discovery_session:1,
 432                                 op_initial_r2t:1,
 433                                 op_immed_data:1,
 434                                 op_data_pdu_in_order:1,
 435                                 op_data_sequence_in_order:1,
 436                                 op_declarative_params_set:1;
 437         uint64_t                op_max_connections;
 438         uint64_t                op_max_recv_data_segment_length;
 439         uint64_t                op_max_burst_length;
 440         uint64_t                op_first_burst_length;
 441         uint64_t                op_default_time_2_wait;
 442         uint64_t                op_default_time_2_retain;
 443         uint64_t                op_max_outstanding_r2t;
 444         uint64_t                op_error_recovery_level;
 445 } iscsit_op_params_t;


 527         iscsit_conn_t           *it_ict;
 528         kmutex_t                it_mutex;
 529         idm_pdu_t               *it_tm_pdu;
 530         uint32_t                it_stmf_abort:1,
 531                                 it_aborted:1,
 532                                 it_active:1,
 533                                 it_tm_task:1,
 534                                 it_tm_responded:1;
 535         uint32_t                it_cmdsn;
 536         uint32_t                it_itt;
 537         uint32_t                it_ttt;
 538         avl_node_t              it_sess_ln;
 539 } iscsit_task_t;
 540 
 541 typedef struct iscsit_isns_cfg {
 542         kmutex_t                isns_mutex;
 543         boolean_t               isns_state;
 544         list_t                  isns_svrs;
 545 } iscsit_isns_cfg_t;
 546 
 547 #define SERVICE_ENABLED_LIST() \
 548         item(ISE_UNDEFINED) \
 549         item(ISE_DETACHED) \
 550         item(ISE_DISABLED) \
 551         item(ISE_ENABLING) \
 552         item(ISE_ENABLED) \
 553         item(ISE_BUSY) \
 554         item(ISE_DISABLING)
 555 
 556 /*
 557  * State values for the iscsit service
 558  */
 559 typedef enum {
 560 #define item(a) a,
 561         SERVICE_ENABLED_LIST()
 562 #undef  item




 563 } iscsit_service_enabled_t;
 564 
 565 
 566 typedef struct {
 567         iscsit_service_enabled_t        global_svc_state;
 568         dev_info_t                      *global_dip;
 569         ldi_ident_t                     global_li;
 570         nvlist_t                        *global_props;
 571         stmf_port_provider_t            *global_pp;
 572         stmf_dbuf_store_t               *global_dbuf_store;
 573         taskq_t                         *global_dispatch_taskq;
 574         idm_refcnt_t                    global_refcnt;
 575         avl_tree_t                      global_discovery_sessions;
 576         avl_tree_t                      global_target_list;
 577         list_t                          global_deleted_target_list;
 578         avl_tree_t                      global_tpg_list;
 579         avl_tree_t                      global_ini_list;
 580         iscsit_tpg_t                    *global_default_tpg;
 581         vmem_t                          *global_tsih_pool;
 582         iscsit_isns_cfg_t               global_isns_cfg;


 649 stmf_status_t
 650 iscsit_send_scsi_status(scsi_task_t *task, uint32_t ioflags);
 651 
 652 void
 653 iscsit_lport_task_free(scsi_task_t *task);
 654 
 655 stmf_status_t
 656 iscsit_abort(stmf_local_port_t *lport, int abort_cmd, void *arg,
 657     uint32_t flags);
 658 
 659 void
 660 iscsit_ctl(stmf_local_port_t *lport, int cmd, void *arg);
 661 
 662 /*
 663  * Connection functions
 664  */
 665 idm_status_t
 666 iscsit_conn_reinstate(iscsit_conn_t *existing_ict, iscsit_conn_t *ict);
 667 
 668 void



 669 iscsit_conn_set_auth(iscsit_conn_t *ict);
 670 
 671 void
 672 iscsit_conn_hold(iscsit_conn_t *ict);
 673 
 674 void
 675 iscsit_conn_rele(iscsit_conn_t *ict);
 676 
 677 void
 678 iscsit_conn_logout(iscsit_conn_t *ict);
 679 
 680 /*
 681  * Session functions
 682  */
 683 int
 684 iscsit_sess_avl_compare(const void *void_sess1, const void *void_sess2);
 685 
 686 iscsit_sess_t *
 687 iscsit_sess_create(iscsit_tgt_t *tgt, iscsit_conn_t *ict,
 688     uint32_t cmdsn, uint8_t *isid, uint16_t tag,