--- /dev/null Fri Apr 4 13:31:05 2008 +++ new/src/sun_nws/idm/hdrs/idm_impl.h Fri Apr 4 13:31:05 2008 @@ -0,0 +1,325 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at src/sun_nws/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at src/sun_nws/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +#ifndef _IDM_IMPL_H_ +#define _IDM_IMPL_H_ + +#pragma ident "@(#)idm_impl.h 1.18 08/03/26 SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct { + kmutex_t idm_global_mutex; + taskq_t *idm_global_taskq; + list_t idm_tgt_svc_list; + list_t idm_ini_conn_list; +} idm_global_t; + +#define CF_LOGIN_READY 0x00000001 +#define CF_INITIAL_LOGIN 0x00000002 +#define CF_ERROR 0x80000000 + +typedef enum { + CONN_TYPE_INI = 1, + CONN_TYPE_TGT +} idm_conn_type_t; + +typedef union idm_sockaddr { + struct sockaddr sin; + struct sockaddr_in sin4; + struct sockaddr_in6 sin6; +} idm_sockaddr_t; + +/* + * connection parameters - These parameters would be populated at + * connection create, or during key-value negotiation at login + */ +typedef struct idm_conn_params_s { + uint32_t max_dataseglen; +} idm_conn_param_t; + +typedef struct idm_svc_s { + list_node_t is_list_node; + kmutex_t is_mutex; + kcondvar_t is_cv; + kmutex_t is_count_mutex; + kcondvar_t is_count_cv; + /* transport-specific service components */ + void *is_so_svc; + /* JBDB - iser_svc_t will go here */ + idm_conn_ops_t is_conn_ops; + list_t is_conn_list; /* Locked by is_mutex */ + int is_conn_count; /* Locked by is_count_mutex */ + uint16_t is_port; +} idm_svc_t; + +typedef struct idm_conn_s { + list_node_t ic_list_node; + void *ic_handle; + struct idm_svc_s *ic_svc_binding; /* Target conn. only */ + idm_sockaddr_t ic_ini_dst_addr; + idm_conn_state_t ic_state; + idm_conn_state_t ic_last_state; + kmutex_t ic_state_mutex; + kcondvar_t ic_state_cv; + uint32_t ic_state_flags; + timeout_id_t ic_state_timeout; + struct idm_conn_s *ic_reinstate_conn; /* For conn reinst. */ + struct idm_conn_s *ic_logout_conn; /* For other conn logout */ + taskq_t *ic_state_taskq; + int ic_pdu_events; + + boolean_t ic_login_info_valid; + uint16_t ic_login_cid; + + kmutex_t ic_mutex; + kcondvar_t ic_cv; + idm_status_t ic_conn_sm_status; + + boolean_t ic_ffm; + uint32_t ic_internal_cid; + unsigned int ic_client_refcount; + unsigned int ic_task_refcount; + unsigned int ic_buf_refcount; + uint32_t ic_conn_flags; + idm_conn_type_t ic_conn_type; + idm_conn_ops_t ic_conn_ops; + idm_transport_ops_t *ic_transport_ops; + idm_transport_type_t ic_transport_type; + void *ic_transport_private; + idm_conn_param_t ic_conn_params; + avl_tree_t ic_task_tree; +} idm_conn_t; + +#define IDM_CONN_HEADER_DIGEST 0x00000001 +#define IDM_CONN_DATA_DIGEST 0x00000002 + +#define IDM_CONN_ISINI(ICI_IC) ((ICI_IC)->ic_conn_type == CONN_TYPE_INI) +#define IDM_CONN_ISTGT(ICI_IC) ((ICI_IC)->ic_conn_type == CONN_TYPE_TGT) + +/* + * An IDM target task can transfer data using multiple buffers. The task + * will maintain a list of buffers, and each buffer will contain the relative + * offset of the transfer and a pointer to the next buffer in the list. + * + * An initiator will require only one buffer per task, the offset will be 0. + */ + +typedef struct idm_task_s { + avl_node_t idt_avl_link; /* node on the avl_tree */ + idm_conn_t *idt_ic; /* Associated connection */ + /* connection type is in idt_ic->ic_conn_type */ + boolean_t idt_active; /* task state */ + kmutex_t idt_mutex; + void *idt_private; /* Client private data */ + uint32_t idt_tt; /* Task tag */ + /* + * Statistics + */ + int idt_tx_to_ini_start; + int idt_tx_to_ini_done; + int idt_rx_from_ini_start; + int idt_rx_from_ini_done; + + /* + * For bi-directional commands, R2T and Data-In PDUs share the input + * PDU numbering sequence + */ + uint32_t idt_exp_sn; /* shared by rttsn and datasn */ + list_t idt_inbufv; /* chunks of IN buffers */ + list_t idt_outbufv; /* chunks of OUT buffers */ +} idm_task_t; + +int idm_task_constructor(void *task_void, void *arg, int flags); +void idm_task_destructor(void *task_void, void *arg); + +#define IDM_TASKIDS_MAX USHRT_MAX /* 64k tasks */ + +typedef struct idm_buf_s { + list_node_t idb_buflink; /* link in a multi-buffer data xfer */ + idm_conn_t *idb_ic; /* Associated connection */ + void *idb_buf; /* data */ + uint64_t idb_buflen; /* length of buffer */ + size_t idb_bufoffset; /* offset in a multi-buffer xfer */ + /* + * DataPDUInOrder=Yes, so to track that the PDUs in a sequence are sent + * in continuously increasing address order, check that offsets for a + * single buffer xfer are in order. + */ + uint32_t idb_exp_offset; + size_t idb_xfer_len; /* Current requested xfer len */ + void *idb_mr_handle; /* iSER - Memory region handle */ + idm_buf_cb_t *idb_buf_cb; /* Data Completion Notify, tgt only */ + void *idb_cb_arg; /* Client private data */ + idm_task_t *idb_task_binding; + idm_status_t idb_status; +} idm_buf_t; + + +#define PDU_MAX_IOVLEN 12 + +typedef struct idm_pdu_s { + idm_conn_t *isp_ic; /* Must be set */ + iscsi_hdr_t *isp_hdr; + uint_t isp_hdrlen; + uint8_t *isp_data; + uint_t isp_datalen; + + /* + * isp_data is used for sending SCSI status, NOP, text, scsi and + * non-scsi data. Data is received using isp_iov and isp_iovlen + * to support data over multiple buffers. + */ + void *isp_private; + idm_pdu_cb_t *isp_callback; + idm_status_t isp_status; + + /* Internal */ + list_node_t isp_client_lnd; + + /* + * The following four elements are only used in + * idm_sorecv_scsidata() currently. + */ + struct iovec isp_iov[PDU_MAX_IOVLEN]; + int isp_iovlen; + idm_task_t *isp_sorx_task; + idm_buf_t *isp_sorx_buf; + + /* Implementation data for idm_pdu_alloc and sorx PDU cache */ + uint32_t isp_flags; + uint_t isp_hdrbuflen; + uint_t isp_databuflen; + +} idm_pdu_t; + +#define IDM_PDU_OPCODE(PDU) \ + ((PDU)->isp_hdr->opcode & ISCSI_OPCODE_MASK) + +#define IDM_PDU_ALLOC 0x00000001 +#define IDM_PDU_ADDL_HDR 0x00000002 +#define IDM_PDU_ADDL_DATA 0x00000004 + +#define OSD_EXT_CDB_AHSLEN (200 - 15) +#define BIDI_AHS_LENGTH 5 +#define IDM_SORX_CACHE_AHSLEN \ + (((OSD_EXT_CDB_AHSLEN + 3) + \ + (BIDI_AHS_LENGTH + 3)) / sizeof (uint32_t)) +#define IDM_SORX_CACHE_HDRLEN (sizeof (iscsi_hdr_t) + IDM_SORX_CACHE_AHSLEN) + +/* + * ID pool + */ + +#define IDM_IDPOOL_MAGIC 0x4944504C /* IDPL */ +#define IDM_IDPOOL_MIN_SIZE 64 /* Number of IDs to begin with */ +#define IDM_IDPOOL_MAX_SIZE 64 * 1024 + +typedef struct idm_idpool { + uint32_t id_magic; + kmutex_t id_mutex; + uint8_t *id_pool; + uint32_t id_size; + uint8_t id_bit; + uint8_t id_bit_idx; + uint32_t id_idx; + uint32_t id_idx_msk; + uint32_t id_free_counter; + uint32_t id_max_free_counter; +} idm_idpool_t; + +int +idm_idpool_create(idm_idpool_t *pool); + +void +idm_idpool_destroy(idm_idpool_t *pool); + +int +idm_idpool_alloc(idm_idpool_t *pool, uint16_t *id); + +void +idm_idpool_free(idm_idpool_t *pool, uint16_t id); + +void +idm_pdu_rx(idm_conn_t *ic, idm_pdu_t *pdu); + +void +idm_pdu_tx_forward(idm_conn_t *ic, idm_pdu_t *pdu); + +boolean_t +idm_pdu_rx_forward_ffm(idm_conn_t *ic, idm_pdu_t *pdu); + +void +idm_pdu_rx_forward(idm_conn_t *ic, idm_pdu_t *pdu); + +void idm_parse_login_rsp(idm_conn_t *ic, idm_pdu_t *logout_req_pdu, + boolean_t rx); + +void idm_parse_logout_req(idm_conn_t *ic, idm_pdu_t *logout_req_pdu, + boolean_t rx); + +void idm_parse_logout_rsp(idm_conn_t *ic, idm_pdu_t *login_rsp_pdu, + boolean_t rx); + +idm_status_t idm_svc_conn_create(idm_svc_t *is, idm_conn_t **ic_result); + +void idm_svc_conn_destroy(idm_conn_t *ic); + +idm_status_t idm_ini_conn_finish(idm_conn_t *ic); + +idm_status_t idm_tgt_conn_finish(idm_conn_t *ic); + +void idm_conn_close(idm_conn_t *ic); + +void idm_conn_hold_impl(idm_conn_t *ic, unsigned int *counter); + +void idm_conn_rele_impl(idm_conn_t *ic, unsigned int *counter); + +void idm_conn_wait_ref(idm_conn_t *ic); + +uint32_t idm_cid_alloc(void); + +void idm_cid_free(uint32_t cid); + +uint32_t idm_crc32c(void *address, unsigned long length); + +uint32_t idm_crc32c_continued(void *address, unsigned long length, + uint32_t crc); + +void idm_listbuf_insert(list_t *lst, idm_buf_t *buf, uint32_t offset); + +int idm_task_compare(const void *v1, const void *v2); + +idm_conn_t *idm_lookup_conn(uint8_t *isid, uint16_t tsih, uint16_t cid); + + +#ifdef __cplusplus +} +#endif + +#endif /* _IDM_IMPL_H_ */