nvme: Add the NVMe over fabrics TCP/IP transport support
It is the first patch to follow the NVMe over fabrics spec and implmenent the NVMe/TCP transport. It can be divided into work in the host and target sides: Host side: Add the TCP/IP transport in nvme lib (lib/nvme). Target side: Add the TCP/IP transport in nvmf lib (lib/nvmf). Change-Id: Idc4f93750df676354f6c2ea8ecdb234e3638fd44 Signed-off-by: Ziye Yang <optimistyzy@gmail.com> Reviewed-on: https://review.gerrithub.io/425191 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
04babbea35
commit
e956be96eb
13
CHANGELOG.md
13
CHANGELOG.md
@ -17,7 +17,18 @@ prior to calling `spdk_nvmf_tgt_listen`.
|
|||||||
|
|
||||||
Related to the previous change, the rpc `set_nvmf_target_options` has been renamed to
|
Related to the previous change, the rpc `set_nvmf_target_options` has been renamed to
|
||||||
`set_nvmf_target_max_subsystems` to indicate that this is the only target option available for the user to edit.
|
`set_nvmf_target_max_subsystems` to indicate that this is the only target option available for the user to edit.
|
||||||
Usage of this rpc is still confined to the time prior to application subsystem initialization.
|
|
||||||
|
### nvme
|
||||||
|
|
||||||
|
Add a new TCP/IP transport(located in lib/nvme/nvme_tcp.c) in nvme driver. With
|
||||||
|
this new transport, it can be used to connect the NVMe-oF target with the
|
||||||
|
same TCP/IP support.
|
||||||
|
|
||||||
|
### nvmf
|
||||||
|
|
||||||
|
Add a new TCP/IP transport (located in lib/nvmf/tcp.c). With this tranport,
|
||||||
|
the SPDK NVMe-oF target can have a new transport, and can serve the NVMe-oF
|
||||||
|
protocol via TCP/IP from the host.
|
||||||
|
|
||||||
## v18.10:
|
## v18.10:
|
||||||
|
|
||||||
|
@ -43,9 +43,9 @@ C_SRCS = fio_plugin.c
|
|||||||
CFLAGS += -I$(CONFIG_FIO_SOURCE_DIR)
|
CFLAGS += -I$(CONFIG_FIO_SOURCE_DIR)
|
||||||
LDFLAGS += -shared -rdynamic
|
LDFLAGS += -shared -rdynamic
|
||||||
|
|
||||||
SPDK_LIB_LIST += thread util bdev conf copy rpc jsonrpc json log trace
|
SPDK_LIB_LIST += thread util bdev conf copy rpc jsonrpc json log sock trace
|
||||||
|
|
||||||
LIBS += $(BLOCKDEV_MODULES_LINKER_ARGS)
|
LIBS += $(BLOCKDEV_MODULES_LINKER_ARGS) $(SOCK_MODULES_LINKER_ARGS)
|
||||||
LIBS += $(SPDK_LIB_LINKER_ARGS) $(ENV_LINKER_ARGS)
|
LIBS += $(SPDK_LIB_LINKER_ARGS) $(ENV_LINKER_ARGS)
|
||||||
|
|
||||||
all: $(APP)
|
all: $(APP)
|
||||||
|
@ -202,6 +202,11 @@ enum spdk_nvme_transport_type {
|
|||||||
* Fibre Channel (FC) Transport
|
* Fibre Channel (FC) Transport
|
||||||
*/
|
*/
|
||||||
SPDK_NVME_TRANSPORT_FC = SPDK_NVMF_TRTYPE_FC,
|
SPDK_NVME_TRANSPORT_FC = SPDK_NVMF_TRTYPE_FC,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TCP Transport
|
||||||
|
*/
|
||||||
|
SPDK_NVME_TRANSPORT_TCP = SPDK_NVMF_TRTYPE_TCP,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* typedef added for coding style reasons */
|
/* typedef added for coding style reasons */
|
||||||
|
@ -392,6 +392,7 @@ enum spdk_nvme_sgl_descriptor_type {
|
|||||||
enum spdk_nvme_sgl_descriptor_subtype {
|
enum spdk_nvme_sgl_descriptor_subtype {
|
||||||
SPDK_NVME_SGL_SUBTYPE_ADDRESS = 0x0,
|
SPDK_NVME_SGL_SUBTYPE_ADDRESS = 0x0,
|
||||||
SPDK_NVME_SGL_SUBTYPE_OFFSET = 0x1,
|
SPDK_NVME_SGL_SUBTYPE_OFFSET = 0x1,
|
||||||
|
SPDK_NVME_SGL_SUBTYPE_TRANSPORT = 0xa,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct __attribute__((packed)) spdk_nvme_sgl_descriptor {
|
struct __attribute__((packed)) spdk_nvme_sgl_descriptor {
|
||||||
|
@ -130,6 +130,9 @@ enum spdk_nvmf_trtype {
|
|||||||
/** Fibre Channel */
|
/** Fibre Channel */
|
||||||
SPDK_NVMF_TRTYPE_FC = 0x2,
|
SPDK_NVMF_TRTYPE_FC = 0x2,
|
||||||
|
|
||||||
|
/** TCP */
|
||||||
|
SPDK_NVMF_TRTYPE_TCP = 0x3,
|
||||||
|
|
||||||
/** Intra-host transport (loopback) */
|
/** Intra-host transport (loopback) */
|
||||||
SPDK_NVMF_TRTYPE_INTRA_HOST = 0xfe,
|
SPDK_NVMF_TRTYPE_INTRA_HOST = 0xfe,
|
||||||
};
|
};
|
||||||
@ -355,12 +358,34 @@ struct spdk_nvmf_rdma_transport_specific_address_subtype {
|
|||||||
SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_rdma_transport_specific_address_subtype) == 256,
|
SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_rdma_transport_specific_address_subtype) == 256,
|
||||||
"Incorrect size");
|
"Incorrect size");
|
||||||
|
|
||||||
|
/** TCP Secure Socket Type */
|
||||||
|
enum spdk_nvme_tcp_secure_socket_type {
|
||||||
|
/** No security */
|
||||||
|
SPDK_NVME_TCP_SECURITY_NONE = 0,
|
||||||
|
|
||||||
|
/** TLS (Secure Sockets) */
|
||||||
|
SPDK_NVME_TCP_SECURITY_TLS = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 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 */
|
/** Transport-specific address subtype */
|
||||||
union spdk_nvmf_transport_specific_address_subtype {
|
union spdk_nvmf_transport_specific_address_subtype {
|
||||||
uint8_t raw[256];
|
uint8_t raw[256];
|
||||||
|
|
||||||
/** RDMA */
|
/** RDMA */
|
||||||
struct spdk_nvmf_rdma_transport_specific_address_subtype 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,
|
SPDK_STATIC_ASSERT(sizeof(union spdk_nvmf_transport_specific_address_subtype) == 256,
|
||||||
"Incorrect size");
|
"Incorrect size");
|
||||||
@ -467,6 +492,242 @@ enum spdk_nvmf_rdma_transport_error {
|
|||||||
SPDK_NVMF_RDMA_ERROR_INVALID_ORD = 0x8,
|
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_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 hdgest 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)
|
#pragma pack(pop)
|
||||||
|
|
||||||
#endif /* __NVMF_SPEC_H__ */
|
#endif /* __NVMF_SPEC_H__ */
|
||||||
|
274
include/spdk_internal/nvme_tcp.h
Normal file
274
include/spdk_internal/nvme_tcp.h
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
/*-
|
||||||
|
* BSD LICENSE
|
||||||
|
*
|
||||||
|
* Copyright (c) Intel Corporation.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * 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.
|
||||||
|
* * Neither the name of Intel Corporation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
|
||||||
|
* OWNER 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPDK_INTERNAL_NVME_TCP_H
|
||||||
|
#define SPDK_INTERNAL_NVME_TCP_H
|
||||||
|
|
||||||
|
#include "spdk/sock.h"
|
||||||
|
|
||||||
|
#define SPDK_CRC32C_XOR 0xffffffffUL
|
||||||
|
#define SPDK_NVME_TCP_DIGEST_LEN 4
|
||||||
|
#define SPDK_NVME_TCP_DIGEST_ALIGNMENT 4
|
||||||
|
#define SPDK_NVME_TCP_QPAIR_EXIT_TIMEOUT 30
|
||||||
|
|
||||||
|
#define MAKE_DIGEST_WORD(BUF, CRC32C) \
|
||||||
|
( ((*((uint8_t *)(BUF)+0)) = (uint8_t)((uint32_t)(CRC32C) >> 0)), \
|
||||||
|
((*((uint8_t *)(BUF)+1)) = (uint8_t)((uint32_t)(CRC32C) >> 8)), \
|
||||||
|
((*((uint8_t *)(BUF)+2)) = (uint8_t)((uint32_t)(CRC32C) >> 16)), \
|
||||||
|
((*((uint8_t *)(BUF)+3)) = (uint8_t)((uint32_t)(CRC32C) >> 24)))
|
||||||
|
|
||||||
|
#define MATCH_DIGEST_WORD(BUF, CRC32C) \
|
||||||
|
( ((((uint32_t) *((uint8_t *)(BUF)+0)) << 0) \
|
||||||
|
| (((uint32_t) *((uint8_t *)(BUF)+1)) << 8) \
|
||||||
|
| (((uint32_t) *((uint8_t *)(BUF)+2)) << 16) \
|
||||||
|
| (((uint32_t) *((uint8_t *)(BUF)+3)) << 24)) \
|
||||||
|
== (CRC32C))
|
||||||
|
|
||||||
|
#define DGET32(B) \
|
||||||
|
((( (uint32_t) *((uint8_t *)(B)+0)) << 0) \
|
||||||
|
| (((uint32_t) *((uint8_t *)(B)+1)) << 8) \
|
||||||
|
| (((uint32_t) *((uint8_t *)(B)+2)) << 16) \
|
||||||
|
| (((uint32_t) *((uint8_t *)(B)+3)) << 24))
|
||||||
|
|
||||||
|
#define DSET32(B,D) \
|
||||||
|
(((*((uint8_t *)(B)+0)) = (uint8_t)((uint32_t)(D) >> 0)), \
|
||||||
|
((*((uint8_t *)(B)+1)) = (uint8_t)((uint32_t)(D) >> 8)), \
|
||||||
|
((*((uint8_t *)(B)+2)) = (uint8_t)((uint32_t)(D) >> 16)), \
|
||||||
|
((*((uint8_t *)(B)+3)) = (uint8_t)((uint32_t)(D) >> 24)))
|
||||||
|
|
||||||
|
struct nvme_tcp_qpair;
|
||||||
|
struct nvme_tcp_req;
|
||||||
|
typedef void (*nvme_tcp_qpair_xfer_complete_cb)(void *cb_arg);
|
||||||
|
|
||||||
|
struct nvme_tcp_pdu {
|
||||||
|
union {
|
||||||
|
/* to hold error pdu data */
|
||||||
|
uint8_t raw[SPDK_NVME_TCP_TERM_REQ_PDU_MAX_SIZE];
|
||||||
|
struct spdk_nvme_tcp_common_pdu_hdr common;
|
||||||
|
struct spdk_nvme_tcp_ic_req ic_req;
|
||||||
|
struct spdk_nvme_tcp_term_req_hdr term_req;
|
||||||
|
struct spdk_nvme_tcp_cmd capsule_cmd;
|
||||||
|
struct spdk_nvme_tcp_h2c_data_hdr h2c_data;
|
||||||
|
struct spdk_nvme_tcp_ic_resp ic_resp;
|
||||||
|
struct spdk_nvme_tcp_rsp capsule_resp;
|
||||||
|
struct spdk_nvme_tcp_c2h_data_hdr c2h_data;
|
||||||
|
struct spdk_nvme_tcp_r2t_hdr r2t;
|
||||||
|
|
||||||
|
} hdr;
|
||||||
|
|
||||||
|
bool has_hdgst;
|
||||||
|
uint8_t data_digest[SPDK_NVME_TCP_DIGEST_LEN];
|
||||||
|
int32_t padding_valid_bytes;
|
||||||
|
uint32_t ddigest_valid_bytes;
|
||||||
|
|
||||||
|
uint32_t ch_valid_bytes;
|
||||||
|
uint32_t psh_valid_bytes;
|
||||||
|
bool hd_is_read;
|
||||||
|
uint32_t data_valid_bytes;
|
||||||
|
|
||||||
|
nvme_tcp_qpair_xfer_complete_cb cb_fn;
|
||||||
|
void *cb_arg;
|
||||||
|
int ref;
|
||||||
|
void *data;
|
||||||
|
uint32_t data_len;
|
||||||
|
struct nvme_tcp_qpair *tqpair;
|
||||||
|
|
||||||
|
struct nvme_tcp_req *tcp_req; /* data tied to a tcp request */
|
||||||
|
uint32_t writev_offset;
|
||||||
|
TAILQ_ENTRY(nvme_tcp_pdu) tailq;
|
||||||
|
uint32_t remaining;
|
||||||
|
uint32_t padding_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum nvme_tcp_pdu_recv_state {
|
||||||
|
/* Ready to wait to wait PDU */
|
||||||
|
NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_READY,
|
||||||
|
|
||||||
|
/* Active tqpair waiting for any PDU common header */
|
||||||
|
NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_CH,
|
||||||
|
|
||||||
|
/* Active tqpair waiting for any PDU specific header */
|
||||||
|
NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_PSH,
|
||||||
|
|
||||||
|
/* Active tqpair waiting for payload */
|
||||||
|
NVME_TCP_PDU_RECV_STATE_AWAIT_PDU_PAYLOAD,
|
||||||
|
|
||||||
|
/* Active tqpair does not wait for payload */
|
||||||
|
NVME_TCP_PDU_RECV_STATE_ERROR,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum nvme_tcp_error_codes {
|
||||||
|
NVME_TCP_PDU_IN_PROGRESS = 0,
|
||||||
|
NVME_TCP_CONNECTION_FATAL = -1,
|
||||||
|
NVME_TCP_PDU_FATAL = -2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum nvme_tcp_qpair_state {
|
||||||
|
NVME_TCP_QPAIR_STATE_INVALID = 0,
|
||||||
|
NVME_TCP_QPAIR_STATE_RUNNING = 1,
|
||||||
|
NVME_TCP_QPAIR_STATE_EXITING = 2,
|
||||||
|
NVME_TCP_QPAIR_STATE_EXITED = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
nvme_tcp_pdu_calc_header_digest(struct nvme_tcp_pdu *pdu)
|
||||||
|
{
|
||||||
|
uint32_t crc32c;
|
||||||
|
uint32_t hlen = pdu->hdr.common.hlen;
|
||||||
|
|
||||||
|
crc32c = spdk_crc32c_update(&pdu->hdr.raw, hlen, ~0);
|
||||||
|
crc32c = crc32c ^ SPDK_CRC32C_XOR;
|
||||||
|
return crc32c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
nvme_tcp_pdu_calc_data_digest(struct nvme_tcp_pdu *pdu)
|
||||||
|
{
|
||||||
|
uint32_t crc32c;
|
||||||
|
uint32_t mod;
|
||||||
|
|
||||||
|
assert(pdu->data != NULL);
|
||||||
|
assert(pdu->data_len != 0);
|
||||||
|
|
||||||
|
crc32c = spdk_crc32c_update(pdu->data, pdu->data_len, ~0);
|
||||||
|
|
||||||
|
mod = pdu->data_len % SPDK_NVME_TCP_DIGEST_ALIGNMENT;
|
||||||
|
if (mod != 0) {
|
||||||
|
uint32_t pad_length = SPDK_NVME_TCP_DIGEST_ALIGNMENT - mod;
|
||||||
|
uint8_t pad[3] = {0, 0, 0};
|
||||||
|
|
||||||
|
assert(pad_length > 0);
|
||||||
|
assert(pad_length <= sizeof(pad));
|
||||||
|
crc32c = spdk_crc32c_update(pad, pad_length, crc32c);
|
||||||
|
}
|
||||||
|
|
||||||
|
crc32c = crc32c ^ SPDK_CRC32C_XOR;
|
||||||
|
return crc32c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
nvme_tcp_build_iovecs(struct iovec *iovec, struct nvme_tcp_pdu *pdu,
|
||||||
|
bool hdgst_enable, bool ddgst_enable)
|
||||||
|
{
|
||||||
|
|
||||||
|
int iovec_cnt = 0;
|
||||||
|
int enable_digest;
|
||||||
|
int hlen;
|
||||||
|
uint32_t plen;
|
||||||
|
|
||||||
|
hlen = pdu->hdr.common.hlen;
|
||||||
|
enable_digest = 1;
|
||||||
|
if (pdu->hdr.common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_IC_REQ ||
|
||||||
|
pdu->hdr.common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_IC_RESP ||
|
||||||
|
pdu->hdr.common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_H2C_TERM_REQ ||
|
||||||
|
pdu->hdr.common.pdu_type == SPDK_NVME_TCP_PDU_TYPE_C2H_TERM_REQ) {
|
||||||
|
/* this PDU should be sent without digest */
|
||||||
|
enable_digest = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header Digest */
|
||||||
|
if (enable_digest && hdgst_enable) {
|
||||||
|
hlen += SPDK_NVME_TCP_DIGEST_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PDU header + possible header digest */
|
||||||
|
iovec[iovec_cnt].iov_base = &pdu->hdr.raw;
|
||||||
|
iovec[iovec_cnt].iov_len = hlen;
|
||||||
|
plen = iovec[iovec_cnt].iov_len;
|
||||||
|
iovec_cnt++;
|
||||||
|
|
||||||
|
if (!pdu->data_len || !pdu->data) {
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Padding */
|
||||||
|
if (pdu->padding_len > 0) {
|
||||||
|
iovec[iovec_cnt - 1].iov_len += pdu->padding_len;
|
||||||
|
plen = iovec[iovec_cnt - 1].iov_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Data Segment */
|
||||||
|
iovec[iovec_cnt].iov_base = pdu->data;
|
||||||
|
iovec[iovec_cnt].iov_len = pdu->data_len;
|
||||||
|
plen += iovec[iovec_cnt].iov_len;
|
||||||
|
iovec_cnt++;
|
||||||
|
|
||||||
|
/* Data Digest */
|
||||||
|
if (enable_digest && ddgst_enable) {
|
||||||
|
iovec[iovec_cnt].iov_base = pdu->data_digest;
|
||||||
|
iovec[iovec_cnt].iov_len = SPDK_NVME_TCP_DIGEST_LEN;
|
||||||
|
plen += iovec[iovec_cnt].iov_len;
|
||||||
|
iovec_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
assert(plen == pdu->hdr.common.plen);
|
||||||
|
return iovec_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
nvme_tcp_read_data(struct spdk_sock *sock, int bytes,
|
||||||
|
void *buf)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
assert(sock != NULL);
|
||||||
|
if (bytes == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = spdk_sock_recv(sock, buf, bytes);
|
||||||
|
|
||||||
|
if (ret > 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For connect reset issue, do not output error log */
|
||||||
|
if (errno == ECONNRESET) {
|
||||||
|
SPDK_DEBUGLOG(SPDK_LOG_NVME, "spdk_sock_recv() failed, errno %d: %s\n",
|
||||||
|
errno, spdk_strerror(errno));
|
||||||
|
} else {
|
||||||
|
SPDK_ERRLOG("spdk_sock_recv() failed, errno %d: %s\n",
|
||||||
|
errno, spdk_strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NVME_TCP_CONNECTION_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SPDK_INTERNAL_NVME_TCP_H */
|
@ -35,7 +35,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
|
|||||||
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
||||||
|
|
||||||
C_SRCS = nvme_ctrlr_cmd.c nvme_ctrlr.c nvme_fabric.c nvme_ns_cmd.c nvme_ns.c nvme_pcie.c nvme_qpair.c nvme.c nvme_quirks.c nvme_transport.c nvme_uevent.c nvme_ctrlr_ocssd_cmd.c \
|
C_SRCS = nvme_ctrlr_cmd.c nvme_ctrlr.c nvme_fabric.c nvme_ns_cmd.c nvme_ns.c nvme_pcie.c nvme_qpair.c nvme.c nvme_quirks.c nvme_transport.c nvme_uevent.c nvme_ctrlr_ocssd_cmd.c \
|
||||||
nvme_ns_ocssd_cmd.c
|
nvme_ns_ocssd_cmd.c nvme_tcp.c
|
||||||
C_SRCS-$(CONFIG_RDMA) += nvme_rdma.c
|
C_SRCS-$(CONFIG_RDMA) += nvme_rdma.c
|
||||||
LIBNAME = nvme
|
LIBNAME = nvme
|
||||||
LOCAL_SYS_LIBS = -luuid
|
LOCAL_SYS_LIBS = -luuid
|
||||||
|
@ -659,6 +659,8 @@ spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const
|
|||||||
*trtype = SPDK_NVME_TRANSPORT_RDMA;
|
*trtype = SPDK_NVME_TRANSPORT_RDMA;
|
||||||
} else if (strcasecmp(str, "FC") == 0) {
|
} else if (strcasecmp(str, "FC") == 0) {
|
||||||
*trtype = SPDK_NVME_TRANSPORT_FC;
|
*trtype = SPDK_NVME_TRANSPORT_FC;
|
||||||
|
} else if (strcasecmp(str, "TCP") == 0) {
|
||||||
|
*trtype = SPDK_NVME_TRANSPORT_TCP;
|
||||||
} else {
|
} else {
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
@ -675,6 +677,8 @@ spdk_nvme_transport_id_trtype_str(enum spdk_nvme_transport_type trtype)
|
|||||||
return "RDMA";
|
return "RDMA";
|
||||||
case SPDK_NVME_TRANSPORT_FC:
|
case SPDK_NVME_TRANSPORT_FC:
|
||||||
return "FC";
|
return "FC";
|
||||||
|
case SPDK_NVME_TRANSPORT_TCP:
|
||||||
|
return "TCP";
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -978,6 +978,7 @@ struct spdk_nvme_ctrlr *spdk_nvme_get_ctrlr_by_trid_unsafe(
|
|||||||
|
|
||||||
DECLARE_TRANSPORT(transport) /* generic transport dispatch functions */
|
DECLARE_TRANSPORT(transport) /* generic transport dispatch functions */
|
||||||
DECLARE_TRANSPORT(pcie)
|
DECLARE_TRANSPORT(pcie)
|
||||||
|
DECLARE_TRANSPORT(tcp)
|
||||||
#ifdef SPDK_CONFIG_RDMA
|
#ifdef SPDK_CONFIG_RDMA
|
||||||
DECLARE_TRANSPORT(rdma)
|
DECLARE_TRANSPORT(rdma)
|
||||||
#endif
|
#endif
|
||||||
|
1812
lib/nvme/nvme_tcp.c
Normal file
1812
lib/nvme/nvme_tcp.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -50,6 +50,9 @@ nvme_transport_unknown(enum spdk_nvme_transport_type trtype)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TRANSPORT_PCIE(func_name, args) case SPDK_NVME_TRANSPORT_PCIE: return nvme_pcie_ ## func_name args;
|
#define TRANSPORT_PCIE(func_name, args) case SPDK_NVME_TRANSPORT_PCIE: return nvme_pcie_ ## func_name args;
|
||||||
|
|
||||||
|
#define TRANSPORT_FABRICS_TCP(func_name, args) case SPDK_NVME_TRANSPORT_TCP: return nvme_tcp_ ## func_name args;
|
||||||
|
|
||||||
#ifdef SPDK_CONFIG_RDMA
|
#ifdef SPDK_CONFIG_RDMA
|
||||||
#define TRANSPORT_FABRICS_RDMA(func_name, args) case SPDK_NVME_TRANSPORT_RDMA: return nvme_rdma_ ## func_name args;
|
#define TRANSPORT_FABRICS_RDMA(func_name, args) case SPDK_NVME_TRANSPORT_RDMA: return nvme_rdma_ ## func_name args;
|
||||||
#define TRANSPORT_RDMA_AVAILABLE true
|
#define TRANSPORT_RDMA_AVAILABLE true
|
||||||
@ -58,12 +61,14 @@ nvme_transport_unknown(enum spdk_nvme_transport_type trtype)
|
|||||||
#define TRANSPORT_RDMA_AVAILABLE false
|
#define TRANSPORT_RDMA_AVAILABLE false
|
||||||
#endif
|
#endif
|
||||||
#define TRANSPORT_FABRICS_FC(func_name, args) case SPDK_NVME_TRANSPORT_FC: SPDK_UNREACHABLE();
|
#define TRANSPORT_FABRICS_FC(func_name, args) case SPDK_NVME_TRANSPORT_FC: SPDK_UNREACHABLE();
|
||||||
|
|
||||||
#define NVME_TRANSPORT_CALL(trtype, func_name, args) \
|
#define NVME_TRANSPORT_CALL(trtype, func_name, args) \
|
||||||
do { \
|
do { \
|
||||||
switch (trtype) { \
|
switch (trtype) { \
|
||||||
TRANSPORT_PCIE(func_name, args) \
|
TRANSPORT_PCIE(func_name, args) \
|
||||||
TRANSPORT_FABRICS_RDMA(func_name, args) \
|
TRANSPORT_FABRICS_RDMA(func_name, args) \
|
||||||
TRANSPORT_FABRICS_FC(func_name, args) \
|
TRANSPORT_FABRICS_FC(func_name, args) \
|
||||||
|
TRANSPORT_FABRICS_TCP(func_name, args) \
|
||||||
TRANSPORT_DEFAULT(trtype) \
|
TRANSPORT_DEFAULT(trtype) \
|
||||||
} \
|
} \
|
||||||
SPDK_UNREACHABLE(); \
|
SPDK_UNREACHABLE(); \
|
||||||
@ -74,6 +79,7 @@ spdk_nvme_transport_available(enum spdk_nvme_transport_type trtype)
|
|||||||
{
|
{
|
||||||
switch (trtype) {
|
switch (trtype) {
|
||||||
case SPDK_NVME_TRANSPORT_PCIE:
|
case SPDK_NVME_TRANSPORT_PCIE:
|
||||||
|
case SPDK_NVME_TRANSPORT_TCP:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case SPDK_NVME_TRANSPORT_RDMA:
|
case SPDK_NVME_TRANSPORT_RDMA:
|
||||||
|
@ -36,7 +36,7 @@ include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
|||||||
|
|
||||||
C_SRCS = ctrlr.c ctrlr_discovery.c ctrlr_bdev.c \
|
C_SRCS = ctrlr.c ctrlr_discovery.c ctrlr_bdev.c \
|
||||||
subsystem.c nvmf.c \
|
subsystem.c nvmf.c \
|
||||||
request.c transport.c
|
request.c transport.c tcp.c
|
||||||
|
|
||||||
C_SRCS-$(CONFIG_RDMA) += rdma.c
|
C_SRCS-$(CONFIG_RDMA) += rdma.c
|
||||||
LIBNAME = nvmf
|
LIBNAME = nvmf
|
||||||
|
@ -404,6 +404,12 @@ spdk_nvmf_ctrlr_connect(struct spdk_nvmf_request *req)
|
|||||||
qpair->sq_head_max = cmd->sqsize;
|
qpair->sq_head_max = cmd->sqsize;
|
||||||
qpair->qid = cmd->qid;
|
qpair->qid = cmd->qid;
|
||||||
|
|
||||||
|
if (spdk_nvmf_transport_qpair_set_sqsize(qpair)) {
|
||||||
|
SPDK_ERRLOG("Can not create SQSIZE %u for qpair=%p\n", cmd->sqsize, qpair);
|
||||||
|
rsp->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
|
||||||
|
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd->qid == 0) {
|
if (cmd->qid == 0) {
|
||||||
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Connect Admin Queue for controller ID 0x%x\n", data->cntlid);
|
SPDK_DEBUGLOG(SPDK_LOG_NVMF, "Connect Admin Queue for controller ID 0x%x\n", data->cntlid);
|
||||||
|
|
||||||
|
2864
lib/nvmf/tcp.c
Normal file
2864
lib/nvmf/tcp.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -46,6 +46,7 @@ static const struct spdk_nvmf_transport_ops *const g_transport_ops[] = {
|
|||||||
#ifdef SPDK_CONFIG_RDMA
|
#ifdef SPDK_CONFIG_RDMA
|
||||||
&spdk_nvmf_transport_rdma,
|
&spdk_nvmf_transport_rdma,
|
||||||
#endif
|
#endif
|
||||||
|
&spdk_nvmf_transport_tcp,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUM_TRANSPORTS (SPDK_COUNTOF(g_transport_ops))
|
#define NUM_TRANSPORTS (SPDK_COUNTOF(g_transport_ops))
|
||||||
@ -258,3 +259,13 @@ spdk_nvmf_transport_opts_init(enum spdk_nvme_transport_type type,
|
|||||||
ops->opts_init(opts);
|
ops->opts_init(opts);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
spdk_nvmf_transport_qpair_set_sqsize(struct spdk_nvmf_qpair *qpair)
|
||||||
|
{
|
||||||
|
if (qpair->transport->ops->qpair_set_sqsize) {
|
||||||
|
return qpair->transport->ops->qpair_set_sqsize(qpair);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -153,6 +153,11 @@ struct spdk_nvmf_transport_ops {
|
|||||||
*/
|
*/
|
||||||
int (*qpair_get_listen_trid)(struct spdk_nvmf_qpair *qpair,
|
int (*qpair_get_listen_trid)(struct spdk_nvmf_qpair *qpair,
|
||||||
struct spdk_nvme_transport_id *trid);
|
struct spdk_nvme_transport_id *trid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set the submission queue size of the queue pair
|
||||||
|
*/
|
||||||
|
int (*qpair_set_sqsize)(struct spdk_nvmf_qpair *qpair);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -191,10 +196,12 @@ int spdk_nvmf_transport_qpair_get_local_trid(struct spdk_nvmf_qpair *qpair,
|
|||||||
|
|
||||||
int spdk_nvmf_transport_qpair_get_listen_trid(struct spdk_nvmf_qpair *qpair,
|
int spdk_nvmf_transport_qpair_get_listen_trid(struct spdk_nvmf_qpair *qpair,
|
||||||
struct spdk_nvme_transport_id *trid);
|
struct spdk_nvme_transport_id *trid);
|
||||||
|
int spdk_nvmf_transport_qpair_set_sqsize(struct spdk_nvmf_qpair *qpair);
|
||||||
|
|
||||||
bool spdk_nvmf_transport_opts_init(enum spdk_nvme_transport_type type,
|
bool spdk_nvmf_transport_opts_init(enum spdk_nvme_transport_type type,
|
||||||
struct spdk_nvmf_transport_opts *opts);
|
struct spdk_nvmf_transport_opts *opts);
|
||||||
|
|
||||||
extern const struct spdk_nvmf_transport_ops spdk_nvmf_transport_rdma;
|
extern const struct spdk_nvmf_transport_ops spdk_nvmf_transport_rdma;
|
||||||
|
extern const struct spdk_nvmf_transport_ops spdk_nvmf_transport_tcp;
|
||||||
|
|
||||||
#endif /* SPDK_NVMF_TRANSPORT_H */
|
#endif /* SPDK_NVMF_TRANSPORT_H */
|
||||||
|
@ -54,7 +54,7 @@ CXXFLAGS += -fno-sanitize=address
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
SPDK_LIB_LIST = event_bdev event_copy
|
SPDK_LIB_LIST = event_bdev event_copy
|
||||||
SPDK_LIB_LIST += bdev copy event util conf trace log jsonrpc json rpc thread
|
SPDK_LIB_LIST += bdev copy event util conf trace log jsonrpc json rpc sock thread
|
||||||
|
|
||||||
AM_LINK += $(COPY_MODULES_LINKER_ARGS) $(BLOCKDEV_MODULES_LINKER_ARGS)
|
AM_LINK += $(COPY_MODULES_LINKER_ARGS) $(BLOCKDEV_MODULES_LINKER_ARGS)
|
||||||
AM_LINK += $(SPDK_LIB_LINKER_ARGS) $(ENV_LINKER_ARGS)
|
AM_LINK += $(SPDK_LIB_LINKER_ARGS) $(ENV_LINKER_ARGS)
|
||||||
|
@ -39,7 +39,7 @@ include $(SPDK_ROOT_DIR)/mk/spdk.modules.mk
|
|||||||
|
|
||||||
C_SRCS = $(APP:%=%.c)
|
C_SRCS = $(APP:%=%.c)
|
||||||
|
|
||||||
SPDK_LIB_LIST = nvme thread util log
|
SPDK_LIB_LIST = nvme thread util log sock
|
||||||
|
|
||||||
LIBS += $(SOCK_MODULES_LINKER_ARGS)
|
LIBS += $(SOCK_MODULES_LINKER_ARGS)
|
||||||
LIBS += $(SPDK_LIB_LINKER_ARGS) $(ENV_LINKER_ARGS)
|
LIBS += $(SPDK_LIB_LINKER_ARGS) $(ENV_LINKER_ARGS)
|
||||||
|
@ -40,7 +40,7 @@ APP = stub
|
|||||||
|
|
||||||
C_SRCS := stub.c
|
C_SRCS := stub.c
|
||||||
|
|
||||||
SPDK_LIB_LIST = event conf nvme log trace rpc jsonrpc json thread util
|
SPDK_LIB_LIST = event conf nvme log trace rpc jsonrpc json thread util sock
|
||||||
|
|
||||||
LIBS += $(SOCK_MODULES_LINKER_ARGS)
|
LIBS += $(SOCK_MODULES_LINKER_ARGS)
|
||||||
LIBS += $(SPDK_LIB_LINKER_ARGS)
|
LIBS += $(SPDK_LIB_LINKER_ARGS)
|
||||||
|
@ -42,7 +42,7 @@ C_SRCS := fuse.c
|
|||||||
|
|
||||||
SPDK_LIB_LIST = event_bdev event_copy
|
SPDK_LIB_LIST = event_bdev event_copy
|
||||||
SPDK_LIB_LIST += bdev copy event thread util conf trace \
|
SPDK_LIB_LIST += bdev copy event thread util conf trace \
|
||||||
log jsonrpc json rpc
|
log jsonrpc json rpc sock
|
||||||
|
|
||||||
LIBS += $(COPY_MODULES_LINKER_ARGS) $(BLOCKDEV_MODULES_LINKER_ARGS)
|
LIBS += $(COPY_MODULES_LINKER_ARGS) $(BLOCKDEV_MODULES_LINKER_ARGS)
|
||||||
LIBS += $(SPDK_LIB_LINKER_ARGS) $(ENV_LINKER_ARGS)
|
LIBS += $(SPDK_LIB_LINKER_ARGS) $(ENV_LINKER_ARGS)
|
||||||
|
@ -42,7 +42,7 @@ C_SRCS := mkfs.c
|
|||||||
|
|
||||||
SPDK_LIB_LIST = event_bdev event_copy
|
SPDK_LIB_LIST = event_bdev event_copy
|
||||||
SPDK_LIB_LIST += bdev copy event thread util conf trace \
|
SPDK_LIB_LIST += bdev copy event thread util conf trace \
|
||||||
log jsonrpc json rpc
|
log jsonrpc json rpc sock
|
||||||
|
|
||||||
LIBS += $(COPY_MODULES_LINKER_ARGS) $(BLOCKDEV_MODULES_LINKER_ARGS) $(SOCK_MODULES_LINKER_ARGS)
|
LIBS += $(COPY_MODULES_LINKER_ARGS) $(BLOCKDEV_MODULES_LINKER_ARGS) $(SOCK_MODULES_LINKER_ARGS)
|
||||||
LIBS += $(SPDK_LIB_LINKER_ARGS) $(ENV_LINKER_ARGS)
|
LIBS += $(SPDK_LIB_LINKER_ARGS) $(ENV_LINKER_ARGS)
|
||||||
|
@ -38,7 +38,7 @@ include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
|||||||
APP = event_perf
|
APP = event_perf
|
||||||
C_SRCS := event_perf.c
|
C_SRCS := event_perf.c
|
||||||
|
|
||||||
SPDK_LIB_LIST = event trace conf thread util log rpc jsonrpc json
|
SPDK_LIB_LIST = event trace conf thread util log rpc jsonrpc json sock
|
||||||
|
|
||||||
LIBS += $(SPDK_LIB_LINKER_ARGS) $(ENV_LINKER_ARGS)
|
LIBS += $(SPDK_LIB_LINKER_ARGS) $(ENV_LINKER_ARGS)
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
|||||||
APP = reactor
|
APP = reactor
|
||||||
C_SRCS := reactor.c
|
C_SRCS := reactor.c
|
||||||
|
|
||||||
SPDK_LIB_LIST = event trace conf thread util log rpc jsonrpc json
|
SPDK_LIB_LIST = event trace conf thread util log rpc jsonrpc json sock
|
||||||
|
|
||||||
LIBS += $(SPDK_LIB_LINKER_ARGS) $(ENV_LINKER_ARGS)
|
LIBS += $(SPDK_LIB_LINKER_ARGS) $(ENV_LINKER_ARGS)
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ include $(SPDK_ROOT_DIR)/mk/spdk.common.mk
|
|||||||
APP = reactor_perf
|
APP = reactor_perf
|
||||||
C_SRCS := reactor_perf.c
|
C_SRCS := reactor_perf.c
|
||||||
|
|
||||||
SPDK_LIB_LIST = event trace conf thread util log rpc jsonrpc json
|
SPDK_LIB_LIST = event trace conf thread util log rpc jsonrpc json sock
|
||||||
|
|
||||||
LIBS += $(SPDK_LIB_LINKER_ARGS) $(ENV_LINKER_ARGS)
|
LIBS += $(SPDK_LIB_LINKER_ARGS) $(ENV_LINKER_ARGS)
|
||||||
|
|
||||||
|
@ -138,6 +138,11 @@ DEFINE_STUB(spdk_nvmf_subsystem_listener_allowed,
|
|||||||
(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvme_transport_id *trid),
|
(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvme_transport_id *trid),
|
||||||
true);
|
true);
|
||||||
|
|
||||||
|
DEFINE_STUB(spdk_nvmf_transport_qpair_set_sqsize,
|
||||||
|
int,
|
||||||
|
(struct spdk_nvmf_qpair *qpair),
|
||||||
|
0);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ctrlr_ut_pass_msg(spdk_thread_fn fn, void *ctx, void *thread_ctx)
|
ctrlr_ut_pass_msg(spdk_thread_fn fn, void *ctx, void *thread_ctx)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user