1 /* 2 * iSCSI Initiator TCP Transport 3 * Copyright (C) 2004 Dmitry Yusupov 4 * Copyright (C) 2004 Alex Aizman 5 * Copyright (C) 2005 Mike Christie 6 * maintained by open-iscsi@googlegroups.com 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published 10 * by the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * See the file COPYING included with this distribution for more details. 19 */ 20 21 #ifndef ISCSI_TCP_H 22 #define ISCSI_TCP_H 23 24 /* Session's states */ 25 #define ISCSI_STATE_FREE 1 26 #define ISCSI_STATE_LOGGED_IN 2 27 #define ISCSI_STATE_FAILED 3 28 #define ISCSI_STATE_TERMINATE 4 29 30 /* Connection's states */ 31 #define ISCSI_CONN_INITIAL_STAGE 0 32 #define ISCSI_CONN_STARTED 1 33 #define ISCSI_CONN_STOPPED 2 34 #define ISCSI_CONN_CLEANUP_WAIT 3 35 36 /* Connection suspend "bit" */ 37 #define SUSPEND_BIT 1 38 39 /* Socket's Receive state machine */ 40 #define IN_PROGRESS_WAIT_HEADER 0x0 41 #define IN_PROGRESS_HEADER_GATHER 0x1 42 #define IN_PROGRESS_DATA_RECV 0x2 43 #define IN_PROGRESS_DDIGEST_RECV 0x3 44 45 /* Task Mgmt states */ 46 #define TMABORT_INITIAL 0x0 47 #define TMABORT_SUCCESS 0x1 48 #define TMABORT_FAILED 0x2 49 #define TMABORT_TIMEDOUT 0x3 50 51 /* xmit state machine */ 52 #define XMSTATE_IDLE 0x0 53 #define XMSTATE_R_HDR 0x1 54 #define XMSTATE_W_HDR 0x2 55 #define XMSTATE_IMM_HDR 0x4 56 #define XMSTATE_IMM_DATA 0x8 57 #define XMSTATE_UNS_INIT 0x10 58 #define XMSTATE_UNS_HDR 0x20 59 #define XMSTATE_UNS_DATA 0x40 60 #define XMSTATE_SOL_HDR 0x80 61 #define XMSTATE_SOL_DATA 0x100 62 #define XMSTATE_W_PAD 0x200 63 #define XMSTATE_DATA_DIGEST 0x400 64 65 #define ISCSI_CONN_MAX 1 66 #define ISCSI_CONN_RCVBUF_MIN 262144 67 #define ISCSI_CONN_SNDBUF_MIN 262144 68 #define ISCSI_PAD_LEN 4 69 #define ISCSI_R2T_MAX 16 70 #define ISCSI_XMIT_CMDS_MAX 128 /* must be power of 2 */ 71 #define ISCSI_MGMT_CMDS_MAX 32 /* must be power of 2 */ 72 #define ISCSI_MGMT_ITT_OFFSET 0xa00 73 #define ISCSI_SG_TABLESIZE SG_ALL 74 #define ISCSI_CMD_PER_LUN 128 75 #define ISCSI_TCP_MAX_CMD_LEN 16 76 77 #define ITT_MASK (0xfff) 78 #define CID_SHIFT 12 79 #define CID_MASK (0xffff<<CID_SHIFT) 80 #define AGE_SHIFT 28 81 #define AGE_MASK (0xf<<AGE_SHIFT) 82 83 struct iscsi_queue { 84 struct kfifo *queue; /* FIFO Queue */ 85 void **pool; /* Pool of elements */ 86 int max; /* Max number of elements */ 87 }; 88 89 struct iscsi_session; 90 struct iscsi_cmd_task; 91 struct iscsi_mgmt_task; 92 93 /* Socket connection recieve helper */ 94 struct iscsi_tcp_recv { 95 struct iscsi_hdr *hdr; 96 struct sk_buff *skb; 97 int offset; 98 int len; 99 int hdr_offset; 100 int copy; 101 int copied; 102 int padding; 103 struct iscsi_cmd_task *ctask; /* current cmd in progress */ 104 105 /* copied and flipped values */ 106 int opcode; 107 int flags; 108 int cmd_status; 109 int ahslen; 110 int datalen; 111 uint32_t itt; 112 int datadgst; 113 }; 114 115 struct iscsi_conn { 116 struct iscsi_hdr hdr; /* header placeholder */ 117 char hdrext[4*sizeof(__u16) + 118 sizeof(__u32)]; 119 int data_copied; 120 char *data; /* data placeholder */ 121 struct socket *sock; /* TCP socket */ 122 int data_size; /* actual recv_dlength */ 123 int stop_stage; /* conn_stop() flag: * 124 * stop to recover, * 125 * stop to terminate */ 126 /* iSCSI connection-wide sequencing */ 127 uint32_t exp_statsn; 128 int hdr_size; /* PDU header size */ 129 unsigned long suspend_rx; /* suspend Rx */ 130 131 struct crypto_tfm *rx_tfm; /* CRC32C (Rx) */ 132 struct crypto_tfm *data_rx_tfm; /* CRC32C (Rx) for data */ 133 134 /* control data */ 135 int senselen; /* scsi sense length */ 136 int id; /* CID */ 137 struct iscsi_tcp_recv in; /* TCP receive context */ 138 struct iscsi_session *session; /* parent session */ 139 struct list_head item; /* maintains list of conns */ 140 int in_progress; /* connection state machine */ 141 int c_stage; /* connection state */ 142 struct iscsi_mgmt_task *login_mtask; /* mtask used for login/text */ 143 struct iscsi_mgmt_task *mtask; /* xmit mtask in progress */ 144 struct iscsi_cmd_task *ctask; /* xmit ctask in progress */ 145 spinlock_t lock; /* FIXME: to be removed */ 146 147 /* old values for socket callbacks */ 148 void (*old_data_ready)(struct sock *, int); 149 void (*old_state_change)(struct sock *); 150 void (*old_write_space)(struct sock *); 151 152 /* xmit */ 153 struct crypto_tfm *tx_tfm; /* CRC32C (Tx) */ 154 struct crypto_tfm *data_tx_tfm; /* CRC32C (Tx) for data */ 155 struct kfifo *writequeue; /* write cmds for Data-Outs */ 156 struct kfifo *immqueue; /* immediate xmit queue */ 157 struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */ 158 struct kfifo *xmitqueue; /* data-path cmd queue */ 159 struct work_struct xmitwork; /* per-conn. xmit workqueue */ 160 struct semaphore xmitsema; /* serializes connection xmit, 161 * access to kfifos: * 162 * xmitqueue, writequeue, * 163 * immqueue, mgmtqueue */ 164 unsigned long suspend_tx; /* suspend Tx */ 165 166 /* abort */ 167 wait_queue_head_t ehwait; /* used in eh_abort() */ 168 struct iscsi_tm tmhdr; 169 struct timer_list tmabort_timer; /* abort timer */ 170 int tmabort_state; /* see TMABORT_INITIAL, etc.*/ 171 172 /* negotiated params */ 173 int max_recv_dlength; 174 int max_xmit_dlength; 175 int hdrdgst_en; 176 int datadgst_en; 177 178 /* MIB-statistics */ 179 uint64_t txdata_octets; 180 uint64_t rxdata_octets; 181 uint32_t scsicmd_pdus_cnt; 182 uint32_t dataout_pdus_cnt; 183 uint32_t scsirsp_pdus_cnt; 184 uint32_t datain_pdus_cnt; 185 uint32_t r2t_pdus_cnt; 186 uint32_t tmfcmd_pdus_cnt; 187 int32_t tmfrsp_pdus_cnt; 188 189 /* custom statistics */ 190 uint32_t sendpage_failures_cnt; 191 uint32_t discontiguous_hdr_cnt; 192 uint32_t eh_abort_cnt; 193 }; 194 195 struct iscsi_session { 196 /* iSCSI session-wide sequencing */ 197 uint32_t cmdsn; 198 uint32_t exp_cmdsn; 199 uint32_t max_cmdsn; 200 201 /* configuration */ 202 int initial_r2t_en; 203 int max_r2t; 204 int imm_data_en; 205 int first_burst; 206 int max_burst; 207 int time2wait; 208 int time2retain; 209 int pdu_inorder_en; 210 int dataseq_inorder_en; 211 int erl; 212 int ifmarker_en; 213 int ofmarker_en; 214 215 /* control data */ 216 struct Scsi_Host *host; 217 int id; 218 struct iscsi_conn *leadconn; /* leading connection */ 219 spinlock_t lock; /* protects session state, * 220 * sequence numbers, * 221 * session resources: * 222 * - cmdpool, * 223 * - mgmtpool, * 224 * - r2tpool */ 225 int state; /* session state */ 226 struct list_head item; 227 void *auth_client; 228 int conn_cnt; 229 int age; /* counts session re-opens */ 230 231 struct list_head connections; /* list of connections */ 232 int cmds_max; /* size of cmds array */ 233 struct iscsi_cmd_task **cmds; /* Original Cmds arr */ 234 struct iscsi_queue cmdpool; /* PDU's pool */ 235 int mgmtpool_max; /* size of mgmt array */ 236 struct iscsi_mgmt_task **mgmt_cmds; /* Original mgmt arr */ 237 struct iscsi_queue mgmtpool; /* Mgmt PDU's pool */ 238 }; 239 240 struct iscsi_buf { 241 struct scatterlist sg; 242 struct kvec iov; 243 unsigned int sent; 244 }; 245 246 struct iscsi_data_task { 247 struct iscsi_data hdr; /* PDU */ 248 char hdrext[sizeof(__u32)]; /* Header-Digest */ 249 struct list_head item; /* data queue item */ 250 struct iscsi_buf digestbuf; /* digest buffer */ 251 uint32_t digest; /* data digest */ 252 }; 253 #define ISCSI_DTASK_DEFAULT_MAX ISCSI_SG_TABLESIZE * PAGE_SIZE / 512 254 255 struct iscsi_mgmt_task { 256 struct iscsi_hdr hdr; /* mgmt. PDU */ 257 char hdrext[sizeof(__u32)]; /* Header-Digest */ 258 char *data; /* mgmt payload */ 259 int xmstate; /* mgmt xmit progress */ 260 int data_count; /* counts data to be sent */ 261 struct iscsi_buf headbuf; /* header buffer */ 262 struct iscsi_buf sendbuf; /* in progress buffer */ 263 int sent; 264 uint32_t itt; /* this ITT */ 265 }; 266 267 struct iscsi_r2t_info { 268 __be32 ttt; /* copied from R2T */ 269 __be32 exp_statsn; /* copied from R2T */ 270 uint32_t data_length; /* copied from R2T */ 271 uint32_t data_offset; /* copied from R2T */ 272 struct iscsi_buf headbuf; /* Data-Out Header Buffer */ 273 struct iscsi_buf sendbuf; /* Data-Out in progress buffer*/ 274 int sent; /* R2T sequence progress */ 275 int data_count; /* DATA-Out payload progress */ 276 struct scatterlist *sg; /* per-R2T SG list */ 277 int solicit_datasn; 278 struct iscsi_data_task *dtask; /* which data task */ 279 }; 280 281 struct iscsi_cmd_task { 282 struct iscsi_cmd hdr; /* iSCSI PDU header */ 283 char hdrext[4*sizeof(__u16)+ /* AHS */ 284 sizeof(__u32)]; /* HeaderDigest */ 285 char pad[ISCSI_PAD_LEN]; 286 int itt; /* this ITT */ 287 int datasn; /* DataSN */ 288 struct iscsi_buf headbuf; /* header buf (xmit) */ 289 struct iscsi_buf sendbuf; /* in progress buffer*/ 290 int sent; 291 struct scatterlist *sg; /* per-cmd SG list */ 292 struct scatterlist *bad_sg; /* assert statement */ 293 int sg_count; /* SG's to process */ 294 uint32_t unsol_datasn; 295 uint32_t exp_r2tsn; 296 int xmstate; /* xmit xtate machine */ 297 int imm_count; /* imm-data (bytes) */ 298 int unsol_count; /* unsolicited (bytes)*/ 299 int r2t_data_count; /* R2T Data-Out bytes */ 300 int data_count; /* remaining Data-Out */ 301 int pad_count; /* padded bytes */ 302 struct scsi_cmnd *sc; /* associated SCSI cmd*/ 303 int total_length; 304 int data_offset; 305 struct iscsi_conn *conn; /* used connection */ 306 struct iscsi_mgmt_task *mtask; /* tmf mtask in progr */ 307 308 struct iscsi_r2t_info *r2t; /* in progress R2T */ 309 struct iscsi_queue r2tpool; 310 struct kfifo *r2tqueue; 311 struct iscsi_r2t_info **r2ts; 312 struct list_head dataqueue; /* Data-Out dataqueue */ 313 mempool_t *datapool; 314 uint32_t datadigest; /* for recover digest */ 315 int digest_count; 316 uint32_t immdigest; /* for imm data */ 317 struct iscsi_buf immbuf; /* for imm data digest */ 318 struct iscsi_data_task *dtask; /* data task in progress*/ 319 int digest_offset; /* for partial buff digest */ 320 }; 321 322 #endif /* ISCSI_H */ 323