/* * 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 usr/src/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 usr/src/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 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _TARGET_CONN_H #define _TARGET_CONN_H #pragma ident "%Z%%M% %I% %E% SMI" /* * Block comment which describes the contents of this file. */ #ifdef __cplusplus extern "C" { #endif #include <sys/iscsi_protocol.h> #include <sys/socket.h> #include "queue.h" #include "iscsi_sess.h" #include "iscsi_cmd.h" #define LBUFSIZE 80 #define TARGET_LOCATION "targets" /* * Currently I'm having some problems with network reads/write when the * data size is larger than 8k. To work around this problem I set the * various negotiation parameters during login to limit things to 8k. */ #define NETWORK_SNDRCV 65536 #define NETWORK_SNDRCV_STR "65536" typedef enum iscsi_state { S1_FREE, /* S2_XPT_WAIT, Not possible for target */ S3_XPT_UP, S4_IN_LOGIN, S5_LOGGED_IN, S6_IN_LOGOUT, S7_LOGOUT_REQUESTED, S8_CLEANUP_WAIT } iscsi_state_t; typedef enum iscsi_transition { T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T15, T16, T17, T18 } iscsi_transition_t; /* * When grabbing mutex's make sure to grab c_mutex before c_mutex_state * if you need to grab both. */ typedef struct iscsi_conn { int c_fd; /* * This is a linked list of all connections. Not just the connections * associated with a particular session. */ struct iscsi_conn *c_next, *c_prev; target_queue_t *c_mgmtq; /* * Time as reported by time(2) when this connection was started. */ time_t c_up_at; /* * This queue is used to accept notification that incoming packets * are available and command completion status from Session. */ target_queue_t *c_dataq; /* * Messages are sent to Session, and from there onto STE, using * this queue. */ target_queue_t *c_sessq; iscsi_sess_t *c_sess; pthread_mutex_t c_state_mutex; iscsi_state_t c_state; /* * Protected by c_mutex */ int c_statsn; int c_cid; /* * Pointer to data buffer used to store text messages which have * the 'C' bit set. Since the text data separates name/value pairs * with a '\0' strlen can't be used to determine the amount of space * used so we keep the length in c_text_len; */ char *c_text_area; int c_text_len; int c_text_sent; sema_t c_datain; pthread_t c_thr_id_poller, c_thr_id_process; pthread_mutex_t c_mutex; iscsi_cmd_t *c_cmd_head; iscsi_cmd_t *c_cmd_tail; struct sockaddr_storage c_initiator_sockaddr; struct sockaddr_storage c_target_sockaddr; int c_num; int c_auth_pass : 1; int c_cmds_active; /* * A performance issue has been found when the backing store * is UFS. Because of the indirect blocks used by UFS large files * (many GBs in size) perform poorly. This in turn can cause the * initiator to issue commands which don't complete in time. So, * we'll monitor the completion times for commands if if it's * increasing the command window will be reduced. * The avg_sum is in nanoseconds. This will wrap once every 584 * years. */ uint64_t c_cmds_avg_cnt; hrtime_t c_cmds_avg_sum; /* * During an orderly shutdown the logout response is created when * we receive the logout request. We must however wait for all I/O * to complete before processing the data else we'll loose data * which the initiator believes was successfully transferred. * Once the STE and sessions have closed they will send a shutdown * complete message. At that point the transmit side of the connection * will set the state to T13 which pushes this message out. * Unfortunately we need information from the Logout Request PDU * to create the Logout Response PDU. Otherwise the response could * be generated on the fly in the T13 state handler. By creating * the response PDU and saving a pointer gives us some flexibility * in the future if the final outgoing packet needs to change. * Otherwise, storing that one bit of information from the request * PDU might become dated. */ iscsi_hdr_t *c_last_pkg; /* * Connection parameters */ Boolean_t c_header_digest, c_data_digest, c_ifmarker, c_ofmarker, c_initialR2T, c_immediate_data, c_data_pdu_in_order, c_data_sequence_in_order; int c_tpgt, c_maxcmdsn, c_max_recv_data, c_default_time_2_wait, c_default_time_2_retain, c_erl, c_max_burst_len, c_first_burst_len, c_max_outstanding_r2t, c_max_connections; char *c_targ_alias, *auth_text; int auth_text_length; } iscsi_conn_t; void *conn_process(void *v); void conn_state(iscsi_conn_t *c, iscsi_transition_t t); void send_iscsi_pkt(iscsi_conn_t *c, iscsi_hdr_t *h, char *opt_text); int read_retry(int fd, char *buf, int count); void iscsi_inventory_change(char *targ_name); void iscsi_capacity_change(char *targ_name, int lun); #ifdef __cplusplus } #endif #endif /* _TARGET_CONN_H */