xref: /plan9-contrib/sys/src/cmd/ip/iscsi.h (revision a9e8ce388a002c20feaa10ccf4ba659568c8c966)
1 /*
2  * iscsi - scsi over tcp/ip
3  *
4  * observations:
5  * iscsi names may be 223 bytes long.
6  * two namespaces, "iqn." and "eui.".
7  * don't need FIM when using tcp.
8  * rfc3720 §3.2.8.1 demonstrates that the authors don't understand (or
9  * don't trust) tcp: data isn't quietly dropped.
10  *
11  * we're not going to implement the optional digests (crcs),
12  * so those are omitted.
13  */
14 
15 enum {
16 	Bhdrsz	= 48,
17 
18 	/* initiator opcodes (requests) */
19 	Iopnopout= 0,
20 	Iopcmd,
21 	Ioptask,
22 	Ioplogin,
23 	Ioptext,
24 	Iopdataout,		/* write */
25 	Ioplogout,
26 	Iopsnack= 0x10,
27 
28 	/* target opcodes (responses) */
29 	Topnopin= 0x20,
30 	Topresp,
31 	Toptask,
32 	Toplogin,
33 	Toptext,
34 	Topdatain,		/* read */
35 	Toplogout,
36 	Topr2t	= 0x31,
37 	Topasync,
38 	Topreject= 0x3f,
39 
40 	Immed	= 1<<6,
41 	Oprsrvd	= 1<<7,
42 
43 	/* opspfc */
44 	Finalpkt= 1<<7,
45 };
46 
47 typedef struct Datainpkt Datainpkt;
48 typedef struct Iscsiasynch Iscsiasynch;
49 typedef struct Iscsicmdreq Iscsicmdreq;
50 typedef struct Iscsicmdresp Iscsicmdresp;
51 typedef struct Iscsidatain Iscsidatain;
52 typedef struct Iscsidataout Iscsidataout;
53 typedef struct Iscsijustbhdr Iscsijustbhdr;
54 typedef struct Iscsiloginreq Iscsiloginreq;
55 typedef struct Iscsiloginresp Iscsiloginresp;
56 typedef struct Iscsilogoutreq Iscsilogoutreq;
57 typedef struct Iscsilogoutresp Iscsilogoutresp;
58 typedef struct Iscsinopreq Iscsinopreq;		/* nop out */
59 typedef struct Iscsinopresp Iscsinopresp;	/* nop in */
60 typedef struct Iscsiready Iscsiready;
61 typedef struct Iscsireject Iscsireject;
62 typedef struct Iscsisnackreq Iscsisnackreq;
63 typedef struct Iscsistate Iscsistate;
64 typedef struct Iscsitaskreq Iscsitaskreq;
65 typedef struct Iscsitaskresp Iscsitaskresp;
66 typedef struct Iscsitextreq Iscsitextreq;
67 typedef struct Iscsitextresp Iscsitextresp;
68 typedef struct Pkt Pkt;
69 typedef struct Pkts Pkts;
70 typedef struct Resppkt Resppkt;
71 
72 /*
73  * iscsi on-the-wire packet formats
74  *
75  * all integers are stored big-endian.
76  * common pkt start is bhs, 48 bytes.
77  */
78 
79 /*
80  * first 20 bytes are common *and* defined; another 28 follow but vary.
81  */
82 #define Iscsibhdr \
83 	uchar	op;		\
84 	uchar	opspfc[3];	\
85 	uchar	totahslen;	\
86 	uchar	dseglen[3];	\
87 	uchar	lun[8];		\
88 	uchar	itt[4]		/* initiator task tag */
89 
90 struct Iscsijustbhdr {
91 	Iscsibhdr;
92 };
93 
94 struct Iscsiasynch {
95 	Iscsibhdr;
96 
97 	uchar	_pad1[4];
98 	uchar	stsseq[4];
99 	uchar	expcmdseq[4];
100 	uchar	maxcmdseq[4];
101 
102 	uchar	event;
103 	uchar	vcode;
104 	uchar	param1[2];
105 	uchar	param2[2];
106 	uchar	param3[2];
107 	uchar	_pad2[4];
108 	uchar	dseg[];		/* dseg[dseglen] */
109 };
110 
111 
112 struct Iscsiloginreq {
113 	Iscsibhdr;
114 
115 	uchar	cid[2];
116 	uchar	_pad1[2];
117 	uchar	cmdseq[4];
118 	uchar	expstsseq[4];
119 
120 	uchar	_pad2[16];
121 	uchar	dseg[];		/* dseg[dseglen] */
122 };
123 
124 struct Iscsiloginresp {
125 	Iscsibhdr;
126 
127 	uchar	_pad1[4];
128 	uchar	stsseq[4];
129 	uchar	expstsseq[4];
130 	uchar	maxstsseq[4];
131 
132 	uchar	stsclass;
133 	uchar	stsdetail;
134 	uchar	_pad2[10];
135 	uchar	dseg[];		/* dseg[dseglen] */
136 };
137 
138 
139 struct Iscsilogoutreq {
140 	Iscsibhdr;
141 
142 	uchar	cid[2];
143 	uchar	_pad1[2];
144 	uchar	cmdseq[4];
145 	uchar	expstsseq[4];
146 	uchar	_pad2[16];
147 };
148 
149 struct Iscsilogoutresp {
150 	Iscsibhdr;
151 
152 	uchar	_pad1[4];
153 	uchar	stsseq[4];
154 	uchar	expcmdseq[4];
155 	uchar	maxcmdseq[4];
156 	uchar	_pad2[4];
157 	uchar	waittime[2];
158 	uchar	retaintime[2];
159 	uchar	_pad3[4];
160 };
161 
162 
163 struct Iscsinopreq {		/* nop-out */
164 	Iscsibhdr;
165 
166 	uchar	ttt[4];
167 	uchar	cmdseq[4];
168 	uchar	expcmdseq[4];
169 	uchar	_pad2[16];
170 	uchar	dseg[];		/* dseg[dseglen] */
171 };
172 
173 struct Iscsinopresp {		/* nop-in */
174 	Iscsibhdr;
175 
176 	uchar	ttt[4];
177 	uchar	stsseq[4];
178 	uchar	expcmdseq[4];
179 	uchar	maxcmdseq[4];
180 	uchar	_pad2[12];
181 	uchar	dseg[];		/* dseg[dseglen] */
182 };
183 
184 
185 struct Iscsiready {
186 	Iscsibhdr;
187 
188 	uchar	ttt[4];
189 	uchar	stsseq[4];
190 	uchar	expcmdseq[4];
191 	uchar	r2tseq[4];
192 	uchar	bufoff[4];
193 	uchar	xferlen[4];
194 };
195 
196 struct Iscsireject {
197 	Iscsibhdr;
198 
199 	uchar	_pad2[4];
200 	uchar	stsseq[4];
201 	uchar	expcmdseq[4];
202 	uchar	maxcmdseq[4];
203 	uchar	r2tseq[4];
204 	uchar	_pad3[4+4];
205 	uchar	dseg[];		/* dseg[dseglen] */
206 };
207 
208 
209 struct Iscsicmdreq {
210 	Iscsibhdr;
211 
212 	uchar	expxferlen[4];
213 	uchar	cmdseq[4];
214 	uchar	expstsseq[4];
215 
216 	uchar	cdb[16];
217 	uchar	dseg[];		/* dseg[dseglen] */
218 };
219 
220 struct Iscsicmdresp {
221 	Iscsibhdr;
222 
223 	uchar	snacktag[4];
224 	uchar	stsseq[4];
225 	uchar	expcmdseq[4];
226 	uchar	maxcmdseq[4];
227 	uchar	expdataseq[4];
228 	uchar	readresid[4];
229 	uchar	resid[4];
230 	uchar	dseg[];		/* dseg[dseglen] */
231 };
232 
233 
234 struct Iscsidatain {
235 	Iscsibhdr;
236 
237 	uchar	ttt[4];
238 	uchar	stsseq[4];
239 	uchar	expcmdseq[4];
240 	uchar	maxcmdseq[4];
241 	uchar	dataseq[4];
242 	uchar	buffoff[4];
243 	uchar	resid[4];
244 	uchar	dseg[];		/* dseg[dseglen] */
245 };
246 
247 struct Iscsidataout {		/* a.k.a. data-out */
248 	Iscsibhdr;
249 
250 	uchar	ttt[4];
251 	uchar	_pad1[4];
252 	uchar	expstsseq[4];
253 	uchar	_pad2[4];
254 	uchar	dataseq[4];
255 	uchar	buffoff[4];
256 	uchar	_pad3[4];
257 	uchar	dseg[];		/* dseg[dseglen] */
258 };
259 
260 
261 struct Iscsisnackreq {
262 	Iscsibhdr;
263 
264 	uchar	ttt[4];
265 	uchar	_pad1[4];
266 	uchar	expstsseq[4];
267 	uchar	_pad2[8];
268 	uchar	begrun[4];
269 	uchar	runlen[4];
270 };
271 
272 
273 struct Iscsitaskreq {
274 	Iscsibhdr;
275 
276 	uchar	rtt[4];
277 	uchar	cmdseq[4];
278 	uchar	expstsseq[4];
279 	uchar	refcmdseq[4];
280 	uchar	expdataseq[4];
281 	uchar	_pad1[8];
282 };
283 
284 struct Iscsitaskresp {
285 	Iscsibhdr;
286 
287 	uchar	_pad2[4];
288 	uchar	stsseq[4];
289 	uchar	expcmdseq[4];
290 	uchar	maxcmdseq[4];
291 	uchar	_pad4[12];
292 };
293 
294 
295 /* req & resp identical? */
296 struct Iscsitextreq {
297 	Iscsibhdr;
298 
299 	uchar	ttt[4];
300 	uchar	cmdseq[4];
301 	uchar	expstsseq[4];
302 	uchar	_pad1[16];
303 	uchar	dseg[];		/* dseg[dseglen] */
304 };
305 
306 struct Iscsitextresp {
307 	Iscsibhdr;
308 
309 	uchar	ttt[4];
310 	uchar	cmdseq[4];
311 	uchar	expstsseq[4];
312 	uchar	_pad1[16];
313 	uchar	dseg[];		/* dseg[dseglen] */
314 };
315 
316 /*
317  * packet-specific data
318  */
319 struct Pkt {
320 	union {
321 		Iscsijustbhdr *pkthdr;
322 		uchar	*pkt;
323 	};
324 	uint	len;
325 };
326 struct Resppkt {
327 	Iscsicmdresp *resppkt;
328 	uint	resplen;
329 };
330 struct Datainpkt {
331 	Iscsidatain *datapkt;
332 	uint	datalen;
333 };
334 
335 /*
336  * a request packet (pkt), its response packet (Resppkt),
337  * and an optional data-in packet for cmd read operations.
338  */
339 struct Pkts {
340 	int	op;
341 	int	immed;
342 	ulong	totahslen;
343 	ulong	dseglen;
344 	ulong	itt;
345 
346 	Pkt;
347 	Datainpkt;
348 	Resppkt;
349 };
350 
351 /*
352  * iscsi state, maintained by both parties.
353  * some are per-connection, some per-session.
354  */
355 struct Iscsistate {
356 	ulong	cmdseq;		/* to be assigned to next command pkt */
357 	ulong	expcmdseq;	/* next cmd expected by target; previous done */
358 	ulong	maxcmdseq;  /* maxcmdseq-expcmdseq+1 is target's queue depth */
359 
360 	ulong	stsseq;
361 	ulong	expstsseq;	/* all previous sts seen */
362 
363 	ulong	dataseq;
364 	ulong	r2tseq;
365 
366 	ulong	maxrcvseglen;
367 };
368