freebsd-nq/sys/dev/iscsi/iscsi_proto.h
Alexander Motin 2124e3b07f Make sequence numbers checks more strict.
While we don't support MCS, hole in received sequence numbers may mean
only PDU loss.  While we don't support lost PDU recovery, terminate the
connection to avoid stuck commands.

While there, improve handling of sequence numbers wrap after 2^32 PDUs.

MFC after:	2 weeks
2014-12-17 15:13:21 +00:00

443 lines
13 KiB
C

/*-
* Copyright (c) 2012 The FreeBSD Foundation
* All rights reserved.
*
* This software was developed by Edward Tomasz Napierala under sponsorship
* from the FreeBSD Foundation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef ISCSI_PROTO_H
#define ISCSI_PROTO_H
#ifndef CTASSERT
#define CTASSERT(x) _CTASSERT(x, __LINE__)
#define _CTASSERT(x, y) __CTASSERT(x, y)
#define __CTASSERT(x, y) typedef char __assert_ ## y [(x) ? 1 : -1]
#endif
#define ISCSI_SNGT(x, y) ((int32_t)(x) - (int32_t)(y) > 0)
#define ISCSI_SNLT(x, y) ((int32_t)(x) - (int32_t)(y) < 0)
#define ISCSI_BHS_SIZE 48
#define ISCSI_HEADER_DIGEST_SIZE 4
#define ISCSI_DATA_DIGEST_SIZE 4
#define ISCSI_BHS_OPCODE_IMMEDIATE 0x40
#define ISCSI_BHS_OPCODE_NOP_OUT 0x00
#define ISCSI_BHS_OPCODE_SCSI_COMMAND 0x01
#define ISCSI_BHS_OPCODE_TASK_REQUEST 0x02
#define ISCSI_BHS_OPCODE_LOGIN_REQUEST 0x03
#define ISCSI_BHS_OPCODE_TEXT_REQUEST 0x04
#define ISCSI_BHS_OPCODE_SCSI_DATA_OUT 0x05
#define ISCSI_BHS_OPCODE_LOGOUT_REQUEST 0x06
#define ISCSI_BHS_OPCODE_NOP_IN 0x20
#define ISCSI_BHS_OPCODE_SCSI_RESPONSE 0x21
#define ISCSI_BHS_OPCODE_TASK_RESPONSE 0x22
#define ISCSI_BHS_OPCODE_LOGIN_RESPONSE 0x23
#define ISCSI_BHS_OPCODE_TEXT_RESPONSE 0x24
#define ISCSI_BHS_OPCODE_SCSI_DATA_IN 0x25
#define ISCSI_BHS_OPCODE_LOGOUT_RESPONSE 0x26
#define ISCSI_BHS_OPCODE_R2T 0x31
#define ISCSI_BHS_OPCODE_ASYNC_MESSAGE 0x32
#define ISCSI_BHS_OPCODE_REJECT 0x3f
struct iscsi_bhs {
uint8_t bhs_opcode;
uint8_t bhs_opcode_specific1[3];
uint8_t bhs_total_ahs_len;
uint8_t bhs_data_segment_len[3];
uint64_t bhs_lun;
uint8_t bhs_inititator_task_tag[4];
uint8_t bhs_opcode_specific4[28];
};
CTASSERT(sizeof(struct iscsi_bhs) == ISCSI_BHS_SIZE);
#define BHSSC_FLAGS_F 0x80
#define BHSSC_FLAGS_R 0x40
#define BHSSC_FLAGS_W 0x20
#define BHSSC_FLAGS_ATTR 0x07
#define BHSSC_FLAGS_ATTR_UNTAGGED 0
#define BHSSC_FLAGS_ATTR_SIMPLE 1
#define BHSSC_FLAGS_ATTR_ORDERED 2
#define BHSSC_FLAGS_ATTR_HOQ 3
#define BHSSC_FLAGS_ATTR_ACA 4
struct iscsi_bhs_scsi_command {
uint8_t bhssc_opcode;
uint8_t bhssc_flags;
uint8_t bhssc_reserved[2];
uint8_t bhssc_total_ahs_len;
uint8_t bhssc_data_segment_len[3];
uint64_t bhssc_lun;
uint32_t bhssc_initiator_task_tag;
uint32_t bhssc_expected_data_transfer_length;
uint32_t bhssc_cmdsn;
uint32_t bhssc_expstatsn;
uint8_t bhssc_cdb[16];
};
CTASSERT(sizeof(struct iscsi_bhs_scsi_command) == ISCSI_BHS_SIZE);
#define BHSSR_FLAGS_RESIDUAL_UNDERFLOW 0x02
#define BHSSR_FLAGS_RESIDUAL_OVERFLOW 0x04
#define BHSSR_RESPONSE_COMMAND_COMPLETED 0x00
struct iscsi_bhs_scsi_response {
uint8_t bhssr_opcode;
uint8_t bhssr_flags;
uint8_t bhssr_response;
uint8_t bhssr_status;
uint8_t bhssr_total_ahs_len;
uint8_t bhssr_data_segment_len[3];
uint64_t bhssr_reserved;
uint32_t bhssr_initiator_task_tag;
uint32_t bhssr_snack_tag;
uint32_t bhssr_statsn;
uint32_t bhssr_expcmdsn;
uint32_t bhssr_maxcmdsn;
uint32_t bhssr_expdatasn;
uint32_t bhssr_bidirectional_read_residual_count;
uint32_t bhssr_residual_count;
};
CTASSERT(sizeof(struct iscsi_bhs_scsi_response) == ISCSI_BHS_SIZE);
#define BHSTMR_FUNCTION_ABORT_TASK 1
#define BHSTMR_FUNCTION_ABORT_TASK_SET 2
#define BHSTMR_FUNCTION_CLEAR_ACA 3
#define BHSTMR_FUNCTION_CLEAR_TASK_SET 4
#define BHSTMR_FUNCTION_LOGICAL_UNIT_RESET 5
#define BHSTMR_FUNCTION_TARGET_WARM_RESET 6
#define BHSTMR_FUNCTION_TARGET_COLD_RESET 7
#define BHSTMR_FUNCTION_TASK_REASSIGN 8
struct iscsi_bhs_task_management_request {
uint8_t bhstmr_opcode;
uint8_t bhstmr_function;
uint8_t bhstmr_reserved[2];
uint8_t bhstmr_total_ahs_len;
uint8_t bhstmr_data_segment_len[3];
uint64_t bhstmr_lun;
uint32_t bhstmr_initiator_task_tag;
uint32_t bhstmr_referenced_task_tag;
uint32_t bhstmr_cmdsn;
uint32_t bhstmr_expstatsn;
uint32_t bhstmr_refcmdsn;
uint32_t bhstmr_expdatasn;
uint64_t bhstmr_reserved2;
};
CTASSERT(sizeof(struct iscsi_bhs_task_management_request) == ISCSI_BHS_SIZE);
#define BHSTMR_RESPONSE_FUNCTION_COMPLETE 0
#define BHSTMR_RESPONSE_FUNCTION_NOT_SUPPORTED 5
struct iscsi_bhs_task_management_response {
uint8_t bhstmr_opcode;
uint8_t bhstmr_flags;
uint8_t bhstmr_response;
uint8_t bhstmr_reserved;
uint8_t bhstmr_total_ahs_len;
uint8_t bhstmr_data_segment_len[3];
uint64_t bhstmr_reserved2;
uint32_t bhstmr_initiator_task_tag;
uint32_t bhstmr_reserved3;
uint32_t bhstmr_statsn;
uint32_t bhstmr_expcmdsn;
uint32_t bhstmr_maxcmdsn;
uint8_t bhstmr_reserved4[12];
};
CTASSERT(sizeof(struct iscsi_bhs_task_management_response) == ISCSI_BHS_SIZE);
#define BHSLR_FLAGS_TRANSIT 0x80
#define BHSLR_FLAGS_CONTINUE 0x40
#define BHSLR_STAGE_SECURITY_NEGOTIATION 0
#define BHSLR_STAGE_OPERATIONAL_NEGOTIATION 1
#define BHSLR_STAGE_FULL_FEATURE_PHASE 3 /* Yes, 3. */
struct iscsi_bhs_login_request {
uint8_t bhslr_opcode;
uint8_t bhslr_flags;
uint8_t bhslr_version_max;
uint8_t bhslr_version_min;
uint8_t bhslr_total_ahs_len;
uint8_t bhslr_data_segment_len[3];
uint8_t bhslr_isid[6];
uint16_t bhslr_tsih;
uint32_t bhslr_initiator_task_tag;
uint16_t bhslr_cid;
uint16_t bhslr_reserved;
uint32_t bhslr_cmdsn;
uint32_t bhslr_expstatsn;
uint8_t bhslr_reserved2[16];
};
CTASSERT(sizeof(struct iscsi_bhs_login_request) == ISCSI_BHS_SIZE);
struct iscsi_bhs_login_response {
uint8_t bhslr_opcode;
uint8_t bhslr_flags;
uint8_t bhslr_version_max;
uint8_t bhslr_version_active;
uint8_t bhslr_total_ahs_len;
uint8_t bhslr_data_segment_len[3];
uint8_t bhslr_isid[6];
uint16_t bhslr_tsih;
uint32_t bhslr_initiator_task_tag;
uint32_t bhslr_reserved;
uint32_t bhslr_statsn;
uint32_t bhslr_expcmdsn;
uint32_t bhslr_maxcmdsn;
uint8_t bhslr_status_class;
uint8_t bhslr_status_detail;
uint16_t bhslr_reserved2;
uint8_t bhslr_reserved3[8];
};
CTASSERT(sizeof(struct iscsi_bhs_login_response) == ISCSI_BHS_SIZE);
#define BHSTR_FLAGS_FINAL 0x80
#define BHSTR_FLAGS_CONTINUE 0x40
struct iscsi_bhs_text_request {
uint8_t bhstr_opcode;
uint8_t bhstr_flags;
uint16_t bhstr_reserved;
uint8_t bhstr_total_ahs_len;
uint8_t bhstr_data_segment_len[3];
uint64_t bhstr_lun;
uint32_t bhstr_initiator_task_tag;
uint32_t bhstr_target_transfer_tag;
uint32_t bhstr_cmdsn;
uint32_t bhstr_expstatsn;
uint8_t bhstr_reserved2[16];
};
CTASSERT(sizeof(struct iscsi_bhs_text_request) == ISCSI_BHS_SIZE);
struct iscsi_bhs_text_response {
uint8_t bhstr_opcode;
uint8_t bhstr_flags;
uint16_t bhstr_reserved;
uint8_t bhstr_total_ahs_len;
uint8_t bhstr_data_segment_len[3];
uint64_t bhstr_lun;
uint32_t bhstr_initiator_task_tag;
uint32_t bhstr_target_transfer_tag;
uint32_t bhstr_statsn;
uint32_t bhstr_expcmdsn;
uint32_t bhstr_maxcmdsn;
uint8_t bhstr_reserved2[12];
};
CTASSERT(sizeof(struct iscsi_bhs_text_response) == ISCSI_BHS_SIZE);
#define BHSDO_FLAGS_F 0x80
struct iscsi_bhs_data_out {
uint8_t bhsdo_opcode;
uint8_t bhsdo_flags;
uint8_t bhsdo_reserved[2];
uint8_t bhsdo_total_ahs_len;
uint8_t bhsdo_data_segment_len[3];
uint64_t bhsdo_lun;
uint32_t bhsdo_initiator_task_tag;
uint32_t bhsdo_target_transfer_tag;
uint32_t bhsdo_reserved2;
uint32_t bhsdo_expstatsn;
uint32_t bhsdo_reserved3;
uint32_t bhsdo_datasn;
uint32_t bhsdo_buffer_offset;
uint32_t bhsdo_reserved4;
};
CTASSERT(sizeof(struct iscsi_bhs_data_out) == ISCSI_BHS_SIZE);
#define BHSDI_FLAGS_F 0x80
#define BHSDI_FLAGS_A 0x40
#define BHSDI_FLAGS_O 0x04
#define BHSDI_FLAGS_U 0x02
#define BHSDI_FLAGS_S 0x01
struct iscsi_bhs_data_in {
uint8_t bhsdi_opcode;
uint8_t bhsdi_flags;
uint8_t bhsdi_reserved;
uint8_t bhsdi_status;
uint8_t bhsdi_total_ahs_len;
uint8_t bhsdi_data_segment_len[3];
uint64_t bhsdi_lun;
uint32_t bhsdi_initiator_task_tag;
uint32_t bhsdi_target_transfer_tag;
uint32_t bhsdi_statsn;
uint32_t bhsdi_expcmdsn;
uint32_t bhsdi_maxcmdsn;
uint32_t bhsdi_datasn;
uint32_t bhsdi_buffer_offset;
uint32_t bhsdi_residual_count;
};
CTASSERT(sizeof(struct iscsi_bhs_data_in) == ISCSI_BHS_SIZE);
struct iscsi_bhs_r2t {
uint8_t bhsr2t_opcode;
uint8_t bhsr2t_flags;
uint16_t bhsr2t_reserved;
uint8_t bhsr2t_total_ahs_len;
uint8_t bhsr2t_data_segment_len[3];
uint64_t bhsr2t_lun;
uint32_t bhsr2t_initiator_task_tag;
uint32_t bhsr2t_target_transfer_tag;
uint32_t bhsr2t_statsn;
uint32_t bhsr2t_expcmdsn;
uint32_t bhsr2t_maxcmdsn;
uint32_t bhsr2t_r2tsn;
uint32_t bhsr2t_buffer_offset;
uint32_t bhsr2t_desired_data_transfer_length;
};
CTASSERT(sizeof(struct iscsi_bhs_r2t) == ISCSI_BHS_SIZE);
struct iscsi_bhs_nop_out {
uint8_t bhsno_opcode;
uint8_t bhsno_flags;
uint16_t bhsno_reserved;
uint8_t bhsno_total_ahs_len;
uint8_t bhsno_data_segment_len[3];
uint64_t bhsno_lun;
uint32_t bhsno_initiator_task_tag;
uint32_t bhsno_target_transfer_tag;
uint32_t bhsno_cmdsn;
uint32_t bhsno_expstatsn;
uint8_t bhsno_reserved2[16];
};
CTASSERT(sizeof(struct iscsi_bhs_nop_out) == ISCSI_BHS_SIZE);
struct iscsi_bhs_nop_in {
uint8_t bhsni_opcode;
uint8_t bhsni_flags;
uint16_t bhsni_reserved;
uint8_t bhsni_total_ahs_len;
uint8_t bhsni_data_segment_len[3];
uint64_t bhsni_lun;
uint32_t bhsni_initiator_task_tag;
uint32_t bhsni_target_transfer_tag;
uint32_t bhsni_statsn;
uint32_t bhsni_expcmdsn;
uint32_t bhsni_maxcmdsn;
uint8_t bhsno_reserved2[12];
};
CTASSERT(sizeof(struct iscsi_bhs_nop_in) == ISCSI_BHS_SIZE);
#define BHSLR_REASON_CLOSE_SESSION 0
#define BHSLR_REASON_CLOSE_CONNECTION 1
#define BHSLR_REASON_REMOVE_FOR_RECOVERY 2
struct iscsi_bhs_logout_request {
uint8_t bhslr_opcode;
uint8_t bhslr_reason;
uint16_t bhslr_reserved;
uint8_t bhslr_total_ahs_len;
uint8_t bhslr_data_segment_len[3];
uint64_t bhslr_reserved2;
uint32_t bhslr_initiator_task_tag;
uint16_t bhslr_cid;
uint16_t bhslr_reserved3;
uint32_t bhslr_cmdsn;
uint32_t bhslr_expstatsn;
uint8_t bhslr_reserved4[16];
};
CTASSERT(sizeof(struct iscsi_bhs_logout_request) == ISCSI_BHS_SIZE);
#define BHSLR_RESPONSE_CLOSED_SUCCESSFULLY 0
#define BHSLR_RESPONSE_RECOVERY_NOT_SUPPORTED 2
struct iscsi_bhs_logout_response {
uint8_t bhslr_opcode;
uint8_t bhslr_flags;
uint8_t bhslr_response;
uint8_t bhslr_reserved;
uint8_t bhslr_total_ahs_len;
uint8_t bhslr_data_segment_len[3];
uint64_t bhslr_reserved2;
uint32_t bhslr_initiator_task_tag;
uint32_t bhslr_reserved3;
uint32_t bhslr_statsn;
uint32_t bhslr_expcmdsn;
uint32_t bhslr_maxcmdsn;
uint32_t bhslr_reserved4;
uint16_t bhslr_time2wait;
uint16_t bhslr_time2retain;
uint32_t bhslr_reserved5;
};
CTASSERT(sizeof(struct iscsi_bhs_logout_response) == ISCSI_BHS_SIZE);
#define BHSAM_EVENT_TARGET_REQUESTS_LOGOUT 1
#define BHSAM_EVENT_TARGET_TERMINATES_CONNECTION 2
#define BHSAM_EVENT_TARGET_TERMINATES_SESSION 3
struct iscsi_bhs_asynchronous_message {
uint8_t bhsam_opcode;
uint8_t bhsam_flags;
uint16_t bhsam_reserved;
uint8_t bhsam_total_ahs_len;
uint8_t bhsam_data_segment_len[3];
uint64_t bhsam_lun;
uint32_t bhsam_0xffffffff;
uint32_t bhsam_reserved2;
uint32_t bhsam_statsn;
uint32_t bhsam_expcmdsn;
uint32_t bhsam_maxcmdsn;
uint8_t bhsam_async_event;
uint8_t bhsam_async_vcode;
uint16_t bhsam_parameter1;
uint16_t bhsam_parameter2;
uint16_t bhsam_parameter3;
uint32_t bhsam_reserved3;
};
CTASSERT(sizeof(struct iscsi_bhs_asynchronous_message) == ISCSI_BHS_SIZE);
#define BHSSR_REASON_DATA_DIGEST_ERROR 0x02
#define BHSSR_PROTOCOL_ERROR 0x04
#define BHSSR_COMMAND_NOT_SUPPORTED 0x05
#define BHSSR_INVALID_PDU_FIELD 0x09
struct iscsi_bhs_reject {
uint8_t bhsr_opcode;
uint8_t bhsr_flags;
uint8_t bhsr_reason;
uint8_t bhsr_reserved;
uint8_t bhsr_total_ahs_len;
uint8_t bhsr_data_segment_len[3];
uint64_t bhsr_reserved2;
uint32_t bhsr_0xffffffff;
uint32_t bhsr_reserved3;
uint32_t bhsr_statsn;
uint32_t bhsr_expcmdsn;
uint32_t bhsr_maxcmdsn;
uint32_t bhsr_datasn_r2tsn;
uint32_t bhsr_reserved4;
uint32_t bhsr_reserved5;
};
CTASSERT(sizeof(struct iscsi_bhs_reject) == ISCSI_BHS_SIZE);
#endif /* !ISCSI_PROTO_H */