1a6d42e7dSPeter Dunlap /* 2a6d42e7dSPeter Dunlap * CDDL HEADER START 3a6d42e7dSPeter Dunlap * 4a6d42e7dSPeter Dunlap * The contents of this file are subject to the terms of the 5a6d42e7dSPeter Dunlap * Common Development and Distribution License (the "License"). 6a6d42e7dSPeter Dunlap * You may not use this file except in compliance with the License. 7a6d42e7dSPeter Dunlap * 8a6d42e7dSPeter Dunlap * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9a6d42e7dSPeter Dunlap * or http://www.opensolaris.org/os/licensing. 10a6d42e7dSPeter Dunlap * See the License for the specific language governing permissions 11a6d42e7dSPeter Dunlap * and limitations under the License. 12a6d42e7dSPeter Dunlap * 13a6d42e7dSPeter Dunlap * When distributing Covered Code, include this CDDL HEADER in each 14a6d42e7dSPeter Dunlap * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15a6d42e7dSPeter Dunlap * If applicable, add the following below this CDDL HEADER, with the 16a6d42e7dSPeter Dunlap * fields enclosed by brackets "[]" replaced with your own identifying 17a6d42e7dSPeter Dunlap * information: Portions Copyright [yyyy] [name of copyright owner] 18a6d42e7dSPeter Dunlap * 19a6d42e7dSPeter Dunlap * CDDL HEADER END 20a6d42e7dSPeter Dunlap */ 21a6d42e7dSPeter Dunlap /* 22d618d68dSPriya Krishnan * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 23a6d42e7dSPeter Dunlap */ 246319b0c7SGarrett D'Amore /* 25*55a3a0efSJosef 'Jeff' Sipek * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 266319b0c7SGarrett D'Amore */ 276319b0c7SGarrett D'Amore 28a6d42e7dSPeter Dunlap #ifndef _IDM_IMPL_H_ 29a6d42e7dSPeter Dunlap #define _IDM_IMPL_H_ 30a6d42e7dSPeter Dunlap 31a6d42e7dSPeter Dunlap #ifdef __cplusplus 32a6d42e7dSPeter Dunlap extern "C" { 33a6d42e7dSPeter Dunlap #endif 34a6d42e7dSPeter Dunlap 35a6d42e7dSPeter Dunlap #include <sys/avl.h> 36a6d42e7dSPeter Dunlap #include <sys/socket_impl.h> 376319b0c7SGarrett D'Amore #include <sys/taskq_impl.h> 38a6d42e7dSPeter Dunlap 39a6d42e7dSPeter Dunlap /* 40a6d42e7dSPeter Dunlap * IDM lock order: 41a6d42e7dSPeter Dunlap * 42a6d42e7dSPeter Dunlap * idm_taskid_table_lock, idm_task_t.idt_mutex 43a6d42e7dSPeter Dunlap */ 44a6d42e7dSPeter Dunlap 45a6d42e7dSPeter Dunlap #define CF_LOGIN_READY 0x00000001 46a6d42e7dSPeter Dunlap #define CF_INITIAL_LOGIN 0x00000002 47a6d42e7dSPeter Dunlap #define CF_ERROR 0x80000000 48a6d42e7dSPeter Dunlap 49a6d42e7dSPeter Dunlap typedef enum { 50a6d42e7dSPeter Dunlap CONN_TYPE_INI = 1, 51a6d42e7dSPeter Dunlap CONN_TYPE_TGT 52a6d42e7dSPeter Dunlap } idm_conn_type_t; 53a6d42e7dSPeter Dunlap 54a6d42e7dSPeter Dunlap /* 55a6d42e7dSPeter Dunlap * Watchdog interval in seconds 56a6d42e7dSPeter Dunlap */ 57a6d42e7dSPeter Dunlap #define IDM_WD_INTERVAL 5 58a6d42e7dSPeter Dunlap 59a6d42e7dSPeter Dunlap /* 6072cf3143Speter dunlap * Timeout period before the client "keepalive" callback is invoked in 6172cf3143Speter dunlap * seconds if the connection is idle. 6272cf3143Speter dunlap */ 6372cf3143Speter dunlap #define IDM_TRANSPORT_KEEPALIVE_IDLE_TIMEOUT 20 6472cf3143Speter dunlap 6572cf3143Speter dunlap /* 66a6d42e7dSPeter Dunlap * Timeout period before a TRANSPORT_FAIL event is generated in seconds 67a6d42e7dSPeter Dunlap * if the connection is idle. 68a6d42e7dSPeter Dunlap */ 69a6d42e7dSPeter Dunlap #define IDM_TRANSPORT_FAIL_IDLE_TIMEOUT 30 70a6d42e7dSPeter Dunlap 71a6d42e7dSPeter Dunlap /* 72a6d42e7dSPeter Dunlap * IDM reference count structure. Audit code is shamelessly adapted 73a6d42e7dSPeter Dunlap * from CIFS server. 74a6d42e7dSPeter Dunlap */ 75a6d42e7dSPeter Dunlap 76a6d42e7dSPeter Dunlap #define REFCNT_AUDIT_STACK_DEPTH 16 77a6d42e7dSPeter Dunlap #define REFCNT_AUDIT_BUF_MAX_REC 16 78a6d42e7dSPeter Dunlap 79a6d42e7dSPeter Dunlap typedef struct { 80a6d42e7dSPeter Dunlap uint32_t anr_refcnt; 81a6d42e7dSPeter Dunlap int anr_depth; 82a6d42e7dSPeter Dunlap pc_t anr_stack[REFCNT_AUDIT_STACK_DEPTH]; 83a6d42e7dSPeter Dunlap } refcnt_audit_record_t; 84a6d42e7dSPeter Dunlap 85a6d42e7dSPeter Dunlap typedef struct { 86a6d42e7dSPeter Dunlap int anb_index; 87a6d42e7dSPeter Dunlap int anb_max_index; 88a6d42e7dSPeter Dunlap refcnt_audit_record_t anb_records[REFCNT_AUDIT_BUF_MAX_REC]; 89a6d42e7dSPeter Dunlap } refcnt_audit_buf_t; 90a6d42e7dSPeter Dunlap 91a6d42e7dSPeter Dunlap #define REFCNT_AUDIT(_rf_) { \ 92a6d42e7dSPeter Dunlap refcnt_audit_record_t *anr; \ 93a6d42e7dSPeter Dunlap \ 94a6d42e7dSPeter Dunlap anr = (_rf_)->ir_audit_buf.anb_records; \ 95a6d42e7dSPeter Dunlap anr += (_rf_)->ir_audit_buf.anb_index; \ 96a6d42e7dSPeter Dunlap (_rf_)->ir_audit_buf.anb_index++; \ 97a6d42e7dSPeter Dunlap (_rf_)->ir_audit_buf.anb_index &= \ 98a6d42e7dSPeter Dunlap (_rf_)->ir_audit_buf.anb_max_index; \ 99a6d42e7dSPeter Dunlap anr->anr_refcnt = (_rf_)->ir_refcnt; \ 100a6d42e7dSPeter Dunlap anr->anr_depth = getpcstack(anr->anr_stack, \ 101a6d42e7dSPeter Dunlap REFCNT_AUDIT_STACK_DEPTH); \ 102a6d42e7dSPeter Dunlap } 103a6d42e7dSPeter Dunlap 104a6d42e7dSPeter Dunlap struct idm_refcnt_s; 105a6d42e7dSPeter Dunlap 106a6d42e7dSPeter Dunlap typedef void (idm_refcnt_cb_t)(void *ref_obj); 107a6d42e7dSPeter Dunlap 108a6d42e7dSPeter Dunlap typedef enum { 109a6d42e7dSPeter Dunlap REF_NOWAIT, 110a6d42e7dSPeter Dunlap REF_WAIT_SYNC, 111a6d42e7dSPeter Dunlap REF_WAIT_ASYNC 112a6d42e7dSPeter Dunlap } idm_refcnt_wait_t; 113a6d42e7dSPeter Dunlap 114a6d42e7dSPeter Dunlap typedef struct idm_refcnt_s { 115a6d42e7dSPeter Dunlap int ir_refcnt; 116a6d42e7dSPeter Dunlap void *ir_referenced_obj; 117a6d42e7dSPeter Dunlap idm_refcnt_wait_t ir_waiting; 118a6d42e7dSPeter Dunlap kmutex_t ir_mutex; 119a6d42e7dSPeter Dunlap kcondvar_t ir_cv; 120a6d42e7dSPeter Dunlap idm_refcnt_cb_t *ir_cb; 121a6d42e7dSPeter Dunlap refcnt_audit_buf_t ir_audit_buf; 122a6d42e7dSPeter Dunlap } idm_refcnt_t; 123a6d42e7dSPeter Dunlap 124a6d42e7dSPeter Dunlap /* 125a6d42e7dSPeter Dunlap * connection parameters - These parameters would be populated at 126a6d42e7dSPeter Dunlap * connection create, or during key-value negotiation at login 127a6d42e7dSPeter Dunlap */ 128a6d42e7dSPeter Dunlap typedef struct idm_conn_params_s { 12956261083SCharles Ting uint32_t max_recv_dataseglen; 13056261083SCharles Ting uint32_t max_xmit_dataseglen; 131aff4bce5Syi zhang - Sun Microsystems - Beijing China uint32_t conn_login_max; 132aff4bce5Syi zhang - Sun Microsystems - Beijing China uint32_t conn_login_interval; 133aff4bce5Syi zhang - Sun Microsystems - Beijing China boolean_t nonblock_socket; 134a6d42e7dSPeter Dunlap } idm_conn_param_t; 135a6d42e7dSPeter Dunlap 136a6d42e7dSPeter Dunlap typedef struct idm_svc_s { 137a6d42e7dSPeter Dunlap list_node_t is_list_node; 138a6d42e7dSPeter Dunlap kmutex_t is_mutex; 139a6d42e7dSPeter Dunlap kcondvar_t is_cv; 140a6d42e7dSPeter Dunlap kmutex_t is_count_mutex; 141a6d42e7dSPeter Dunlap kcondvar_t is_count_cv; 142a6d42e7dSPeter Dunlap idm_refcnt_t is_refcnt; 143a6d42e7dSPeter Dunlap int is_online; 144a6d42e7dSPeter Dunlap /* transport-specific service components */ 145a6d42e7dSPeter Dunlap void *is_so_svc; 146a6d42e7dSPeter Dunlap void *is_iser_svc; 147a6d42e7dSPeter Dunlap idm_svc_req_t is_svc_req; 148a6d42e7dSPeter Dunlap } idm_svc_t; 149a6d42e7dSPeter Dunlap 150a668b114SPriya Krishnan #define ISCSI_MAX_TSIH_LEN 6 /* 0x%04x */ 151a668b114SPriya Krishnan #define ISCSI_MAX_ISID_LEN ISCSI_ISID_LEN * 2 152a668b114SPriya Krishnan 153a6d42e7dSPeter Dunlap typedef struct idm_conn_s { 154a6d42e7dSPeter Dunlap list_node_t ic_list_node; 155a6d42e7dSPeter Dunlap void *ic_handle; 156a6d42e7dSPeter Dunlap idm_refcnt_t ic_refcnt; 157a6d42e7dSPeter Dunlap idm_svc_t *ic_svc_binding; /* Target conn. only */ 158a6d42e7dSPeter Dunlap idm_sockaddr_t ic_ini_dst_addr; 159a6d42e7dSPeter Dunlap struct sockaddr_storage ic_laddr; /* conn local address */ 160a6d42e7dSPeter Dunlap struct sockaddr_storage ic_raddr; /* conn remote address */ 161a668b114SPriya Krishnan 162a668b114SPriya Krishnan /* 163a668b114SPriya Krishnan * the target_name, initiator_name, initiator session 164a668b114SPriya Krishnan * identifier and target session identifying handle 165a668b114SPriya Krishnan * are only used for target connections. 166a668b114SPriya Krishnan */ 167a668b114SPriya Krishnan char ic_target_name[ISCSI_MAX_NAME_LEN + 1]; 168a668b114SPriya Krishnan char ic_initiator_name[ISCSI_MAX_NAME_LEN + 1]; 169a668b114SPriya Krishnan char ic_tsih[ISCSI_MAX_TSIH_LEN + 1]; 170a668b114SPriya Krishnan char ic_isid[ISCSI_MAX_ISID_LEN + 1]; 171a6d42e7dSPeter Dunlap idm_conn_state_t ic_state; 172a6d42e7dSPeter Dunlap idm_conn_state_t ic_last_state; 173a6d42e7dSPeter Dunlap sm_audit_buf_t ic_state_audit; 174a6d42e7dSPeter Dunlap kmutex_t ic_state_mutex; 175a6d42e7dSPeter Dunlap kcondvar_t ic_state_cv; 176a6d42e7dSPeter Dunlap uint32_t ic_state_flags; 177a6d42e7dSPeter Dunlap timeout_id_t ic_state_timeout; 178a6d42e7dSPeter Dunlap struct idm_conn_s *ic_reinstate_conn; /* For conn reinst. */ 179a6d42e7dSPeter Dunlap struct idm_conn_s *ic_logout_conn; /* For other conn logout */ 180a6d42e7dSPeter Dunlap taskq_t *ic_state_taskq; 181a6d42e7dSPeter Dunlap int ic_pdu_events; 182a6d42e7dSPeter Dunlap boolean_t ic_login_info_valid; 183a6d42e7dSPeter Dunlap boolean_t ic_rdma_extensions; 184a6d42e7dSPeter Dunlap uint16_t ic_login_cid; 185a6d42e7dSPeter Dunlap 186a6d42e7dSPeter Dunlap kmutex_t ic_mutex; 187a6d42e7dSPeter Dunlap kcondvar_t ic_cv; 188a6d42e7dSPeter Dunlap idm_status_t ic_conn_sm_status; 189a6d42e7dSPeter Dunlap 190a6d42e7dSPeter Dunlap boolean_t ic_ffp; 19172cf3143Speter dunlap boolean_t ic_keepalive; 192a6d42e7dSPeter Dunlap uint32_t ic_internal_cid; 193a6d42e7dSPeter Dunlap 194a6d42e7dSPeter Dunlap uint32_t ic_conn_flags; 195a6d42e7dSPeter Dunlap idm_conn_type_t ic_conn_type; 196a6d42e7dSPeter Dunlap idm_conn_ops_t ic_conn_ops; 197a6d42e7dSPeter Dunlap idm_transport_ops_t *ic_transport_ops; 198a6d42e7dSPeter Dunlap idm_transport_type_t ic_transport_type; 199a6d42e7dSPeter Dunlap int ic_transport_hdrlen; 200a6d42e7dSPeter Dunlap void *ic_transport_private; 201a6d42e7dSPeter Dunlap idm_conn_param_t ic_conn_params; 202a6d42e7dSPeter Dunlap /* 203a6d42e7dSPeter Dunlap * Save client callback to interpose idm callback 204a6d42e7dSPeter Dunlap */ 205a6d42e7dSPeter Dunlap idm_pdu_cb_t *ic_client_callback; 206a6d42e7dSPeter Dunlap clock_t ic_timestamp; 207a6d42e7dSPeter Dunlap } idm_conn_t; 208a6d42e7dSPeter Dunlap 209a6d42e7dSPeter Dunlap #define IDM_CONN_HEADER_DIGEST 0x00000001 210a6d42e7dSPeter Dunlap #define IDM_CONN_DATA_DIGEST 0x00000002 211a6d42e7dSPeter Dunlap #define IDM_CONN_USE_SCOREBOARD 0x00000004 212a6d42e7dSPeter Dunlap 213a6d42e7dSPeter Dunlap #define IDM_CONN_ISINI(ICI_IC) ((ICI_IC)->ic_conn_type == CONN_TYPE_INI) 214a6d42e7dSPeter Dunlap #define IDM_CONN_ISTGT(ICI_IC) ((ICI_IC)->ic_conn_type == CONN_TYPE_TGT) 215a6d42e7dSPeter Dunlap 216a6d42e7dSPeter Dunlap /* 217a6d42e7dSPeter Dunlap * An IDM target task can transfer data using multiple buffers. The task 218a6d42e7dSPeter Dunlap * will maintain a list of buffers, and each buffer will contain the relative 219a6d42e7dSPeter Dunlap * offset of the transfer and a pointer to the next buffer in the list. 220a6d42e7dSPeter Dunlap * 221a6d42e7dSPeter Dunlap * Note on client private data: 222a6d42e7dSPeter Dunlap * idt_private is intended to be a pointer to some sort of client- 223a6d42e7dSPeter Dunlap * specific state. 224a6d42e7dSPeter Dunlap * 225a6d42e7dSPeter Dunlap * idt_client_handle is a more generic client-private piece of data that can 226a6d42e7dSPeter Dunlap * be used by the client for the express purpose of task lookup. The driving 227a6d42e7dSPeter Dunlap * use case for this is for the client to store the initiator task tag for 228a6d42e7dSPeter Dunlap * a given task so that it may be more easily retrieved for task management. 229a6d42e7dSPeter Dunlap * 230a6d42e7dSPeter Dunlap * The key take away here is that clients should never call 231a6d42e7dSPeter Dunlap * idm_task_find_by_handle in the performance path. 232a6d42e7dSPeter Dunlap * 233a6d42e7dSPeter Dunlap * An initiator will require only one buffer per task, the offset will be 0. 234a6d42e7dSPeter Dunlap */ 235a6d42e7dSPeter Dunlap 236a6d42e7dSPeter Dunlap typedef struct idm_task_s { 237a6d42e7dSPeter Dunlap idm_conn_t *idt_ic; /* Associated connection */ 238a6d42e7dSPeter Dunlap /* connection type is in idt_ic->ic_conn_type */ 239a6d42e7dSPeter Dunlap kmutex_t idt_mutex; 240a6d42e7dSPeter Dunlap void *idt_private; /* Client private data */ 241a6d42e7dSPeter Dunlap uintptr_t idt_client_handle; /* Client private */ 242a6d42e7dSPeter Dunlap uint32_t idt_tt; /* Task tag */ 243a6d42e7dSPeter Dunlap uint32_t idt_r2t_ttt; /* R2T Target Task tag */ 244a6d42e7dSPeter Dunlap idm_task_state_t idt_state; 245a6d42e7dSPeter Dunlap idm_refcnt_t idt_refcnt; 246a6d42e7dSPeter Dunlap 247a6d42e7dSPeter Dunlap /* 248a6d42e7dSPeter Dunlap * Statistics 249a6d42e7dSPeter Dunlap */ 250a6d42e7dSPeter Dunlap int idt_tx_to_ini_start; 251a6d42e7dSPeter Dunlap int idt_tx_to_ini_done; 252a6d42e7dSPeter Dunlap int idt_rx_from_ini_start; 253a6d42e7dSPeter Dunlap int idt_rx_from_ini_done; 25430e7468fSPeter Dunlap int idt_tx_bytes; /* IDM_CONN_USE_SCOREBOARD */ 25530e7468fSPeter Dunlap int idt_rx_bytes; /* IDM_CONN_USE_SCOREBOARD */ 256a6d42e7dSPeter Dunlap 257a6d42e7dSPeter Dunlap uint32_t idt_exp_datasn; /* expected datasn */ 258a6d42e7dSPeter Dunlap uint32_t idt_exp_rttsn; /* expected rttsn */ 259a6d42e7dSPeter Dunlap list_t idt_inbufv; /* chunks of IN buffers */ 260a6d42e7dSPeter Dunlap list_t idt_outbufv; /* chunks of OUT buffers */ 261a6d42e7dSPeter Dunlap 262a6d42e7dSPeter Dunlap /* 263a6d42e7dSPeter Dunlap * Transport header, which describes this tasks remote tagged buffer 264a6d42e7dSPeter Dunlap */ 265a6d42e7dSPeter Dunlap int idt_transport_hdrlen; 266a6d42e7dSPeter Dunlap void *idt_transport_hdr; 26760220f10SPriya Krishnan uint32_t idt_flags; /* phase collapse */ 268a6d42e7dSPeter Dunlap } idm_task_t; 269a6d42e7dSPeter Dunlap 270a6d42e7dSPeter Dunlap int idm_task_constructor(void *task_void, void *arg, int flags); 271a6d42e7dSPeter Dunlap void idm_task_destructor(void *task_void, void *arg); 272a6d42e7dSPeter Dunlap 273a6d42e7dSPeter Dunlap #define IDM_TASKIDS_MAX 16384 274a6d42e7dSPeter Dunlap #define IDM_BUF_MAGIC 0x49425546 /* "IBUF" */ 275a6d42e7dSPeter Dunlap 27660220f10SPriya Krishnan #define IDM_TASK_PHASECOLLAPSE_REQ 0x00000001 /* request phase collapse */ 27760220f10SPriya Krishnan #define IDM_TASK_PHASECOLLAPSE_SUCCESS 0x00000002 /* phase collapse success */ 27860220f10SPriya Krishnan 279a6d42e7dSPeter Dunlap /* Protect with task mutex */ 280a6d42e7dSPeter Dunlap typedef struct idm_buf_s { 281a6d42e7dSPeter Dunlap uint32_t idb_magic; /* "IBUF" */ 282a6d42e7dSPeter Dunlap 283a6d42e7dSPeter Dunlap /* 284a6d42e7dSPeter Dunlap * Note: idm_tx_link *must* be the second element in the list for 285a6d42e7dSPeter Dunlap * proper TX PDU ordering. 286a6d42e7dSPeter Dunlap */ 287a6d42e7dSPeter Dunlap list_node_t idm_tx_link; /* link in a list of TX objects */ 288a6d42e7dSPeter Dunlap 289a6d42e7dSPeter Dunlap list_node_t idb_buflink; /* link in a multi-buffer data xfer */ 290a6d42e7dSPeter Dunlap idm_conn_t *idb_ic; /* Associated connection */ 291a6d42e7dSPeter Dunlap void *idb_buf; /* data */ 292a6d42e7dSPeter Dunlap uint64_t idb_buflen; /* length of buffer */ 293a6d42e7dSPeter Dunlap size_t idb_bufoffset; /* offset in a multi-buffer xfer */ 294a6d42e7dSPeter Dunlap boolean_t idb_bufalloc; /* true if alloc'd in idm_buf_alloc */ 295a6d42e7dSPeter Dunlap /* 296a6d42e7dSPeter Dunlap * DataPDUInOrder=Yes, so to track that the PDUs in a sequence are sent 297a6d42e7dSPeter Dunlap * in continuously increasing address order, check that offsets for a 298a6d42e7dSPeter Dunlap * single buffer xfer are in order. 299a6d42e7dSPeter Dunlap */ 300a6d42e7dSPeter Dunlap uint32_t idb_exp_offset; 301a6d42e7dSPeter Dunlap size_t idb_xfer_len; /* Current requested xfer len */ 302a6d42e7dSPeter Dunlap void *idb_buf_private; /* transport-specific buf handle */ 303a6d42e7dSPeter Dunlap void *idb_reg_private; /* transport-specific reg handle */ 30430e7468fSPeter Dunlap void *idb_bufptr; /* transport-specific bcopy pointer */ 30530e7468fSPeter Dunlap boolean_t idb_bufbcopy; /* true if bcopy required */ 30630e7468fSPeter Dunlap 307a6d42e7dSPeter Dunlap idm_buf_cb_t *idb_buf_cb; /* Data Completion Notify, tgt only */ 308a6d42e7dSPeter Dunlap void *idb_cb_arg; /* Client private data */ 309a6d42e7dSPeter Dunlap idm_task_t *idb_task_binding; 31030e7468fSPeter Dunlap timespec_t idb_xfer_start; 31130e7468fSPeter Dunlap timespec_t idb_xfer_done; 312a6d42e7dSPeter Dunlap boolean_t idb_in_transport; 313a6d42e7dSPeter Dunlap boolean_t idb_tx_thread; /* Sockets only */ 314a6d42e7dSPeter Dunlap iscsi_hdr_t idb_data_hdr_tmpl; /* Sockets only */ 315a6d42e7dSPeter Dunlap idm_status_t idb_status; 316a6d42e7dSPeter Dunlap } idm_buf_t; 317a6d42e7dSPeter Dunlap 31830e7468fSPeter Dunlap typedef enum { 31930e7468fSPeter Dunlap BP_CHECK_QUICK, 32030e7468fSPeter Dunlap BP_CHECK_THOROUGH, 32130e7468fSPeter Dunlap BP_CHECK_ASSERT 32230e7468fSPeter Dunlap } idm_bufpat_check_type_t; 32330e7468fSPeter Dunlap 32430e7468fSPeter Dunlap #define BUFPAT_MATCH(bc_bufpat, bc_idb) \ 32530e7468fSPeter Dunlap ((bufpat->bufpat_idb == bc_idb) && \ 32630e7468fSPeter Dunlap (bufpat->bufpat_bufmagic == IDM_BUF_MAGIC)) 32730e7468fSPeter Dunlap 32830e7468fSPeter Dunlap typedef struct idm_bufpat_s { 32930e7468fSPeter Dunlap void *bufpat_idb; 33030e7468fSPeter Dunlap uint32_t bufpat_bufmagic; 33130e7468fSPeter Dunlap uint32_t bufpat_offset; 33230e7468fSPeter Dunlap } idm_bufpat_t; 33330e7468fSPeter Dunlap 334a6d42e7dSPeter Dunlap #define PDU_MAX_IOVLEN 12 335a6d42e7dSPeter Dunlap #define IDM_PDU_MAGIC 0x49504455 /* "IPDU" */ 336a6d42e7dSPeter Dunlap 337a6d42e7dSPeter Dunlap typedef struct idm_pdu_s { 338a6d42e7dSPeter Dunlap uint32_t isp_magic; /* "IPDU" */ 339a6d42e7dSPeter Dunlap 340a6d42e7dSPeter Dunlap /* 341a6d42e7dSPeter Dunlap * Internal - Order is vital. idm_tx_link *must* be the second 342a6d42e7dSPeter Dunlap * element in this structure for proper TX PDU ordering. 343a6d42e7dSPeter Dunlap */ 344a6d42e7dSPeter Dunlap list_node_t idm_tx_link; 345a6d42e7dSPeter Dunlap 346a6d42e7dSPeter Dunlap list_node_t isp_client_lnd; 347a6d42e7dSPeter Dunlap 348a6d42e7dSPeter Dunlap idm_conn_t *isp_ic; /* Must be set */ 349a6d42e7dSPeter Dunlap iscsi_hdr_t *isp_hdr; 350a6d42e7dSPeter Dunlap uint_t isp_hdrlen; 351a6d42e7dSPeter Dunlap uint8_t *isp_data; 352a6d42e7dSPeter Dunlap uint_t isp_datalen; 353a6d42e7dSPeter Dunlap 354a6d42e7dSPeter Dunlap /* Transport header */ 355a6d42e7dSPeter Dunlap void *isp_transport_hdr; 356a6d42e7dSPeter Dunlap uint32_t isp_transport_hdrlen; 357a6d42e7dSPeter Dunlap void *isp_transport_private; 358a6d42e7dSPeter Dunlap 359a6d42e7dSPeter Dunlap /* 360a6d42e7dSPeter Dunlap * isp_data is used for sending SCSI status, NOP, text, scsi and 361a6d42e7dSPeter Dunlap * non-scsi data. Data is received using isp_iov and isp_iovlen 362a6d42e7dSPeter Dunlap * to support data over multiple buffers. 363a6d42e7dSPeter Dunlap */ 364a6d42e7dSPeter Dunlap void *isp_private; 365a6d42e7dSPeter Dunlap idm_pdu_cb_t *isp_callback; 366a6d42e7dSPeter Dunlap idm_status_t isp_status; 367a6d42e7dSPeter Dunlap 368a6d42e7dSPeter Dunlap /* 369a6d42e7dSPeter Dunlap * The following four elements are only used in 370a6d42e7dSPeter Dunlap * idm_sorecv_scsidata() currently. 371a6d42e7dSPeter Dunlap */ 372a6d42e7dSPeter Dunlap struct iovec isp_iov[PDU_MAX_IOVLEN]; 373a6d42e7dSPeter Dunlap int isp_iovlen; 374a6d42e7dSPeter Dunlap idm_buf_t *isp_sorx_buf; 375a6d42e7dSPeter Dunlap 376a6d42e7dSPeter Dunlap /* Implementation data for idm_pdu_alloc and sorx PDU cache */ 377a6d42e7dSPeter Dunlap uint32_t isp_flags; 378a6d42e7dSPeter Dunlap uint_t isp_hdrbuflen; 379a6d42e7dSPeter Dunlap uint_t isp_databuflen; 380*55a3a0efSJosef 'Jeff' Sipek hrtime_t isp_queue_time; 3816319b0c7SGarrett D'Amore 3826319b0c7SGarrett D'Amore /* Taskq dispatching state for deferred PDU */ 3836319b0c7SGarrett D'Amore taskq_ent_t isp_tqent; 384a6d42e7dSPeter Dunlap } idm_pdu_t; 385a6d42e7dSPeter Dunlap 386a6d42e7dSPeter Dunlap /* 387a6d42e7dSPeter Dunlap * This "generic" object is used when removing an item from the ic_tx_list 388a6d42e7dSPeter Dunlap * in order to determine whether it's an idm_pdu_t or an idm_buf_t 389a6d42e7dSPeter Dunlap */ 390a6d42e7dSPeter Dunlap 391a6d42e7dSPeter Dunlap typedef struct { 392a6d42e7dSPeter Dunlap uint32_t idm_tx_obj_magic; 393a6d42e7dSPeter Dunlap /* 394a6d42e7dSPeter Dunlap * idm_tx_link *must* be the second element in this structure. 395a6d42e7dSPeter Dunlap */ 396a6d42e7dSPeter Dunlap list_node_t idm_tx_link; 397a6d42e7dSPeter Dunlap } idm_tx_obj_t; 398a6d42e7dSPeter Dunlap 399a6d42e7dSPeter Dunlap 400a6d42e7dSPeter Dunlap #define IDM_PDU_OPCODE(PDU) \ 401a6d42e7dSPeter Dunlap ((PDU)->isp_hdr->opcode & ISCSI_OPCODE_MASK) 402a6d42e7dSPeter Dunlap 403a6d42e7dSPeter Dunlap #define IDM_PDU_ALLOC 0x00000001 404a6d42e7dSPeter Dunlap #define IDM_PDU_ADDL_HDR 0x00000002 405a6d42e7dSPeter Dunlap #define IDM_PDU_ADDL_DATA 0x00000004 406a6d42e7dSPeter Dunlap #define IDM_PDU_LOGIN_TX 0x00000008 40760220f10SPriya Krishnan #define IDM_PDU_SET_STATSN 0x00000010 40860220f10SPriya Krishnan #define IDM_PDU_ADVANCE_STATSN 0x00000020 409a6d42e7dSPeter Dunlap 410a6d42e7dSPeter Dunlap #define OSD_EXT_CDB_AHSLEN (200 - 15) 411a6d42e7dSPeter Dunlap #define BIDI_AHS_LENGTH 5 412a6d42e7dSPeter Dunlap #define IDM_SORX_CACHE_AHSLEN \ 413a6d42e7dSPeter Dunlap (((OSD_EXT_CDB_AHSLEN + 3) + \ 414a6d42e7dSPeter Dunlap (BIDI_AHS_LENGTH + 3)) / sizeof (uint32_t)) 415a6d42e7dSPeter Dunlap #define IDM_SORX_CACHE_HDRLEN (sizeof (iscsi_hdr_t) + IDM_SORX_CACHE_AHSLEN) 416a6d42e7dSPeter Dunlap 417a6d42e7dSPeter Dunlap /* 418a6d42e7dSPeter Dunlap * ID pool 419a6d42e7dSPeter Dunlap */ 420a6d42e7dSPeter Dunlap 421a6d42e7dSPeter Dunlap #define IDM_IDPOOL_MAGIC 0x4944504C /* IDPL */ 422a6d42e7dSPeter Dunlap #define IDM_IDPOOL_MIN_SIZE 64 /* Number of IDs to begin with */ 423a6d42e7dSPeter Dunlap #define IDM_IDPOOL_MAX_SIZE 64 * 1024 424a6d42e7dSPeter Dunlap 425a6d42e7dSPeter Dunlap typedef struct idm_idpool { 426a6d42e7dSPeter Dunlap uint32_t id_magic; 427a6d42e7dSPeter Dunlap kmutex_t id_mutex; 428a6d42e7dSPeter Dunlap uint8_t *id_pool; 429a6d42e7dSPeter Dunlap uint32_t id_size; 430a6d42e7dSPeter Dunlap uint8_t id_bit; 431a6d42e7dSPeter Dunlap uint8_t id_bit_idx; 432a6d42e7dSPeter Dunlap uint32_t id_idx; 433a6d42e7dSPeter Dunlap uint32_t id_idx_msk; 434a6d42e7dSPeter Dunlap uint32_t id_free_counter; 435a6d42e7dSPeter Dunlap uint32_t id_max_free_counter; 436a6d42e7dSPeter Dunlap } idm_idpool_t; 437a6d42e7dSPeter Dunlap 438a6d42e7dSPeter Dunlap /* 439a6d42e7dSPeter Dunlap * Global IDM state structure 440a6d42e7dSPeter Dunlap */ 441a6d42e7dSPeter Dunlap typedef struct { 442a6d42e7dSPeter Dunlap kmutex_t idm_global_mutex; 443a6d42e7dSPeter Dunlap taskq_t *idm_global_taskq; 444a6d42e7dSPeter Dunlap kthread_t *idm_wd_thread; 445a6d42e7dSPeter Dunlap kt_did_t idm_wd_thread_did; 446a6d42e7dSPeter Dunlap boolean_t idm_wd_thread_running; 447a6d42e7dSPeter Dunlap kcondvar_t idm_wd_cv; 448a6d42e7dSPeter Dunlap list_t idm_tgt_svc_list; 449a6d42e7dSPeter Dunlap kcondvar_t idm_tgt_svc_cv; 450a6d42e7dSPeter Dunlap list_t idm_tgt_conn_list; 451a6d42e7dSPeter Dunlap int idm_tgt_conn_count; 452a6d42e7dSPeter Dunlap list_t idm_ini_conn_list; 453a6d42e7dSPeter Dunlap kmem_cache_t *idm_buf_cache; 454a6d42e7dSPeter Dunlap kmem_cache_t *idm_task_cache; 455a6d42e7dSPeter Dunlap krwlock_t idm_taskid_table_lock; 456a6d42e7dSPeter Dunlap idm_task_t **idm_taskid_table; 457a6d42e7dSPeter Dunlap uint32_t idm_taskid_next; 458a6d42e7dSPeter Dunlap uint32_t idm_taskid_max; 459a6d42e7dSPeter Dunlap idm_idpool_t idm_conn_id_pool; 460a6d42e7dSPeter Dunlap kmem_cache_t *idm_sotx_pdu_cache; 461a6d42e7dSPeter Dunlap kmem_cache_t *idm_sorx_pdu_cache; 462cf8c0ebaSPeter Dunlap kmem_cache_t *idm_so_128k_buf_cache; 463a6d42e7dSPeter Dunlap } idm_global_t; 464a6d42e7dSPeter Dunlap 465a6d42e7dSPeter Dunlap idm_global_t idm; /* Global state */ 466a6d42e7dSPeter Dunlap 467a6d42e7dSPeter Dunlap int 468a6d42e7dSPeter Dunlap idm_idpool_create(idm_idpool_t *pool); 469a6d42e7dSPeter Dunlap 470a6d42e7dSPeter Dunlap void 471a6d42e7dSPeter Dunlap idm_idpool_destroy(idm_idpool_t *pool); 472a6d42e7dSPeter Dunlap 473a6d42e7dSPeter Dunlap int 474a6d42e7dSPeter Dunlap idm_idpool_alloc(idm_idpool_t *pool, uint16_t *id); 475a6d42e7dSPeter Dunlap 476a6d42e7dSPeter Dunlap void 477a6d42e7dSPeter Dunlap idm_idpool_free(idm_idpool_t *pool, uint16_t id); 478a6d42e7dSPeter Dunlap 479a6d42e7dSPeter Dunlap void 480a6d42e7dSPeter Dunlap idm_pdu_rx(idm_conn_t *ic, idm_pdu_t *pdu); 481a6d42e7dSPeter Dunlap 482a6d42e7dSPeter Dunlap void 483a6d42e7dSPeter Dunlap idm_pdu_tx_forward(idm_conn_t *ic, idm_pdu_t *pdu); 484a6d42e7dSPeter Dunlap 485a6d42e7dSPeter Dunlap boolean_t 486a6d42e7dSPeter Dunlap idm_pdu_rx_forward_ffp(idm_conn_t *ic, idm_pdu_t *pdu); 487a6d42e7dSPeter Dunlap 488a6d42e7dSPeter Dunlap void 489a6d42e7dSPeter Dunlap idm_pdu_rx_forward(idm_conn_t *ic, idm_pdu_t *pdu); 490a6d42e7dSPeter Dunlap 491a6d42e7dSPeter Dunlap void 492a6d42e7dSPeter Dunlap idm_pdu_tx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu); 493a6d42e7dSPeter Dunlap 494a6d42e7dSPeter Dunlap void 495a6d42e7dSPeter Dunlap idm_pdu_rx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu); 496a6d42e7dSPeter Dunlap 497a6d42e7dSPeter Dunlap void idm_parse_login_rsp(idm_conn_t *ic, idm_pdu_t *logout_req_pdu, 498a6d42e7dSPeter Dunlap boolean_t rx); 499a6d42e7dSPeter Dunlap 500a6d42e7dSPeter Dunlap void idm_parse_logout_req(idm_conn_t *ic, idm_pdu_t *logout_req_pdu, 501a6d42e7dSPeter Dunlap boolean_t rx); 502a6d42e7dSPeter Dunlap 503a6d42e7dSPeter Dunlap void idm_parse_logout_rsp(idm_conn_t *ic, idm_pdu_t *login_rsp_pdu, 504a6d42e7dSPeter Dunlap boolean_t rx); 505a6d42e7dSPeter Dunlap 506a6d42e7dSPeter Dunlap idm_status_t idm_svc_conn_create(idm_svc_t *is, idm_transport_type_t type, 507a6d42e7dSPeter Dunlap idm_conn_t **ic_result); 508a6d42e7dSPeter Dunlap 509a6d42e7dSPeter Dunlap void idm_svc_conn_destroy(idm_conn_t *ic); 510a6d42e7dSPeter Dunlap 511a6d42e7dSPeter Dunlap idm_status_t idm_ini_conn_finish(idm_conn_t *ic); 512a6d42e7dSPeter Dunlap 513a6d42e7dSPeter Dunlap idm_status_t idm_tgt_conn_finish(idm_conn_t *ic); 514a6d42e7dSPeter Dunlap 515a6d42e7dSPeter Dunlap idm_conn_t *idm_conn_create_common(idm_conn_type_t conn_type, 516a6d42e7dSPeter Dunlap idm_transport_type_t tt, idm_conn_ops_t *conn_ops); 517a6d42e7dSPeter Dunlap 518a6d42e7dSPeter Dunlap void idm_conn_destroy_common(idm_conn_t *ic); 519a6d42e7dSPeter Dunlap 520a6d42e7dSPeter Dunlap void idm_conn_close(idm_conn_t *ic); 521a6d42e7dSPeter Dunlap 522a6d42e7dSPeter Dunlap uint32_t idm_cid_alloc(void); 523a6d42e7dSPeter Dunlap 524a6d42e7dSPeter Dunlap void idm_cid_free(uint32_t cid); 525a6d42e7dSPeter Dunlap 526a6d42e7dSPeter Dunlap uint32_t idm_crc32c(void *address, unsigned long length); 527a6d42e7dSPeter Dunlap 528a6d42e7dSPeter Dunlap uint32_t idm_crc32c_continued(void *address, unsigned long length, 529a6d42e7dSPeter Dunlap uint32_t crc); 530a6d42e7dSPeter Dunlap 531a6d42e7dSPeter Dunlap void idm_listbuf_insert(list_t *lst, idm_buf_t *buf); 532a6d42e7dSPeter Dunlap 533a6d42e7dSPeter Dunlap idm_conn_t *idm_lookup_conn(uint8_t *isid, uint16_t tsih, uint16_t cid); 534a6d42e7dSPeter Dunlap 535a6d42e7dSPeter Dunlap #ifdef __cplusplus 536a6d42e7dSPeter Dunlap } 537a6d42e7dSPeter Dunlap #endif 538a6d42e7dSPeter Dunlap 539a6d42e7dSPeter Dunlap #endif /* _IDM_IMPL_H_ */ 540