xref: /illumos-gate/usr/src/uts/common/sys/idm/idm_impl.h (revision a98e9e2e)
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 /*
2561dfa509SRick McNeal  * Copyright 2014-2015 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 
5972cf3143Speter 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 
65a6d42e7dSPeter 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 */
15861dfa509SRick McNeal 	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 
32461dfa509SRick McNeal #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;
38055a3a0efSJosef '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
41261dfa509SRick McNeal /*
41361dfa509SRick McNeal  * Additional Header Segment (AHS)
41461dfa509SRick McNeal  * AHS is only valid for SCSI Requests and contains SCSI CDB information
41561dfa509SRick McNeal  * which doesn't fit in the standard 16 byte area of the PDU. Commonly
41661dfa509SRick McNeal  * this only holds true for OSD device commands.
41761dfa509SRick McNeal  *
41861dfa509SRick McNeal  * IDM_SORX_CACHE_ASHLEN is the amount of memory which is preallocated in bytes.
41961dfa509SRick McNeal  * When used in the header the AHS length is stored as the number of 4-byte
42061dfa509SRick McNeal  * words; so IDM_SORX_WIRE_ASHLEN is IDM_SORX_CACHE_ASHLEN in words.
42161dfa509SRick McNeal  */
422a6d42e7dSPeter Dunlap #define	IDM_SORX_CACHE_AHSLEN \
42361dfa509SRick McNeal 	((OSD_EXT_CDB_AHSLEN + 3) + (BIDI_AHS_LENGTH + 3))
42461dfa509SRick McNeal #define	IDM_SORX_WIRE_AHSLEN (IDM_SORX_CACHE_AHSLEN / sizeof (uint32_t))
425a6d42e7dSPeter Dunlap #define	IDM_SORX_CACHE_HDRLEN	(sizeof (iscsi_hdr_t) + IDM_SORX_CACHE_AHSLEN)
426a6d42e7dSPeter Dunlap 
427a6d42e7dSPeter Dunlap /*
428a6d42e7dSPeter Dunlap  * ID pool
429a6d42e7dSPeter Dunlap  */
430a6d42e7dSPeter Dunlap 
431a6d42e7dSPeter Dunlap #define	IDM_IDPOOL_MAGIC	0x4944504C	/* IDPL */
432a6d42e7dSPeter Dunlap #define	IDM_IDPOOL_MIN_SIZE	64	/* Number of IDs to begin with */
433a6d42e7dSPeter Dunlap #define	IDM_IDPOOL_MAX_SIZE	64 * 1024
434a6d42e7dSPeter Dunlap 
435a6d42e7dSPeter Dunlap typedef struct idm_idpool {
436a6d42e7dSPeter Dunlap 	uint32_t	id_magic;
437a6d42e7dSPeter Dunlap 	kmutex_t	id_mutex;
438a6d42e7dSPeter Dunlap 	uint8_t		*id_pool;
439a6d42e7dSPeter Dunlap 	uint32_t	id_size;
440a6d42e7dSPeter Dunlap 	uint8_t		id_bit;
441a6d42e7dSPeter Dunlap 	uint8_t		id_bit_idx;
442a6d42e7dSPeter Dunlap 	uint32_t	id_idx;
443a6d42e7dSPeter Dunlap 	uint32_t	id_idx_msk;
444a6d42e7dSPeter Dunlap 	uint32_t	id_free_counter;
445a6d42e7dSPeter Dunlap 	uint32_t	id_max_free_counter;
446a6d42e7dSPeter Dunlap } idm_idpool_t;
447a6d42e7dSPeter Dunlap 
448a6d42e7dSPeter Dunlap /*
449a6d42e7dSPeter Dunlap  * Global IDM state structure
450a6d42e7dSPeter Dunlap  */
451a6d42e7dSPeter Dunlap typedef struct {
452a6d42e7dSPeter Dunlap 	kmutex_t	idm_global_mutex;
453a6d42e7dSPeter Dunlap 	taskq_t		*idm_global_taskq;
454a6d42e7dSPeter Dunlap 	kthread_t	*idm_wd_thread;
455a6d42e7dSPeter Dunlap 	kt_did_t	idm_wd_thread_did;
456a6d42e7dSPeter Dunlap 	boolean_t	idm_wd_thread_running;
457a6d42e7dSPeter Dunlap 	kcondvar_t	idm_wd_cv;
458a6d42e7dSPeter Dunlap 	list_t		idm_tgt_svc_list;
459a6d42e7dSPeter Dunlap 	kcondvar_t	idm_tgt_svc_cv;
460a6d42e7dSPeter Dunlap 	list_t		idm_tgt_conn_list;
461a6d42e7dSPeter Dunlap 	int		idm_tgt_conn_count;
462a6d42e7dSPeter Dunlap 	list_t		idm_ini_conn_list;
463a6d42e7dSPeter Dunlap 	kmem_cache_t	*idm_buf_cache;
464a6d42e7dSPeter Dunlap 	kmem_cache_t	*idm_task_cache;
465a6d42e7dSPeter Dunlap 	krwlock_t	idm_taskid_table_lock;
466a6d42e7dSPeter Dunlap 	idm_task_t	**idm_taskid_table;
467a6d42e7dSPeter Dunlap 	uint32_t	idm_taskid_next;
468a6d42e7dSPeter Dunlap 	uint32_t	idm_taskid_max;
469a6d42e7dSPeter Dunlap 	idm_idpool_t	idm_conn_id_pool;
470a6d42e7dSPeter Dunlap 	kmem_cache_t	*idm_sotx_pdu_cache;
471a6d42e7dSPeter Dunlap 	kmem_cache_t	*idm_sorx_pdu_cache;
472cf8c0ebaSPeter Dunlap 	kmem_cache_t	*idm_so_128k_buf_cache;
473a6d42e7dSPeter Dunlap } idm_global_t;
474a6d42e7dSPeter Dunlap 
475*a98e9e2eSToomas Soome extern idm_global_t	idm; /* Global state */
476a6d42e7dSPeter Dunlap 
477a6d42e7dSPeter Dunlap int
478a6d42e7dSPeter Dunlap idm_idpool_create(idm_idpool_t	*pool);
479a6d42e7dSPeter Dunlap 
480a6d42e7dSPeter Dunlap void
481a6d42e7dSPeter Dunlap idm_idpool_destroy(idm_idpool_t *pool);
482a6d42e7dSPeter Dunlap 
483a6d42e7dSPeter Dunlap int
484a6d42e7dSPeter Dunlap idm_idpool_alloc(idm_idpool_t *pool, uint16_t *id);
485a6d42e7dSPeter Dunlap 
486a6d42e7dSPeter Dunlap void
487a6d42e7dSPeter Dunlap idm_idpool_free(idm_idpool_t *pool, uint16_t id);
488a6d42e7dSPeter Dunlap 
489a6d42e7dSPeter Dunlap void
490a6d42e7dSPeter Dunlap idm_pdu_rx(idm_conn_t *ic, idm_pdu_t *pdu);
491a6d42e7dSPeter Dunlap 
492a6d42e7dSPeter Dunlap void
493a6d42e7dSPeter Dunlap idm_pdu_tx_forward(idm_conn_t *ic, idm_pdu_t *pdu);
494a6d42e7dSPeter Dunlap 
495a6d42e7dSPeter Dunlap boolean_t
496a6d42e7dSPeter Dunlap idm_pdu_rx_forward_ffp(idm_conn_t *ic, idm_pdu_t *pdu);
497a6d42e7dSPeter Dunlap 
498a6d42e7dSPeter Dunlap void
499a6d42e7dSPeter Dunlap idm_pdu_rx_forward(idm_conn_t *ic, idm_pdu_t *pdu);
500a6d42e7dSPeter Dunlap 
501a6d42e7dSPeter Dunlap void
502a6d42e7dSPeter Dunlap idm_pdu_tx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu);
503a6d42e7dSPeter Dunlap 
504a6d42e7dSPeter Dunlap void
505a6d42e7dSPeter Dunlap idm_pdu_rx_protocol_error(idm_conn_t *ic, idm_pdu_t *pdu);
506a6d42e7dSPeter Dunlap 
507a6d42e7dSPeter Dunlap void idm_parse_login_rsp(idm_conn_t *ic, idm_pdu_t *logout_req_pdu,
508a6d42e7dSPeter Dunlap     boolean_t rx);
509a6d42e7dSPeter Dunlap 
510a6d42e7dSPeter Dunlap void idm_parse_logout_req(idm_conn_t *ic, idm_pdu_t *logout_req_pdu,
511a6d42e7dSPeter Dunlap     boolean_t rx);
512a6d42e7dSPeter Dunlap 
513a6d42e7dSPeter Dunlap void idm_parse_logout_rsp(idm_conn_t *ic, idm_pdu_t *login_rsp_pdu,
514a6d42e7dSPeter Dunlap     boolean_t rx);
515a6d42e7dSPeter Dunlap 
516a6d42e7dSPeter Dunlap idm_status_t idm_svc_conn_create(idm_svc_t *is, idm_transport_type_t type,
517a6d42e7dSPeter Dunlap     idm_conn_t **ic_result);
518a6d42e7dSPeter Dunlap 
519a6d42e7dSPeter Dunlap void idm_svc_conn_destroy(idm_conn_t *ic);
520a6d42e7dSPeter Dunlap 
521a6d42e7dSPeter Dunlap idm_status_t idm_ini_conn_finish(idm_conn_t *ic);
522a6d42e7dSPeter Dunlap 
523a6d42e7dSPeter Dunlap idm_status_t idm_tgt_conn_finish(idm_conn_t *ic);
524a6d42e7dSPeter Dunlap 
525a6d42e7dSPeter Dunlap idm_conn_t *idm_conn_create_common(idm_conn_type_t conn_type,
526a6d42e7dSPeter Dunlap     idm_transport_type_t tt, idm_conn_ops_t *conn_ops);
527a6d42e7dSPeter Dunlap 
528a6d42e7dSPeter Dunlap void idm_conn_destroy_common(idm_conn_t *ic);
529a6d42e7dSPeter Dunlap 
530a6d42e7dSPeter Dunlap void idm_conn_close(idm_conn_t *ic);
531a6d42e7dSPeter Dunlap 
532a6d42e7dSPeter Dunlap uint32_t idm_cid_alloc(void);
533a6d42e7dSPeter Dunlap 
534a6d42e7dSPeter Dunlap void idm_cid_free(uint32_t cid);
535a6d42e7dSPeter Dunlap 
536a6d42e7dSPeter Dunlap uint32_t idm_crc32c(void *address, unsigned long length);
537a6d42e7dSPeter Dunlap 
538a6d42e7dSPeter Dunlap uint32_t idm_crc32c_continued(void *address, unsigned long length,
539a6d42e7dSPeter Dunlap     uint32_t crc);
540a6d42e7dSPeter Dunlap 
541a6d42e7dSPeter Dunlap void idm_listbuf_insert(list_t *lst, idm_buf_t *buf);
542a6d42e7dSPeter Dunlap 
543a6d42e7dSPeter Dunlap idm_conn_t *idm_lookup_conn(uint8_t *isid, uint16_t tsih, uint16_t cid);
544a6d42e7dSPeter Dunlap 
545a6d42e7dSPeter Dunlap #ifdef	__cplusplus
546a6d42e7dSPeter Dunlap }
547a6d42e7dSPeter Dunlap #endif
548a6d42e7dSPeter Dunlap 
549a6d42e7dSPeter Dunlap #endif /* _IDM_IMPL_H_ */
550