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_DEF_CMD_PER_LUN 32 75 #define ISCSI_MAX_CMD_PER_LUN 128 76 #define ISCSI_TCP_MAX_CMD_LEN 16 77 78 #define ITT_MASK (0xfff) 79 #define CID_SHIFT 12 80 #define CID_MASK (0xffff<<CID_SHIFT) 81 #define AGE_SHIFT 28 82 #define AGE_MASK (0xf<<AGE_SHIFT) 83 84 struct iscsi_queue { 85 struct kfifo *queue; /* FIFO Queue */ 86 void **pool; /* Pool of elements */ 87 int max; /* Max number of elements */ 88 }; 89 90 struct iscsi_session; 91 struct iscsi_cmd_task; 92 struct iscsi_mgmt_task; 93 94 /* Socket connection recieve helper */ 95 struct iscsi_tcp_recv { 96 struct iscsi_hdr *hdr; 97 struct sk_buff *skb; 98 int offset; 99 int len; 100 int hdr_offset; 101 int copy; 102 int copied; 103 int padding; 104 struct iscsi_cmd_task *ctask; /* current cmd in progress */ 105 106 /* copied and flipped values */ 107 int opcode; 108 int flags; 109 int cmd_status; 110 int ahslen; 111 int datalen; 112 uint32_t itt; 113 int datadgst; 114 }; 115 116 struct iscsi_cls_conn; 117 118 struct iscsi_conn { 119 struct iscsi_cls_conn *cls_conn; /* ptr to class connection */ 120 struct iscsi_hdr hdr; /* header placeholder */ 121 char hdrext[4*sizeof(__u16) + 122 sizeof(__u32)]; 123 int data_copied; 124 char *data; /* data placeholder */ 125 struct socket *sock; /* TCP socket */ 126 int data_size; /* actual recv_dlength */ 127 int stop_stage; /* conn_stop() flag: * 128 * stop to recover, * 129 * stop to terminate */ 130 /* iSCSI connection-wide sequencing */ 131 uint32_t exp_statsn; 132 int hdr_size; /* PDU header size */ 133 unsigned long suspend_rx; /* suspend Rx */ 134 135 struct crypto_tfm *rx_tfm; /* CRC32C (Rx) */ 136 struct crypto_tfm *data_rx_tfm; /* CRC32C (Rx) for data */ 137 138 /* control data */ 139 int senselen; /* scsi sense length */ 140 int id; /* CID */ 141 struct iscsi_tcp_recv in; /* TCP receive context */ 142 struct iscsi_session *session; /* parent session */ 143 struct list_head item; /* maintains list of conns */ 144 int in_progress; /* connection state machine */ 145 int c_stage; /* connection state */ 146 struct iscsi_mgmt_task *login_mtask; /* mtask used for login/text */ 147 struct iscsi_mgmt_task *mtask; /* xmit mtask in progress */ 148 struct iscsi_cmd_task *ctask; /* xmit ctask in progress */ 149 150 /* old values for socket callbacks */ 151 void (*old_data_ready)(struct sock *, int); 152 void (*old_state_change)(struct sock *); 153 void (*old_write_space)(struct sock *); 154 155 /* xmit */ 156 struct crypto_tfm *tx_tfm; /* CRC32C (Tx) */ 157 struct crypto_tfm *data_tx_tfm; /* CRC32C (Tx) for data */ 158 struct kfifo *writequeue; /* write cmds for Data-Outs */ 159 struct kfifo *immqueue; /* immediate xmit queue */ 160 struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */ 161 struct kfifo *xmitqueue; /* data-path cmd queue */ 162 struct work_struct xmitwork; /* per-conn. xmit workqueue */ 163 struct mutex xmitmutex; /* serializes connection xmit, 164 * access to kfifos: * 165 * xmitqueue, writequeue, * 166 * immqueue, mgmtqueue */ 167 unsigned long suspend_tx; /* suspend Tx */ 168 169 /* abort */ 170 wait_queue_head_t ehwait; /* used in eh_abort() */ 171 struct iscsi_tm tmhdr; 172 struct timer_list tmabort_timer; /* abort timer */ 173 int tmabort_state; /* see TMABORT_INITIAL, etc.*/ 174 175 /* negotiated params */ 176 int max_recv_dlength; 177 int max_xmit_dlength; 178 int hdrdgst_en; 179 int datadgst_en; 180 181 /* MIB-statistics */ 182 uint64_t txdata_octets; 183 uint64_t rxdata_octets; 184 uint32_t scsicmd_pdus_cnt; 185 uint32_t dataout_pdus_cnt; 186 uint32_t scsirsp_pdus_cnt; 187 uint32_t datain_pdus_cnt; 188 uint32_t r2t_pdus_cnt; 189 uint32_t tmfcmd_pdus_cnt; 190 int32_t tmfrsp_pdus_cnt; 191 192 /* custom statistics */ 193 uint32_t sendpage_failures_cnt; 194 uint32_t discontiguous_hdr_cnt; 195 uint32_t eh_abort_cnt; 196 197 ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int); 198 }; 199 200 struct iscsi_session { 201 /* iSCSI session-wide sequencing */ 202 uint32_t cmdsn; 203 uint32_t exp_cmdsn; 204 uint32_t max_cmdsn; 205 206 /* configuration */ 207 int initial_r2t_en; 208 int max_r2t; 209 int imm_data_en; 210 int first_burst; 211 int max_burst; 212 int time2wait; 213 int time2retain; 214 int pdu_inorder_en; 215 int dataseq_inorder_en; 216 int erl; 217 int ifmarker_en; 218 int ofmarker_en; 219 220 /* control data */ 221 struct Scsi_Host *host; 222 int id; 223 struct iscsi_conn *leadconn; /* leading connection */ 224 spinlock_t lock; /* protects session state, * 225 * sequence numbers, * 226 * session resources: * 227 * - cmdpool, * 228 * - mgmtpool, * 229 * - r2tpool */ 230 int state; /* session state */ 231 struct list_head item; 232 void *auth_client; 233 int conn_cnt; 234 int age; /* counts session re-opens */ 235 236 struct list_head connections; /* list of connections */ 237 int cmds_max; /* size of cmds array */ 238 struct iscsi_cmd_task **cmds; /* Original Cmds arr */ 239 struct iscsi_queue cmdpool; /* PDU's pool */ 240 int mgmtpool_max; /* size of mgmt array */ 241 struct iscsi_mgmt_task **mgmt_cmds; /* Original mgmt arr */ 242 struct iscsi_queue mgmtpool; /* Mgmt PDU's pool */ 243 }; 244 245 struct iscsi_buf { 246 struct scatterlist sg; 247 unsigned int sent; 248 char use_sendmsg; 249 }; 250 251 struct iscsi_data_task { 252 struct iscsi_data hdr; /* PDU */ 253 char hdrext[sizeof(__u32)]; /* Header-Digest */ 254 struct list_head item; /* data queue item */ 255 struct iscsi_buf digestbuf; /* digest buffer */ 256 uint32_t digest; /* data digest */ 257 }; 258 #define ISCSI_DTASK_DEFAULT_MAX ISCSI_SG_TABLESIZE * PAGE_SIZE / 512 259 260 struct iscsi_mgmt_task { 261 struct iscsi_hdr hdr; /* mgmt. PDU */ 262 char hdrext[sizeof(__u32)]; /* Header-Digest */ 263 char *data; /* mgmt payload */ 264 int xmstate; /* mgmt xmit progress */ 265 int data_count; /* counts data to be sent */ 266 struct iscsi_buf headbuf; /* header buffer */ 267 struct iscsi_buf sendbuf; /* in progress buffer */ 268 int sent; 269 uint32_t itt; /* this ITT */ 270 }; 271 272 struct iscsi_r2t_info { 273 __be32 ttt; /* copied from R2T */ 274 __be32 exp_statsn; /* copied from R2T */ 275 uint32_t data_length; /* copied from R2T */ 276 uint32_t data_offset; /* copied from R2T */ 277 struct iscsi_buf headbuf; /* Data-Out Header Buffer */ 278 struct iscsi_buf sendbuf; /* Data-Out in progress buffer*/ 279 int sent; /* R2T sequence progress */ 280 int data_count; /* DATA-Out payload progress */ 281 struct scatterlist *sg; /* per-R2T SG list */ 282 int solicit_datasn; 283 struct iscsi_data_task *dtask; /* which data task */ 284 }; 285 286 struct iscsi_cmd_task { 287 struct iscsi_cmd hdr; /* iSCSI PDU header */ 288 char hdrext[4*sizeof(__u16)+ /* AHS */ 289 sizeof(__u32)]; /* HeaderDigest */ 290 char pad[ISCSI_PAD_LEN]; 291 int itt; /* this ITT */ 292 int datasn; /* DataSN */ 293 struct iscsi_buf headbuf; /* header buf (xmit) */ 294 struct iscsi_buf sendbuf; /* in progress buffer*/ 295 int sent; 296 struct scatterlist *sg; /* per-cmd SG list */ 297 struct scatterlist *bad_sg; /* assert statement */ 298 int sg_count; /* SG's to process */ 299 uint32_t unsol_datasn; 300 uint32_t exp_r2tsn; 301 int xmstate; /* xmit xtate machine */ 302 int imm_count; /* imm-data (bytes) */ 303 int unsol_count; /* unsolicited (bytes)*/ 304 int r2t_data_count; /* R2T Data-Out bytes */ 305 int data_count; /* remaining Data-Out */ 306 int pad_count; /* padded bytes */ 307 struct scsi_cmnd *sc; /* associated SCSI cmd*/ 308 int total_length; 309 int data_offset; 310 struct iscsi_conn *conn; /* used connection */ 311 struct iscsi_mgmt_task *mtask; /* tmf mtask in progr */ 312 313 struct iscsi_r2t_info *r2t; /* in progress R2T */ 314 struct iscsi_queue r2tpool; 315 struct kfifo *r2tqueue; 316 struct iscsi_r2t_info **r2ts; 317 struct list_head dataqueue; /* Data-Out dataqueue */ 318 mempool_t *datapool; 319 uint32_t datadigest; /* for recover digest */ 320 int digest_count; 321 uint32_t immdigest; /* for imm data */ 322 struct iscsi_buf immbuf; /* for imm data digest */ 323 struct iscsi_data_task *dtask; /* data task in progress*/ 324 int digest_offset; /* for partial buff digest */ 325 }; 326 327 #endif /* ISCSI_H */ 328