summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Vater2025-07-30 17:07:21 +0200
committerSebastian Vater2025-07-30 17:07:21 +0200
commitca0f87d76e10ca7458bb6909928dc05302ec098f (patch)
tree5e5f6c52ec7b53de33d6d2e743adaca8f46c8c91
parentFixed some iSCSI packet header definitions, also added other iSCSI protocol c... (diff)
downloaddnbd3-ca0f87d76e10ca7458bb6909928dc05302ec098f.tar.gz
dnbd3-ca0f87d76e10ca7458bb6909928dc05302ec098f.tar.xz
dnbd3-ca0f87d76e10ca7458bb6909928dc05302ec098f.zip
Fixed iSCSI implementation doxygen stuff and beginning of conversion of iSCSI header file comments to doxygen style.
-rw-r--r--Doxyfile5
-rw-r--r--src/server/iscsi.c12
-rw-r--r--src/server/iscsi.h2075
3 files changed, 1391 insertions, 701 deletions
diff --git a/Doxyfile b/Doxyfile
index aa35fd5..75de69e 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -28,8 +28,9 @@ STRIP_CODE_COMMENTS = NO
# Preprocessor
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
-EXPAND_ONLY_PREDEF = NO
-SKIP_FUNCTION_MACROS = YES
+EXPAND_ONLY_PREDEF = YES
+SKIP_FUNCTION_MACROS = NO
+PREDEFINED = __attribute__(x)=
# Warnings
WARN_IF_UNDOCUMENTED = YES
diff --git a/src/server/iscsi.c b/src/server/iscsi.c
index d59d6df..b6057c8 100644
--- a/src/server/iscsi.c
+++ b/src/server/iscsi.c
@@ -413,7 +413,7 @@ void iscsi_hashmap_key_destroy(uint8_t *key) {
* be a multiple of 8 bytes which is NOT checked, so
* be careful.
* @param[in] value Value of the key, NULL is allowed.
- * @param[in] user_data This argument is not used by
+ * @param[in,out] user_data This argument is not used by
* this function and should be always NULL for now, as
* there is a possibility for future usage.
* @return Always returns 0 as this function cannot fail.
@@ -570,7 +570,7 @@ int iscsi_hashmap_get_put(iscsi_hashmap *map, const uint8_t *key, const size_t k
* overwritten key and value pair. The function is
* invoked just before overwriting the old values.
* This may NOT be NULL, so take caution.
- * @param[in] user_data Pointer to user specific data
+ * @param[in,out] user_data Pointer to user specific data
* passed to the callback function in case more
* information is needed.
* @return -1 in case adding key / value pair would
@@ -721,7 +721,7 @@ void iscsi_hashmap_remove(iscsi_hashmap *map, const uint8_t *key, const size_t k
* key and value pair to be removed. The function is
* invoked just before marking the key / value pair
* as removed. This may NOT be NULL, so take caution.
- * @param[in] user_data Pointer to user specific data
+ * @param[in,out] user_data Pointer to user specific data
* passed to the callback function in case more
* information is needed.
*/
@@ -770,7 +770,7 @@ int iscsi_hashmap_size(iscsi_hashmap *map)
* invoked for each element not marked for removal
* in the hash map. If the return value of the callback
* function is below zero, the iteration will stop.
- * @param[in] user_data Pointer to user specific data
+ * @param[in,out] user_data Pointer to user specific data
* passed to the callback function in case more
* information is needed.
* @return The return code from the last invoked
@@ -1708,7 +1708,7 @@ int iscsi_parse_key_value_pairs(iscsi_hashmap *pairs, const uint8_t *packet_data
* be careful.
* @param[in] value Value of the key, NULL creates an
* empty key assignment.
- * @param[in] user_data Pointer to a data structure
+ * @param[in,out] user_data Pointer to a data structure
* containing the memory buffer and length for the
* iSCSI packet data (iscsi_key_value_pair_packet
* structure), may NOT be NULL, so be careful.
@@ -1896,7 +1896,7 @@ void iscsi_connection_destroy(iscsi_connection *conn)
* be a multiple of 8 bytes which is NOT checked, so
* be careful.
* @param[in] value Value of the key, NULL is allowed.
- * @param[in] user_data This argument is not used by
+ * @param[in,out] user_data This argument is not used by
* this function and should be always NULL for now, as
* there is a possibility for future usage.
* @return Always returns 0 as this function cannot fail.
diff --git a/src/server/iscsi.h b/src/server/iscsi.h
index 7fa1558..ff2920c 100644
--- a/src/server/iscsi.h
+++ b/src/server/iscsi.h
@@ -123,34 +123,84 @@ uint8_t *iscsi_sprintf_append_realloc(char *buf, const char *format, ...); // Al
uint8_t *iscsi_vsprintf_alloc(const char *format, va_list args); // Allocates a buffer and sprintf's it
uint8_t *iscsi_sprintf_alloc(const char *format, ... ); // Allocates a buffer and sprintf's it
-#define ISCSI_HASHMAP_DEFAULT_CAPACITY_SHIFT 5UL // Shift factor for default capacity
-#define ISCSI_HASHMAP_DEFAULT_CAPACITY (1UL << (ISCSI_HASHMAP_DEFAULT_CAPACITY_SHIFT)) // Default capacity is 32 buckets
-#define ISCSI_HASHMAP_RESIZE_SHIFT 1UL // Number of bits to shift left when resizing
-#define ISCSI_HASHMAP_KEY_ALIGN_SHIFT 3UL // Key data shift value for alignment enforcement
-#define ISCSI_HASHMAP_KEY_ALIGN (1UL << (ISCSI_HASHMAP_KEY_ALIGN_SHIFT)) // Key data size must be multiple of 8 bytes by now
-#define ISCSI_HASHMAP_HASH_INITIAL 0x811C9DC5UL // Initial hash code
-#define ISCSI_HASHMAP_HASH_MUL 0xBF58476D1CE4E5B9ULL // Value to multiply hash code with
+/// Shift factor for default capacity.
+#define ISCSI_HASHMAP_DEFAULT_CAPACITY_SHIFT 5UL
+/// Default capacity is 32 buckets.
+#define ISCSI_HASHMAP_DEFAULT_CAPACITY (1UL << (ISCSI_HASHMAP_DEFAULT_CAPACITY_SHIFT))
+
+/// Number of bits to shift left when resizing.
+#define ISCSI_HASHMAP_RESIZE_SHIFT 1UL
+
+/// Key data shift value for alignment enforcement.
+#define ISCSI_HASHMAP_KEY_ALIGN_SHIFT 3UL
+
+/// Key data size must be multiple of 8 bytes by now.
+#define ISCSI_HASHMAP_KEY_ALIGN (1UL << (ISCSI_HASHMAP_KEY_ALIGN_SHIFT))
+
+/// Initial hash code.
+#define ISCSI_HASHMAP_HASH_INITIAL 0x811C9DC5UL
+
+/// Value to multiply hash code with.
+#define ISCSI_HASHMAP_HASH_MUL 0xBF58476D1CE4E5B9ULL
+
+/**
+ * @brief Hash map bucket containing key, value and hash code.
+ *
+ * This structure is used by the iSCSI hash map implementation
+ * in order to maintain the elements.
+ */
typedef struct iscsi_hashmap_bucket {
- struct iscsi_hashmap_bucket *next; // Must be first element
+ /// Next bucket, must be first element.
+ struct iscsi_hashmap_bucket *next;
+
+ /// Data used as key, must be aligned to 8 bytes and zero padded.
+ uint8_t *key;
- uint8_t *key; // Data used as key, zero padding
- size_t key_size; // Size of key, must be a multiple of 8 bytes
- uint32_t hash; // Hash code
- uint8_t *value; // Value
+ /// Size of key, must be a multiple of 8 bytes.
+ size_t key_size;
+
+ /// Hash code for the key.
+ uint32_t hash;
+
+ /// Associate4d value to the key, NULL is allowed.
+ uint8_t *value;
} iscsi_hashmap_bucket;
+/**
+ * @brief Hash map containing an expandable list of buckets
+ *
+ * This structure is used by the ultra performant hash map
+ * implementation. It uses a linked list allowing fast
+ * insertions. Elements can be removed and are marked for
+ * deletion until a resize operation is necessary.
+ */
typedef struct iscsi_hashmap {
- iscsi_hashmap_bucket *buckets; // Hashmap buckets
- uint capacity; // Current capacity in elements
+ /// Linked list containing the hash map buckets.
+ iscsi_hashmap_bucket *buckets;
+
+ /// Current bucket capacity, MUST be a power of two.
+ uint capacity;
+
+ /// Current capacity threshold triggering resize operation.
uint cap_load; // Capacity load threshold before next resize
- uint count; // Number of buckets
- uint removed_count; // Number of removed buckets
- iscsi_hashmap_bucket *first; // First bucket of linked list
- iscsi_hashmap_bucket *last; // Last bucket, allows faster traversion
+
+ /// Current count of buckets including ones marked for removal.
+ uint count;
+
+ /// Number of buckets marked for removal.
+ uint removed_count;
+
+ /// First linked list bucket for fast insertion.
+ iscsi_hashmap_bucket *first;
+
+ /// Last linked list bucket for faster traversion.
+ iscsi_hashmap_bucket *last;
} iscsi_hashmap;
/**
+ * @brief A Callback for iterating over map, freeing and removing entries. user_data is free for personal use.
+ *
* Callback function. This is a pointer to a
* function for various purposes like iterating
* through a hash map. It is also used for replacing
@@ -162,6 +212,11 @@ typedef struct iscsi_hashmap {
* be a multiple of 8 bytes which is NOT checked, so
* be careful.
* @param[in] value Value of the key, NULL is allowed.
+ * @param[in,out] user_data User data to be used by the
+ * callback function. User data can be modified if
+ * desired and may also be NULL if the callback
+ * function handles this case. See the documentation
+ * of the callback implementation for details.
* @return A negative result indicates as fatal error,
* 0 means successful operation and a positive value
* indicates a non-fatal error or a warning.
@@ -190,100 +245,237 @@ int iscsi_hashmap_iterate(iscsi_hashmap *map, iscsi_hashmap_callback callback, u
/* iSCSI protocol stuff (all WORD/DWORD/QWORD values are big endian by default
unless specified otherwise). */
-#define ISCSI_BHS_SIZE 48UL // iSCSI Basic Header Segment size
-#define ISCSI_DIGEST_SIZE 4UL // iSCSI header and data digest size (CRC32C)
-#define ISCSI_ALIGN_SIZE 4UL // iSCSI packet data alignment (BHS, AHS and DS)
+/// iSCSI Basic Header Segment size.
+#define ISCSI_BHS_SIZE 48UL
+
+/// iSCSI header and data digest size (CRC32C).
+#define ISCSI_DIGEST_SIZE 4UL
+
+/// iSCSI packet data alignment (BHS, AHS and DataSegment).
+#define ISCSI_ALIGN_SIZE 4UL
+
+/// Current minimum iSCSI protocol version supported by this implementation.
+#define ISCSI_VERSION_MIN 0
+
+/// Current maximum iSCSI protocol version supported by this implementation.
+#define ISCSI_VERSION_MAX 0
-#define ISCSI_VERSION_MIN 0 // Current minimum iSCSI protocol version supported by this implementation
-#define ISCSI_VERSION_MAX 0 // Current maximum iSCSI protocol version supported by this implementation
-// CRC32C constants for header and data digest
+/// CRC32C initial constant for header and data digest.
#define ISCSI_CRC32C_INITIAL 0xFFFFFFFFUL
+
+/// CRC32C initial constant for header and data digest.
#define ISCSI_CRC32C_XOR 0xFFFFFFFFUL
-// iSCSI initiator (client) command opcodes
-#define ISCSI_CLIENT_NOP_OUT 0x00 // NOP-Out
-#define ISCSI_CLIENT_SCSI_CMD 0x01 // SCSI Command (encapsulates a SCSI Command Descriptor Block)
-#define ISCSI_CLIENT_TASK_FUNC_REQ 0x02 // SCSI Task Management Function Request
-#define ISCSI_CLIENT_LOGIN_REQ 0x03 // Login Request
-#define ISCSI_CLIENT_TEXT_REQ 0x04 // Text Request
-#define ISCSI_CLIENT_SCSI_DATA_OUT 0x05 // SCSI Data-Out (for write operations)
-#define ISCSI_CLIENT_LOGOUT_REQ 0x06 // Logout Request
-#define ISCSI_CLIENT_SNACK_REQ 0x10 // SNACK Request
-#define ISCSI_CLIENT_VENDOR_CODE1 0x1C // Vendor-specific code #1
-#define ISCSI_CLIENT_VENDOR_CODE2 0x1D // Vendor-specific code #2
-#define ISCSI_CLIENT_VENDOR_CODE3 0x1E // Vendor-specific code #3
-
-#define ISCSI_CLIENT_FIRST_OPCODE 0x00 // First client opcode value
-#define ISCSI_CLIENT_LAST_OPCODE 0x1F // Last client opcode value
-
-// iSCSI target (server) command opcodes
-#define ISCSI_SERVER_NOP_IN 0x20 // NOP-In
-#define ISCSI_SERVER_SCSI_RESPONSE 0x21 // SCSI Response - contains SCSI status and possibly sense information or other response information
-#define ISCSI_SERVER_TASK_FUNC_RES 0x22 // SCSI Task Management Function Response
-#define ISCSI_SERVER_LOGIN_RES 0x23 // Login Response
-#define ISCSI_SERVER_TEXT_RES 0x24 // Text Response
-#define ISCSI_SERVER_SCSI_DATA_IN 0x25 // SCSI Data-In (for read operations)
-#define ISCSI_SERVER_LOGOUT_RES 0x26 // Logout Response
-#define ISCSI_SERVER_READY_XFER 0x31 // Ready To Transfer (R2T) - sent by target when it is ready to receive data
-#define ISCSI_SERVER_ASYNC_MSG 0x32 // Asynchronous Message - sent by target to indicate certain special conditions
-#define ISCSI_SERVER_VENDOR_CODE1 0x3C // Vendor-specific code #1
-#define ISCSI_SERVER_VENDOR_CODE2 0x3D // Vendor-specific code #2
-#define ISCSI_SERVER_VENDOR_CODE3 0x3E // Vendor-specific code #3
-#define ISCSI_SERVER_REJECT 0x3F // Reject
-
-#define ISCSI_SERVER_FIRST_OPCODE 0x20 // First client opcode value
-#define ISCSI_SERVER_LAST_OPCODE 0x3F // Last client opcode value
-
-#define ISCSI_OPCODE_MASK 0x3F // ISCSI opcode bit mask (bits 0-5 used)
-#define ISCSI_GET_OPCODE(x) ((x) & ISCSI_OPCODE_MASK) // Funky macro to get iSCSI packet opcode
+/// iSCSI initiator (client) command opcode: NOP-Out.
+#define ISCSI_CLIENT_NOP_OUT 0x00
+
+/// iSCSI initiator (client) command opcode: SCSI Command (encapsulates a SCSI Command Descriptor Block).
+#define ISCSI_CLIENT_SCSI_CMD 0x01
+
+/// iSCSI initiator (client) command opcode: SCSI Task Management Function Request.
+#define ISCSI_CLIENT_TASK_FUNC_REQ 0x02
+
+/// iSCSI initiator (client) command opcode: Login Request.
+#define ISCSI_CLIENT_LOGIN_REQ 0x03
+
+/// iSCSI initiator (client) command opcode: Text Request.
+#define ISCSI_CLIENT_TEXT_REQ 0x04
+
+/// iSCSI initiator (client) command opcode: SCSI Data-Out (for write operations).
+#define ISCSI_CLIENT_SCSI_DATA_OUT 0x05
+
+/// iSCSI initiator (client) command opcode: Logout Request.
+#define ISCSI_CLIENT_LOGOUT_REQ 0x06
+
+/// iSCSI initiator (client) command opcode: SNACK Request.
+#define ISCSI_CLIENT_SNACK_REQ 0x10
+
+/// iSCSI initiator (client) command opcode: Vendor-specific code #1.
+#define ISCSI_CLIENT_VENDOR_CODE1 0x1C
+
+/// iSCSI initiator (client) command opcode: Vendor-specific code #2.
+#define ISCSI_CLIENT_VENDOR_CODE2 0x1D
+
+/// iSCSI initiator (client) command opcode: Vendor-specific code #3.
+#define ISCSI_CLIENT_VENDOR_CODE3 0x1E
+
+/// First iSCSI initiator (client) command opcode.
+#define ISCSI_CLIENT_FIRST_OPCODE 0x00
+
+/// Last iSCSI initiator (client) command opcode.
+#define ISCSI_CLIENT_LAST_OPCODE 0x1F
+
+
+/// iSCSI target (server) command opcode: NOP-In.
+#define ISCSI_SERVER_NOP_IN 0x20
+
+/// iSCSI target (server) command opcode: SCSI Response - contains SCSI status and possibly sense information or other response information.
+#define ISCSI_SERVER_SCSI_RESPONSE 0x21
+
+/// iSCSI target (server) command opcode: SCSI Task Management Function Response.
+#define ISCSI_SERVER_TASK_FUNC_RES 0x22
+
+/// iSCSI target (server) command opcode: Login Response.
+#define ISCSI_SERVER_LOGIN_RES 0x23
+
+/// iSCSI target (server) command opcode: Text Response.
+#define ISCSI_SERVER_TEXT_RES 0x24
+
+/// iSCSI target (server) command opcode: SCSI Data-In (for read operations).
+#define ISCSI_SERVER_SCSI_DATA_IN 0x25
+
+/// iSCSI target (server) command opcode: Logout Response.
+#define ISCSI_SERVER_LOGOUT_RES 0x26
+
+/// iSCSI target (server) command opcode: Ready To Transfer (R2T) - sent by target when it is ready to receive data.
+#define ISCSI_SERVER_READY_XFER 0x31
+
+/// iSCSI target (server) command opcode: Asynchronous Message - sent by target to indicate certain special conditions.
+#define ISCSI_SERVER_ASYNC_MSG 0x32
+
+/// iSCSI target (server) command opcode: Vendor-specific code #1.
+#define ISCSI_SERVER_VENDOR_CODE1 0x3C
+
+/// iSCSI target (server) command opcode: Vendor-specific code #2.
+#define ISCSI_SERVER_VENDOR_CODE2 0x3D
+
+/// iSCSI target (server) command opcode: Vendor-specific code #3.
+#define ISCSI_SERVER_VENDOR_CODE3 0x3E
+
+/// iSCSI target (server) command opcode: Reject.
+#define ISCSI_SERVER_REJECT 0x3F
+
+
+/// First iSCSI target (server) command opcode.
+#define ISCSI_SERVER_FIRST_OPCODE 0x20
+
+/// Last iSCSI target (server) command opcode.
+#define ISCSI_SERVER_LAST_OPCODE 0x3F
+
+
+/// iSCSI opcode bit mask (bits 0-5 used).
+#define ISCSI_OPCODE_MASK 0x3F
+
+/// Macro which extracts iSCSI packet data opcode out of opcode byte
+#define ISCSI_GET_OPCODE(x) ((x) & ISCSI_OPCODE_MASK)
+
+/**
+ * @brief iSCSI Basic Header Segment packet data.
+ *
+ * This structure contains the basic iSCSI packet
+ * data and is shared among all opcodes. This has
+ * to be used before the opcode of the packet data
+ * has been determined.
+ */
typedef struct __attribute__((packed)) iscsi_bhs_packet {
- uint8_t opcode; // Command opcode (see above)
- uint8_t opcode_fields[3]; // Opcode-specific fields
- uint8_t total_ahs_len; // Total AHS length
- uint8_t ds_len[3]; // Data segment length
+ /// Command opcode.
+ uint8_t opcode;
+
+ /// Opcode-specific fields.
+ uint8_t opcode_fields[3];
+
+ /// Total length of AHS (Advanced Header Segment).
+ uint8_t total_ahs_len;
+
+ /// Length of Data Segment.
+ uint8_t ds_len[3];
+
union {
- uint64_t lun; // LUN bitmask
- uint8_t opcode_spec[8]; // Opcode-specific fields
+ /// SCSI LUN bit mask.
+ uint64_t lun;
+
+ /// Opcode-specific fields.
+ uint8_t opcode_spec[8];
} lun_opcode;
- uint32_t init_task_tag; // Initiator task tag
+
+ /// Initiator Task Tag (ITT).
+ uint32_t init_task_tag;
+
+ /// Opcode-specific fields.
uint8_t opcode_spec_fields[28];
} iscsi_bhs_packet;
-#define ISCSI_AHS_TYPE_EXT_CDB_PACKET 0x01 // Command Descriptor Block (CDB)
+
+/// iSCSI AHS type: Extended Command Descriptor Block (CDB).
+#define ISCSI_AHS_TYPE_EXT_CDB_PACKET 0x01
+
+/// iSCSI AHS type: Bidirectional Read Expected Data Transfer Length.
#define ISCSI_AHS_TYPE_BIDI_READ_EXP_XFER_AHS_PACKET 0x02
+
+/**
+ * @brief iSCSI Advanced Header Segment packet data.
+ *
+ * This structure contains the advanced iSCSI packet
+ * data and is shared among all opcodes. This has
+ * to be used before the opcode of the packet data
+ * has been determined.
+ */
typedef struct __attribute__((packed)) iscsi_ahs_packet {
- uint16_t len; // AHSLength
- uint8_t type; // AHSType
- uint8_t specific; // AHS-Specific
- uint8_t data[0]; // AHS-Specific data
+ /// AHSLength.
+ uint16_t len;
+
+ /// AHSType.
+ uint8_t type;
+
+ /// AHS-Specific.
+ uint8_t specific;
+
+ /// AHS-Specific data.
+ uint8_t data[0];
} iscsi_ahs_packet;
-/* There are 16 bytes in the CDB field to accommodate the commonly used
- CDBs. Whenever the CDB is larger than 16 bytes, an Extended CDB AHS
- MUST be used to contain the CDB spillover.
-*/
+/**
+ * @brief iSCSI CDB packet data structure.
+ *
+ * There are 16 bytes in the CDB field to accommodate the commonly used
+ * CDBs. Whenever the CDB is larger than 16 bytes, an Extended CDB AHS
+ * MUST be used to contain the CDB spillover.
+ */
typedef struct __attribute__((packed)) iscsi_cdb {
uint8_t data[16];
} iscsi_cdb;
-/* This type of AHS MUST NOT be used if the CDBLength is less than 17.
- The length includes the reserved byte 3.
-*/
+/**
+ * @brief iSCSI Extended CDB AHS packet data structure.
+ *
+ * This type of AHS MUST NOT be used if the CDBLength is less than 17.
+ * The length includes the reserved byte 3.
+ */
typedef struct __attribute__((packed)) iscsi_ext_cdb_ahs_packet {
- uint16_t len; // AHSLength - (CDBLength - 15)
- uint8_t type; // Identifier (always 0x01 according to specs)
- uint8_t reserved; // Reserved for future usage
- uint8_t data[0]; // ExtendedCDB
+ /// AHSLength: AHSLength - (CDBLength - 15).
+ uint16_t len;
+
+ // AHSType: Identifier (always 1 according to iSCSI specifications).
+ uint8_t type;
+
+ /// Reserved for future usage, always MUST be 0.
+ uint8_t reserved;
+
+ /// ExtendedCDB.
+ uint8_t data[0];
} iscsi_ext_cdb_ahs_packet;
+/**
+ * @brief iSCSI Bidirectional Read Expected Data Transfer Length AHS packet data structure.
+ *
+ * This structure is used to determine the bidirectional read
+ * expected data transfer length.
+ */
typedef struct __attribute__((packed)) iscsi_bidi_read_exp_xfer_ahs_packet {
- uint16_t len; // Always 0x0005 according to specs
+ /// AHSLength: Always 5 according to ISCSI specifications for now.
+ uint16_t len;
+
+ /// AHSType: Always 2 according to ISCSI specifications for now.
uint8_t type; // Identifier (always 0x02 according to specs)
- uint8_t reserved; // Reserved for future usage
- uint32_t bidi_read_exp_xfer_len; // Bidirectional Read Expected Data Transfer Length
+
+ /// Reserved for future usage, always MUST be 0.
+ uint8_t reserved;
+
+ /// Bidirectional Read Expected Data Transfer Length.
+ uint32_t bidi_read_exp_xfer_len;
} iscsi_bidi_read_exp_xfer_ahs_packet;
/* Certain iSCSI conditions result in the command being terminated at
@@ -303,368 +495,795 @@ typedef struct __attribute__((packed)) iscsi_bidi_read_exp_xfer_ahs_packet {
#define ISCSI_DS_ERROR_SNACK_REJECTED_ASC 0x11 // SNACK rejected
#define ISCSI_DS_ERROR_SNACK_REJECTED_ASCQ 0x13
-/* Optional header and data digests protect the integrity of the header
- and data, respectively. The digests, if present, are located,
- respectively, after the header and PDU-specific data and cover,
- respectively, the header and the PDU data, each including the padding
- bytes, if any.
- The existence and type of digests are negotiated during the Login
- Phase.
-*/
+/**
+ * @brief iSCSI header digest in case CRC32C has been negotiated.
+ *
+ * Optional header and data digests protect the integrity of the header
+ * and data, respectively. The digests, if present, are located,
+ * respectively, after the header and PDU-specific data and cover,
+ * respectively, the header and the PDU data, each including the padding
+ * bytes, if any.
+ *
+ * The existence and type of digests are negotiated during the Login
+ * Phase.
+ */
typedef struct __attribute__((packed)) iscsi_header_digest {
- uint32_t crc32c; // Header digest is a CRC32C for ensuring integrity
+ /// Header digest is a CRC32C for ensuring integrity.
+ uint32_t crc32c;
} iscsi_header_digest;
+/**
+ * @brief iSCSI data digest in case CRC32C has been negotiated.
+ *
+ * Optional header and data digests protect the integrity of the header
+ * and data, respectively. The digests, if present, are located,
+ * respectively, after the header and PDU-specific data and cover,
+ * respectively, the header and the PDU data, each including the padding
+ * bytes, if any.
+ *
+ * The existence and type of digests are negotiated during the Login
+ * Phase.
+ */
typedef struct __attribute__((packed)) iscsi_data_digest {
- uint32_t crc32c; // Data digest is a CRC32C for ensuring integrity
+ /// Data digest is a CRC32C for ensuring integrity.
+ uint32_t crc32c;
} iscsi_data_digest;
-/* iSCSI targets MUST support and enable Autosense. If Status is CHECK
- CONDITION (0x02), then the data segment MUST contain sense data for
- the failed command.
+/**
+ * @brief iSCSI DataSegment Command packet structure.
+ *
+ * iSCSI targets MUST support and enable Autosense. If Status is CHECK
+ * CONDITION (0x02), then the data segment MUST contain sense data for
+ * the failed command.
+ *
+ * For some iSCSI responses, the response data segment MAY contain some
+ * response-related information (e.g., for a target failure, it may
+ * contain a vendor-specific detailed description of the failure).
+ */
+typedef struct __attribute__((packed)) iscsi_ds_cmd_data {
+ /// SenseLength: This field indicates the length of Sense Data.
+ uint16_t len;
- For some iSCSI responses, the response data segment MAY contain some
- response-related information (e.g., for a target failure, it may
- contain a vendor-specific detailed description of the failure).
-*/
+ /// The Sense Data contains detailed information about a CHECK CONDITION. SPC3 specifies the format and content of the Sense Data.
+ uint8_t sense_data[0];
-typedef struct __attribute__((packed)) iscsi_ds_cmd_data {
- uint16_t len; // SenseLength - This field indicates the length of Sense Data.
- uint8_t sense_data[0]; // The Sense Data contains detailed information about a CHECK CONDITION.
- // SPC3 specifies the format and content of the Sense Data.
- uint8_t res_data[0]; // Response Data
+ /// Response Data.
+ uint8_t res_data[0];
} iscsi_ds_cmd_data;
-// SCSI command opcodes (embedded in iSCSI protocol)
-#define SCSI_OPCODE_TESTUNITREADY 0x00 // TEST UNIT READY
-#define SCSI_OPCODE_READ6 0x08 // READ(6)
-#define SCSI_OPCODE_INQUIRY 0x12 // INQUIRY
-#define SCSI_OPCODE_MODESELECT6 0x15 // MODE SELECT(6)
-#define SCSI_OPCODE_RESERVE6 0x16 // RESERVE(6)
-#define SCSI_OPCODE_RELEASE6 0x17 // RELEASE(6)
-#define SCSI_OPCODE_MODESENSE6 0x1A // MODE SENSE(6)
-#define SCSI_OPCODE_STARTSTOPUNIT 0x1B // START STOP UNIT
-#define SCSI_OPCODE_PREVENTALLOW 0x1E // PREVENT ALLOW MEDIUM REMOVAL
-#define SCSI_OPCODE_READCAPACITY10 0x25 // READ CAPACITY(10)
-#define SCSI_OPCODE_READ10 0x28 // READ(10)
-#define SCSI_OPCODE_WRITE10 0x2A // WRITE(10)
-#define SCSI_OPCODE_WRITE_VERIFY10 0x2E // WRITE AND VERIFY(10)
-#define SCSI_OPCODE_VERIFY10 0x2F // VERIFY(10)
-#define SCSI_OPCODE_PREFETCH10 0x34 // PRE-FETCH(10)
-#define SCSI_OPCODE_SYNCHRONIZECACHE10 0x35 // SYNCHRONIZE CACHE(10)
-#define SCSI_OPCODE_READ_DEFECT_DATA10 0x37 // READ DEFECT DATA(10)
-#define SCSI_OPCODE_WRITE_SAME10 0x41 // WRITE SAME(10)
-#define SCSI_OPCODE_UNMAP 0x42 // UNMAP
-#define SCSI_OPCODE_READTOC 0x43 // READ TOC/PMA/ATIP
-#define SCSI_OPCODE_SANITIZE 0x48 // SANITIZE
-#define SCSI_OPCODE_MODESELECT10 0x55 // MODE SELECT(10)
-#define SCSI_OPCODE_MODESENSE10 0x5A // MODE SENSE(10)
-#define SCSI_OPCODE_PERSISTENT_RESERVE_IN 0x5E // PERSISTENT RESERVE IN
-#define SCSI_OPCODE_PERSISTENT_RESERVE_OUT 0x5F // PERSISTENT RESERVE OUT
-#define SCSI_OPCODE_EXTENDED_COPY 0x83 // Third-party Copy OUT
-#define SCSI_OPCODE_RECEIVE_COPY_RESULTS 0x84 // Third-party Copy IN
-#define SCSI_OPCODE_READ16 0x88 // READ(16)
-#define SCSI_OPCODE_COMPARE_AND_WRITE 0x89 // COMPARE AND WRITE
-#define SCSI_OPCODE_WRITE16 0x8A // WRITE(16)
-#define SCSI_OPCODE_ORWRITE 0x8B // ORWRITE
-#define SCSI_OPCODE_WRITE_VERIFY16 0x8E // WRITE AND VERIFY(16)
-#define SCSI_OPCODE_VERIFY16 0x8F // VERIFY(16)
-#define SCSI_OPCODE_PREFETCH16 0x90 // PRE-FETCH(16)
-#define SCSI_OPCODE_SYNCHRONIZECACHE16 0x91 // SYNCHRONIZE CACHE(16)
-#define SCSI_OPCODE_WRITE_SAME16 0x93 // WRITE SAME(16)
-#define SCSI_OPCODE_WRITE_ATOMIC16 0x9C // WRITE ATOMIC(16)
-#define SCSI_OPCODE_SERVICE_ACTION_IN 0x9E // SERVICE ACTION IN(16)
-#define SCSI_OPCODE_REPORTLUNS 0xA0 // REPORT LUNS
-#define SCSI_OPCODE_MAINTENANCE_IN 0xA3 // MAINTENANCE IN
-#define SCSI_OPCODE_READ12 0xA8 // READ(12)
-#define SCSI_OPCODE_WRITE12 0xAA // WRITE(12)
-#define SCSI_OPCODE_WRITE_VERIFY12 0xAE // WRITE AND VERIFY(12)
-#define SCSI_OPCODE_VERIFY12 0xAF // VERIFY(12)
-#define SCSI_OPCODE_READ_DEFECT_DATA12 0xB7 // READ DEFECT DATA(12)
-
-#define ISCSI_SCSI_CMD_FLAGS_TASK_NO_UNSOLICITED_DATA (1 << 7) // (F) is set to 1 when no unsolicited SCSI Data-Out PDUs
- // follow this PDU. When F = 1 for a write and if Expected
- // Data Transfer Length is larger than the
- // DataSegmentLength, the target may solicit additional data
- // through R2T.
-#define ISCSI_SCSI_CMD_FLAGS_TASK_READ (1 << 6) // (R) is set to 1 when the command is expected to input data
-#define ISCSI_SCSI_CMD_FLAGS_TASK_WRITE (1 << 5) // (W) is set to 1 when the command is expected to output data
-
-#define ISCSI_SCSI_CMD_FLAGS_TASK_ATTR_UNTAGGED 0x0 // Untagged task attribute
-#define ISCSI_SCSI_CMD_FLAGS_TASK_ATTR_SIMPLE 0x1 // Simple task attribute
-#define ISCSI_SCSI_CMD_FLAGS_TASK_ATTR_ORDERED 0x2 // Ordered task attribute
-#define ISCSI_SCSI_CMD_FLAGS_TASK_ATTR_HEAD_QUEUE 0x3 // Head of queue task attribute
-#define ISCSI_SCSI_CMD_FLAGS_TASK_ATTR_ACA 0x4 // ACA task attribute
-#define ISCSI_SCSI_CMD_FLAGS_TASK_ATTR_RESERVED_1 0x5 // ACA task attribute
-#define ISCSI_SCSI_CMD_FLAGS_TASK_ATTR_RESERVED_2 0x6 // ACA task attribute
-#define ISCSI_SCSI_CMD_FLAGS_TASK_ATTR_RESERVED_3 0x7 // ACA task attribute
-
-/* Flags and Task Attributes:
- At least one of the W and F bits MUST be set to 1.
- Either or both of R and W MAY be 1 when the Expected Data Transfer
- Length and/or the Bidirectional Read Expected Data Transfer Length
- are 0, but they MUST NOT both be 0 when the Expected Data Transfer
- Length and/or Bidirectional Read Expected Data Transfer Length are
- not 0 (i.e., when some data transfer is expected, the transfer
- direction is indicated by the R and/or W bit).
-*/
+/// SCSI command opcode (embedded in iSCSI protocol): TEST UNIT READY.
+#define ISCSI_SCSI_OPCODE_TESTUNITREADY 0x00
+
+/// SCSI command opcode (embedded in iSCSI protocol): READ(6).
+#define ISCSI_SCSI_OPCODE_READ6 0x08
+
+/// SCSI command opcode (embedded in iSCSI protocol): INQUIRY.
+#define ISCSI_SCSI_OPCODE_INQUIRY 0x12
+
+/// SCSI command opcode (embedded in iSCSI protocol): MODE SELECT(6).
+#define ISCSI_SCSI_OPCODE_MODESELECT6 0x15
+
+/// SCSI command opcode (embedded in iSCSI protocol): RESERVE(6).
+#define ISCSI_SCSI_OPCODE_RESERVE6 0x16
+
+/// SCSI command opcode (embedded in iSCSI protocol): RELEASE(6).
+#define ISCSI_SCSI_OPCODE_RELEASE6 0x17
+
+/// SCSI command opcode (embedded in iSCSI protocol): MODE SENSE(6).
+#define ISCSI_SCSI_OPCODE_MODESENSE6 0x1A
+
+/// SCSI command opcode (embedded in iSCSI protocol): START STOP UNIT.
+#define ISCSI_SCSI_OPCODE_STARTSTOPUNIT 0x1B
+
+/// SCSI command opcode (embedded in iSCSI protocol): PREVENT ALLOW MEDIUM REMOVAL.
+#define ISCSI_SCSI_OPCODE_PREVENTALLOW 0x1E
+
+/// SCSI command opcode (embedded in iSCSI protocol): READ CAPACITY(10).
+#define ISCSI_SCSI_OPCODE_READCAPACITY10 0x25
+
+/// SCSI command opcode (embedded in iSCSI protocol): READ(10).
+#define ISCSI_SCSI_OPCODE_READ10 0x28
+
+/// SCSI command opcode (embedded in iSCSI protocol): WRITE(10).
+#define ISCSI_SCSI_OPCODE_WRITE10 0x2A
+
+/// SCSI command opcode (embedded in iSCSI protocol): WRITE AND VERIFY(10).
+#define ISCSI_SCSI_OPCODE_WRITE_VERIFY10 0x2E
+
+/// SCSI command opcode (embedded in iSCSI protocol): VERIFY(10).
+#define ISCSI_SCSI_OPCODE_VERIFY10 0x2F
+
+/// SCSI command opcode (embedded in iSCSI protocol): PRE-FETCH(10).
+#define ISCSI_SCSI_OPCODE_PREFETCH10 0x34
+
+/// SCSI command opcode (embedded in iSCSI protocol): SYNCHRONIZE CACHE(10).
+#define ISCSI_SCSI_OPCODE_SYNCHRONIZECACHE10 0x35
+
+/// SCSI command opcode (embedded in iSCSI protocol): READ DEFECT DATA(10).
+#define ISCSI_SCSI_OPCODE_READ_DEFECT_DATA10 0x37
+
+/// SCSI command opcode (embedded in iSCSI protocol): WRITE SAME(10).
+#define ISCSI_SCSI_OPCODE_WRITE_SAME10 0x41
+
+/// SCSI command opcode (embedded in iSCSI protocol): UNMAP.
+#define ISCSI_SCSI_OPCODE_UNMAP 0x42
+
+/// SCSI command opcode (embedded in iSCSI protocol): READ TOC/PMA/ATIP.
+#define ISCSI_SCSI_OPCODE_READTOC 0x43
+
+/// SCSI command opcode (embedded in iSCSI protocol): SANITIZE.
+#define ISCSI_SCSI_OPCODE_SANITIZE 0x48
+
+/// SCSI command opcode (embedded in iSCSI protocol): MODE SELECT(10).
+#define ISCSI_SCSI_OPCODE_MODESELECT10 0x55
+
+/// SCSI command opcode (embedded in iSCSI protocol): MODE SENSE(10).
+#define ISCSI_SCSI_OPCODE_MODESENSE10 0x5A
+
+/// SCSI command opcode (embedded in iSCSI protocol): PERSISTENT RESERVE IN.
+#define ISCSI_SCSI_OPCODE_PERSISTENT_RESERVE_IN 0x5E
+
+/// SCSI command opcode (embedded in iSCSI protocol): PERSISTENT RESERVE OUT.
+#define ISCSI_SCSI_OPCODE_PERSISTENT_RESERVE_OUT 0x5F
+
+/// SCSI command opcode (embedded in iSCSI protocol): Third-party Copy OUT.
+#define ISCSI_SCSI_OPCODE_EXTENDED_COPY 0x83
+
+/// SCSI command opcode (embedded in iSCSI protocol): Third-party Copy IN.
+#define ISCSI_SCSI_OPCODE_RECEIVE_COPY_RESULTS 0x84
+
+/// SCSI command opcode (embedded in iSCSI protocol): READ(16).
+#define ISCSI_SCSI_OPCODE_READ16 0x88
+
+/// SCSI command opcode (embedded in iSCSI protocol): COMPARE AND WRITE.
+#define ISCSI_SCSI_OPCODE_COMPARE_AND_WRITE 0x89
+
+/// SCSI command opcode (embedded in iSCSI protocol): WRITE(16).
+#define ISCSI_SCSI_OPCODE_WRITE16 0x8A
+
+/// SCSI command opcode (embedded in iSCSI protocol): ORWRITE.
+#define ISCSI_SCSI_OPCODE_ORWRITE 0x8B
+
+/// SCSI command opcode (embedded in iSCSI protocol): WRITE AND VERIFY(16).
+#define ISCSI_SCSI_OPCODE_WRITE_VERIFY16 0x8E
+
+/// SCSI command opcode (embedded in iSCSI protocol): VERIFY(16).
+#define ISCSI_SCSI_OPCODE_VERIFY16 0x8F
+
+/// SCSI command opcode (embedded in iSCSI protocol): PRE-FETCH(16).
+#define ISCSI_SCSI_OPCODE_PREFETCH16 0x90
+
+/// SCSI command opcode (embedded in iSCSI protocol): SYNCHRONIZE CACHE(16).
+#define ISCSI_SCSI_OPCODE_SYNCHRONIZECACHE16 0x91
+
+/// SCSI command opcode (embedded in iSCSI protocol): WRITE SAME(16).
+#define ISCSI_SCSI_OPCODE_WRITE_SAME16 0x93
-#define ISCSI_SCSI_CMD_FLAGS_TASK_ATTR_MASK 0x7 // Task Attributes (ATTR) are encoded in the first three LSBs'
+/// SCSI command opcode (embedded in iSCSI protocol): WRITE ATOMIC(16).
+#define ISCSI_SCSI_OPCODE_WRITE_ATOMIC16 0x9C
+/// SCSI command opcode (embedded in iSCSI protocol): SERVICE ACTION IN(16).
+#define ISCSI_SCSI_OPCODE_SERVICE_ACTION_IN 0x9E
+
+/// SCSI command opcode (embedded in iSCSI protocol): REPORT LUNS.
+#define ISCSI_SCSI_OPCODE_REPORTLUNS 0xA0
+
+/// SCSI command opcode (embedded in iSCSI protocol): MAINTENANCE IN.
+#define ISCSI_SCSI_OPCODE_MAINTENANCE_IN 0xA3
+
+/// SCSI command opcode (embedded in iSCSI protocol): READ(12).
+#define ISCSI_SCSI_OPCODE_READ12 0xA8
+
+/// SCSI command opcode (embedded in iSCSI protocol): WRITE(12).
+#define ISCSI_SCSI_OPCODE_WRITE12 0xAA
+
+/// SCSI command opcode (embedded in iSCSI protocol): WRITE AND VERIFY(12).
+#define ISCSI_SCSI_OPCODE_WRITE_VERIFY12 0xAE
+
+/// SCSI command opcode (embedded in iSCSI protocol): VERIFY(12).
+#define ISCSI_SCSI_OPCODE_VERIFY12 0xAF
+
+/// SCSI command opcode (embedded in iSCSI protocol): READ DEFECT DATA(12).
+#define ISCSI_SCSI_OPCODE_READ_DEFECT_DATA12 0xB7
+
+
+/**
+ * @brief iSCSI SCSI command flags: No unsolicited data.
+ *
+ * (F) is set to 1 when no unsolicited SCSI Data-Out PDUs
+ * follow this PDU. When F = 1 for a write and if Expected
+ * Data Transfer Length is larger than the
+ * DataSegmentLength, the target may solicit additional data
+ * through R2T.
+ */
+#define ISCSI_SCSI_CMD_FLAGS_TASK_NO_UNSOLICITED_DATA (1 << 7)
+
+/**
+ * @brief iSCSI SCSI command flags: Expected input data.
+ *
+ * (R) is set to 1 when the command is expected to input data.
+ */
+#define ISCSI_SCSI_CMD_FLAGS_TASK_READ (1 << 6)
+
+/**
+ * @brief iSCSI SCSI command flags: Expected output data.
+ *
+ * (W) is set to 1 when the command is expected to output data.
+ */
+#define ISCSI_SCSI_CMD_FLAGS_TASK_WRITE (1 << 5)
+
+
+/// SCSI command flags task attribute: Untagged.
+#define ISCSI_SCSI_CMD_FLAGS_TASK_ATTR_UNTAGGED 0x0
+
+/// SCSI command flags task attribute: Simple.
+#define ISCSI_SCSI_CMD_FLAGS_TASK_ATTR_SIMPLE 0x1
+
+/// SCSI command flags task attribute: Ordered.
+#define ISCSI_SCSI_CMD_FLAGS_TASK_ATTR_ORDERED 0x2
+
+/// SCSI command flags task attribute: Head of queue.
+#define ISCSI_SCSI_CMD_FLAGS_TASK_ATTR_HEAD_QUEUE 0x3
+
+/// SCSI command flags task attribute: ACA.
+#define ISCSI_SCSI_CMD_FLAGS_TASK_ATTR_ACA 0x4
+
+/// SCSI command flags task attribute: Reserved.
+#define ISCSI_SCSI_CMD_FLAGS_TASK_ATTR_RESERVED_1 0x5
+
+/// SCSI command flags task attribute: Reserved.
+#define ISCSI_SCSI_CMD_FLAGS_TASK_ATTR_RESERVED_2 0x6
+
+/// SCSI command flags task attribute: Reserved.
+#define ISCSI_SCSI_CMD_FLAGS_TASK_ATTR_RESERVED_3 0x7
+
+/// SCSI command flags Task Attributes (ATTR) are encoded in the first three LSBs.
+#define ISCSI_SCSI_CMD_FLAGS_TASK_ATTR_MASK 0x7
+
+
+/**
+ * @brief iSCSI Flag and Task Attributes for SCSI command packet data.
+ *
+ * Flags and Task Attributes:
+ * At least one of the W and F bits MUST be set to 1.
+ * Either or both of R and W MAY be 1 when the Expected Data Transfer
+ * Length and/or the Bidirectional Read Expected Data Transfer Length
+ * are 0, but they MUST NOT both be 0 when the Expected Data Transfer
+ * Length and/or Bidirectional Read Expected Data Transfer Length are
+ * not 0 (i.e., when some data transfer is expected, the transfer
+ * direction is indicated by the R and/or W bit).
+ */
typedef struct __attribute__((packed)) iscsi_scsi_cmd_packet {
- uint8_t opcode; // Always 0x01 according to specification (see above)
- int8_t flags_task; // Flags and Task Attributes
- uint16_t reserved; // Reserved for future usage
- uint8_t total_ahs_len; // Total AHS length
- uint8_t ds_len[3]; // Data segment length
- uint64_t lun; // LUN bitmask
- uint32_t init_task_tag; // Initiator task tag
- uint32_t exp_xfer_len; // Expected Data Transfer Length
- // For unidirectional operations, the Expected Data Transfer Length
- // field contains the number of bytes of data involved in this SCSI
- // operation. For a unidirectional write operation (W flag set to 1 and
- // R flag set to 0), the initiator uses this field to specify the number
- // of bytes of data it expects to transfer for this operation. For a
- // unidirectional read operation (W flag set to 0 and R flag set to 1),
- // the initiator uses this field to specify the number of bytes of data
- // it expects the target to transfer to the initiator. It corresponds
- // to the SAM-2 byte count.
- // For bidirectional operations (both R and W flags are set to 1), this
- // field contains the number of data bytes involved in the write
- // transfer. For bidirectional operations, an additional header segment
- // MUST be present in the header sequence that indicates the
- // Bidirectional Read Expected Data Transfer Length. The Expected Data
- // Transfer Length field and the Bidirectional Read Expected Data
- // Transfer Length field correspond to the SAM-2 byte count.
- // If the Expected Data Transfer Length for a write and the length of
- // the immediate data part that follows the command (if any) are the
- // same, then no more data PDUs are expected to follow. In this case,
- // the F bit MUST be set to 1.
- // If the Expected Data Transfer Length is higher than the
- // FirstBurstLength (the negotiated maximum amount of unsolicited data
- // the target will accept), the initiator MUST send the maximum amount
- // of unsolicited data OR ONLY the immediate data, if any.
- // Upon completion of a data transfer, the target informs the initiator
- // (through residual counts) of how many bytes were actually processed
- // (sent and/or received) by the target.
- uint32_t cmd_sn; // The CmdSN enables ordered delivery across multiple connections in a single session
- uint32_t exp_stat_sn; // Command responses up to ExpStatSN - 1 (modulo 2**32) have been
- // received (acknowledges status) on the connection.
- struct iscsi_cdb scsi_cdb; // SCSI Command Descriptor Block (CDB)
- // There are 16 bytes in the CDB field to accommodate the commonly used
- // CDBs. Whenever the CDB is larger than 16 bytes, an Extended CDB AHS
- // MUST be used to contain the CDB spillover.
- struct iscsi_ahs_packet ahs; // Optional AHS packet data
- struct iscsi_header_digest hdr_digest; // Optional header digest
- struct iscsi_ds_cmd_data ds_cmd_data; // Optional data segment, command data
- struct iscsi_data_digest data_digest; // Optional data digest
+ /// Always 1 according to the iSCSI specification.
+ uint8_t opcode;
+
+ /// Flags and Task Attributes.
+ int8_t flags_task;
+
+ /// Reserved for future usage, MUST always be 0.
+ uint16_t reserved;
+
+ /// Total length of AHS.
+ uint8_t total_ahs_len;
+
+ /// Length of DataSegment.
+ uint8_t ds_len[3];
+
+ /// SCSI LUN bit mask.
+ uint64_t lun;
+
+ /// Initiator Task Tag (ITT).
+ uint32_t init_task_tag;
+
+ /**
+ * @brief Expected Data Transfer Length.
+ *
+ * For unidirectional operations, the Expected Data Transfer Length
+ * field contains the number of bytes of data involved in this SCSI
+ * operation. For a unidirectional write operation (W flag set to 1 and
+ * R flag set to 0), the initiator uses this field to specify the number
+ * of bytes of data it expects to transfer for this operation. For a
+ * unidirectional read operation (W flag set to 0 and R flag set to 1),
+ * the initiator uses this field to specify the number of bytes of data
+ * it expects the target to transfer to the initiator. It corresponds
+ * to the SAM-2 byte count.
+ * For bidirectional operations (both R and W flags are set to 1), this
+ * field contains the number of data bytes involved in the write
+ * transfer. For bidirectional operations, an additional header segment
+ * MUST be present in the header sequence that indicates the
+ * Bidirectional Read Expected Data Transfer Length. The Expected Data
+ * Transfer Length field and the Bidirectional Read Expected Data
+ * Transfer Length field correspond to the SAM-2 byte count.
+ * If the Expected Data Transfer Length for a write and the length of
+ * the immediate data part that follows the command (if any) are the
+ * same, then no more data PDUs are expected to follow. In this case,
+ * the F bit MUST be set to 1.
+ * If the Expected Data Transfer Length is higher than the
+ * FirstBurstLength (the negotiated maximum amount of unsolicited data
+ * the target will accept), the initiator MUST send the maximum amount
+ * of unsolicited data OR ONLY the immediate data, if any.
+ * Upon completion of a data transfer, the target informs the initiator
+ * (through residual counts) of how many bytes were actually processed
+ * (sent and/or received) by the target.
+ */
+ uint32_t exp_xfer_len;
+
+ /// The CmdSN enables ordered delivery across multiple connections in a single session.
+ uint32_t cmd_sn;
+
+ /// Command responses up to ExpStatSN - 1 (modulo 2**32) have been received (acknowledges status) on the connection.
+ uint32_t exp_stat_sn;
+
+ /**
+ * @brief SCSI Command Descriptor Block (CDB).
+ *
+ * There are 16 bytes in the CDB field to accommodate the commonly used
+ * CDBs. Whenever the CDB is larger than 16 bytes, an Extended CDB AHS
+ * MUST be used to contain the CDB spillover.
+ */
+ iscsi_cdb scsi_cdb;
+
+ /// Optional AHS packet data.
+ iscsi_ahs_packet ahs;
+
+ /// Optional header digest.
+ iscsi_header_digest hdr_digest;
+
+ /// Optional data segment, command data.
+ iscsi_ds_cmd_data ds_cmd_data;
+
+ /// Optional data digest.
+ iscsi_data_digest data_digest;
} iscsi_scsi_cmd_packet;
-#define ISCSI_SCSI_RESPONSE_FLAGS_RES_UNDERFLOW (1 << 1) // (U) set for Residual Underflow. In this case, the Residual
- // Count indicates the number of bytes that were not
- // transferred out of the number of bytes that were expected
- // to be transferred. For a bidirectional operation, the
- // Residual Count contains the residual for the write
- // operation.
-
-#define ISCSI_SCSI_RESPONSE_FLAGS_RES_OVERFLOW (1 << 2) // (O) set for Residual Overflow. In this case, the Residual
- // Count indicates the number of bytes that were not
- // transferred because the initiator's Expected Data
- // Transfer Length was not sufficient. For a bidirectional
- // operation, the Residual Count contains the residual for
- // the write operation.
-
-#define ISCSI_SCSI_RESPONSE_FLAGS_BIDI_READ_RES_UNDERFLOW (1 << 3) // (u) set for Bidirectional Read Residual Underflow. In this
- // case, the Bidirectional Read Residual Count indicates the
- // number of bytes that were not transferred to the
- // initiator out of the number of bytes expected to be
- // transferred.
-
-#define ISCSI_SCSI_RESPONSE_FLAGS_BIDI_READ_RES_OVERFLOW (1 << 4) // (o) set for Bidirectional Read Residual Overflow. In this
- // case, the Bidirectional Read Residual Count indicates the
- // number of bytes that were not transferred to the
- // initiator because the initiator's Bidirectional Read
- // Expected Data Transfer Length was not sufficient.
-
-/* Bits O and U and bits o and u are mutually exclusive (i.e., having
- both o and u or O and U set to 1 is a protocol error).
-
- For a response other than "Command Completed at Target", bits 3-6
- MUST be 0.
-*/
-#define ISCSI_SCSI_RESPONSE_STATUS_GOOD 0x00
-#define ISCSI_SCSI_RESPONSE_STATUS_CHECK_COND 0x02
-#define ISCSI_SCSI_RESPONSE_STATUS_BUSY 0x08
-#define ISCSI_SCSI_RESPONSE_STATUS_RES_CONFLICT 0x18
-#define ISCSI_SCSI_RESPONSE_STATUS_TASK_SET_FULL 0x28
-#define ISCSI_SCSI_RESPONSE_STATUS_ACA_ACTIVE 0x30
-#define ISCSI_SCSI_RESPONSE_STATUS_TASK_ABORTED 0x40
-
-/* The Status field is used to report the SCSI status of the command (as
- specified in SAM2) and is only valid if the response code is
- Command Completed at Target.
-
- If a SCSI device error is detected while data from the initiator is
- still expected (the command PDU did not contain all the data and the
- target has not received a data PDU with the Final bit set), the
- target MUST wait until it receives a data PDU with the F bit set in
- the last expected sequence before sending the Response PDU.
-*/
+/**
+ * @brief SCSI response flags: Residual Underflow.
+ *
+ * (U) set for Residual Underflow. In this case, the Residual
+ * Count indicates the number of bytes that were not
+ * transferred out of the number of bytes that were expected
+ * to be transferred. For a bidirectional operation, the
+ * Residual Count contains the residual for the write
+ * operation.
+ *
+ * Bits O and U and bits o and u are mutually exclusive (i.e., having
+ * both o and u or O and U set to 1 is a protocol error).
+ *
+ * For a response other than "Command Completed at Target", bits 3-6
+ * MUST be 0.
+ */
+#define ISCSI_SCSI_RESPONSE_FLAGS_RES_UNDERFLOW (1 << 1)
+
+/**
+ * @brief SCSI response flags: Residual Overflow.
+ *
+ * (O) set for Residual Overflow. In this case, the Residual
+ * Count indicates the number of bytes that were not
+ * transferred because the initiator's Expected Data
+ * Transfer Length was not sufficient. For a bidirectional
+ * operation, the Residual Count contains the residual for
+ * the write operation.
+ *
+ * Bits O and U and bits o and u are mutually exclusive (i.e., having
+ * both o and u or O and U set to 1 is a protocol error).
+ *
+ * For a response other than "Command Completed at Target", bits 3-6
+ * MUST be 0.
+ */
+#define ISCSI_SCSI_RESPONSE_FLAGS_RES_OVERFLOW (1 << 2)
-#define ISCSI_SCSI_RESPONSE_CODE_OK 0x00 // Command Completed at Target
-#define ISCSI_SCSI_RESPONSE_CODE_FAIL 0x01 // Target Failure
-#define ISCSI_SCSI_RESPONSE_CODE_VENDOR_FIRST 0x80 // First vendor specific response code
-#define ISCSI_SCSI_RESPONSE_CODE_VENDOR_LAST 0xFF // Last vendor specific response code
+/**
+ * @brief SCSI response flags: Bidirectional Read Residual Underflow.
+ *
+ * (u) set for Bidirectional Read Residual Underflow. In this
+ * case, the Bidirectional Read Residual Count indicates the
+ * number of bytes that were not transferred to the
+ * initiator out of the number of bytes expected to be
+ * transferred.
+ *
+ * Bits O and U and bits o and u are mutually exclusive (i.e., having
+ * both o and u or O and U set to 1 is a protocol error).
+ *
+ * For a response other than "Command Completed at Target", bits 3-6
+ * MUST be 0.
+ */
+#define ISCSI_SCSI_RESPONSE_FLAGS_BIDI_READ_RES_UNDERFLOW (1 << 3)
-/* The Response field is used to report a service response. The mapping
- of the response code into a SCSI service response code value, if
- needed, is outside the scope of this document. However, in symbolic
- terms, response value 0x00 maps to the SCSI service response (see
-*/
+/**
+ * @brief SCSI response flags: Bidirectional Read Residual Overflow.
+ *
+ + (o) set for Bidirectional Read Residual Overflow. In this
+ * case, the Bidirectional Read Residual Count indicates the
+ * number of bytes that were not transferred to the
+ * initiator because the initiator's Bidirectional Read
+ * Expected Data Transfer Length was not sufficient.
+ *
+ * Bits O and U and bits o and u are mutually exclusive (i.e., having
+ * both o and u or O and U set to 1 is a protocol error).
+ *
+ * For a response other than "Command Completed at Target", bits 3-6
+ * MUST be 0.
+ */
+#define ISCSI_SCSI_RESPONSE_FLAGS_BIDI_READ_RES_OVERFLOW (1 << 4)
+
+/**
+ * @brief SCSI status response code: Good.
+ *
+ * The Status field is used to report the SCSI status of the command (as
+ * specified in SAM2) and is only valid if the response code is
+ * Command Completed at Target.
+ *
+ * If a SCSI device error is detected while data from the initiator is
+ * still expected (the command PDU did not contain all the data and the
+ * target has not received a data PDU with the Final bit set), the
+ * target MUST wait until it receives a data PDU with the F bit set in
+ * the last expected sequence before sending the Response PDU.
+ */
+#define ISCSI_SCSI_RESPONSE_STATUS_GOOD 0x00
+
+/**
+ * @brief SCSI status response code: Check condition.
+ *
+ * The Status field is used to report the SCSI status of the command (as
+ * specified in SAM2) and is only valid if the response code is
+ * Command Completed at Target.
+ *
+ * If a SCSI device error is detected while data from the initiator is
+ * still expected (the command PDU did not contain all the data and the
+ * target has not received a data PDU with the Final bit set), the
+ * target MUST wait until it receives a data PDU with the F bit set in
+ * the last expected sequence before sending the Response PDU.
+ */
+#define ISCSI_SCSI_RESPONSE_STATUS_CHECK_COND 0x02
+
+/**
+ * @brief SCSI status response code: Busy.
+ *
+ * The Status field is used to report the SCSI status of the command (as
+ * specified in SAM2) and is only valid if the response code is
+ * Command Completed at Target.
+ *
+ * If a SCSI device error is detected while data from the initiator is
+ * still expected (the command PDU did not contain all the data and the
+ * target has not received a data PDU with the Final bit set), the
+ * target MUST wait until it receives a data PDU with the F bit set in
+ * the last expected sequence before sending the Response PDU.
+ */
+#define ISCSI_SCSI_RESPONSE_STATUS_BUSY 0x08
+
+/**
+ * @brief SCSI status response code: Residual conflict.
+ *
+ * The Status field is used to report the SCSI status of the command (as
+ * specified in SAM2) and is only valid if the response code is
+ * Command Completed at Target.
+ *
+ * If a SCSI device error is detected while data from the initiator is
+ * still expected (the command PDU did not contain all the data and the
+ * target has not received a data PDU with the Final bit set), the
+ * target MUST wait until it receives a data PDU with the F bit set in
+ * the last expected sequence before sending the Response PDU.
+ */
+#define ISCSI_SCSI_RESPONSE_STATUS_RES_CONFLICT 0x18
+
+/**
+ * @brief SCSI status response code: Task set full.
+ *
+ * The Status field is used to report the SCSI status of the command (as
+ * specified in SAM2) and is only valid if the response code is
+ * Command Completed at Target.
+ *
+ * If a SCSI device error is detected while data from the initiator is
+ * still expected (the command PDU did not contain all the data and the
+ * target has not received a data PDU with the Final bit set), the
+ * target MUST wait until it receives a data PDU with the F bit set in
+ * the last expected sequence before sending the Response PDU.
+ */
+#define ISCSI_SCSI_RESPONSE_STATUS_TASK_SET_FULL 0x28
+
+/**
+ * @brief SCSI status response code: ACA active.
+ *
+ * The Status field is used to report the SCSI status of the command (as
+ * specified in SAM2) and is only valid if the response code is
+ * Command Completed at Target.
+ *
+ * If a SCSI device error is detected while data from the initiator is
+ * still expected (the command PDU did not contain all the data and the
+ * target has not received a data PDU with the Final bit set), the
+ * target MUST wait until it receives a data PDU with the F bit set in
+ * the last expected sequence before sending the Response PDU.
+ */
+#define ISCSI_SCSI_RESPONSE_STATUS_ACA_ACTIVE 0x30
+
+/**
+ * @brief SCSI status response code: Task aborted.
+ *
+ * The Status field is used to report the SCSI status of the command (as
+ * specified in SAM2) and is only valid if the response code is
+ * Command Completed at Target.
+ *
+ * If a SCSI device error is detected while data from the initiator is
+ * still expected (the command PDU did not contain all the data and the
+ * target has not received a data PDU with the Final bit set), the
+ * target MUST wait until it receives a data PDU with the F bit set in
+ * the last expected sequence before sending the Response PDU.
+ */
+#define ISCSI_SCSI_RESPONSE_STATUS_TASK_ABORTED 0x40
+
+/// SCSI response code: Command Completed at Target.
+#define ISCSI_SCSI_RESPONSE_CODE_OK 0x00
+
+/// SCSI response code: Target Failure.
+#define ISCSI_SCSI_RESPONSE_CODE_FAIL 0x01
+
+/// SCSI response code: First vendor specific response code.
+#define ISCSI_SCSI_RESPONSE_CODE_VENDOR_FIRST 0x80
+
+/// SCSI response code: Last vendor specific response code.
+#define ISCSI_SCSI_RESPONSE_CODE_VENDOR_LAST 0xFF
+
+/**
+ * @brief iSCSI SCSI command response packet data.
+ *
+ * The Response field is used to report a service response. The mapping
+ * of the response code into a SCSI service response code value, if
+ * needed, is outside the scope of this document. However, in symbolic
+ * terms, response value 0x00 maps to the SCSI service response (see
+ */
typedef struct __attribute__((packed)) iscsi_scsi_response_packet {
- uint8_t opcode; // Always 0x21 according to specification (see above)
- int8_t flags; // Flags (see above)
- uint8_t response; // This field contains the iSCSI service response.
- uint8_t status; // The Status field is used to report the SCSI status of the command (as
- // specified in SAM2) and is only valid if the response code is
- // Command Completed at Target. See above for codes.
- uint8_t total_ahs_len; // Total AHS length
- uint8_t ds_len[3]; // Data segment length
- uint64_t reserved; // Reserved for future usage
- uint32_t init_task_tag; // Initiator task tag
- uint32_t snack_tag; // This field contains a copy of the SNACK Tag of the last SNACK Tag
- // accepted by the target on the same connection and for the command for
- // which the response is issued. Otherwise, it is reserved and should
- // be set to 0.
- // After issuing a R-Data SNACK, the initiator must discard any SCSI
- // status unless contained in a SCSI Response PDU carrying the same
- // SNACK Tag as the last issued R-Data SNACK for the SCSI command on the
- // current connection.
- uint32_t stat_sn; // StatSN - Status Sequence Number
- // The StatSN is a sequence number that the target iSCSI layer generates
- // per connection and that in turn enables the initiator to acknowledge
- // status reception. The StatSN is incremented by 1 for every
- // response/status sent on a connection, except for responses sent as a
- // result of a retry or SNACK. In the case of responses sent due to a
- // retransmission request, the StatSN MUST be the same as the first time
- // the PDU was sent, unless the connection has since been restarted.
- uint32_t exp_cmd_sn; // ExpCmdSN - Next Expected CmdSN from This Initiator
- // The ExpCmdSN is a sequence number that the target iSCSI returns to
- // the initiator to acknowledge command reception. It is used to update
- // a local variable with the same name. An ExpCmdSN equal to
- // MaxCmdSN + 1 indicates that the target cannot accept new commands.
- uint32_t max_cmd_sn; // MaxCmdSN - Maximum CmdSN from This Initiator
- // The MaxCmdSN is a sequence number that the target iSCSI returns to
- // the initiator to indicate the maximum CmdSN the initiator can send.
- // It is used to update a local variable with the same name. If the
- // MaxCmdSN is equal to ExpCmdSN - 1, this indicates to the initiator
- // that the target cannot receive any additional commands. When the
- // MaxCmdSN changes at the target while the target has no pending PDUs
- // to convey this information to the initiator, it MUST generate a
- // NOP-In to carry the new MaxCmdSN.
- uint32_t exp_data_sn; // ExpDataSN or Reserved
- // This field indicates the number of Data-In (read) PDUs the target has
- // sent for the command.
- // This field MUST be 0 if the response code is not Command Completed at
- // Target or the target sent no Data-In PDUs for the command.
- uint32_t bidi_read_res_cnt; // Bidirectional Read Residual Count or Reserved
- // The Bidirectional Read Residual Count field MUST be valid in the case
- // where either the u bit or the o bit is set. If neither bit is set,
- // the Bidirectional Read Residual Count field is reserved. Targets may
- // set the Bidirectional Read Residual Count, and initiators may use it
- // when the response code is Command Completed at Target. If the o bit
- // is set, the Bidirectional Read Residual Count indicates the number of
- // bytes that were not transferred to the initiator because the
- // initiator's Bidirectional Read Expected Data Transfer Length was not
- // sufficient. If the u bit is set, the Bidirectional Read Residual
- // Count indicates the number of bytes that were not transferred to the
- // initiator out of the number of bytes expected to be transferred.
- uint32_t res_cnt; // Residual Count or Reserved
- // The Residual Count field MUST be valid in the case where either the U
- // bit or the O bit is set. If neither bit is set, the Residual Count
- // field MUST be ignored on reception and SHOULD be set to 0 when
- // sending. Targets may set the residual count, and initiators may use
- // it when the response code is Command Completed at Target (even if the
- // status returned is not GOOD). If the O bit is set, the Residual
- // Count indicates the number of bytes that were not transferred because
- // the initiator's Expected Data Transfer Length was not sufficient. If
- // the U bit is set, the Residual Count indicates the number of bytes
- // that were not transferred out of the number of bytes expected to be
- // transferred.
- struct iscsi_header_digest hdr_digest; // Optional header digest
- struct iscsi_ds_cmd_data ds_cmd_data; // Optional data segment, command data
- struct iscsi_data_digest data_digest; // Optional data digest
+ /// Always 0x21 according to specification.
+ uint8_t opcode;
+
+ /// Flags.
+ int8_t flags;
+
+ /// This field contains the iSCSI service response.
+ uint8_t response;
+
+ /// The Status field is used to report the SCSI status of the command (as specified in SAM2) and is only valid if the response code is Command Completed at Target.
+ uint8_t status;
+
+ /// Total AHS length.
+ uint8_t total_ahs_len;
+
+ /// Data segment length.
+ uint8_t ds_len[3];
+
+ /// Reserved for future usage. Always MUST be 0.
+ uint64_t reserved;
+
+ /// Initiator Task Tag (ITT).
+ uint32_t init_task_tag;
+
+ /**
+ * @brief Copy of the last accepted SNACK tag.
+ *
+ * This field contains a copy of the SNACK Tag of the last SNACK Tag
+ * accepted by the target on the same connection and for the command for
+ * which the response is issued. Otherwise, it is reserved and should
+ * be set to 0.
+ * After issuing a R-Data SNACK, the initiator must discard any SCSI
+ * status unless contained in a SCSI Response PDU carrying the same
+ * SNACK Tag as the last issued R-Data SNACK for the SCSI command on the
+ * current connection.
+ */
+ uint32_t snack_tag;
+
+ /**
+ * @brief StatSN - Status Sequence Number.
+ *
+ * The StatSN is a sequence number that the target iSCSI layer generates
+ * per connection and that in turn enables the initiator to acknowledge
+ * status reception. The StatSN is incremented by 1 for every
+ * response/status sent on a connection, except for responses sent as a
+ * result of a retry or SNACK. In the case of responses sent due to a
+ * retransmission request, the StatSN MUST be the same as the first time
+ * the PDU was sent, unless the connection has since been restarted.
+ */
+ uint32_t stat_sn;
+
+ /**
+ * @brief ExpCmdSN - Next Expected CmdSN from This Initiator.
+ *
+ * The ExpCmdSN is a sequence number that the target iSCSI returns to
+ * the initiator to acknowledge command reception. It is used to update
+ * a local variable with the same name. An ExpCmdSN equal to
+ * MaxCmdSN + 1 indicates that the target cannot accept new commands.
+ */
+ uint32_t exp_cmd_sn;
+
+ /**
+ * @brief MaxCmdSN - Maximum CmdSN from This Initiator.
+ *
+ * The MaxCmdSN is a sequence number that the target iSCSI returns to
+ * the initiator to indicate the maximum CmdSN the initiator can send.
+ * It is used to update a local variable with the same name. If the
+ * MaxCmdSN is equal to ExpCmdSN - 1, this indicates to the initiator
+ * that the target cannot receive any additional commands. When the
+ * MaxCmdSN changes at the target while the target has no pending PDUs
+ * to convey this information to the initiator, it MUST generate a
+ * NOP-In to carry the new MaxCmdSN.
+ */
+ uint32_t max_cmd_sn;
+
+ /**
+ * @brief ExpDataSN or Reserved.
+ *
+ * This field indicates the number of Data-In (read) PDUs the target has
+ * sent for the command.
+ * This field MUST be 0 if the response code is not Command Completed at
+ * Target or the target sent no Data-In PDUs for the command.
+ */
+ uint32_t exp_data_sn;
+
+ /**
+ * @brief Bidirectional Read Residual Count or Reserved.
+ *
+ * The Bidirectional Read Residual Count field MUST be valid in the case
+ * where either the u bit or the o bit is set. If neither bit is set,
+ * the Bidirectional Read Residual Count field is reserved. Targets may
+ * set the Bidirectional Read Residual Count, and initiators may use it
+ * when the response code is Command Completed at Target. If the o bit
+ * is set, the Bidirectional Read Residual Count indicates the number of
+ * bytes that were not transferred to the initiator because the
+ * initiator's Bidirectional Read Expected Data Transfer Length was not
+ * sufficient. If the u bit is set, the Bidirectional Read Residual
+ * Count indicates the number of bytes that were not transferred to the
+ * initiator out of the number of bytes expected to be transferred.
+ */
+ uint32_t bidi_read_res_cnt;
+
+ /**
+ * @brief Residual Count or Reserved.
+ *
+ * The Residual Count field MUST be valid in the case where either the U
+ * bit or the O bit is set. If neither bit is set, the Residual Count
+ * field MUST be ignored on reception and SHOULD be set to 0 when
+ * sending. Targets may set the residual count, and initiators may use
+ * it when the response code is Command Completed at Target (even if the
+ * status returned is not GOOD). If the O bit is set, the Residual
+ * Count indicates the number of bytes that were not transferred because
+ * the initiator's Expected Data Transfer Length was not sufficient. If
+ * the U bit is set, the Residual Count indicates the number of bytes
+ * that were not transferred out of the number of bytes expected to be
+ * transferred.
+ */
+ uint32_t res_cnt;
+
+ /// Optional header digest.
+ iscsi_header_digest hdr_digest;
+
+ /// Optional data segment, command data.
+ iscsi_ds_cmd_data ds_cmd_data;
+
+ /// Optional data digest.
+ iscsi_data_digest data_digest;
} iscsi_scsi_response_packet;
-#define ISCSI_TASK_MGMT_FUNC_REQ_FUNC_ABORT_TASK 0x01 // ABORT TASK - aborts the task identified by the Referenced Task Tag field
-#define ISCSI_TASK_MGMT_FUNC_REQ_FUNC_ABORT_TASK_SET 0x02 // ABORT TASK SET - aborts all tasks issued via this session on the LU
-#define ISCSI_TASK_MGMT_FUNC_REQ_FUNC_CLEAR_ACA 0x03 // CLEAR ACA - clears the Auto Contingent Allegiance condition
-#define ISCSI_TASK_MGMT_FUNC_REQ_FUNC_CLEAR_TASK_SET 0x04 // CLEAR TASK SET - aborts all tasks in the appropriate task set
- // as defined by the TST field in the Control mode page
- // (see SPC3)
-#define ISCSI_TASK_MGMT_FUNC_REQ_FUNC_LOGICAL_UNIT_RESET 0x05 // LOGICAL UNIT RESET
-#define ISCSI_TASK_MGMT_FUNC_REQ_FUNC_TARGET_WARM_RESET 0x06 // TARGET WARM RESET
-#define ISCSI_TASK_MGMT_FUNC_REQ_FUNC_TARGET_COLD_RESET 0x07 // TARGET COLD RESET
-#define ISCSI_TASK_MGMT_FUNC_REQ_FUNC_TASK_REASSIGN 0x08 // TASK REASSIGN - reassigns connection allegiance for the task
- // identified by the Initiator Task Tag field to this connection,
- // thus resuming the iSCSI exchanges for the task
+
+/// Task management request function: ABORT TASK: aborts the task identified by the Referenced Task Tag field.
+#define ISCSI_TASK_MGMT_FUNC_REQ_FUNC_ABORT_TASK 0x01
+
+/// Task management request function: ABORT TASK SET: aborts all tasks issued via this session on the LU.
+#define ISCSI_TASK_MGMT_FUNC_REQ_FUNC_ABORT_TASK_SET 0x02
+
+/// Task management request function: CLEAR ACA - clears the Auto Contingent Allegiance condition.
+#define ISCSI_TASK_MGMT_FUNC_REQ_FUNC_CLEAR_ACA 0x03
+
+/// Task management request function: CLEAR TASK SET - aborts all tasks in the appropriate task set as defined by the TST field in the Control mode page (see SPC3).
+#define ISCSI_TASK_MGMT_FUNC_REQ_FUNC_CLEAR_TASK_SET 0x04
+
+/// Task management request function: LOGICAL UNIT RESET.
+#define ISCSI_TASK_MGMT_FUNC_REQ_FUNC_LOGICAL_UNIT_RESET 0x05
+
+/// Task management request function: TARGET WARM RESET.
+#define ISCSI_TASK_MGMT_FUNC_REQ_FUNC_TARGET_WARM_RESET 0x06
+
+/// Task management request function: TARGET COLD RESET.
+#define ISCSI_TASK_MGMT_FUNC_REQ_FUNC_TARGET_COLD_RESET 0x07
+
+/// Task management request function: TASK REASSIGN - reassigns connection allegiance for the task identified by the Initiator Task Tag field to this connection, thus resuming the iSCSI exchanges for the task.
+#define ISCSI_TASK_MGMT_FUNC_REQ_FUNC_TASK_REASSIGN 0x08
typedef struct __attribute__((packed)) iscsi_task_mgmt_func_req_packet {
- uint8_t opcode; // Always 0x02 according to specification (see above)
- int8_t func; // Function.
- // The task management functions provide an initiator with a way to
- // explicitly control the execution of one or more tasks (SCSI and iSCSI
- // tasks). The task management function codes are listed below. For a
- // more detailed description of SCSI task management, see SAM2.
- uint16_t reserved; // Reserved for future usage
- uint8_t total_ahs_len; // TotalAHSLength (MUST be 0 for this PDU)
- uint8_t ds_len[3]; // DataSegmentLength (MUST be 0 for this PDU)
- uint64_t lun; // Logical Unit Number (LUN) or Reserved
- // This field is required for functions that address a specific LU
- // (ABORT TASK, CLEAR TASK SET, ABORT TASK SET, CLEAR ACA, LOGICAL UNIT
- // RESET) and is reserved in all others
- uint32_t init_task_tag; // Initiator task tag
- // This is the Initiator Task Tag of the task to be aborted for the
- // ABORT TASK function or reassigned for the TASK REASSIGN function.
- // For all the other functions, this field MUST be set to the reserved
- // value 0xFFFFFFFF
- uint32_t ref_task_tag; // Referenced task tag or 0xFFFFFFFF
- uint32_t cmd_sn; // CmdSN
- uint32_t exp_stat_sn; // ExpStatSN
- uint32_t ref_cmd_sn; // RefCmdSN or Reserved
- // If an ABORT TASK is issued for a task created by an immediate
- // command, then the RefCmdSN MUST be that of the task management
- // request itself (i.e., the CmdSN and RefCmdSN are equal).
- // For an ABORT TASK of a task created by a non-immediate command, the
- // RefCmdSN MUST be set to the CmdSN of the task identified by the
- // Referenced Task Tag field. Targets must use this field when the task
- // identified by the Referenced Task Tag field is not with the target.
- // Otherwise, this field is reserved
- uint32_t exp_data_sn; // ExpDataSN or Reserved
- // For recovery purposes, the iSCSI target and initiator maintain a data
- // acknowledgment reference number - the first input DataSN number
- // unacknowledged by the initiator. When issuing a new command, this
- // number is set to 0. If the function is TASK REASSIGN, which
- // establishes a new connection allegiance for a previously issued read
- // or bidirectional command, the ExpDataSN will contain an updated data
- // acknowledgment reference number or the value 0; the latter indicates
- // that the data acknowledgment reference number is unchanged. The
- // initiator MUST discard any data PDUs from the previous execution that
- // it did not acknowledge, and the target MUST transmit all Data-In PDUs
- // (if any) starting with the data acknowledgment reference number. The
- // number of retransmitted PDUs may or may not be the same as the
- // original transmission, depending on if there was a change in
- // MaxRecvDataSegmentLength in the reassignment. The target MAY also
- // send no more Data-In PDUs if all data has been acknowledged.
- // The value of ExpDataSN MUST be 0 or higher than the DataSN of the
- // last acknowledged Data-In PDU, but not larger than DataSN + 1 of the
- // last Data-IN PDU sent by the target. Any other value MUST be ignored
- // by the target.
- // For other functions, this field is reserved
- uint64_t reserved2; // Reserved for future usage
- struct iscsi_header_digest hdr_digest; // Optional header digest
+ /// Always 2 according to iSCSI specification.
+ uint8_t opcode;
+
+ /**
+ * @brief Function.
+ *
+ * The task management functions provide an initiator with a way to
+ * explicitly control the execution of one or more tasks (SCSI and iSCSI
+ * tasks). The task management function codes are listed below. For a
+ * more detailed description of SCSI task management, see SAM2.
+ */
+ int8_t func;
+
+ /// Reserved fot future usage, always MUST be 0.
+ uint16_t reserved;
+
+ /// TotalAHSLength (MUST be 0 for this PDU).
+ uint8_t total_ahs_len;
+
+ /// DataSegmentLength (MUST be 0 for this PDU).
+ uint8_t ds_len[3];
+
+ /**
+ * @brief Logical Unit Number (LUN) or Reserved.
+ *
+ * This field is required for functions that address a specific LU
+ * (ABORT TASK, CLEAR TASK SET, ABORT TASK SET, CLEAR ACA, LOGICAL UNIT
+ * RESET) and is reserved in all others
+ */
+ uint64_t lun;
+
+ /**
+ * @brief Initiator Task Tag (ITT).
+ *
+ * This is the Initiator Task Tag of the task to be aborted for the
+ * ABORT TASK function or reassigned for the TASK REASSIGN function.
+ * For all the other functions, this field MUST be set to the reserved
+ * value 0xFFFFFFFF.
+ */
+ uint32_t init_task_tag;
+
+ /// Referenced task tag or 0xFFFFFFFF.
+ uint32_t ref_task_tag;
+
+ /// CmdSN.
+ uint32_t cmd_sn;
+
+ /// ExpStatSN
+ uint32_t exp_stat_sn;
+
+ /**
+ * @brief RefCmdSN or Reserved.
+ *
+ * If an ABORT TASK is issued for a task created by an immediate
+ * command, then the RefCmdSN MUST be that of the task management
+ * request itself (i.e., the CmdSN and RefCmdSN are equal).
+ * For an ABORT TASK of a task created by a non-immediate command, the
+ * RefCmdSN MUST be set to the CmdSN of the task identified by the
+ * Referenced Task Tag field. Targets must use this field when the task
+ * identified by the Referenced Task Tag field is not with the target.
+ * Otherwise, this field is reserved.
+ */
+ uint32_t ref_cmd_sn;
+
+ /**
+ * @brief ExpDataSN or Reserved.
+ *
+ * For recovery purposes, the iSCSI target and initiator maintain a data
+ * acknowledgment reference number - the first input DataSN number
+ * unacknowledged by the initiator. When issuing a new command, this
+ * number is set to 0. If the function is TASK REASSIGN, which
+ * establishes a new connection allegiance for a previously issued read
+ * or bidirectional command, the ExpDataSN will contain an updated data
+ * acknowledgment reference number or the value 0; the latter indicates
+ * that the data acknowledgment reference number is unchanged. The
+ * initiator MUST discard any data PDUs from the previous execution that
+ * it did not acknowledge, and the target MUST transmit all Data-In PDUs
+ * (if any) starting with the data acknowledgment reference number. The
+ * number of retransmitted PDUs may or may not be the same as the
+ * original transmission, depending on if there was a change in
+ * MaxRecvDataSegmentLength in the reassignment. The target MAY also
+ * send no more Data-In PDUs if all data has been acknowledged.
+ * The value of ExpDataSN MUST be 0 or higher than the DataSN of the
+ * last acknowledged Data-In PDU, but not larger than DataSN + 1 of the
+ * last Data-IN PDU sent by the target. Any other value MUST be ignored
+ * by the target.
+ * For other functions, this field is reserved
+ */
+ uint32_t exp_data_sn;
+
+ /// Reserved for future usage, always MUST be 0.
+ uint64_t reserved2;
+
+ /// Optional header digest.
+ iscsi_header_digest hdr_digest;
} iscsi_task_mgmt_func_req_packet;
#define ISCSI_TASK_MGMT_FUNC_RESPONSE_FUNC_COMPLETE 0x00 // Function complete
@@ -676,14 +1295,17 @@ typedef struct __attribute__((packed)) iscsi_task_mgmt_func_req_packet {
#define ISCSI_TASK_MGMT_FUNC_RESPONSE_FUNC_AUTH_FAILED 0x06 // Function authorization failed
#define ISCSI_TASK_MGMT_FUNC_RESPONSE_FUNC_REJECTED 0xFF // Function rejected
-/* For the functions ABORT TASK, ABORT TASK SET, CLEAR ACA, CLEAR TASK
- SET, LOGICAL UNIT RESET, TARGET COLD RESET, TARGET WARM RESET, and
- TASK REASSIGN, the target performs the requested task management
- function and sends a task management response back to the initiator.
- For TASK REASSIGN, the new connection allegiance MUST ONLY become
- effective at the target after the target issues the task management
- response.
-*/
+/**
+ * @brief iSCSI Task Management Function response packet data.
+ *
+ * For the functions ABORT TASK, ABORT TASK SET, CLEAR ACA, CLEAR TASK
+ * SET, LOGICAL UNIT RESET, TARGET COLD RESET, TARGET WARM RESET, and
+ * TASK REASSIGN, the target performs the requested task management
+ * function and sends a task management response back to the initiator.
+ * For TASK REASSIGN, the new connection allegiance MUST ONLY become
+ * effective at the target after the target issues the task management
+ * response.
+ */
typedef struct __attribute__((packed)) iscsi_task_mgmt_func_response_packet {
uint8_t opcode; // Always 0x22 according to specification (see above)
int8_t flags; // Reserved for future usage (must be always 0x80 for now)
@@ -895,58 +1517,61 @@ typedef struct __attribute__((packed)) iscsi_scsi_data_in_response_packet {
struct iscsi_data_digest data_digest; // Optional data digest
} iscsi_scsi_data_in_response_packet;
-/* When an initiator has submitted a SCSI command with data that passes
- from the initiator to the target (write), the target may specify
- which blocks of data it is ready to receive. The target may request
- that the data blocks be delivered in whichever order is convenient
- for the target at that particular instant. This information is
- passed from the target to the initiator in the Ready To Transfer
- (R2T) PDU.
-
- In order to allow write operations without an explicit initial R2T,
- the initiator and target MUST have negotiated the key InitialR2T to
- No during login.
-
- An R2T MAY be answered with one or more SCSI Data-Out PDUs with a
- matching Target Transfer Tag. If an R2T is answered with a single
- Data-Out PDU, the buffer offset in the data PDU MUST be the same as
- the one specified by the R2T, and the data length of the data PDU
- MUST be the same as the Desired Data Transfer Length specified in the
- R2T. If the R2T is answered with a sequence of data PDUs, the buffer
- offset and length MUST be within the range of those specified by the
- R2T, and the last PDU MUST have the F bit set to 1. If the last PDU
- (marked with the F bit) is received before the Desired Data Transfer
- Length is transferred, a target MAY choose to reject that PDU with
- the "Protocol Error" reason code. DataPDUInOrder governs the
- Data-Out PDU ordering. If DataPDUInOrder is set to Yes, the buffer
- offsets and lengths for consecutive PDUs MUST form a continuous
- non-overlapping range, and the PDUs MUST be sent in increasing offset
- order.
-
- The target may send several R2T PDUs. It therefore can have a number
- of pending data transfers. The number of outstanding R2T PDUs is
- limited by the value of the negotiated key MaxOutstandingR2T. Within
- a task, outstanding R2Ts MUST be fulfilled by the initiator in the
- order in which they were received.
-
- R2T PDUs MAY also be used to recover Data-Out PDUs. Such an R2T
- (Recovery-R2T) is generated by a target upon detecting the loss of
- one or more Data-Out PDUs due to:
-
- - Digest error
-
- - Sequence error
-
- - Sequence reception timeout
-
- A Recovery-R2T carries the next unused R2TSN but requests part of or
- the entire data burst that an earlier R2T (with a lower R2TSN) had
- already requested.
-
- DataSequenceInOrder governs the buffer offset ordering in consecutive
- R2Ts. If DataSequenceInOrder is Yes, then consecutive R2Ts MUST
- refer to continuous non-overlapping ranges, except for Recovery-R2Ts.
-*/
+/**
+ * @brief iSCSI Ready To Transfer packet data.
+ *
+ * When an initiator has submitted a SCSI command with data that passes
+ * from the initiator to the target (write), the target may specify
+ * which blocks of data it is ready to receive. The target may request
+ * that the data blocks be delivered in whichever order is convenient
+ * for the target at that particular instant. This information is
+ * passed from the target to the initiator in the Ready To Transfer
+ * (R2T) PDU.
+ *
+ * In order to allow write operations without an explicit initial R2T,
+ * the initiator and target MUST have negotiated the key InitialR2T to
+ * No during login.
+ *
+ * An R2T MAY be answered with one or more SCSI Data-Out PDUs with a
+ * matching Target Transfer Tag. If an R2T is answered with a single
+ * Data-Out PDU, the buffer offset in the data PDU MUST be the same as
+ * the one specified by the R2T, and the data length of the data PDU
+ * MUST be the same as the Desired Data Transfer Length specified in the
+ * R2T. If the R2T is answered with a sequence of data PDUs, the buffer
+ * offset and length MUST be within the range of those specified by the
+ * R2T, and the last PDU MUST have the F bit set to 1. If the last PDU
+ * (marked with the F bit) is received before the Desired Data Transfer
+ * Length is transferred, a target MAY choose to reject that PDU with
+ * the "Protocol Error" reason code. DataPDUInOrder governs the
+ * Data-Out PDU ordering. If DataPDUInOrder is set to Yes, the buffer
+ * offsets and lengths for consecutive PDUs MUST form a continuous
+ * non-overlapping range, and the PDUs MUST be sent in increasing offset
+ * order.
+ *
+ * The target may send several R2T PDUs. It therefore can have a number
+ * of pending data transfers. The number of outstanding R2T PDUs is
+ * limited by the value of the negotiated key MaxOutstandingR2T. Within
+ * a task, outstanding R2Ts MUST be fulfilled by the initiator in the
+ * order in which they were received.
+ *
+ * R2T PDUs MAY also be used to recover Data-Out PDUs. Such an R2T
+ * (Recovery-R2T) is generated by a target upon detecting the loss of
+ * one or more Data-Out PDUs due to:
+ *
+ * - Digest error
+ *
+ * - Sequence error
+ *
+ * - Sequence reception timeout
+ *
+ * A Recovery-R2T carries the next unused R2TSN but requests part of or
+ * the entire data burst that an earlier R2T (with a lower R2TSN) had
+ * already requested.
+ *
+ * DataSequenceInOrder governs the buffer offset ordering in consecutive
+ * R2Ts. If DataSequenceInOrder is Yes, then consecutive R2Ts MUST
+ * refer to continuous non-overlapping ranges, except for Recovery-R2Ts.
+ */
typedef struct __attribute__((packed)) iscsi_r2t_packet {
uint8_t opcode; // Always 0x31 according to specification (see above)
int8_t flags; // Reserved for future usage (must be always 0x80 for now)
@@ -1062,12 +1687,15 @@ typedef struct __attribute__((packed)) iscsi_r2t_packet {
#define ISCSI_ASYNC_MSG_EVENT_VENDOR_LAST 0xFF // Last vendor-specific iSCSI event. The AsyncVCode details the
// vendor code, and data MAY accompany the report
-/* An Asynchronous Message may be sent from the target to the initiator
- without corresponding to a particular command. The target specifies
- the reason for the event and sense data.
- Some Asynchronous Messages are strictly related to iSCSI, while
- others are related to SCSI
-*/
+/**
+ * @brief iSCSI Asynchronous Message packet data.
+ *
+ * An Asynchronous Message may be sent from the target to the initiator
+ * without corresponding to a particular command. The target specifies
+ * the reason for the event and sense data.
+ * Some Asynchronous Messages are strictly related to iSCSI, while
+ * others are related to SCSI
+ */
typedef struct __attribute__((packed)) iscsi_async_msg_packet {
uint8_t opcode; // Always 0x32 according to specification (see above
int8_t flags; // Reserved for future usage (must be always 0x80 for now)
@@ -1096,16 +1724,19 @@ typedef struct __attribute__((packed)) iscsi_async_msg_packet {
struct iscsi_data_digest data_digest; // Optional data digest
} iscsi_async_msg_packet;
-/* For a SCSI event, this data accompanies the report in the data
- segment and identifies the condition.
-
- For an iSCSI event, additional vendor-unique data MAY accompany the
- Async event. Initiators MAY ignore the data when not understood,
- while processing the rest of the PDU.
-
- If the DataSegmentLength is not 0, the format of the DataSegment is
- as follows:
-*/
+/**
+ * @brief iSCSI Sense Event data packet.
+ *
+ * For a SCSI event, this data accompanies the report in the data
+ * segment and identifies the condition.
+ *
+ * For an iSCSI event, additional vendor-unique data MAY accompany the
+ * Async event. Initiators MAY ignore the data when not understood,
+ * while processing the rest of the PDU.
+ *
+ * If the DataSegmentLength is not 0, the format of the DataSegment is
+ * as follows:
+ */
typedef struct __attribute__((packed)) iscsi_sense_event_data_packet {
uint16_t sense_len; // SenseLength
// This is the length of Sense Data. When the Sense Data field is empty
@@ -1123,17 +1754,20 @@ typedef struct __attribute__((packed)) iscsi_sense_event_data_packet {
// Request in a sequence of Text Requests; otherwise, it indicates that
// more Text Requests will follow.
-/* The Text Request is provided to allow for the exchange of information
- and for future extensions. It permits the initiator to inform a
- target of its capabilities or request some special operations.
-
- An initiator MUST NOT have more than one outstanding Text Request on
- a connection at any given time.
-
- On a connection failure, an initiator must either explicitly abort
- any active allegiant text negotiation task or cause such a task to be
- implicitly terminated by the target.
-*/
+/**
+ * @brief iSCSI Text Request packet data.
+ *
+ * The Text Request is provided to allow for the exchange of information
+ * and for future extensions. It permits the initiator to inform a
+ * target of its capabilities or request some special operations.
+ *
+ * An initiator MUST NOT have more than one outstanding Text Request on
+ * a connection at any given time.
+ *
+ * On a connection failure, an initiator must either explicitly abort
+ * any active allegiant text negotiation task or cause such a task to be
+ * implicitly terminated by the target.
+ */
typedef struct __attribute__((packed)) iscsi_text_req_packet {
uint8_t opcode; // Always 0x04 according to specification (see above)
int8_t flags; // Text request flags (see above)
@@ -1216,10 +1850,13 @@ typedef struct __attribute__((packed)) iscsi_text_req_packet {
// A Text Response with the F bit set to 0 MUST have a Target Transfer
// Tag field set to a value other than the reserved value 0xFFFFFFFF
-/* The Text Response PDU contains the target's responses to the
- initiator's Text Request. The format of the Text field matches that
- of the Text Request.
-*/
+/**
+ * @brief iSCSI Text Response packet data.
+ *
+ * The Text Response PDU contains the target's responses to the
+ * initiator's Text Request. The format of the Text field matches that
+ * of the Text Request.
+ */
typedef struct __attribute__((packed)) iscsi_text_response_packet {
uint8_t opcode; // Always 0x24 according to specification (see above)
int8_t flags; // Text response flags (see above)
@@ -2102,32 +2739,35 @@ typedef struct __attribute__((packed)) iscsi_text_response_packet {
// implementation MUST NOT respond with a "NotUnderstood" value for
// either of these keys
-/* This is an initiator-defined component of the session identifier and
- is structured as follows:
-
- For the T field values 00b and 01b, a combination of A and B (for
- 00b) or B and C (for 01b) identifies the vendor or organization whose
- component (software or hardware) generates this ISID. A vendor or
- organization with one or more OUIs, or one or more Enterprise
- Numbers, MUST use at least one of these numbers and select the
- appropriate value for the T field when its components generate ISIDs.
- An OUI or EN MUST be set in the corresponding fields in network byte
- order (byte big-endian).
-
- If the T field is 10b, B and C are set to a random 24-bit unsigned
- integer value in network byte order (byte big-endian).
-
- The Qualifier field is a 16-bit or 24-bit unsigned integer value that
- provides a range of possible values for the ISID within the selected
- namespace. It may be set to any value within the constraints
- specified in the iSCSI protocol.
-
- If the ISID is derived from something assigned to a hardware adapter
- or interface by a vendor as a preset default value, it MUST be
- configurable to a value assigned according to the SCSI port behavior
- desired by the system in which it is installed. The resultant ISID
- MUST also be persistent over power cycles, reboot, card swap, etc.
-*/
+/**
+ * @brief iSCSI ISID packet data.
+ *
+ * This is an initiator-defined component of the session identifier and
+ * is structured as follows:
+ *
+ * For the T field values 00b and 01b, a combination of A and B (for
+ * 00b) or B and C (for 01b) identifies the vendor or organization whose
+ * component (software or hardware) generates this ISID. A vendor or
+ * organization with one or more OUIs, or one or more Enterprise
+ * Numbers, MUST use at least one of these numbers and select the
+ * appropriate value for the T field when its components generate ISIDs.
+ * An OUI or EN MUST be set in the corresponding fields in network byte
+ * order (byte big-endian).
+ *
+ * If the T field is 10b, B and C are set to a random 24-bit unsigned
+ * integer value in network byte order (byte big-endian).
+ *
+ * The Qualifier field is a 16-bit or 24-bit unsigned integer value that
+ * provides a range of possible values for the ISID within the selected
+ * namespace. It may be set to any value within the constraints
+ * specified in the iSCSI protocol.
+ *
+ * If the ISID is derived from something assigned to a hardware adapter
+ * or interface by a vendor as a preset default value, it MUST be
+ * configurable to a value assigned according to the SCSI port behavior
+ * desired by the system in which it is installed. The resultant ISID
+ * MUST also be persistent over power cycles, reboot, card swap, etc.
+ */
typedef struct __attribute__((packed)) iscsi_isid {
uint8_t a; // Meaning depends on T bit (see above)
uint16_t b; // Meaning depends on T bit (see above)
@@ -2165,15 +2805,18 @@ typedef struct __attribute__((packed)) iscsi_isid {
// this also indicates that the initiator is ready for the Login
// Final-Response.
-/* After establishing a TCP connection between an initiator and a
- target, the initiator MUST start a Login Phase to gain further access
- to the target's resources.
-
- The Login Phase consists of a sequence of Login Requests and Login
- Responses that carry the same Initiator Task Tag.
-
- Login Requests are always considered as immediate.
-*/
+/**
+ * @brief iSCSI Login Request packet data.
+ *
+ * After establishing a TCP connection between an initiator and a
+ * target, the initiator MUST start a Login Phase to gain further access
+ * to the target's resources.
+ *
+ * The Login Phase consists of a sequence of Login Requests and Login
+ * Responses that carry the same Initiator Task Tag.
+ *
+ * Login Requests are always considered as immediate.
+ */
typedef struct __attribute__((packed)) iscsi_login_req_packet {
uint8_t opcode; // Always 0x03 according to specification (see above)
int8_t flags; // Login request flags (see above)
@@ -2332,9 +2975,12 @@ typedef struct __attribute__((packed)) iscsi_login_req_packet {
#define ISCSI_LOGIN_RESPONSE_STATUS_DETAILS_SERVER_ERR_OUT_OF_RESOURCES 0x02 // The target has insufficient session,
// connection, or other resources
-/* The Login Response indicates the progress and/or end of the Login
- Phase.
-*/
+/**
+ * @brief iSCSI Login Response packet data.
+ *
+ * The Login Response indicates the progress and/or end of the Login
+ * Phase.
+ */
typedef struct __attribute__((packed)) iscsi_login_response_packet {
uint8_t opcode; // Always 0x23 according to specification (see above)
int8_t flags; // Login response flags (see above)
@@ -2403,62 +3049,65 @@ typedef struct __attribute__((packed)) iscsi_login_response_packet {
#define ISCSI_LOGOUT_REQ_REASON_CODE_IMPLICIT_CONNECTION_REINSTATEMENT_2 0x02 // connection reinstatement when the operational
// ErrorRecoveryLevel = 2
-/* The Logout Request is used to perform a controlled closing of a
- connection.
-
- An initiator MAY use a Logout Request to remove a connection from a
- session or to close an entire session.
-
- After sending the Logout Request PDU, an initiator MUST NOT send any
- new iSCSI requests on the closing connection. If the Logout Request
- is intended to close the session, new iSCSI requests MUST NOT be sent
- on any of the connections participating in the session.
-
- When receiving a Logout Request with the reason code "close the
- connection" or "close the session", the target MUST terminate all
- pending commands, whether acknowledged via the ExpCmdSN or not, on
- that connection or session, respectively.
-
- When receiving a Logout Request with the reason code "remove the
- connection for recovery", the target MUST discard all requests not
- yet acknowledged via the ExpCmdSN that were issued on the specified
- connection and suspend all data/status/R2T transfers on behalf of
- pending commands on the specified connection.
-
- The target then issues the Logout Response and half-closes the TCP
- connection (sends FIN). After receiving the Logout Response and
- attempting to receive the FIN (if still possible), the initiator MUST
- completely close the logging-out connection. For the terminated
- commands, no additional responses should be expected.
-
- A Logout for a CID may be performed on a different transport
- connection when the TCP connection for the CID has already been
- terminated. In such a case, only a logical "closing" of the iSCSI
- connection for the CID is implied with a Logout.
-
- All commands that were not terminated or not completed (with status)
- and acknowledged when the connection is closed completely can be
- reassigned to a new connection if the target supports connection
- recovery.
-
- If an initiator intends to start recovery for a failing connection,
- it MUST use the Logout Request to "clean up" the target end of a
- failing connection and enable recovery to start, or use the Login
- Request with a non-zero TSIH and the same CID on a new connection for
- the same effect. In sessions with a single connection, the
- connection can be closed and then a new connection reopened. A
- connection reinstatement login can be used for recovery.
-
- A successful completion of a Logout Request with the reason code
- "close the connection" or "remove the connection for recovery"
- results at the target in the discarding of unacknowledged commands
- received on the connection being logged out. These are commands that
- have arrived on the connection being logged out but that have not
- been delivered to SCSI because one or more commands with a smaller
- CmdSN have not been received by iSCSI. The resulting holes in the
- command sequence numbers will have to be handled by appropriate
- recovery, unless the session is also closed.
-*/
+/**
+ * @brief iSCSI Logout Request packet data.
+ *
+ * The Logout Request is used to perform a controlled closing of a
+ * connection.
+ *
+ * An initiator MAY use a Logout Request to remove a connection from a
+ * session or to close an entire session.
+ *
+ * After sending the Logout Request PDU, an initiator MUST NOT send any
+ * new iSCSI requests on the closing connection. If the Logout Request
+ * is intended to close the session, new iSCSI requests MUST NOT be sent
+ * on any of the connections participating in the session.
+ *
+ * When receiving a Logout Request with the reason code "close the
+ * connection" or "close the session", the target MUST terminate all
+ * pending commands, whether acknowledged via the ExpCmdSN or not, on
+ * that connection or session, respectively.
+ *
+ * When receiving a Logout Request with the reason code "remove the
+ * connection for recovery", the target MUST discard all requests not
+ * yet acknowledged via the ExpCmdSN that were issued on the specified
+ * connection and suspend all data/status/R2T transfers on behalf of
+ * pending commands on the specified connection.
+ *
+ * The target then issues the Logout Response and half-closes the TCP
+ * connection (sends FIN). After receiving the Logout Response and
+ * attempting to receive the FIN (if still possible), the initiator MUST
+ * completely close the logging-out connection. For the terminated
+ * commands, no additional responses should be expected.
+ *
+ * A Logout for a CID may be performed on a different transport
+ * connection when the TCP connection for the CID has already been
+ * terminated. In such a case, only a logical "closing" of the iSCSI
+ * connection for the CID is implied with a Logout.
+ *
+ * All commands that were not terminated or not completed (with status)
+ * and acknowledged when the connection is closed completely can be
+ * reassigned to a new connection if the target supports connection
+ * recovery.
+ *
+ * If an initiator intends to start recovery for a failing connection,
+ * it MUST use the Logout Request to "clean up" the target end of a
+ * failing connection and enable recovery to start, or use the Login
+ * Request with a non-zero TSIH and the same CID on a new connection for
+ * the same effect. In sessions with a single connection, the
+ * connection can be closed and then a new connection reopened. A
+ * connection reinstatement login can be used for recovery.
+ *
+ * A successful completion of a Logout Request with the reason code
+ * "close the connection" or "remove the connection for recovery"
+ * results at the target in the discarding of unacknowledged commands
+ * received on the connection being logged out. These are commands that
+ * have arrived on the connection being logged out but that have not
+ * been delivered to SCSI because one or more commands with a smaller
+ * CmdSN have not been received by iSCSI. The resulting holes in the
+ * command sequence numbers will have to be handled by appropriate
+ * recovery, unless the session is also closed.
+ */
typedef struct __attribute__((packed)) iscsi_logout_req_packet {
uint8_t opcode; // Always 0x06 according to specification (see above)
int8_t reason_code; // Reason Code
@@ -2513,13 +3162,16 @@ typedef struct __attribute__((packed)) iscsi_logout_req_packet {
// ErrorRecoveryLevel)
#define ISCSI_LOGOUT_RESPONSE_CLEANUP_FAILED 0x03 // Cleanup failed for various reasons
-/* The Logout Response is used by the target to indicate if the cleanup
- operation for the connection(s) has completed.
-
- After Logout, the TCP connection referred by the CID MUST be closed
- at both ends (or all connections must be closed if the logout reason
- was session close).
-*/
+/**
+ * @brief iSCSI Logout Response packet data.
+ *
+ * The Logout Response is used by the target to indicate if the cleanup
+ * operation for the connection(s) has completed.
+ *
+ * After Logout, the TCP connection referred by the CID MUST be closed
+ * at both ends (or all connections must be closed if the logout reason
+ * was session close).
+ */
typedef struct __attribute__((packed)) iscsi_logout_response_packet {
uint8_t opcode; // Always 0x26 according to specification (see above)
int8_t flags; // Reserved for future usage (must be always 0x80 for now)
@@ -2611,39 +3263,42 @@ typedef struct __attribute__((packed)) iscsi_logout_response_packet {
// For considerations in allegiance reassignment of a task to a
// connection with a different MaxRecvDataSegmentLength.
-/* If the implementation supports ErrorRecoveryLevel greater than zero,
- it MUST support all SNACK types.
-
- The SNACK is used by the initiator to request the retransmission of
- numbered responses, data, or R2T PDUs from the target. The SNACK
- Request indicates the numbered responses or data "runs" whose
- retransmission is requested, where the run starts with the first
- StatSN, DataSN, or R2TSN whose retransmission is requested and
- indicates the number of Status, Data, or R2T PDUs requested,
- including the first. 0 has special meaning when used as a starting
- number and length:
-
- - When used in RunLength, it means all PDUs starting with the
- initial.
-
- - When used in both BegRun and RunLength, it means all
- unacknowledged PDUs.
-
- The numbered response(s) or R2T(s) requested by a SNACK MUST be
- delivered as exact replicas of the ones that the target transmitted
- originally, except for the fields ExpCmdSN, MaxCmdSN, and ExpDataSN,
- which MUST carry the current values. R2T(s)requested by SNACK MUST
- also carry the current value of the StatSN.
-
- The numbered Data-In PDUs requested by a Data SNACK MUST be delivered
- as exact replicas of the ones that the target transmitted originally,
- except for the fields ExpCmdSN and MaxCmdSN, which MUST carry the
- current values; and except for resegmentation.
-
- Any SNACK that requests a numbered response, data, or R2T that was
- not sent by the target or was already acknowledged by the initiator
- MUST be rejected with a reason code of "Protocol Error".
-*/
+/**
+ * @brief iSCSI SNACK Request packet data.
+ *
+ * If the implementation supports ErrorRecoveryLevel greater than zero,
+ * it MUST support all SNACK types.
+ *
+ * The SNACK is used by the initiator to request the retransmission of
+ * numbered responses, data, or R2T PDUs from the target. The SNACK
+ * Request indicates the numbered responses or data "runs" whose
+ * retransmission is requested, where the run starts with the first
+ * StatSN, DataSN, or R2TSN whose retransmission is requested and
+ * indicates the number of Status, Data, or R2T PDUs requested,
+ * including the first. 0 has special meaning when used as a starting
+ * number and length:
+ *
+ * - When used in RunLength, it means all PDUs starting with the
+ * initial.
+ *
+ * - When used in both BegRun and RunLength, it means all
+ * unacknowledged PDUs.
+ *
+ * The numbered response(s) or R2T(s) requested by a SNACK MUST be
+ * delivered as exact replicas of the ones that the target transmitted
+ * originally, except for the fields ExpCmdSN, MaxCmdSN, and ExpDataSN,
+ * which MUST carry the current values. R2T(s)requested by SNACK MUST
+ * also carry the current value of the StatSN.
+ *
+ * The numbered Data-In PDUs requested by a Data SNACK MUST be delivered
+ * as exact replicas of the ones that the target transmitted originally,
+ * except for the fields ExpCmdSN and MaxCmdSN, which MUST carry the
+ * current values; and except for resegmentation.
+ *
+ * Any SNACK that requests a numbered response, data, or R2T that was
+ * not sent by the target or was already acknowledged by the initiator
+ * MUST be rejected with a reason code of "Protocol Error".
+ */
typedef struct __attribute__((packed)) iscsi_snack_req_packet {
uint8_t opcode; // Always 0x10 according to specification (see above)
int8_t type; // Type
@@ -2758,24 +3413,27 @@ typedef struct __attribute__((packed)) iscsi_reject_packet {
struct iscsi_data_digest data_digest; // Optional data digest
} iscsi_reject_packet;
-/* NOP-Out may be used by an initiator as a "ping request" to verify
- that a connection/session is still active and all its components are
- operational. The NOP-In response is the "ping echo".
-
- A NOP-Out is also sent by an initiator in response to a NOP-In.
-
- A NOP-Out may also be used to confirm a changed ExpStatSN if another
- PDU will not be available for a long time.
-
- Upon receipt of a NOP-In with the Target Transfer Tag set to a valid
- value (not the reserved value 0xffffffff), the initiator MUST respond
- with a NOP-Out. In this case, the NOP-Out Target Transfer Tag MUST
- contain a copy of the NOP-In Target Transfer Tag. The initiator
-
- SHOULD NOT send a NOP-Out in response to any other received NOP-In,
- in order to avoid lengthy sequences of NOP-In and NOP-Out PDUs sent
- in response to each other.
-*/
+/**
+ * @brief iSCSI NOP-Out packet data.
+ *
+ * NOP-Out may be used by an initiator as a "ping request" to verify
+ * that a connection/session is still active and all its components are
+ * operational. The NOP-In response is the "ping echo".
+ *
+ * A NOP-Out is also sent by an initiator in response to a NOP-In.
+ *
+ * A NOP-Out may also be used to confirm a changed ExpStatSN if another
+ * PDU will not be available for a long time.
+ *
+ * Upon receipt of a NOP-In with the Target Transfer Tag set to a valid
+ * value (not the reserved value 0xffffffff), the initiator MUST respond
+ * with a NOP-Out. In this case, the NOP-Out Target Transfer Tag MUST
+ * contain a copy of the NOP-In Target Transfer Tag. The initiator
+ *
+ * SHOULD NOT send a NOP-Out in response to any other received NOP-In,
+ * in order to avoid lengthy sequences of NOP-In and NOP-Out PDUs sent
+ * in response to each other.
+ */
typedef struct __attribute__((packed)) iscsi_nop_out_packet {
uint8_t opcode; // Always 0x00 according to specification (see above)
int8_t flags; // Reserved for future usage (must be always 0x80 for now)
@@ -2811,28 +3469,30 @@ typedef struct __attribute__((packed)) iscsi_nop_out_packet {
struct iscsi_data_digest data_digest; // Optional data digest
} iscsi_nop_out_packet;
-/* NOP-In is sent by a target as either a response to a NOP-Out, a
- "ping" to an initiator, or a means to carry a changed ExpCmdSN and/or
- MaxCmdSN if another PDU will not be available for a long time (as
- determined by the target).
-
- When a target receives the NOP-Out with a valid Initiator Task Tag
- (not the reserved value 0xFFFFFFFF), it MUST respond with a NOP-In
- with the same Initiator Task Tag that was provided in the NOP-Out
- request. It MUST also duplicate up to the first
- MaxRecvDataSegmentLength bytes of the initiator-provided Ping Data.
- For such a response, the Target Transfer Tag MUST be 0xFFFFFFFF. The
-
- target SHOULD NOT send a NOP-In in response to any other received
- NOP-Out in order to avoid lengthy sequences of NOP-In and NOP-Out
- PDUs sent in response to each other.
-
- Otherwise, when a target sends a NOP-In that is not a response to a
- NOP-Out received from the initiator, the Initiator Task Tag MUST be
- set to 0xFFFFFFFF, and the data segment MUST NOT contain any data
- (DataSegmentLength MUST be 0).
-*/
-
+/**
+ * @brief iSCSI NOP-In packet data.
+ *
+ * NOP-In is sent by a target as either a response to a NOP-Out, a
+ * "ping" to an initiator, or a means to carry a changed ExpCmdSN and/or
+ * MaxCmdSN if another PDU will not be available for a long time (as
+ * determined by the target).
+ *
+ * When a target receives the NOP-Out with a valid Initiator Task Tag
+ * (not the reserved value 0xFFFFFFFF), it MUST respond with a NOP-In
+ * with the same Initiator Task Tag that was provided in the NOP-Out
+ * request. It MUST also duplicate up to the first
+ * MaxRecvDataSegmentLength bytes of the initiator-provided Ping Data.
+ * For such a response, the Target Transfer Tag MUST be 0xFFFFFFFF. The
+ *
+ * target SHOULD NOT send a NOP-In in response to any other received
+ * NOP-Out in order to avoid lengthy sequences of NOP-In and NOP-Out
+ * PDUs sent in response to each other.
+ *
+ * Otherwise, when a target sends a NOP-In that is not a response to a
+ * NOP-Out received from the initiator, the Initiator Task Tag MUST be
+ * set to 0xFFFFFFFF, and the data segment MUST NOT contain any data
+ * (DataSegmentLength MUST be 0).
+ */
typedef struct __attribute__((packed)) iscsi_nop_in_packet {
uint8_t opcode; // Always 0x20 according to specification (see above)
int8_t flags; // Reserved for future usage (must be always 0x80 for now)
@@ -2900,15 +3560,36 @@ int iscsi_validate_packet(const struct iscsi_bhs_packet *packet_data, const uint
#define ISCSI_TEXT_KEY_VALUE_PAIR_TYPE_BOOL_OR 6L // Boolean OR
#define ISCSI_TEXT_KEY_VALUE_PAIR_TYPE_BOOL_AND 7L // Boolean AND
+/**
+ * @brief iSCSI Text / Login extracted key=value pair.
+ *
+ * This structure is used for accessing key and value
+ * pairs which have been extracted from either the
+ * Text or Login packet data.
+ */
typedef struct iscsi_key_value_pair {
- int type; // Type of pair (see above)
+ /// Type of key and value pair.
+ int type;
+
+ /// State index.
int state_index;
- uint8_t *value; // Value of key
+
+ /// Value of the key which is stored in the hash map.
+ uint8_t *value;
} iscsi_key_value_pair;
+/**
+ * @brief iSCSI Text / Login key=value packet data construction helper.
+ *
+ * This structure is used to store the key=value plus NUL terminator
+ * pairs for sending as DataSegment packet data to the client.
+ */
typedef struct iscsi_key_value_pair_packet {
- uint8_t *buf; // Current text buffer containing multiple zeroes
- uint len; // Current length of buffer including final zero terminator
+ /// Current text buffer containing multiple key=value + NUL terminator pairs.
+ uint8_t *buf;
+
+ /// Current length of buffer including final NUL terminator without iSCSI zero padding.
+ uint len;
} iscsi_key_value_pair_packet;
static int iscsi_parse_text_key_value_pair(iscsi_hashmap *pairs, const uint8_t *packet_data, const uint32_t len); // Extracts a single text key / value pairs out of an iSCSI packet into a hash map
@@ -2916,6 +3597,14 @@ int iscsi_parse_key_value_pairs(iscsi_hashmap *pairs, const uint8_t *packet_data
int iscsi_create_key_value_pair_packet_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data); // Creates a single partial iSCSI packet stream out of a single text key and value pair
iscsi_key_value_pair_packet *iscsi_create_key_value_pairs_packet(const iscsi_hashmap *pairs); // Creates a properly aligned iSCSI packet DataSegment out of a hash map containing text key and value pairs
+/**
+ * @brief iSCSI incoming connection.
+ *
+ * This structure is used for maintaining incoming iSCSI
+ * connections. Negiotiated text key=value pairs are
+ * stored here, status of the connection, session
+ * and iSCSI portals.
+ */
typedef struct iscsi_connection {
iscsi_hashmap *key_value_pairs; // Hash map containing text key / value pairs associated to this connection
int header_digest; // iSCSI connection contains a header digest (CRC32), must be 0 or 4 for now