You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

iscsi.h 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. #ifndef _GPXE_ISCSI_H
  2. #define _GPXE_ISCSI_H
  3. /** @file
  4. *
  5. * iSCSI protocol
  6. *
  7. */
  8. #include <stdint.h>
  9. #include <gpxe/tcp.h>
  10. #include <gpxe/scsi.h>
  11. /**
  12. * iSCSI segment lengths
  13. *
  14. * iSCSI uses an icky structure with one one-byte field (a dword
  15. * count) and one three-byte field (a byte count). This structure,
  16. * and the accompanying macros, relieve some of the pain.
  17. */
  18. union iscsi_segment_lengths {
  19. struct {
  20. /** The AHS length (measured in dwords) */
  21. uint8_t ahs_len;
  22. /** The data length (measured in bytes), in network
  23. * byte order
  24. */
  25. uint8_t data_len[3];
  26. } bytes;
  27. /** Ths data length (measured in bytes), in network byte
  28. * order, with ahs_len as the first byte.
  29. */
  30. uint32_t ahs_and_data_len;
  31. };
  32. /** The length of the additional header segment, in dwords */
  33. #define ISCSI_AHS_LEN( segment_lengths ) \
  34. ( (segment_lengths).bytes.ahs_len )
  35. /** The length of the data segment, in bytes, excluding any padding */
  36. #define ISCSI_DATA_LEN( segment_lengths ) \
  37. ( ntohl ( (segment_lengths).ahs_and_data_len ) & 0xffffff )
  38. /** The padding of the data segment, in bytes */
  39. #define ISCSI_DATA_PAD_LEN( segment_lengths ) \
  40. ( ( 0 - (segment_lengths).bytes.data_len[2] ) & 0x03 )
  41. /** Set additional header and data segment lengths */
  42. #define ISCSI_SET_LENGTHS( segment_lengths, ahs_len, data_len ) do { \
  43. (segment_lengths).ahs_and_data_len = \
  44. htonl ( data_len | ( ahs_len << 24 ) ); \
  45. } while ( 0 )
  46. /**
  47. * iSCSI basic header segment common fields
  48. *
  49. */
  50. struct iscsi_bhs_common {
  51. /** Opcode */
  52. uint8_t opcode;
  53. /** Flags */
  54. uint8_t flags;
  55. /** Fields specific to the PDU type */
  56. uint8_t other_a[2];
  57. /** Segment lengths */
  58. union iscsi_segment_lengths lengths;
  59. /** Fields specific to the PDU type */
  60. uint8_t other_b[8];
  61. /** Initiator Task Tag */
  62. uint32_t itt;
  63. /** Fields specific to the PDU type */
  64. uint8_t other_c[28];
  65. };
  66. /** Opcode mask */
  67. #define ISCSI_OPCODE_MASK 0x3f
  68. /** Immediate delivery */
  69. #define ISCSI_FLAG_IMMEDIATE 0x40
  70. /** Final PDU of a sequence */
  71. #define ISCSI_FLAG_FINAL 0x80
  72. /**
  73. * iSCSI login request basic header segment
  74. *
  75. */
  76. struct iscsi_bhs_login_request {
  77. /** Opcode */
  78. uint8_t opcode;
  79. /** Flags */
  80. uint8_t flags;
  81. /** Maximum supported version number */
  82. uint8_t version_max;
  83. /** Minimum supported version number */
  84. uint8_t version_min;
  85. /** Segment lengths */
  86. union iscsi_segment_lengths lengths;
  87. /** Initiator session ID (IANA format) enterprise number and flags */
  88. uint32_t isid_iana_en;
  89. /** Initiator session ID (IANA format) qualifier */
  90. uint16_t isid_iana_qual;
  91. /** Target session identifying handle */
  92. uint16_t tsih;
  93. /** Initiator Task Tag */
  94. uint32_t itt;
  95. /** Connection ID */
  96. uint16_t cid;
  97. /** Reserved */
  98. uint16_t reserved_a;
  99. /** Command sequence number */
  100. uint32_t cmdsn;
  101. /** Expected status sequence number */
  102. uint32_t expstatsn;
  103. /** Reserved */
  104. uint8_t reserved_b[16];
  105. };
  106. /** Login request opcode */
  107. #define ISCSI_OPCODE_LOGIN_REQUEST 0x03
  108. /** Willingness to transition to next stage */
  109. #define ISCSI_LOGIN_FLAG_TRANSITION 0x80
  110. /** Key=value pairs continued in subsequent request */
  111. #define ISCSI_LOGIN_FLAG_CONTINUE 0x40
  112. /* Current stage values and mask */
  113. #define ISCSI_LOGIN_CSG_MASK 0x0c
  114. #define ISCSI_LOGIN_CSG_SECURITY_NEGOTIATION 0x00
  115. #define ISCSI_LOGIN_CSG_OPERATIONAL_NEGOTIATION 0x04
  116. #define ISCSI_LOGIN_CSG_FULL_FEATURE_PHASE 0x0c
  117. /* Next stage values and mask */
  118. #define ISCSI_LOGIN_NSG_MASK 0x03
  119. #define ISCSI_LOGIN_NSG_SECURITY_NEGOTIATION 0x00
  120. #define ISCSI_LOGIN_NSG_OPERATIONAL_NEGOTIATION 0x01
  121. #define ISCSI_LOGIN_NSG_FULL_FEATURE_PHASE 0x03
  122. /** ISID IANA format marker */
  123. #define ISCSI_ISID_IANA 0x40000000
  124. /** Fen Systems Ltd. IANA enterprise number
  125. *
  126. * Permission is hereby granted to use Fen Systems Ltd.'s IANA
  127. * enterprise number with this iSCSI implementation.
  128. */
  129. #define IANA_EN_FEN_SYSTEMS 10019
  130. /**
  131. * iSCSI login response basic header segment
  132. *
  133. */
  134. struct iscsi_bhs_login_response {
  135. /** Opcode */
  136. uint8_t opcode;
  137. /** Flags */
  138. uint8_t flags;
  139. /** Maximum supported version number */
  140. uint8_t version_max;
  141. /** Minimum supported version number */
  142. uint8_t version_min;
  143. /** Segment lengths */
  144. union iscsi_segment_lengths lengths;
  145. /** Initiator session ID (IANA format) enterprise number and flags */
  146. uint32_t isid_iana_en;
  147. /** Initiator session ID (IANA format) qualifier */
  148. uint16_t isid_iana_qual;
  149. /** Target session identifying handle */
  150. uint16_t tsih;
  151. /** Initiator Task Tag */
  152. uint32_t itt;
  153. /** Reserved */
  154. uint32_t reserved_a;
  155. /** Status sequence number */
  156. uint32_t statsn;
  157. /** Expected command sequence number */
  158. uint32_t expcmdsn;
  159. /** Maximum command sequence number */
  160. uint32_t maxcmdsn;
  161. /** Status class */
  162. uint8_t status_class;
  163. /** Status detail */
  164. uint8_t status_detail;
  165. /** Reserved */
  166. uint8_t reserved_b[10];
  167. };
  168. /** Login response opcode */
  169. #define ISCSI_OPCODE_LOGIN_RESPONSE 0x23
  170. /**
  171. * iSCSI SCSI command basic header segment
  172. *
  173. */
  174. struct iscsi_bhs_scsi_command {
  175. /** Opcode */
  176. uint8_t opcode;
  177. /** Flags */
  178. uint8_t flags;
  179. /** Reserved */
  180. uint16_t reserved_a;
  181. /** Segment lengths */
  182. union iscsi_segment_lengths lengths;
  183. /** SCSI Logical Unit Number */
  184. uint8_t lun[8];
  185. /** Initiator Task Tag */
  186. uint32_t itt;
  187. /** Expected data transfer length */
  188. uint32_t exp_len;
  189. /** Command sequence number */
  190. uint32_t cmdsn;
  191. /** Expected status sequence number */
  192. uint32_t expstatsn;
  193. /** SCSI Command Descriptor Block (CDB) */
  194. union scsi_cdb cdb;
  195. };
  196. /** SCSI command opcode */
  197. #define ISCSI_OPCODE_SCSI_COMMAND 0x01
  198. /** Command will read data */
  199. #define ISCSI_COMMAND_FLAG_READ 0x40
  200. /** Command will write data */
  201. #define ISCSI_COMMAND_FLAG_WRITE 0x20
  202. /* Task attributes */
  203. #define ISCSI_COMMAND_ATTR_UNTAGGED 0x00
  204. #define ISCSI_COMMAND_ATTR_SIMPLE 0x01
  205. #define ISCSI_COMMAND_ATTR_ORDERED 0x02
  206. #define ISCSI_COMMAND_ATTR_HEAD_OF_QUEUE 0x03
  207. #define ISCSI_COMMAND_ATTR_ACA 0x04
  208. /**
  209. * iSCSI SCSI response basic header segment
  210. *
  211. */
  212. struct iscsi_bhs_scsi_response {
  213. /** Opcode */
  214. uint8_t opcode;
  215. /** Flags */
  216. uint8_t flags;
  217. /** Response code */
  218. uint8_t response;
  219. /** SCSI status code */
  220. uint8_t status;
  221. /** Segment lengths */
  222. union iscsi_segment_lengths lengths;
  223. /** Reserved */
  224. uint8_t reserved_a[8];
  225. /** Initiator Task Tag */
  226. uint32_t itt;
  227. /** SNACK tag */
  228. uint32_t snack;
  229. /** Status sequence number */
  230. uint32_t statsn;
  231. /** Expected command sequence number */
  232. uint32_t expcmdsn;
  233. /** Maximum command sequence number */
  234. uint32_t maxcmdsn;
  235. /** Expected data sequence number */
  236. uint32_t expdatasn;
  237. /** Reserved */
  238. uint8_t reserved_b[8];
  239. };
  240. /** SCSI response opcode */
  241. #define ISCSI_OPCODE_SCSI_RESPONSE 0x21
  242. /** SCSI command completed at target */
  243. #define ISCSI_RESPONSE_COMMAND_COMPLETE 0x00
  244. /** SCSI target failure */
  245. #define ISCSI_RESPONSE_TARGET_FAILURE 0x01
  246. /**
  247. * iSCSI data in basic header segment
  248. *
  249. */
  250. struct iscsi_bhs_data_in {
  251. /** Opcode */
  252. uint8_t opcode;
  253. /** Flags */
  254. uint8_t flags;
  255. /** Reserved */
  256. uint8_t reserved_a;
  257. /** SCSI status code */
  258. uint8_t status;
  259. /** Segment lengths */
  260. union iscsi_segment_lengths lengths;
  261. /** Logical Unit Number */
  262. uint8_t lun[8];
  263. /** Initiator Task Tag */
  264. uint32_t itt;
  265. /** Target Transfer Tag */
  266. uint32_t ttt;
  267. /** Status sequence number */
  268. uint32_t statsn;
  269. /** Expected command sequence number */
  270. uint32_t expcmdsn;
  271. /** Maximum command sequence number */
  272. uint32_t maxcmdsn;
  273. /** Data sequence number */
  274. uint32_t datasn;
  275. /** Buffer offset */
  276. uint32_t offset;
  277. /** Residual count */
  278. uint32_t residual_count;
  279. };
  280. /** Data in opcode */
  281. #define ISCSI_OPCODE_DATA_IN 0x25
  282. /** Data requires acknowledgement */
  283. #define ISCSI_DATA_FLAG_ACKNOWLEDGE 0x40
  284. /** Data overflow occurred */
  285. #define ISCSI_DATA_FLAG_OVERFLOW 0x04
  286. /** Data underflow occurred */
  287. #define ISCSI_DATA_FLAG_UNDERFLOW 0x02
  288. /** SCSI status code and verflow/underflow flags are valid */
  289. #define ISCSI_DATA_FLAG_STATUS 0x01
  290. /**
  291. * An iSCSI basic header segment
  292. */
  293. union iscsi_bhs {
  294. struct iscsi_bhs_common common;
  295. struct iscsi_bhs_login_request login_request;
  296. struct iscsi_bhs_login_response login_response;
  297. struct iscsi_bhs_scsi_command scsi_command;
  298. struct iscsi_bhs_scsi_response scsi_response;
  299. struct iscsi_bhs_data_in data_in;
  300. unsigned char bytes[ sizeof ( struct iscsi_bhs_common ) ];
  301. };
  302. /** State */
  303. enum iscsi_state {
  304. /** In the process of logging in */
  305. ISCSI_STATE_FAILED = -1,
  306. ISCSI_STATE_NOT_CONNECTED = 0,
  307. ISCSI_STATE_IDLE,
  308. ISCSI_STATE_LOGGING_IN,
  309. ISCSI_STATE_READING_DATA,
  310. };
  311. /** State of an iSCSI TX engine */
  312. enum iscsi_tx_state {
  313. /** Nothing to send */
  314. ISCSI_TX_IDLE = 0,
  315. /** Sending the basic header segment */
  316. ISCSI_TX_BHS,
  317. /** Sending the additional header segment */
  318. ISCSI_TX_AHS,
  319. /** Sending the data segment */
  320. ISCSI_TX_DATA,
  321. /** Sending the data segment padding */
  322. ISCSI_TX_DATA_PADDING,
  323. };
  324. /** State of an iSCSI RX engine */
  325. enum iscsi_rx_state {
  326. /** Receiving the basic header segment */
  327. ISCSI_RX_BHS = 0,
  328. /** Receiving the additional header segment */
  329. ISCSI_RX_AHS,
  330. /** Receiving the data segment */
  331. ISCSI_RX_DATA,
  332. /** Receiving the data segment padding */
  333. ISCSI_RX_DATA_PADDING,
  334. };
  335. /** An iSCSI session */
  336. struct iscsi_session {
  337. /** TCP connection for this session */
  338. struct tcp_connection tcp;
  339. /** Initiator IQN */
  340. const char *initiator;
  341. /** Target IQN */
  342. const char *target;
  343. /** Block size in bytes */
  344. size_t block_size;
  345. /** Starting block number of the current data transfer */
  346. unsigned long block_start;
  347. /** Block count of the current data transfer */
  348. unsigned long block_count;
  349. /** Block read callback function
  350. *
  351. * Note that this may be called several times, since it is
  352. * called per-packet rather than per-block.
  353. */
  354. void ( * block_read_callback ) ( void *private, const void *data,
  355. unsigned long offset, size_t len );
  356. /** Block read callback private data
  357. *
  358. * This is passed to block_read_callback()
  359. */
  360. void *block_read_private;
  361. /** State of the session */
  362. enum iscsi_state state;
  363. /** Target session identifying handle
  364. *
  365. * This is assigned by the target when we first log in, and
  366. * must be reused on subsequent login attempts.
  367. */
  368. uint16_t tsih;
  369. /** Initiator task tag
  370. *
  371. * This is the tag of the current command. It is incremented
  372. * whenever a final response PDU is received.
  373. */
  374. uint32_t itt;
  375. /** Command sequence number
  376. *
  377. * This is the sequence number of the current command, used to
  378. * fill out the CmdSN field in iSCSI request PDUs. It is
  379. * updated with the value of the ExpCmdSN field whenever we
  380. * receive an iSCSI response PDU containing such a field.
  381. */
  382. uint32_t cmdsn;
  383. /** Status sequence number
  384. *
  385. * This is the most recent status sequence number present in
  386. * the StatSN field of an iSCSI response PDU containing such a
  387. * field. Whenever we send an iSCSI request PDU, we fill out
  388. * the ExpStatSN field with this value plus one.
  389. */
  390. uint32_t statsn;
  391. /** Basic header segment for current TX PDU */
  392. union iscsi_bhs tx_bhs;
  393. /** State of the TX engine */
  394. enum iscsi_tx_state tx_state;
  395. /** Byte offset within the current TX state */
  396. size_t tx_offset;
  397. /** Basic header segment for current RX PDU */
  398. union iscsi_bhs rx_bhs;
  399. /** State of the RX engine */
  400. enum iscsi_rx_state rx_state;
  401. /** Byte offset within the current RX state */
  402. size_t rx_offset;
  403. };
  404. static inline int iscsi_busy ( struct iscsi_session *iscsi ) {
  405. return ( iscsi->state > ISCSI_STATE_IDLE );
  406. }
  407. static inline int iscsi_error ( struct iscsi_session *iscsi ) {
  408. return ( iscsi->state == ISCSI_STATE_FAILED );
  409. }
  410. #endif /* _GPXE_ISCSI_H */