git: f2e737683eef - main - nvmf_proto.h: NVMe over Fabrics protocol definitions
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 03 May 2024 00:15:37 UTC
The branch main has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=f2e737683eef00469722265a2f957e867de6e354 commit f2e737683eef00469722265a2f957e867de6e354 Author: John Baldwin <jhb@FreeBSD.org> AuthorDate: 2024-05-02 23:26:16 +0000 Commit: John Baldwin <jhb@FreeBSD.org> CommitDate: 2024-05-02 23:26:16 +0000 nvmf_proto.h: NVMe over Fabrics protocol definitions This is a copy of spdk/include/spdk/nvmf_spec.h as of commit 470e851852bb948334a272c9f8de495020fa082f from Intel's SPDK. Subsequent commits will modify it to be suitable header for the kernel, but importing the stock file first makes it easier to see how the resulting header is derived from the original. Reviewed by: imp Obtained from: SPDK (https://github.com/spdk/spdk.git) Sponsored by: Chelsio Communications Differential Revision: https://reviews.freebsd.org/D44703 --- sys/dev/nvmf/nvmf_proto.h | 721 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 721 insertions(+) diff --git a/sys/dev/nvmf/nvmf_proto.h b/sys/dev/nvmf/nvmf_proto.h new file mode 100644 index 000000000000..75f6db2f8b15 --- /dev/null +++ b/sys/dev/nvmf/nvmf_proto.h @@ -0,0 +1,721 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (C) 2016 Intel Corporation. + * All rights reserved. + */ + +#ifndef SPDK_NVMF_SPEC_H +#define SPDK_NVMF_SPEC_H + +#include "spdk/stdinc.h" + +#include "spdk/assert.h" +#include "spdk/nvme_spec.h" + +/** + * \file + * NVMe over Fabrics specification definitions + */ + +#pragma pack(push, 1) + +struct spdk_nvmf_capsule_cmd { + uint8_t opcode; + uint8_t reserved1; + uint16_t cid; + uint8_t fctype; + uint8_t reserved2[35]; + uint8_t fabric_specific[24]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_capsule_cmd) == 64, "Incorrect size"); + +/* Fabric Command Set */ +#define SPDK_NVME_OPC_FABRIC 0x7f + +enum spdk_nvmf_fabric_cmd_types { + SPDK_NVMF_FABRIC_COMMAND_PROPERTY_SET = 0x00, + SPDK_NVMF_FABRIC_COMMAND_CONNECT = 0x01, + SPDK_NVMF_FABRIC_COMMAND_PROPERTY_GET = 0x04, + SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_SEND = 0x05, + SPDK_NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV = 0x06, + SPDK_NVMF_FABRIC_COMMAND_START_VENDOR_SPECIFIC = 0xC0, +}; + +enum spdk_nvmf_fabric_cmd_status_code { + SPDK_NVMF_FABRIC_SC_INCOMPATIBLE_FORMAT = 0x80, + SPDK_NVMF_FABRIC_SC_CONTROLLER_BUSY = 0x81, + SPDK_NVMF_FABRIC_SC_INVALID_PARAM = 0x82, + SPDK_NVMF_FABRIC_SC_RESTART_DISCOVERY = 0x83, + SPDK_NVMF_FABRIC_SC_INVALID_HOST = 0x84, + SPDK_NVMF_FABRIC_SC_LOG_RESTART_DISCOVERY = 0x90, + SPDK_NVMF_FABRIC_SC_AUTH_REQUIRED = 0x91, +}; + +/** + * RDMA Queue Pair service types + */ +enum spdk_nvmf_rdma_qptype { + /** Reliable connected */ + SPDK_NVMF_RDMA_QPTYPE_RELIABLE_CONNECTED = 0x1, + + /** Reliable datagram */ + SPDK_NVMF_RDMA_QPTYPE_RELIABLE_DATAGRAM = 0x2, +}; + +/** + * RDMA provider types + */ +enum spdk_nvmf_rdma_prtype { + /** No provider specified */ + SPDK_NVMF_RDMA_PRTYPE_NONE = 0x1, + + /** InfiniBand */ + SPDK_NVMF_RDMA_PRTYPE_IB = 0x2, + + /** RoCE v1 */ + SPDK_NVMF_RDMA_PRTYPE_ROCE = 0x3, + + /** RoCE v2 */ + SPDK_NVMF_RDMA_PRTYPE_ROCE2 = 0x4, + + /** iWARP */ + SPDK_NVMF_RDMA_PRTYPE_IWARP = 0x5, +}; + +/** + * RDMA connection management service types + */ +enum spdk_nvmf_rdma_cms { + /** Sockets based endpoint addressing */ + SPDK_NVMF_RDMA_CMS_RDMA_CM = 0x1, +}; + +/** + * NVMe over Fabrics transport types + */ +enum spdk_nvmf_trtype { + /** RDMA */ + SPDK_NVMF_TRTYPE_RDMA = 0x1, + + /** Fibre Channel */ + SPDK_NVMF_TRTYPE_FC = 0x2, + + /** TCP */ + SPDK_NVMF_TRTYPE_TCP = 0x3, + + /** Intra-host transport (loopback) */ + SPDK_NVMF_TRTYPE_INTRA_HOST = 0xfe, +}; + +/** + * Address family types + */ +enum spdk_nvmf_adrfam { + /** IPv4 (AF_INET) */ + SPDK_NVMF_ADRFAM_IPV4 = 0x1, + + /** IPv6 (AF_INET6) */ + SPDK_NVMF_ADRFAM_IPV6 = 0x2, + + /** InfiniBand (AF_IB) */ + SPDK_NVMF_ADRFAM_IB = 0x3, + + /** Fibre Channel address family */ + SPDK_NVMF_ADRFAM_FC = 0x4, + + /** Intra-host transport (loopback) */ + SPDK_NVMF_ADRFAM_INTRA_HOST = 0xfe, +}; + +/** + * NVM subsystem types + */ +enum spdk_nvmf_subtype { + /** Referral to a discovery service */ + SPDK_NVMF_SUBTYPE_DISCOVERY = 0x1, + + /** NVM Subsystem */ + SPDK_NVMF_SUBTYPE_NVME = 0x2, + + /** Current Discovery Subsystem */ + SPDK_NVMF_SUBTYPE_DISCOVERY_CURRENT = 0x3 +}; + +/* Discovery Log Entry Flags - Duplicate Returned Information */ +#define SPDK_NVMF_DISCOVERY_LOG_EFLAGS_DUPRETINFO (1u << 0u) + +/* Discovery Log Entry Flags - Explicit Persistent Connection Support for Discovery */ +#define SPDK_NVMF_DISCOVERY_LOG_EFLAGS_EPCSD (1u << 1u) + +/** + * Connections shall be made over a fabric secure channel + */ +enum spdk_nvmf_treq_secure_channel { + /** Not specified */ + SPDK_NVMF_TREQ_SECURE_CHANNEL_NOT_SPECIFIED = 0x0, + + /** Required */ + SPDK_NVMF_TREQ_SECURE_CHANNEL_REQUIRED = 0x1, + + /** Not required */ + SPDK_NVMF_TREQ_SECURE_CHANNEL_NOT_REQUIRED = 0x2, +}; + +struct spdk_nvmf_fabric_auth_recv_cmd { + uint8_t opcode; + uint8_t reserved1; + uint16_t cid; + uint8_t fctype; /* NVMF_FABRIC_COMMAND_AUTHENTICATION_RECV (0x06) */ + uint8_t reserved2[19]; + struct spdk_nvme_sgl_descriptor sgl1; + uint8_t reserved3; + uint8_t spsp0; + uint8_t spsp1; + uint8_t secp; + uint32_t al; + uint8_t reserved4[16]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fabric_auth_recv_cmd) == 64, "Incorrect size"); + +struct spdk_nvmf_fabric_auth_send_cmd { + uint8_t opcode; + uint8_t reserved1; + uint16_t cid; + uint8_t fctype; /* NVMF_FABRIC_COMMAND_AUTHENTICATION_SEND (0x05) */ + uint8_t reserved2[19]; + struct spdk_nvme_sgl_descriptor sgl1; + uint8_t reserved3; + uint8_t spsp0; + uint8_t spsp1; + uint8_t secp; + uint32_t tl; + uint8_t reserved4[16]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fabric_auth_send_cmd) == 64, "Incorrect size"); + +struct spdk_nvmf_fabric_connect_data { + uint8_t hostid[16]; + uint16_t cntlid; + uint8_t reserved5[238]; + uint8_t subnqn[SPDK_NVME_NQN_FIELD_SIZE]; + uint8_t hostnqn[SPDK_NVME_NQN_FIELD_SIZE]; + uint8_t reserved6[256]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fabric_connect_data) == 1024, "Incorrect size"); + +struct spdk_nvmf_fabric_connect_cmd { + uint8_t opcode; + uint8_t reserved1; + uint16_t cid; + uint8_t fctype; + uint8_t reserved2[19]; + struct spdk_nvme_sgl_descriptor sgl1; + uint16_t recfmt; /* Connect Record Format */ + uint16_t qid; /* Queue Identifier */ + uint16_t sqsize; /* Submission Queue Size */ + uint8_t cattr; /* queue attributes */ + uint8_t reserved3; + uint32_t kato; /* keep alive timeout */ + uint8_t reserved4[12]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fabric_connect_cmd) == 64, "Incorrect size"); + +struct spdk_nvmf_fabric_connect_rsp { + union { + struct { + uint16_t cntlid; + uint16_t authreq; + } success; + + struct { + uint16_t ipo; + uint8_t iattr; + uint8_t reserved; + } invalid; + + uint32_t raw; + } status_code_specific; + + uint32_t reserved0; + uint16_t sqhd; + uint16_t reserved1; + uint16_t cid; + struct spdk_nvme_status status; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fabric_connect_rsp) == 16, "Incorrect size"); + +#define SPDK_NVMF_PROP_SIZE_4 0 +#define SPDK_NVMF_PROP_SIZE_8 1 + +struct spdk_nvmf_fabric_prop_get_cmd { + uint8_t opcode; + uint8_t reserved1; + uint16_t cid; + uint8_t fctype; + uint8_t reserved2[35]; + struct { + uint8_t size : 3; + uint8_t reserved : 5; + } attrib; + uint8_t reserved3[3]; + uint32_t ofst; + uint8_t reserved4[16]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fabric_prop_get_cmd) == 64, "Incorrect size"); + +struct spdk_nvmf_fabric_prop_get_rsp { + union { + uint64_t u64; + struct { + uint32_t low; + uint32_t high; + } u32; + } value; + + uint16_t sqhd; + uint16_t reserved0; + uint16_t cid; + struct spdk_nvme_status status; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fabric_prop_get_rsp) == 16, "Incorrect size"); + +struct spdk_nvmf_fabric_prop_set_cmd { + uint8_t opcode; + uint8_t reserved0; + uint16_t cid; + uint8_t fctype; + uint8_t reserved1[35]; + struct { + uint8_t size : 3; + uint8_t reserved : 5; + } attrib; + uint8_t reserved2[3]; + uint32_t ofst; + + union { + uint64_t u64; + struct { + uint32_t low; + uint32_t high; + } u32; + } value; + + uint8_t reserved4[8]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fabric_prop_set_cmd) == 64, "Incorrect size"); + +#define SPDK_NVMF_NQN_MIN_LEN 11 /* The prefix in the spec is 11 characters */ +#define SPDK_NVMF_NQN_MAX_LEN 223 +#define SPDK_NVMF_NQN_UUID_PRE_LEN 32 +#define SPDK_NVMF_UUID_STRING_LEN 36 +#define SPDK_NVMF_NQN_UUID_PRE "nqn.2014-08.org.nvmexpress:uuid:" +#define SPDK_NVMF_DISCOVERY_NQN "nqn.2014-08.org.nvmexpress.discovery" + +#define SPDK_DOMAIN_LABEL_MAX_LEN 63 /* RFC 1034 max domain label length */ + +#define SPDK_NVMF_TRSTRING_MAX_LEN 32 +#define SPDK_NVMF_TRADDR_MAX_LEN 256 +#define SPDK_NVMF_TRSVCID_MAX_LEN 32 + +/** RDMA transport-specific address subtype */ +struct spdk_nvmf_rdma_transport_specific_address_subtype { + /** RDMA QP service type (\ref spdk_nvmf_rdma_qptype) */ + uint8_t rdma_qptype; + + /** RDMA provider type (\ref spdk_nvmf_rdma_prtype) */ + uint8_t rdma_prtype; + + /** RDMA connection management service (\ref spdk_nvmf_rdma_cms) */ + uint8_t rdma_cms; + + uint8_t reserved0[5]; + + /** RDMA partition key for AF_IB */ + uint16_t rdma_pkey; + + uint8_t reserved2[246]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_rdma_transport_specific_address_subtype) == 256, + "Incorrect size"); + +/** TCP Secure Socket Type */ +enum spdk_nvme_tcp_secure_socket_type { + /** No security */ + SPDK_NVME_TCP_SECURITY_NONE = 0, + + /** TLS (Secure Sockets) version 1.2 */ + SPDK_NVME_TCP_SECURITY_TLS_1_2 = 1, + + /** TLS (Secure Sockets) version 1.3 */ + SPDK_NVME_TCP_SECURITY_TLS_1_3 = 2, +}; + +/** TCP transport-specific address subtype */ +struct spdk_nvme_tcp_transport_specific_address_subtype { + /** Security type (\ref spdk_nvme_tcp_secure_socket_type) */ + uint8_t sectype; + + uint8_t reserved0[255]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_tcp_transport_specific_address_subtype) == 256, + "Incorrect size"); + +/** Transport-specific address subtype */ +union spdk_nvmf_transport_specific_address_subtype { + uint8_t raw[256]; + + /** RDMA */ + struct spdk_nvmf_rdma_transport_specific_address_subtype rdma; + + /** TCP */ + struct spdk_nvme_tcp_transport_specific_address_subtype tcp; +}; +SPDK_STATIC_ASSERT(sizeof(union spdk_nvmf_transport_specific_address_subtype) == 256, + "Incorrect size"); + +#define SPDK_NVMF_MIN_ADMIN_MAX_SQ_SIZE 32 + +/** + * Discovery Log Page entry + */ +struct spdk_nvmf_discovery_log_page_entry { + /** Transport type (\ref spdk_nvmf_trtype) */ + uint8_t trtype; + + /** Address family (\ref spdk_nvmf_adrfam) */ + uint8_t adrfam; + + /** Subsystem type (\ref spdk_nvmf_subtype) */ + uint8_t subtype; + + /** Transport requirements */ + struct { + /** Secure channel requirements (\ref spdk_nvmf_treq_secure_channel) */ + uint8_t secure_channel : 2; + + uint8_t reserved : 6; + } treq; + + /** NVM subsystem port ID */ + uint16_t portid; + + /** Controller ID */ + uint16_t cntlid; + + /** Admin max SQ size */ + uint16_t asqsz; + + /** Entry Flags */ + uint16_t eflags; + + uint8_t reserved0[20]; + + /** Transport service identifier */ + uint8_t trsvcid[SPDK_NVMF_TRSVCID_MAX_LEN]; + + uint8_t reserved1[192]; + + /** NVM subsystem qualified name */ + uint8_t subnqn[256]; + + /** Transport address */ + uint8_t traddr[SPDK_NVMF_TRADDR_MAX_LEN]; + + /** Transport-specific address subtype */ + union spdk_nvmf_transport_specific_address_subtype tsas; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_discovery_log_page_entry) == 1024, "Incorrect size"); + +struct spdk_nvmf_discovery_log_page { + uint64_t genctr; + uint64_t numrec; + uint16_t recfmt; + uint8_t reserved0[1006]; + struct spdk_nvmf_discovery_log_page_entry entries[0]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_discovery_log_page) == 1024, "Incorrect size"); + +/* RDMA Fabric specific definitions below */ + +#define SPDK_NVME_SGL_SUBTYPE_INVALIDATE_KEY 0xF + +struct spdk_nvmf_rdma_request_private_data { + uint16_t recfmt; /* record format */ + uint16_t qid; /* queue id */ + uint16_t hrqsize; /* host receive queue size */ + uint16_t hsqsize; /* host send queue size */ + uint16_t cntlid; /* controller id */ + uint8_t reserved[22]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_rdma_request_private_data) == 32, "Incorrect size"); + +struct spdk_nvmf_rdma_accept_private_data { + uint16_t recfmt; /* record format */ + uint16_t crqsize; /* controller receive queue size */ + uint8_t reserved[28]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_rdma_accept_private_data) == 32, "Incorrect size"); + +struct spdk_nvmf_rdma_reject_private_data { + uint16_t recfmt; /* record format */ + uint16_t sts; /* status */ +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_rdma_reject_private_data) == 4, "Incorrect size"); + +union spdk_nvmf_rdma_private_data { + struct spdk_nvmf_rdma_request_private_data pd_request; + struct spdk_nvmf_rdma_accept_private_data pd_accept; + struct spdk_nvmf_rdma_reject_private_data pd_reject; +}; +SPDK_STATIC_ASSERT(sizeof(union spdk_nvmf_rdma_private_data) == 32, "Incorrect size"); + +enum spdk_nvmf_rdma_transport_error { + SPDK_NVMF_RDMA_ERROR_INVALID_PRIVATE_DATA_LENGTH = 0x1, + SPDK_NVMF_RDMA_ERROR_INVALID_RECFMT = 0x2, + SPDK_NVMF_RDMA_ERROR_INVALID_QID = 0x3, + SPDK_NVMF_RDMA_ERROR_INVALID_HSQSIZE = 0x4, + SPDK_NVMF_RDMA_ERROR_INVALID_HRQSIZE = 0x5, + SPDK_NVMF_RDMA_ERROR_NO_RESOURCES = 0x6, + SPDK_NVMF_RDMA_ERROR_INVALID_IRD = 0x7, + SPDK_NVMF_RDMA_ERROR_INVALID_ORD = 0x8, +}; + +/* TCP transport specific definitions below */ + +/** NVMe/TCP PDU type */ +enum spdk_nvme_tcp_pdu_type { + /** Initialize Connection Request (ICReq) */ + SPDK_NVME_TCP_PDU_TYPE_IC_REQ = 0x00, + + /** Initialize Connection Response (ICResp) */ + SPDK_NVME_TCP_PDU_TYPE_IC_RESP = 0x01, + + /** Terminate Connection Request (TermReq) */ + SPDK_NVME_TCP_PDU_TYPE_H2C_TERM_REQ = 0x02, + + /** Terminate Connection Response (TermResp) */ + SPDK_NVME_TCP_PDU_TYPE_C2H_TERM_REQ = 0x03, + + /** Command Capsule (CapsuleCmd) */ + SPDK_NVME_TCP_PDU_TYPE_CAPSULE_CMD = 0x04, + + /** Response Capsule (CapsuleRsp) */ + SPDK_NVME_TCP_PDU_TYPE_CAPSULE_RESP = 0x05, + + /** Host To Controller Data (H2CData) */ + SPDK_NVME_TCP_PDU_TYPE_H2C_DATA = 0x06, + + /** Controller To Host Data (C2HData) */ + SPDK_NVME_TCP_PDU_TYPE_C2H_DATA = 0x07, + + /** Ready to Transfer (R2T) */ + SPDK_NVME_TCP_PDU_TYPE_R2T = 0x09, +}; + +/** Common NVMe/TCP PDU header */ +struct spdk_nvme_tcp_common_pdu_hdr { + /** PDU type (\ref spdk_nvme_tcp_pdu_type) */ + uint8_t pdu_type; + + /** pdu_type-specific flags */ + uint8_t flags; + + /** Length of PDU header (not including the Header Digest) */ + uint8_t hlen; + + /** PDU Data Offset from the start of the PDU */ + uint8_t pdo; + + /** Total number of bytes in PDU, including pdu_hdr */ + uint32_t plen; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_tcp_common_pdu_hdr) == 8, "Incorrect size"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_common_pdu_hdr, pdu_type) == 0, + "Incorrect offset"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_common_pdu_hdr, flags) == 1, "Incorrect offset"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_common_pdu_hdr, hlen) == 2, "Incorrect offset"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_common_pdu_hdr, pdo) == 3, "Incorrect offset"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_common_pdu_hdr, plen) == 4, "Incorrect offset"); + +#define SPDK_NVME_TCP_CH_FLAGS_HDGSTF (1u << 0) +#define SPDK_NVME_TCP_CH_FLAGS_DDGSTF (1u << 1) + +/** + * ICReq + * + * common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_IC_REQ + */ +struct spdk_nvme_tcp_ic_req { + struct spdk_nvme_tcp_common_pdu_hdr common; + uint16_t pfv; + /** Specifies the data alignment for all PDUs transferred from the controller to the host that contain data */ + uint8_t hpda; + union { + uint8_t raw; + struct { + uint8_t hdgst_enable : 1; + uint8_t ddgst_enable : 1; + uint8_t reserved : 6; + } bits; + } dgst; + uint32_t maxr2t; + uint8_t reserved16[112]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_tcp_ic_req) == 128, "Incorrect size"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_ic_req, pfv) == 8, "Incorrect offset"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_ic_req, hpda) == 10, "Incorrect offset"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_ic_req, maxr2t) == 12, "Incorrect offset"); + +#define SPDK_NVME_TCP_HPDA_MAX 31 +#define SPDK_NVME_TCP_CPDA_MAX 31 +#define SPDK_NVME_TCP_PDU_PDO_MAX_OFFSET ((SPDK_NVME_TCP_CPDA_MAX + 1) << 2) + +/** + * ICResp + * + * common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_IC_RESP + */ +struct spdk_nvme_tcp_ic_resp { + struct spdk_nvme_tcp_common_pdu_hdr common; + uint16_t pfv; + /** Specifies the data alignment for all PDUs transferred from the host to the controller that contain data */ + uint8_t cpda; + union { + uint8_t raw; + struct { + uint8_t hdgst_enable : 1; + uint8_t ddgst_enable : 1; + uint8_t reserved : 6; + } bits; + } dgst; + /** Specifies the maximum number of PDU-Data bytes per H2C Data Transfer PDU */ + uint32_t maxh2cdata; + uint8_t reserved16[112]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_tcp_ic_resp) == 128, "Incorrect size"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_ic_resp, pfv) == 8, "Incorrect offset"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_ic_resp, cpda) == 10, "Incorrect offset"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_ic_resp, maxh2cdata) == 12, "Incorrect offset"); + +/** + * TermReq + * + * common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_TERM_REQ + */ +struct spdk_nvme_tcp_term_req_hdr { + struct spdk_nvme_tcp_common_pdu_hdr common; + uint16_t fes; + uint8_t fei[4]; + uint8_t reserved14[10]; +}; + +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_tcp_term_req_hdr) == 24, "Incorrect size"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_term_req_hdr, fes) == 8, "Incorrect offset"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_term_req_hdr, fei) == 10, "Incorrect offset"); + +enum spdk_nvme_tcp_term_req_fes { + SPDK_NVME_TCP_TERM_REQ_FES_INVALID_HEADER_FIELD = 0x01, + SPDK_NVME_TCP_TERM_REQ_FES_PDU_SEQUENCE_ERROR = 0x02, + SPDK_NVME_TCP_TERM_REQ_FES_HDGST_ERROR = 0x03, + SPDK_NVME_TCP_TERM_REQ_FES_DATA_TRANSFER_OUT_OF_RANGE = 0x04, + SPDK_NVME_TCP_TERM_REQ_FES_DATA_TRANSFER_LIMIT_EXCEEDED = 0x05, + SPDK_NVME_TCP_TERM_REQ_FES_R2T_LIMIT_EXCEEDED = 0x05, + SPDK_NVME_TCP_TERM_REQ_FES_INVALID_DATA_UNSUPPORTED_PARAMETER = 0x06, +}; + +/* Total length of term req PDU (including PDU header and DATA) in bytes shall not exceed a limit of 152 bytes. */ +#define SPDK_NVME_TCP_TERM_REQ_ERROR_DATA_MAX_SIZE 128 +#define SPDK_NVME_TCP_TERM_REQ_PDU_MAX_SIZE (SPDK_NVME_TCP_TERM_REQ_ERROR_DATA_MAX_SIZE + sizeof(struct spdk_nvme_tcp_term_req_hdr)) + +/** + * CapsuleCmd + * + * common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_CAPSULE_CMD + */ +struct spdk_nvme_tcp_cmd { + struct spdk_nvme_tcp_common_pdu_hdr common; + struct spdk_nvme_cmd ccsqe; + /**< icdoff hdgst padding + in-capsule data + ddgst (if enabled) */ +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_tcp_cmd) == 72, "Incorrect size"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_cmd, ccsqe) == 8, "Incorrect offset"); + +/** + * CapsuleResp + * + * common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_CAPSULE_RESP + */ +struct spdk_nvme_tcp_rsp { + struct spdk_nvme_tcp_common_pdu_hdr common; + struct spdk_nvme_cpl rccqe; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_tcp_rsp) == 24, "incorrect size"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_rsp, rccqe) == 8, "Incorrect offset"); + + +/** + * H2CData + * + * hdr.pdu_type == SPDK_NVME_TCP_PDU_TYPE_H2C_DATA + */ +struct spdk_nvme_tcp_h2c_data_hdr { + struct spdk_nvme_tcp_common_pdu_hdr common; + uint16_t cccid; + uint16_t ttag; + uint32_t datao; + uint32_t datal; + uint8_t reserved20[4]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_tcp_h2c_data_hdr) == 24, "Incorrect size"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_h2c_data_hdr, cccid) == 8, "Incorrect offset"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_h2c_data_hdr, ttag) == 10, "Incorrect offset"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_h2c_data_hdr, datao) == 12, "Incorrect offset"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_h2c_data_hdr, datal) == 16, "Incorrect offset"); + +#define SPDK_NVME_TCP_H2C_DATA_FLAGS_LAST_PDU (1u << 2) +#define SPDK_NVME_TCP_H2C_DATA_FLAGS_SUCCESS (1u << 3) +#define SPDK_NVME_TCP_H2C_DATA_PDO_MULT 8u + +/** + * C2HData + * + * hdr.pdu_type == SPDK_NVME_TCP_PDU_TYPE_C2H_DATA + */ +struct spdk_nvme_tcp_c2h_data_hdr { + struct spdk_nvme_tcp_common_pdu_hdr common; + uint16_t cccid; + uint8_t reserved10[2]; + uint32_t datao; + uint32_t datal; + uint8_t reserved20[4]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_tcp_c2h_data_hdr) == 24, "Incorrect size"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_c2h_data_hdr, cccid) == 8, "Incorrect offset"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_c2h_data_hdr, datao) == 12, "Incorrect offset"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_c2h_data_hdr, datal) == 16, "Incorrect offset"); + +#define SPDK_NVME_TCP_C2H_DATA_FLAGS_SUCCESS (1u << 3) +#define SPDK_NVME_TCP_C2H_DATA_FLAGS_LAST_PDU (1u << 2) +#define SPDK_NVME_TCP_C2H_DATA_PDO_MULT 8u + +/** + * R2T + * + * common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_R2T + */ +struct spdk_nvme_tcp_r2t_hdr { + struct spdk_nvme_tcp_common_pdu_hdr common; + uint16_t cccid; + uint16_t ttag; + uint32_t r2to; + uint32_t r2tl; + uint8_t reserved20[4]; +}; +SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_tcp_r2t_hdr) == 24, "Incorrect size"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_r2t_hdr, cccid) == 8, "Incorrect offset"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_r2t_hdr, ttag) == 10, "Incorrect offset"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_r2t_hdr, r2to) == 12, "Incorrect offset"); +SPDK_STATIC_ASSERT(offsetof(struct spdk_nvme_tcp_r2t_hdr, r2tl) == 16, "Incorrect offset"); + +#pragma pack(pop) + +#endif /* __NVMF_SPEC_H__ */