NVMe-oF Target: Add FC transport.

- New files and updates to existing SPDK files to add the NVMf-FC transport.
  - Depends on an existing low level driver library. This driver is not part of SPDK repository.
  - Makefile updates to build FC transport (using CONFIG_FC)
  - Update configure script for FC build.
  - New FC unit test for FC-LS commands.
  - Update unittest.sh to run FC unit test (when built).

Signed-off-by: John Barnard <john.barnard@broadcom.com>
Signed-off-by: Anil Veerabhadrappa <anil.veerabhadrappa@broadcom.com>
Change-Id: If31d4d25feab76c2dbe90a7faf71d465c2c3a354
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/450077
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Anil Veerabhadrappa 2019-04-22 18:28:02 +09:00 committed by Ben Walker
parent e10fc6ea00
commit ed56a3d482
24 changed files with 7944 additions and 234 deletions

View File

@ -22,6 +22,12 @@ and `spdk_dix_remap_ref_tag` have been added to remap DIF reference tag.
New APIs `spdk_dif_update_crc32c` and `spdk_dif_update_crc32c_stream` have been
added to compute CRC-32C checksum for extended LBA payload.
### NVME-oF Target (FC)
New Fibre Channel transport for NVMe over Fabrics target. Requires an FC HBA to use.
Also, requires a Fibre Channel HBA low level driver (lld) library. The driver library
and API header file path can be provided as an argument to "--with-fc".
### NVMe-oF Target
Persistent reservation emulation has been added to the NVMe-oF target. Persistent reservation

5
CONFIG
View File

@ -94,6 +94,11 @@ CONFIG_FIO_SOURCE_DIR=/usr/src/fio
CONFIG_RDMA=n
CONFIG_RDMA_SEND_WITH_INVAL=n
# Enable FC support for the NVMf target.
# Requires FC low level driver (from FC vendor)
CONFIG_FC=n
CONFIG_FC_PATH=
# Build Ceph RBD support in bdev modules
# Requires librbd development libraries
CONFIG_RBD=n

View File

@ -48,4 +48,11 @@ ifeq ($(OS),Linux)
SPDK_LIB_LIST += event_nbd nbd
endif
ifeq ($(CONFIG_FC),y)
ifneq ($(strip $(CONFIG_FC_PATH)),)
SYS_LIBS += -L$(CONFIG_FC_PATH)
endif
SYS_LIBS += -lufc
endif
include $(SPDK_ROOT_DIR)/mk/spdk.app.mk

View File

@ -58,6 +58,13 @@ ifeq ($(OS),Linux)
SPDK_LIB_LIST += event_nbd nbd
endif
ifeq ($(CONFIG_FC),y)
ifneq ($(strip $(CONFIG_FC_PATH)),)
SYS_LIBS += -L$(CONFIG_FC_PATH)
endif
SYS_LIBS += -lufc
endif
include $(SPDK_ROOT_DIR)/mk/spdk.app.mk
install: $(APP)

25
configure vendored
View File

@ -69,6 +69,10 @@ function usage()
echo " No path required."
echo " rdma Build RDMA transport for NVMf target and initiator."
echo " No path required."
echo " fc Build FC transport for NVMf target."
echo " If an argument is provided, it is considered a directory containing"
echo " libufc.a and fc_lld.h. Otherwise the regular system paths will"
echo " be searched."
echo " shared Build spdk shared libraries."
echo " No path required."
echo " iscsi-initiator Build with iscsi bdev module."
@ -218,6 +222,18 @@ for i in "$@"; do
--without-rdma)
CONFIG[RDMA]=n
;;
--with-fc=*)
CONFIG[FC]=y
CONFIG[FC_PATH]=$(readlink -f ${i#*=})
;;
--with-fc)
CONFIG[FC]=y
CONFIG[FC_PATH]=
;;
--without-fc)
CONFIG[FC]=n
CONFIG[FC_PATH]=
;;
--with-shared)
CONFIG[SHARED]=y
;;
@ -499,6 +515,15 @@ than or equal to 4.14 will see significantly reduced performance.
fi
fi
if [[ "${CONFIG[FC]}" = "y" ]]; then
if [[ -n "${CONFIG[FC_PATH]}" ]]; then
if [ ! -d "${CONFIG[FC_PATH]}" ]; then
echo "${CONFIG[FC_PATH]}: directory not found"
exit 1
fi
fi
fi
if [[ "${CONFIG[ISAL]}" = "y" ]] || [[ "${CONFIG[CRYPTO]}" = "y" ]]; then
ver=$(nasm -v | awk '{print $3}' | sed 's/[^0-9]*//g')
if [[ "${ver:0:1}" -le "2" ]] && [[ "${ver:0:3}" -le "213" ]] && [[ "${ver:0:5}" -lt "21303" ]]; then

View File

@ -125,6 +125,31 @@ Using .ini style configuration files for configuration of the NVMe-oF target is
be replaced with JSON based RPCs. .ini style configuration files can be converted to json format by way
of the new script `scripts/config_converter.py`.
## FC transport support {#nvmf_fc_transport}
To build nvmf_tgt with the FC transport, there is an additional FC LLD (Low Level Driver) code dependency.
Please contact your FC vendor for instructions to obtain FC driver module.
### Broadcom FC LLD code
FC LLD driver for Broadcom FC NVMe capable adapters can be obtained from,
https://github.com/ecdufcdrvr/bcmufctdrvr.
### Fetch FC LLD module and then build SPDK with FC enabled:
After cloning SPDK repo and initialize submodules, FC LLD library is built which then can be linked with
the fc transport.
~~~{.sh}
git clone https://github.com/spdk/spdk spdk
git clone https://github.com/ecdufcdrvr/bcmufctdrvr fc
cd spdk
git submodule update --init
cd ../fc
make DPDK_DIR=../spdk/dpdk/build SPDK_DIR=../spdk
cd ../spdk
./configure --with-fc=../fc/build
make
~~~
### Using RPCs {#nvmf_config_rpc}
Start the nvmf_tgt application with elevated privileges. Once the target is started,

View File

@ -146,6 +146,22 @@
# Set whether to use the C2H Success optimization, only used for TCP transport.
# C2HSuccess true
# Define FC transport
#[Transport]
# Set FC transport type.
#Type FC
# Set the maximum number of submission and completion queues per session.
# Setting this to '8', for example, allows for 8 submission and 8 completion queues
# per session.
#MaxQueuesPerSession 5
# Set the maximum number of outstanding I/O per queue.
#MaxQueueDepth 128
# Set the maximum I/O size. Must be a multiple of 4096.
#MaxIOSize 65536
[Nvme]
# NVMe Device Whitelist
# Users may specify which NVMe devices to claim by their transport id.

View File

@ -1,7 +1,7 @@
/*
* BSD LICENSE
*
* Copyright (c) 2018 Broadcom. All Rights Reserved.
* Copyright (c) 2018-2019 Broadcom. All Rights Reserved.
* The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
*
* Redistribution and use in source and binary forms, with or without
@ -400,4 +400,14 @@ struct spdk_nvmf_fc_ls_rjt {
};
SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_rjt) == 40, "size_mismatch");
/*
* FC World Wide Name
*/
struct spdk_nvmf_fc_wwn {
union {
uint64_t wwn; /* World Wide Names consist of eight bytes */
uint8_t octets[sizeof(uint64_t)];
} u;
};
#endif

View File

@ -59,4 +59,12 @@ endif
endif
endif
ifeq ($(CONFIG_FC),y)
C_SRCS += fc.c fc_ls.c
CFLAGS += -I$(CURDIR)
ifneq ($(strip $(CONFIG_FC_PATH)),)
CFLAGS += -I$(CONFIG_FC_PATH)
endif
endif
include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk

3986
lib/nvmf/fc.c Normal file

File diff suppressed because it is too large Load Diff

1681
lib/nvmf/fc_ls.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
* BSD LICENSE
*
* Copyright (c) 2018 Broadcom. All Rights Reserved.
* Copyright (c) 2018-2019 Broadcom. All Rights Reserved.
* The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
*
* Redistribution and use in source and binary forms, with or without
@ -34,6 +34,7 @@
#ifndef __NVMF_FC_H__
#define __NVMF_FC_H__
#include "spdk/nvme.h"
#include "spdk/nvmf.h"
#include "spdk/assert.h"
#include "spdk/nvme_spec.h"
@ -43,6 +44,16 @@
#include "nvmf_internal.h"
#define SPDK_NVMF_FC_TR_ADDR_LEN 64
#define NVMF_FC_INVALID_CONN_ID UINT64_MAX
#define SPDK_FC_HW_DUMP_REASON_STR_MAX_SIZE 256
#define SPDK_MAX_NUM_OF_FC_PORTS 32
#define SPDK_NVMF_PORT_ID_MAX_LEN 32
/*
* FC HWQP pointer
*/
typedef void *spdk_nvmf_fc_lld_hwqp_t;
/*
* FC HW port states.
@ -59,7 +70,7 @@ enum spdk_fc_hwqp_state {
};
/*
* NVMF BCM FC Object state
* NVMF FC Object state
* Add all the generic states of the object here.
* Specific object states can be added separately
*/
@ -86,25 +97,11 @@ enum spdk_nvmf_fc_request_state {
SPDK_NVMF_FC_REQ_SUCCESS,
SPDK_NVMF_FC_REQ_FAILED,
SPDK_NVMF_FC_REQ_ABORTED,
SPDK_NVMF_FC_REQ_BDEV_ABORTED,
SPDK_NVMF_FC_REQ_PENDING,
SPDK_NVMF_FC_REQ_MAX_STATE,
};
/*
* FC HWQP pointer
*/
typedef void *spdk_nvmf_fc_lld_hwqp_t;
/*
* FC World Wide Name
*/
struct spdk_nvmf_fc_wwn {
union {
uint64_t wwn; /* World Wide Names consist of eight bytes */
uint8_t octets[sizeof(uint64_t)];
} u;
};
/*
* Generic DMA buffer descriptor
*/
@ -142,7 +139,7 @@ struct spdk_nvmf_fc_abts_ctx {
* NVME FC transport errors
*/
struct spdk_nvmf_fc_errors {
uint32_t no_xri;
uint32_t no_xchg;
uint32_t nport_invalid;
uint32_t unknown_frame;
uint32_t wqe_cmplt_err;
@ -154,9 +151,7 @@ struct spdk_nvmf_fc_errors {
uint32_t invalid_cq_type;
uint32_t invalid_cq_id;
uint32_t fc_req_buf_err;
uint32_t aq_buf_alloc_err;
uint32_t write_buf_alloc_err;
uint32_t read_buf_alloc_err;
uint32_t buf_alloc_err;
uint32_t unexpected_err;
uint32_t nvme_cmd_iu_err;
uint32_t nvme_cmd_xfer_err;
@ -173,10 +168,11 @@ struct spdk_nvmf_fc_errors {
/*
* Send Single Request/Response Sequence.
*/
struct spdk_nvmf_fc_send_srsr {
struct spdk_nvmf_fc_buffer_desc rqst;
struct spdk_nvmf_fc_buffer_desc rsp;
struct spdk_nvmf_fc_buffer_desc sgl; /* Note: Len = (2 * bcm_sge_t) */
struct spdk_nvmf_fc_srsr_bufs {
void *rqst;
size_t rqst_len;
void *rsp;
size_t rsp_len;
uint16_t rpi;
};
@ -210,6 +206,7 @@ struct spdk_nvmf_fc_nport {
*/
struct spdk_nvmf_fc_conn {
struct spdk_nvmf_qpair qpair;
struct spdk_nvme_transport_id trid;
uint64_t conn_id;
struct spdk_nvmf_fc_hwqp *hwqp;
@ -229,12 +226,11 @@ struct spdk_nvmf_fc_conn {
/* number of read/write requests that are outstanding */
uint16_t cur_fc_rw_depth;
/* requests that are waiting to obtain xri/buffer */
/* requests that are waiting to obtain xchg/buffer */
TAILQ_HEAD(, spdk_nvmf_fc_request) pending_queue;
struct spdk_nvmf_fc_association *fc_assoc;
/* additional FC info here - TBD */
uint16_t rpi;
/* for association's connection list */
@ -245,67 +241,70 @@ struct spdk_nvmf_fc_conn {
/* for hwqp's connection list */
TAILQ_ENTRY(spdk_nvmf_fc_conn) link;
/* New QP create context. */
struct nvmf_fc_ls_op_ctx *create_opd;
};
/*
* Structure for maintaining the XRI's
* Structure for maintaining the FC exchanges
*/
struct spdk_nvmf_fc_xri {
uint32_t xri; /* The actual xri value */
struct spdk_nvmf_fc_xchg {
uint32_t xchg_id; /* The actual xchg identifier */
/* Internal */
TAILQ_ENTRY(spdk_nvmf_fc_xri) link;
bool is_active;
TAILQ_ENTRY(spdk_nvmf_fc_xchg) link;
bool active;
bool aborted;
bool send_abts; /* Valid if is_aborted is set. */
};
struct spdk_nvmf_fc_poll_group;
/*
* FC poll group structure
*/
struct spdk_nvmf_fc_poll_group {
struct spdk_nvmf_transport_poll_group tp_poll_group;
struct spdk_nvmf_poll_group *poll_group;
struct spdk_nvmf_tgt *nvmf_tgt;
struct spdk_nvmf_fc_transport *fc_transport;
uint32_t hwqp_count; /* number of hwqp's assigned to this pg */
TAILQ_HEAD(, spdk_nvmf_fc_hwqp) hwqp_list;
TAILQ_ENTRY(spdk_nvmf_fc_poll_group) link;
};
/*
* HWQP poller structure passed from Master thread
*/
struct spdk_nvmf_fc_hwqp {
enum spdk_fc_hwqp_state state; /* queue state (for poller) */
uint32_t lcore_id; /* core hwqp is running on (for tracing purposes only) */
struct spdk_thread *thread; /* thread hwqp is running on */
uint32_t hwqp_id; /* A unique id (per physical port) for a hwqp */
uint32_t rq_size; /* receive queue size */
spdk_nvmf_fc_lld_hwqp_t queues; /* vendor HW queue set */
spdk_nvmf_fc_lld_hwqp_t queues; /* vendor HW queue set */
struct spdk_nvmf_fc_port *fc_port; /* HW port structure for these queues */
struct spdk_nvmf_fc_poll_group *poll_group;
void *context; /* Vendor Context */
struct spdk_nvmf_fc_poll_group *fc_poll_group;
/* qpair (fc_connection) list */
TAILQ_HEAD(, spdk_nvmf_fc_conn) connection_list;
uint32_t num_conns; /* number of connections to queue */
uint16_t cid_cnt; /* used to generate unique conn. id for RQ */
uint32_t free_q_slots; /* free q slots available for connections */
enum spdk_fc_hwqp_state state; /* Poller state (e.g. online, offline) */
/* Internal */
struct spdk_mempool *fc_request_pool;
struct spdk_nvmf_fc_request *fc_reqs_buf;
TAILQ_HEAD(, spdk_nvmf_fc_request) free_reqs;
TAILQ_HEAD(, spdk_nvmf_fc_request) in_use_reqs;
TAILQ_HEAD(, spdk_nvmf_fc_xri) pending_xri_list;
struct spdk_nvmf_fc_errors counters;
uint32_t send_frame_xri;
uint8_t send_frame_seqid;
/* Pending LS request waiting for XRI. */
/* Pending LS request waiting for FC resource */
TAILQ_HEAD(, spdk_nvmf_fc_ls_rqst) ls_pending_queue;
/* Sync req list */
TAILQ_HEAD(, spdk_nvmf_fc_poller_api_queue_sync_args) sync_cbs;
TAILQ_ENTRY(spdk_nvmf_fc_hwqp) link;
};
struct spdk_nvmf_fc_ls_rsrc_pool {
void *assocs_mptr;
uint32_t assocs_count;
TAILQ_HEAD(, spdk_nvmf_fc_association) assoc_free_list;
void *conns_mptr;
uint32_t conns_count;
TAILQ_HEAD(, spdk_nvmf_fc_conn) fc_conn_free_list;
void *context; /* Vendor specific context data */
};
/*
@ -314,11 +313,10 @@ struct spdk_nvmf_fc_ls_rsrc_pool {
struct spdk_nvmf_fc_port {
uint8_t port_hdl;
enum spdk_fc_port_state hw_port_status;
uint32_t xri_base;
uint32_t xri_count;
uint16_t fcp_rq_id;
struct spdk_ring *xri_ring;
struct spdk_nvmf_fc_hwqp ls_queue;
new_qpair_fn new_qp_cb;
uint32_t num_io_queues;
struct spdk_nvmf_fc_hwqp *io_queues;
/*
@ -328,8 +326,7 @@ struct spdk_nvmf_fc_port {
int num_nports;
TAILQ_ENTRY(spdk_nvmf_fc_port) link;
struct spdk_nvmf_fc_ls_rsrc_pool ls_rsrc_pool;
struct spdk_mempool *io_rsrc_pool; /* Pools to store bdev_io's for this port */
struct spdk_mempool *io_resource_pool; /* Pools to store bdev_io's for this port */
void *port_ctx;
};
@ -342,7 +339,7 @@ struct spdk_nvmf_fc_request {
uint32_t poller_lcore; /* for tracing purposes only */
struct spdk_thread *poller_thread;
uint16_t buf_index;
struct spdk_nvmf_fc_xri *xri;
struct spdk_nvmf_fc_xchg *xchg;
uint16_t oxid;
uint16_t rpi;
struct spdk_nvmf_fc_conn *fc_conn;
@ -353,6 +350,8 @@ struct spdk_nvmf_fc_request {
uint32_t magic;
uint32_t s_id;
uint32_t d_id;
void *buffers[SPDK_NVMF_MAX_SGL_ENTRIES];
bool data_from_pool;
TAILQ_ENTRY(spdk_nvmf_fc_request) link;
TAILQ_ENTRY(spdk_nvmf_fc_request) pending_link;
TAILQ_HEAD(, spdk_nvmf_fc_caller_ctx) abort_cbs;
@ -361,6 +360,7 @@ struct spdk_nvmf_fc_request {
SPDK_STATIC_ASSERT(!offsetof(struct spdk_nvmf_fc_request, req),
"FC request and NVMF request address don't match.");
/*
* NVMF FC Association
*/
@ -370,7 +370,6 @@ struct spdk_nvmf_fc_association {
struct spdk_nvmf_fc_nport *tgtport;
struct spdk_nvmf_fc_remote_port_info *rport;
struct spdk_nvmf_subsystem *subsystem;
struct spdk_nvmf_host *host;
enum spdk_nvmf_fc_object_state assoc_state;
char host_id[FCNVME_ASSOC_HOSTID_LEN];
@ -392,8 +391,8 @@ struct spdk_nvmf_fc_association {
void *ls_del_op_ctx; /* delete assoc. callback list */
/* req/resp buffers used to send disconnect to initiator */
struct spdk_nvmf_fc_send_srsr snd_disconn_bufs;
/* disconnect cmd buffers (sent to initiator) */
struct spdk_nvmf_fc_srsr_bufs *snd_disconn_bufs;
};
/*
@ -430,10 +429,13 @@ enum spdk_nvmf_fc_poller_api {
SPDK_NVMF_FC_POLLER_API_QUIESCE_QUEUE,
SPDK_NVMF_FC_POLLER_API_ACTIVATE_QUEUE,
SPDK_NVMF_FC_POLLER_API_ABTS_RECEIVED,
SPDK_NVMF_FC_POLLER_API_REQ_ABORT_COMPLETE,
SPDK_NVMF_FC_POLLER_API_ADAPTER_EVENT,
SPDK_NVMF_FC_POLLER_API_AEN,
SPDK_NVMF_FC_POLLER_API_QUEUE_SYNC,
SPDK_NVMF_FC_POLLER_API_QUEUE_SYNC_DONE,
SPDK_NVMF_FC_POLLER_API_ADD_HWQP,
SPDK_NVMF_FC_POLLER_API_REMOVE_HWQP,
};
/*
@ -445,6 +447,7 @@ typedef void (*spdk_nvmf_fc_poller_api_cb)(void *cb_data, enum spdk_nvmf_fc_poll
* Poller API callback data
*/
struct spdk_nvmf_fc_poller_api_cb_info {
struct spdk_thread *cb_thread;
spdk_nvmf_fc_poller_api_cb cb_func;
void *cb_data;
enum spdk_nvmf_fc_poller_api_ret ret;
@ -465,6 +468,7 @@ struct spdk_nvmf_fc_poller_api_del_connection_args {
bool send_abts;
/* internal */
int fc_request_cnt;
bool backend_initiated;
};
struct spdk_nvmf_fc_poller_api_quiesce_queue_args {
@ -486,6 +490,7 @@ struct spdk_nvmf_fc_poller_api_abts_recvd_args {
struct spdk_nvmf_fc_poller_api_queue_sync_done_args {
struct spdk_nvmf_fc_hwqp *hwqp;
struct spdk_nvmf_fc_poller_api_cb_info cb_info;
uint64_t tag;
};
@ -498,7 +503,7 @@ struct spdk_nvmf_fc_ls_rqst {
uint32_t rqst_len;
uint32_t rsp_len;
uint32_t rpi;
struct spdk_nvmf_fc_xri *xri;
struct spdk_nvmf_fc_xchg *xchg;
uint16_t oxid;
void *private_data; /* for LLD only (LS does not touch) */
TAILQ_ENTRY(spdk_nvmf_fc_ls_rqst) ls_pending_link;
@ -525,6 +530,48 @@ struct __attribute__((__packed__)) spdk_nvmf_fc_rq_buf_ls_request {
SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_rq_buf_ls_request) ==
FCNVME_MAX_LS_BUFFER_SIZE, "LS RQ Buffer overflow");
/* Poller API structures (arguments and callback data */
typedef void (*spdk_nvmf_fc_del_assoc_cb)(void *arg, uint32_t err);
struct spdk_nvmf_fc_ls_add_conn_api_data {
struct spdk_nvmf_fc_poller_api_add_connection_args args;
struct spdk_nvmf_fc_ls_rqst *ls_rqst;
struct spdk_nvmf_fc_association *assoc;
bool aq_conn; /* true if adding connection for new association */
};
/* Disconnect (connection) request functions */
struct spdk_nvmf_fc_ls_del_conn_api_data {
struct spdk_nvmf_fc_poller_api_del_connection_args args;
struct spdk_nvmf_fc_ls_rqst *ls_rqst;
struct spdk_nvmf_fc_association *assoc;
bool aq_conn; /* true if deleting AQ connection */
};
/* used by LS disconnect association cmd handling */
struct spdk_nvmf_fc_ls_disconn_assoc_api_data {
struct spdk_nvmf_fc_nport *tgtport;
struct spdk_nvmf_fc_ls_rqst *ls_rqst;
};
/* used by delete association call */
struct spdk_nvmf_fc_delete_assoc_api_data {
struct spdk_nvmf_fc_poller_api_del_connection_args args;
struct spdk_nvmf_fc_association *assoc;
bool from_ls_rqst; /* true = request came for LS */
spdk_nvmf_fc_del_assoc_cb del_assoc_cb;
void *del_assoc_cb_data;
};
struct nvmf_fc_ls_op_ctx {
union {
struct spdk_nvmf_fc_ls_add_conn_api_data add_conn;
struct spdk_nvmf_fc_ls_del_conn_api_data del_conn;
struct spdk_nvmf_fc_ls_disconn_assoc_api_data disconn_assoc;
struct spdk_nvmf_fc_delete_assoc_api_data del_assoc;
} u;
struct nvmf_fc_ls_op_ctx *next_op_ctx;
};
struct spdk_nvmf_fc_poller_api_queue_sync_args {
uint64_t u_id;
@ -535,6 +582,185 @@ struct spdk_nvmf_fc_poller_api_queue_sync_args {
TAILQ_ENTRY(spdk_nvmf_fc_poller_api_queue_sync_args) link;
};
/**
* Following defines and structures are used to pass messages between master thread
* and FCT driver.
*/
enum spdk_fc_event {
SPDK_FC_HW_PORT_INIT,
SPDK_FC_HW_PORT_ONLINE,
SPDK_FC_HW_PORT_OFFLINE,
SPDK_FC_HW_PORT_RESET,
SPDK_FC_NPORT_CREATE,
SPDK_FC_NPORT_DELETE,
SPDK_FC_IT_ADD, /* PRLI */
SPDK_FC_IT_DELETE, /* PRLI */
SPDK_FC_ABTS_RECV,
SPDK_FC_LINK_BREAK,
SPDK_FC_HW_PORT_DUMP,
SPDK_FC_UNRECOVERABLE_ERR,
SPDK_FC_EVENT_MAX,
};
/**
* Arguments for to dump assoc id
*/
struct spdk_nvmf_fc_dump_assoc_id_args {
uint8_t pport_handle;
uint16_t nport_handle;
uint32_t assoc_id;
};
/**
* Arguments for HW port init event.
*/
struct spdk_nvmf_fc_hw_port_init_args {
uint32_t ls_queue_size;
spdk_nvmf_fc_lld_hwqp_t ls_queue;
uint32_t io_queue_size;
uint32_t io_queue_cnt;
spdk_nvmf_fc_lld_hwqp_t *io_queues;
void *cb_ctx;
void *port_ctx;
uint8_t port_handle;
uint8_t nvme_aq_index; /* io_queue used for nvme admin queue */
uint16_t fcp_rq_id; /* Base rq ID of SCSI queue */
};
/**
* Arguments for HW port link break event.
*/
struct spdk_nvmf_hw_port_link_break_args {
uint8_t port_handle;
void *cb_ctx;
};
/**
* Arguments for HW port online event.
*/
struct spdk_nvmf_fc_hw_port_online_args {
uint8_t port_handle;
void *cb_ctx;
};
/**
* Arguments for HW port offline event.
*/
struct spdk_nvmf_fc_hw_port_offline_args {
uint8_t port_handle;
void *cb_ctx;
};
/**
* Arguments for n-port add event.
*/
struct spdk_nvmf_fc_nport_create_args {
uint8_t port_handle;
uint16_t nport_handle;
struct spdk_uuid container_uuid; /* UUID of the nports container */
struct spdk_uuid nport_uuid; /* Unique UUID for the nport */
uint32_t d_id;
struct spdk_nvmf_fc_wwn fc_nodename;
struct spdk_nvmf_fc_wwn fc_portname;
uint32_t subsys_id; /* Subsystemid */
char port_id[SPDK_NVMF_PORT_ID_MAX_LEN];
void *cb_ctx;
};
/**
* Arguments for n-port delete event.
*/
struct spdk_nvmf_fc_nport_delete_args {
uint8_t port_handle;
uint32_t nport_handle;
uint32_t subsys_id; /* Subsystem id */
void *cb_ctx;
};
/**
* Arguments for I_T add event.
*/
struct spdk_nvmf_fc_hw_i_t_add_args {
uint8_t port_handle;
uint32_t nport_handle;
uint16_t itn_handle;
uint32_t rpi;
uint32_t s_id;
uint32_t initiator_prli_info;
uint32_t target_prli_info; /* populated by the SPDK master */
struct spdk_nvmf_fc_wwn fc_nodename;
struct spdk_nvmf_fc_wwn fc_portname;
void *cb_ctx;
};
/**
* Arguments for I_T delete event.
*/
struct spdk_nvmf_fc_hw_i_t_delete_args {
uint8_t port_handle;
uint32_t nport_handle;
uint16_t itn_handle; /* Only used by FC LLD driver; unused in SPDK */
uint32_t rpi;
uint32_t s_id;
void *cb_ctx;
};
/**
* Arguments for ABTS event.
*/
struct spdk_nvmf_fc_abts_args {
uint8_t port_handle;
uint32_t nport_handle;
uint32_t rpi;
uint16_t oxid, rxid;
void *cb_ctx;
};
/**
* Arguments for link break event.
*/
struct spdk_nvmf_fc_link_break_args {
uint8_t port_handle;
};
/**
* Arguments for port reset event.
*/
struct spdk_nvmf_fc_hw_port_reset_args {
uint8_t port_handle;
bool dump_queues;
char reason[SPDK_FC_HW_DUMP_REASON_STR_MAX_SIZE];
uint32_t **dump_buf;
void *cb_ctx;
};
/**
* Arguments for unrecoverable error event
*/
struct spdk_nvmf_fc_unrecoverable_error_event_args {
};
/**
* Callback function to the FCT driver.
*/
typedef void (*spdk_nvmf_fc_callback)(uint8_t port_handle,
enum spdk_fc_event event_type,
void *arg, int err);
/**
* Enqueue an FCT event to master thread
*
* \param event_type Type of the event.
* \param args Pointer to the argument structure.
* \param cb_func Callback function into fc driver.
*
* \return 0 on success, non-zero on failure.
*/
int
spdk_nvmf_fc_master_enqueue_event(enum spdk_fc_event event_type,
void *args,
spdk_nvmf_fc_callback cb_func);
/*
* dump info
*/
@ -578,79 +804,16 @@ struct spdk_nvmf_fc_caller_ctx {
};
/*
* Low level FC driver function table (functions provided by vendor FC device driver)
* NVMF FC Exchange Info (for debug)
*/
struct spdk_nvmf_fc_ll_drvr_ops {
/* initialize the low level driver */
int (*lld_init)(void);
/* low level driver finish */
void (*lld_fini)(void);
/* initialize hw queues */
int (*init_q)(struct spdk_nvmf_fc_hwqp *hwqp);
void (*reinit_q)(spdk_nvmf_fc_lld_hwqp_t queues_prev,
spdk_nvmf_fc_lld_hwqp_t queues_curr);
/* initialize hw queue buffers */
int (*init_q_buffers)(struct spdk_nvmf_fc_hwqp *hwqp);
/* poll the hw queues for requests */
uint32_t (*poll_queue)(struct spdk_nvmf_fc_hwqp *hwqp);
/* receive data (for data-in requests) */
int (*recv_data)(struct spdk_nvmf_fc_request *fc_req);
/* send data (for data-out requests) */
int (*send_data)(struct spdk_nvmf_fc_request *fc_req);
/* release hw queust buffer */
void (*q_buffer_release)(struct spdk_nvmf_fc_hwqp *hwqp, uint16_t buff_idx);
/* transmist nvme response */
int (*xmt_rsp)(struct spdk_nvmf_fc_request *fc_req, uint8_t *ersp_buf, uint32_t ersp_len);
/* transmist LS response */
int (*xmt_ls_rsp)(struct spdk_nvmf_fc_nport *tgtport, struct spdk_nvmf_fc_ls_rqst *ls_rqst);
/* issue abts */
int (*issue_abort)(struct spdk_nvmf_fc_hwqp *hwqp, struct spdk_nvmf_fc_xri *xri,
bool send_abts, spdk_nvmf_fc_caller_cb cb, void *cb_args);
/* transmit abts response */
int (*xmt_bls_rsp)(struct spdk_nvmf_fc_hwqp *hwqp, uint16_t ox_id, uint16_t rx_id, uint16_t rpi,
bool rjt, uint8_t rjt_exp, spdk_nvmf_fc_caller_cb cb, void *cb_args);
/* transmit single request - single response */
int (*xmt_srsr_req)(struct spdk_nvmf_fc_hwqp *hwqp, struct spdk_nvmf_fc_send_srsr *srsr,
spdk_nvmf_fc_caller_cb cb, void *cb_args);
/* issue queue marker (abts processing) */
int (*issue_q_marker)(struct spdk_nvmf_fc_hwqp *hwqp, uint64_t u_id, uint16_t skip_rq);
/* assign a new connection to a hwqp (return connection ID) */
struct spdk_nvmf_fc_hwqp *(*assign_conn_to_hwqp)(
struct spdk_nvmf_fc_hwqp *queues, uint32_t num_queues,
uint64_t *conn_id, uint32_t sq_size, bool for_aq);
/* get the hwqp from the given connection id */
struct spdk_nvmf_fc_hwqp *(*get_hwqp_from_conn_id)(struct spdk_nvmf_fc_hwqp *hwqp,
uint32_t num_queues, uint64_t conn_id);
/* release connection ID (done with using it) */
void (*release_conn)(struct spdk_nvmf_fc_hwqp *hwqp, uint64_t conn_id, uint32_t sq_size);
/* dump all queue info into dump_info */
void (*dump_all_queues)(struct spdk_nvmf_fc_hwqp *ls_queues,
struct spdk_nvmf_fc_hwqp *io_queues,
uint32_t num_queues,
struct spdk_nvmf_fc_queue_dump_info *dump_info);
struct spdk_nvmf_fc_xchg_info {
uint32_t xchg_base;
uint32_t xchg_total_count;
uint32_t xchg_avail_count;
uint32_t send_frame_xchg_id;
uint8_t send_frame_seqid;
};
extern struct spdk_nvmf_fc_ll_drvr_ops spdk_nvmf_fc_lld_ops;
/*
* NVMF FC inline and function prototypes
*/
@ -688,41 +851,39 @@ spdk_nvmf_fc_req_in_xfer(struct spdk_nvmf_fc_request *fc_req)
}
}
typedef void (*spdk_nvmf_fc_del_assoc_cb)(void *arg, uint32_t err);
int spdk_nvmf_fc_delete_association(struct spdk_nvmf_fc_nport *tgtport,
uint64_t assoc_id, bool send_abts,
spdk_nvmf_fc_del_assoc_cb del_assoc_cb,
void *cb_data);
static inline void
spdk_nvmf_fc_create_trid(struct spdk_nvme_transport_id *trid, uint64_t n_wwn, uint64_t p_wwn)
{
trid->trtype = (enum spdk_nvme_transport_type) SPDK_NVMF_TRTYPE_FC;
trid->adrfam = SPDK_NVMF_ADRFAM_FC;
snprintf(trid->trsvcid, sizeof(trid->trsvcid), "none");
snprintf(trid->traddr, sizeof(trid->traddr), "nn-0x%lx:pn-0x%lx", n_wwn, p_wwn);
}
void spdk_nvmf_fc_ls_init(struct spdk_nvmf_fc_port *fc_port);
void spdk_nvmf_fc_ls_fini(struct spdk_nvmf_fc_port *fc_port);
struct spdk_nvmf_fc_port *spdk_nvmf_fc_port_list_get(uint8_t port_hdl);
void spdk_nvmf_fc_handle_ls_rqst(struct spdk_nvmf_fc_ls_rqst *ls_rqst);
void nvmf_fc_ls_add_conn_failure(
struct spdk_nvmf_fc_association *assoc,
struct spdk_nvmf_fc_ls_rqst *ls_rqst,
struct spdk_nvmf_fc_conn *fc_conn,
bool aq_conn);
int spdk_nvmf_fc_nport_set_state(struct spdk_nvmf_fc_nport *nport,
enum spdk_nvmf_fc_object_state state);
int spdk_nvmf_fc_xmt_ls_rsp(struct spdk_nvmf_fc_nport *tgtport,
struct spdk_nvmf_fc_ls_rqst *ls_rqst);
int spdk_nvmf_fc_assoc_set_state(struct spdk_nvmf_fc_association *assoc,
enum spdk_nvmf_fc_object_state state);
bool spdk_nvmf_fc_nport_add_rem_port(struct spdk_nvmf_fc_nport *nport,
struct spdk_nvmf_fc_remote_port_info *rem_port);
bool spdk_nvmf_fc_nport_remove_rem_port(struct spdk_nvmf_fc_nport *nport,
struct spdk_nvmf_fc_remote_port_info *rem_port);
void spdk_nvmf_fc_init_hwqp(struct spdk_nvmf_fc_port *fc_port, struct spdk_nvmf_fc_hwqp *hwqp);
void spdk_nvmf_fc_init_poller_queues(struct spdk_nvmf_fc_hwqp *hwqp);
void spdk_nvmf_fc_reinit_poller_queues(struct spdk_nvmf_fc_hwqp *hwqp,
void *queues_curr);
struct spdk_nvmf_fc_conn *spdk_nvmf_fc_hwqp_find_fc_conn(struct spdk_nvmf_fc_hwqp *hwqp,
uint64_t conn_id);
void spdk_nvmf_fc_init_poller(struct spdk_nvmf_fc_port *fc_port,
struct spdk_nvmf_fc_hwqp *hwqp);
void spdk_nvmf_fc_hwqp_reinit_poller_queues(struct spdk_nvmf_fc_hwqp *hwqp, void *queues_curr);
void spdk_nvmf_fc_add_hwqp_to_poller(struct spdk_nvmf_fc_hwqp *hwqp, bool admin_q);
void spdk_nvmf_fc_remove_hwqp_from_poller(struct spdk_nvmf_fc_hwqp *hwqp);
struct spdk_nvmf_fc_port *spdk_nvmf_fc_port_lookup(uint8_t port_hdl);
bool spdk_nvmf_fc_port_is_offline(struct spdk_nvmf_fc_port *fc_port);
@ -732,81 +893,72 @@ bool spdk_nvmf_fc_port_is_online(struct spdk_nvmf_fc_port *fc_port);
int spdk_nvmf_fc_port_set_online(struct spdk_nvmf_fc_port *fc_port);
int spdk_nvmf_fc_hwqp_port_set_online(struct spdk_nvmf_fc_hwqp *hwqp);
int spdk_nvmf_fc_hwqp_port_set_offline(struct spdk_nvmf_fc_hwqp *hwqp);
int spdk_nvmf_fc_rport_set_state(struct spdk_nvmf_fc_remote_port_info *rport,
enum spdk_nvmf_fc_object_state state);
void spdk_nvmf_fc_port_list_add(struct spdk_nvmf_fc_port *fc_port);
struct spdk_nvmf_fc_nport *spdk_nvmf_fc_nport_get(uint8_t port_hdl, uint16_t nport_hdl);
void spdk_nvmf_fc_port_add(struct spdk_nvmf_fc_port *fc_port);
int spdk_nvmf_fc_port_add_nport(struct spdk_nvmf_fc_port *fc_port,
struct spdk_nvmf_fc_nport *nport);
uint32_t spdk_nvmf_fc_nport_get_association_count(struct spdk_nvmf_fc_nport *nport);
int spdk_nvmf_fc_port_remove_nport(struct spdk_nvmf_fc_port *fc_port,
struct spdk_nvmf_fc_nport *nport);
struct spdk_nvmf_fc_nport *spdk_nvmf_fc_nport_find(uint8_t port_hdl, uint16_t nport_hdl);
int spdk_nvmf_fc_nport_set_state(struct spdk_nvmf_fc_nport *nport,
enum spdk_nvmf_fc_object_state state);
bool spdk_nvmf_fc_nport_add_rem_port(struct spdk_nvmf_fc_nport *nport,
struct spdk_nvmf_fc_remote_port_info *rem_port);
bool spdk_nvmf_fc_nport_remove_rem_port(struct spdk_nvmf_fc_nport *nport,
struct spdk_nvmf_fc_remote_port_info *rem_port);
bool spdk_nvmf_fc_nport_has_no_rport(struct spdk_nvmf_fc_nport *nport);
int spdk_nvmf_fc_assoc_set_state(struct spdk_nvmf_fc_association *assoc,
enum spdk_nvmf_fc_object_state state);
int spdk_nvmf_fc_delete_association(struct spdk_nvmf_fc_nport *tgtport,
uint64_t assoc_id, bool send_abts, bool backend_initiated,
spdk_nvmf_fc_del_assoc_cb del_assoc_cb,
void *cb_data);
bool spdk_nvmf_ctrlr_is_on_nport(uint8_t port_hdl, uint16_t nport_hdl,
struct spdk_nvmf_ctrlr *ctrlr);
void spdk_nvmf_fc_assign_queue_to_master_thread(struct spdk_nvmf_fc_hwqp *hwqp);
void spdk_nvmf_fc_poll_group_add_hwqp(struct spdk_nvmf_fc_hwqp *hwqp);
void spdk_nvmf_fc_poll_group_remove_hwqp(struct spdk_nvmf_fc_hwqp *hwqp);
int spdk_nvmf_fc_hwqp_set_online(struct spdk_nvmf_fc_hwqp *hwqp);
int spdk_nvmf_fc_hwqp_set_offline(struct spdk_nvmf_fc_hwqp *hwqp);
uint32_t spdk_nvmf_fc_get_prli_service_params(void);
bool spdk_nvmf_fc_nport_is_rport_empty(struct spdk_nvmf_fc_nport *nport);
void spdk_nvmf_fc_handle_abts_frame(struct spdk_nvmf_fc_nport *nport,
uint16_t rpi, uint16_t oxid,
void spdk_nvmf_fc_handle_abts_frame(struct spdk_nvmf_fc_nport *nport, uint16_t rpi, uint16_t oxid,
uint16_t rxid);
void spdk_nvmf_fc_request_abort(struct spdk_nvmf_fc_request *fc_req, bool send_abts,
spdk_nvmf_fc_caller_cb cb, void *cb_args);
int spdk_nvmf_fc_xmt_srsr_req(struct spdk_nvmf_fc_hwqp *hwqp,
struct spdk_nvmf_fc_srsr_bufs *srsr_bufs,
spdk_nvmf_fc_caller_cb cb, void *cb_args);
struct spdk_nvmf_tgt *spdk_nvmf_fc_get_tgt(void);
void spdk_nvmf_fc_dump_all_queues(struct spdk_nvmf_fc_port *fc_port,
struct spdk_nvmf_fc_queue_dump_info *dump_info);
void spdk_nvmf_fc_handle_ls_rqst(struct spdk_nvmf_fc_ls_rqst *ls_rqst);
int spdk_nvmf_fc_xmt_ls_rsp(struct spdk_nvmf_fc_nport *tgtport,
struct spdk_nvmf_fc_ls_rqst *ls_rqst);
struct spdk_nvmf_fc_nport *spdk_nvmf_bcm_req_fc_nport_get(struct spdk_nvmf_request *req);
struct spdk_nvmf_fc_association *spdk_nvmf_fc_get_ctrlr_assoc(struct spdk_nvmf_ctrlr *ctrlr);
bool spdk_nvmf_fc_nport_is_association_empty(struct spdk_nvmf_fc_nport *nport);
int spdk_nvmf_fc_xmt_srsr_req(struct spdk_nvmf_fc_hwqp *hwqp,
struct spdk_nvmf_fc_send_srsr *srsr,
spdk_nvmf_fc_caller_cb cb, void *cb_args);
uint32_t spdk_nvmf_fc_get_num_nport_ctrlrs_in_subsystem(uint8_t port_hdl, uint16_t nport_hdl,
struct spdk_nvmf_subsystem *subsys);
bool spdk_nvmf_fc_is_spdk_ctrlr_on_nport(uint8_t port_hdl, uint16_t nport_hdl,
struct spdk_nvmf_ctrlr *ctrlr);
int spdk_nvmf_fc_get_ctrlr_init_traddr(char *traddr, struct spdk_nvmf_ctrlr *ctrlr);
uint32_t spdk_nvmf_fc_get_hwqp_id(struct spdk_nvmf_request *req);
void spdk_nvmf_fc_req_abort(struct spdk_nvmf_fc_request *fc_req,
bool send_abts, spdk_nvmf_fc_caller_cb cb,
void *cb_args);
int spdk_nvmf_fc_add_port_listen(void *arg1, void *arg2);
int spdk_nvmf_fc_remove_port_listen(void *arg1, void *arg2);
void spdk_nvmf_fc_subsys_connect_cb(void *cb_ctx,
struct spdk_nvmf_request *req);
void spdk_nvmf_fc_subsys_disconnect_cb(void *cb_ctx,
struct spdk_nvmf_qpair *qpair);
uint32_t spdk_nvmf_fc_get_master_lcore(void);
struct spdk_thread *spdk_nvmf_fc_get_master_thread(void);
/*
* These functions are used by low level FC driver
* These functions are called by low level FC driver
*/
static inline struct spdk_nvmf_fc_conn *
@ -841,31 +993,26 @@ enum spdk_nvmf_fc_poller_api_ret spdk_nvmf_fc_poller_api_func(
enum spdk_nvmf_fc_poller_api api,
void *api_args);
int spdk_nvmf_fc_process_frame(struct spdk_nvmf_fc_hwqp *hwqp, uint32_t buff_idx,
struct spdk_nvmf_fc_frame_hdr *frame,
struct spdk_nvmf_fc_buffer_desc *buffer, uint32_t plen);
int spdk_nvmf_fc_hwqp_process_frame(struct spdk_nvmf_fc_hwqp *hwqp, uint32_t buff_idx,
struct spdk_nvmf_fc_frame_hdr *frame,
struct spdk_nvmf_fc_buffer_desc *buffer, uint32_t plen);
void spdk_nvmf_fc_process_pending_req(struct spdk_nvmf_fc_hwqp *hwqp);
void spdk_nvmf_fc_hwqp_process_pending_reqs(struct spdk_nvmf_fc_hwqp *hwqp);
void spdk_nvmf_fc_process_pending_ls_rqst(struct spdk_nvmf_fc_hwqp *hwqp);
void spdk_nvmf_fc_hwqp_process_pending_ls_rqsts(struct spdk_nvmf_fc_hwqp *hwqp);
void spdk_nvmf_fc_req_set_state(struct spdk_nvmf_fc_request *fc_req,
enum spdk_nvmf_fc_request_state state);
void spdk_nvmf_fc_request_set_state(struct spdk_nvmf_fc_request *fc_req,
enum spdk_nvmf_fc_request_state state);
void spdk_nvmf_fc_free_req(struct spdk_nvmf_fc_request *fc_req);
char *spdk_nvmf_fc_request_get_state_str(int state);
void spdk_nvmf_fc_req_abort_complete(void *arg1);
void spdk_nvmf_fc_request_free(struct spdk_nvmf_fc_request *fc_req);
void spdk_nvmf_fc_request_abort_complete(void *arg1);
bool spdk_nvmf_fc_send_ersp_required(struct spdk_nvmf_fc_request *fc_req,
uint32_t rsp_cnt, uint32_t xfer_len);
struct spdk_nvmf_fc_xri *spdk_nvmf_fc_get_xri(struct spdk_nvmf_fc_hwqp *hwqp);
int spdk_nvmf_fc_put_xri(struct spdk_nvmf_fc_hwqp *hwqp,
struct spdk_nvmf_fc_xri *xri);
void spdk_nvmf_fc_release_xri(struct spdk_nvmf_fc_hwqp *hwqp,
struct spdk_nvmf_fc_xri *xri, bool xb, bool abts);
int spdk_nvmf_fc_handle_rsp(struct spdk_nvmf_fc_request *req);
#endif

View File

@ -47,6 +47,9 @@ static const struct spdk_nvmf_transport_ops *const g_transport_ops[] = {
&spdk_nvmf_transport_rdma,
#endif
&spdk_nvmf_transport_tcp,
#ifdef SPDK_CONFIG_FC
&spdk_nvmf_transport_fc,
#endif
};
#define NUM_TRANSPORTS (SPDK_COUNTOF(g_transport_ops))
@ -87,7 +90,7 @@ spdk_nvmf_transport_create(enum spdk_nvme_transport_type type,
ops = spdk_nvmf_get_transport_ops(type);
if (!ops) {
SPDK_ERRLOG("Transport type %s unavailable.\n",
SPDK_ERRLOG("Transport type '%s' unavailable.\n",
spdk_nvme_transport_id_trtype_str(type));
return NULL;
}

View File

@ -225,5 +225,6 @@ bool spdk_nvmf_transport_opts_init(enum spdk_nvme_transport_type type,
extern const struct spdk_nvmf_transport_ops spdk_nvmf_transport_rdma;
extern const struct spdk_nvmf_transport_ops spdk_nvmf_transport_tcp;
extern const struct spdk_nvmf_transport_ops spdk_nvmf_transport_fc;
#endif /* SPDK_NVMF_TRANSPORT_H */

View File

@ -48,4 +48,11 @@ ifeq ($(OS),Linux)
SPDK_LIB_LIST += event_nbd nbd
endif
ifeq ($(CONFIG_FC),y)
ifneq ($(strip $(CONFIG_FC_PATH)),)
SYS_LIBS += -L$(CONFIG_FC_PATH)
endif
SYS_LIBS += -lufc
endif
include $(SPDK_ROOT_DIR)/mk/spdk.app.mk

View File

@ -46,7 +46,7 @@ DEFINE_STUB(spdk_pci_ioat_get_driver, struct spdk_pci_driver *, (void), NULL)
DEFINE_STUB(spdk_pci_virtio_get_driver, struct spdk_pci_driver *, (void), NULL)
DEFINE_STUB(spdk_env_get_first_core, uint32_t, (void), 0);
DEFINE_STUB(spdk_env_get_next_core, uint32_t, (uint32_t prev_core), 0);
DEFINE_STUB(spdk_env_get_last_core, uint32_t, (void), 0);
DEFINE_STUB(spdk_env_get_last_core, uint32_t, (void), 1);
DEFINE_STUB(spdk_env_get_current_core, uint32_t, (void), 0);
DEFINE_STUB(spdk_env_get_socket_id, uint32_t, (uint32_t core), 0);

View File

@ -38,6 +38,8 @@ DIRS-y = tcp.c ctrlr.c subsystem.c ctrlr_discovery.c ctrlr_bdev.c
DIRS-$(CONFIG_RDMA) += rdma.c
DIRS-$(CONFIG_FC) += fc.c fc_ls.c
.PHONY: all clean $(DIRS-y)
all: $(DIRS-y)

1
test/unit/lib/nvmf/fc.c/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
fc_ut

View File

@ -0,0 +1,58 @@
#
# BSD LICENSE
#
# Copyright (c) 2018 Broadcom. All Rights Reserved.
# The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
#
# 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.
#
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../../)
include $(SPDK_ROOT_DIR)/mk/config.mk
CFLAGS += -I$(SPDK_ROOT_DIR)/test/common/lib -I$(SPDK_ROOT_DIR)/lib \
-I$(SPDK_ROOT_DIR)/lib/nvmf
ifneq ($(strip $(CONFIG_FC_PATH)),)
CFLAGS += -I$(CONFIG_FC_PATH)
endif
TEST_FILE = fc_ut.c
include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk
# Disable clang warning: taking address of packed member of class or structure may result in an unaligned pointer value [-Werror,-Waddress-of-packed-member]
ifeq ($(CC),clang)
CLANG_VERSION := $(shell $(CC) -v 2>&1 | \
sed -n "s/.*version \([0-9]*\.[0-9]*\).*/\1/p")
CLANG_MAJOR_VERSION := $(shell echo $(CLANG_VERSION) | cut -f1 -d.)
ifeq ($(shell test $(CLANG_MAJOR_VERSION) -ge 4 && echo 1), 1)
CFLAGS += -Wno-address-of-packed-member
endif
endif

View File

@ -0,0 +1,536 @@
/*
* BSD LICENSE
*
* Copyright (c) 2018-2019 Broadcom. All Rights Reserved.
* The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
*
* 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.
*/
/* NVMF FC Transport Unit Test */
#include "spdk/env.h"
#include "spdk_cunit.h"
#include "spdk/nvmf.h"
#include "spdk_internal/event.h"
#include "spdk/endian.h"
#include "spdk/trace.h"
#include "spdk_internal/log.h"
#include "ut_multithread.c"
#include "transport.h"
#include "nvmf_internal.h"
#include "nvmf_fc.h"
#include "json/json_util.c"
#include "json/json_write.c"
#include "nvmf/nvmf.c"
#include "nvmf/transport.c"
#include "nvmf/subsystem.c"
#include "nvmf/fc.c"
#include "nvmf/fc_ls.c"
/*
* SPDK Stuff
*/
#ifdef SPDK_CONFIG_RDMA
const struct spdk_nvmf_transport_ops spdk_nvmf_transport_rdma = {
.type = SPDK_NVME_TRANSPORT_RDMA,
.opts_init = NULL,
.create = NULL,
.destroy = NULL,
.listen = NULL,
.stop_listen = NULL,
.accept = NULL,
.listener_discover = NULL,
.poll_group_create = NULL,
.poll_group_destroy = NULL,
.poll_group_add = NULL,
.poll_group_poll = NULL,
.req_free = NULL,
.req_complete = NULL,
.qpair_fini = NULL,
.qpair_is_idle = NULL,
.qpair_get_peer_trid = NULL,
.qpair_get_local_trid = NULL,
.qpair_get_listen_trid = NULL,
};
#endif
const struct spdk_nvmf_transport_ops spdk_nvmf_transport_tcp = {
.type = SPDK_NVME_TRANSPORT_TCP,
};
struct spdk_trace_histories *g_trace_histories;
DEFINE_STUB_V(_spdk_trace_record, (uint64_t tsc, uint16_t tpoint_id, uint16_t poller_id,
uint32_t size, uint64_t object_id, uint64_t arg1));
DEFINE_STUB(spdk_env_get_core_count, uint32_t, (void), 4);
DEFINE_STUB(spdk_nvme_transport_id_compare, int,
(const struct spdk_nvme_transport_id *trid1,
const struct spdk_nvme_transport_id *trid2), 0);
DEFINE_STUB_V(spdk_trace_register_object, (uint8_t type, char id_prefix));
DEFINE_STUB_V(spdk_trace_register_description,
(const char *name, uint16_t tpoint_id, uint8_t owner_type,
uint8_t object_type, uint8_t new_object, uint8_t arg1_type,
const char *arg1_name));
DEFINE_STUB_V(spdk_trace_add_register_fn, (struct spdk_trace_register_fn *reg_fn));
DEFINE_STUB(spdk_bdev_get_name, const char *, (const struct spdk_bdev *bdev), "fc_ut_test");
DEFINE_STUB_V(spdk_nvmf_ctrlr_destruct, (struct spdk_nvmf_ctrlr *ctrlr));
DEFINE_STUB_V(spdk_nvmf_qpair_free_aer, (struct spdk_nvmf_qpair *qpair));
DEFINE_STUB(spdk_bdev_get_io_channel, struct spdk_io_channel *, (struct spdk_bdev_desc *desc),
NULL);
DEFINE_STUB_V(spdk_nvmf_request_exec, (struct spdk_nvmf_request *req));
DEFINE_STUB_V(spdk_nvmf_ctrlr_ns_changed, (struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid));
DEFINE_STUB(spdk_bdev_open, int, (struct spdk_bdev *bdev, bool write,
spdk_bdev_remove_cb_t remove_cb,
void *remove_ctx, struct spdk_bdev_desc **desc), 0);
DEFINE_STUB_V(spdk_bdev_close, (struct spdk_bdev_desc *desc));
DEFINE_STUB(spdk_bdev_module_claim_bdev, int,
(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
struct spdk_bdev_module *module), 0);
DEFINE_STUB_V(spdk_bdev_module_release_bdev, (struct spdk_bdev *bdev));
DEFINE_STUB(spdk_bdev_get_block_size, uint32_t, (const struct spdk_bdev *bdev), 512);
const char *
spdk_nvme_transport_id_trtype_str(enum spdk_nvme_transport_type trtype)
{
switch (trtype) {
case SPDK_NVME_TRANSPORT_PCIE:
return "PCIe";
case SPDK_NVME_TRANSPORT_RDMA:
return "RDMA";
case SPDK_NVME_TRANSPORT_FC:
return "FC";
default:
return NULL;
}
}
const char *
spdk_nvme_transport_id_adrfam_str(enum spdk_nvmf_adrfam adrfam)
{
switch (adrfam) {
case SPDK_NVMF_ADRFAM_IPV4:
return "IPv4";
case SPDK_NVMF_ADRFAM_IPV6:
return "IPv6";
case SPDK_NVMF_ADRFAM_IB:
return "IB";
case SPDK_NVMF_ADRFAM_FC:
return "FC";
default:
return NULL;
}
}
const struct spdk_uuid *
spdk_bdev_get_uuid(const struct spdk_bdev *bdev)
{
return &bdev->uuid;
}
static bool g_lld_init_called = false;
int
nvmf_fc_lld_init(void)
{
g_lld_init_called = true;
return 0;
}
static bool g_lld_fini_called = false;
void
nvmf_fc_lld_fini(void)
{
g_lld_fini_called = true;
}
DEFINE_STUB_V(nvmf_fc_lld_start, (void));
DEFINE_STUB(nvmf_fc_init_q, int, (struct spdk_nvmf_fc_hwqp *hwqp), 0);
DEFINE_STUB_V(nvmf_fc_reinit_q, (void *queues_prev, void *queues_curr));
DEFINE_STUB(nvmf_fc_init_rqpair_buffers, int, (struct spdk_nvmf_fc_hwqp *hwqp), 0);
DEFINE_STUB(nvmf_fc_set_q_online_state, int, (struct spdk_nvmf_fc_hwqp *hwqp, bool online), 0);
DEFINE_STUB(nvmf_fc_put_xchg, int, (struct spdk_nvmf_fc_hwqp *hwqp, struct spdk_nvmf_fc_xchg *xri),
0);
DEFINE_STUB(nvmf_fc_recv_data, int, (struct spdk_nvmf_fc_request *fc_req), 0);
DEFINE_STUB(nvmf_fc_send_data, int, (struct spdk_nvmf_fc_request *fc_req), 0);
DEFINE_STUB_V(nvmf_fc_rqpair_buffer_release, (struct spdk_nvmf_fc_hwqp *hwqp, uint16_t buff_idx));
DEFINE_STUB(nvmf_fc_xmt_rsp, int, (struct spdk_nvmf_fc_request *fc_req, uint8_t *ersp_buf,
uint32_t ersp_len), 0);
DEFINE_STUB(nvmf_fc_xmt_ls_rsp, int, (struct spdk_nvmf_fc_nport *tgtport,
struct spdk_nvmf_fc_ls_rqst *ls_rqst), 0);
DEFINE_STUB(nvmf_fc_issue_abort, int, (struct spdk_nvmf_fc_hwqp *hwqp,
struct spdk_nvmf_fc_xchg *xri,
spdk_nvmf_fc_caller_cb cb, void *cb_args), 0);
DEFINE_STUB(nvmf_fc_xmt_bls_rsp, int, (struct spdk_nvmf_fc_hwqp *hwqp,
uint16_t ox_id, uint16_t rx_id,
uint16_t rpi, bool rjt, uint8_t rjt_exp,
spdk_nvmf_fc_caller_cb cb, void *cb_args), 0);
DEFINE_STUB(nvmf_fc_alloc_srsr_bufs, struct spdk_nvmf_fc_srsr_bufs *, (size_t rqst_len,
size_t rsp_len), NULL);
DEFINE_STUB_V(nvmf_fc_free_srsr_bufs, (struct spdk_nvmf_fc_srsr_bufs *srsr_bufs));
DEFINE_STUB(nvmf_fc_xmt_srsr_req, int, (struct spdk_nvmf_fc_hwqp *hwqp,
struct spdk_nvmf_fc_srsr_bufs *xmt_srsr_bufs,
spdk_nvmf_fc_caller_cb cb, void *cb_args), 0);
DEFINE_STUB(nvmf_fc_q_sync_available, bool, (void), true);
DEFINE_STUB(nvmf_fc_issue_q_sync, int, (struct spdk_nvmf_fc_hwqp *hwqp, uint64_t u_id,
uint16_t skip_rq), 0);
DEFINE_STUB(nvmf_fc_assign_conn_to_hwqp, bool, (struct spdk_nvmf_fc_hwqp *hwqp,
uint64_t *conn_id, uint32_t sq_size), true);
DEFINE_STUB(nvmf_fc_get_hwqp_from_conn_id, struct spdk_nvmf_fc_hwqp *,
(struct spdk_nvmf_fc_hwqp *queues,
uint32_t num_queues, uint64_t conn_id), NULL);
DEFINE_STUB_V(nvmf_fc_release_conn, (struct spdk_nvmf_fc_hwqp *hwqp, uint64_t conn_id,
uint32_t sq_size));
DEFINE_STUB_V(nvmf_fc_dump_all_queues, (struct spdk_nvmf_fc_hwqp *ls_queue,
struct spdk_nvmf_fc_hwqp *io_queues,
uint32_t num_io_queues,
struct spdk_nvmf_fc_queue_dump_info *dump_info));
DEFINE_STUB_V(nvmf_fc_get_xri_info, (struct spdk_nvmf_fc_hwqp *hwqp,
struct spdk_nvmf_fc_xchg_info *info));
DEFINE_STUB(nvmf_fc_get_rsvd_thread, struct spdk_thread *, (void), NULL);
uint32_t
nvmf_fc_process_queue(struct spdk_nvmf_fc_hwqp *hwqp)
{
hwqp->lcore_id++;
return 0; /* always return 0 or else it will poll forever */
}
struct spdk_nvmf_fc_xchg *
nvmf_fc_get_xri(struct spdk_nvmf_fc_hwqp *hwqp)
{
static struct spdk_nvmf_fc_xchg xchg;
xchg.xchg_id = 1;
return &xchg;
}
#define MAX_FC_UT_POLL_THREADS 8
static struct spdk_nvmf_poll_group *g_poll_groups[MAX_FC_UT_POLL_THREADS] = {0};
#define MAX_FC_UT_HWQPS MAX_FC_UT_POLL_THREADS
static struct spdk_nvmf_tgt *g_nvmf_tgt = NULL;
static struct spdk_nvmf_transport *g_nvmf_tprt = NULL;
uint8_t g_fc_port_handle = 0xff;
struct spdk_nvmf_fc_hwqp lld_q[MAX_FC_UT_HWQPS];
static void
_add_transport_done(void *arg, int status)
{
CU_ASSERT(status == 0);
}
static void
_add_transport_done_dup_err(void *arg, int status)
{
CU_ASSERT(status == -EEXIST);
}
static void
create_transport_test(void)
{
const struct spdk_nvmf_transport_ops *ops = NULL;
struct spdk_nvmf_transport_opts opts = { 0 };
allocate_threads(8);
set_thread(0);
g_nvmf_tgt = spdk_nvmf_tgt_create(2);
SPDK_CU_ASSERT_FATAL(g_nvmf_tgt != NULL);
ops = spdk_nvmf_get_transport_ops((enum spdk_nvme_transport_type) SPDK_NVMF_TRTYPE_FC);
SPDK_CU_ASSERT_FATAL(ops != NULL);
ops->opts_init(&opts);
g_lld_init_called = false;
g_nvmf_tprt = spdk_nvmf_transport_create((enum spdk_nvme_transport_type) SPDK_NVMF_TRTYPE_FC,
&opts);
SPDK_CU_ASSERT_FATAL(g_nvmf_tprt != NULL);
CU_ASSERT(g_lld_init_called == true);
CU_ASSERT(opts.max_queue_depth == g_nvmf_tprt->opts.max_queue_depth);
CU_ASSERT(opts.max_qpairs_per_ctrlr == g_nvmf_tprt->opts.max_qpairs_per_ctrlr);
CU_ASSERT(opts.in_capsule_data_size == g_nvmf_tprt->opts.in_capsule_data_size);
CU_ASSERT(opts.max_io_size == g_nvmf_tprt->opts.max_io_size);
CU_ASSERT(opts.io_unit_size == g_nvmf_tprt->opts.io_unit_size);
CU_ASSERT(opts.max_aq_depth == g_nvmf_tprt->opts.max_aq_depth);
set_thread(0);
spdk_nvmf_tgt_add_transport(g_nvmf_tgt, g_nvmf_tprt,
_add_transport_done, 0);
poll_thread(0);
/* Add transport again - should get error */
spdk_nvmf_tgt_add_transport(g_nvmf_tgt, g_nvmf_tprt,
_add_transport_done_dup_err, 0);
poll_thread(0);
/* create transport with bad args/options */
#ifndef SPDK_CONFIG_RDMA
CU_ASSERT(spdk_nvmf_transport_create(SPDK_NVMF_TRTYPE_RDMA, &opts) == NULL);
#endif
CU_ASSERT(spdk_nvmf_transport_create(998, &opts) == NULL);
opts.max_io_size = 1024 ^ 3;
CU_ASSERT(spdk_nvmf_transport_create((enum spdk_nvme_transport_type) SPDK_NVMF_TRTYPE_FC,
&opts) == NULL);
opts.max_io_size = 999;
opts.io_unit_size = 1024;
CU_ASSERT(spdk_nvmf_transport_create((enum spdk_nvme_transport_type) SPDK_NVMF_TRTYPE_FC,
&opts) == NULL);
}
static void
port_init_cb(uint8_t port_handle, enum spdk_fc_event event_type, void *arg, int err)
{
CU_ASSERT(err == 0);
CU_ASSERT(port_handle == 2);
g_fc_port_handle = port_handle;
}
static void
create_fc_port_test(void)
{
struct spdk_nvmf_fc_hw_port_init_args init_args = { 0 };
struct spdk_nvmf_fc_port *fc_port = NULL;
int err;
SPDK_CU_ASSERT_FATAL(g_nvmf_tprt != NULL);
init_args.port_handle = 2;
init_args.io_queue_cnt = spdk_min(MAX_FC_UT_HWQPS, spdk_env_get_core_count());
init_args.ls_queue_size = 100;
init_args.io_queue_size = 100;
init_args.io_queues = (void *)lld_q;
set_thread(0);
err = spdk_nvmf_fc_master_enqueue_event(SPDK_FC_HW_PORT_INIT, (void *)&init_args, port_init_cb);
CU_ASSERT(err == 0);
poll_thread(0);
fc_port = spdk_nvmf_fc_port_lookup(g_fc_port_handle);
CU_ASSERT(fc_port != NULL);
}
static void
online_fc_port_test(void)
{
struct spdk_nvmf_fc_port *fc_port;
struct spdk_nvmf_fc_hw_port_online_args args;
int err;
SPDK_CU_ASSERT_FATAL(g_nvmf_tprt != NULL);
fc_port = spdk_nvmf_fc_port_lookup(g_fc_port_handle);
SPDK_CU_ASSERT_FATAL(fc_port != NULL);
set_thread(0);
args.port_handle = g_fc_port_handle;
err = spdk_nvmf_fc_master_enqueue_event(SPDK_FC_HW_PORT_ONLINE, (void *)&args, port_init_cb);
CU_ASSERT(err == 0);
poll_threads();
set_thread(0);
if (err == 0) {
uint32_t i;
for (i = 0; i < fc_port->num_io_queues; i++) {
CU_ASSERT(fc_port->io_queues[i].fc_poll_group != 0);
CU_ASSERT(fc_port->io_queues[i].fc_poll_group != 0);
CU_ASSERT(fc_port->io_queues[i].fc_poll_group->hwqp_count != 0);
}
}
}
static void
create_poll_groups_test(void)
{
unsigned i;
SPDK_CU_ASSERT_FATAL(g_nvmf_tprt != NULL);
for (i = 0; i < MAX_FC_UT_POLL_THREADS; i++) {
set_thread(i);
g_poll_groups[i] = spdk_nvmf_poll_group_create(g_nvmf_tgt);
poll_thread(i);
CU_ASSERT(g_poll_groups[i] != NULL);
}
set_thread(0);
}
static void
poll_group_poll_test(void)
{
unsigned i;
unsigned poll_cnt = 10;
struct spdk_nvmf_fc_port *fc_port = NULL;
SPDK_CU_ASSERT_FATAL(g_nvmf_tprt != NULL);
set_thread(0);
fc_port = spdk_nvmf_fc_port_lookup(g_fc_port_handle);
SPDK_CU_ASSERT_FATAL(fc_port != NULL);
for (i = 0; i < fc_port->num_io_queues; i++) {
fc_port->io_queues[i].lcore_id = 0;
}
for (i = 0; i < poll_cnt; i++) {
/* this should cause spdk_nvmf_fc_poll_group_poll to be called() */
poll_threads();
}
/* check if hwqp's lcore_id has been updated */
for (i = 0; i < fc_port->num_io_queues; i++) {
CU_ASSERT(fc_port->io_queues[i].lcore_id == poll_cnt);
}
}
static void
remove_hwqps_from_poll_groups_test(void)
{
unsigned i;
struct spdk_nvmf_fc_port *fc_port = NULL;
SPDK_CU_ASSERT_FATAL(g_nvmf_tprt != NULL);
fc_port = spdk_nvmf_fc_port_lookup(g_fc_port_handle);
SPDK_CU_ASSERT_FATAL(fc_port != NULL);
for (i = 0; i < fc_port->num_io_queues; i++) {
spdk_nvmf_fc_poll_group_remove_hwqp(&fc_port->io_queues[i]);
poll_threads();
CU_ASSERT(fc_port->io_queues[i].fc_poll_group == 0);
}
}
static void
destroy_transport_test(void)
{
unsigned i;
set_thread(0);
SPDK_CU_ASSERT_FATAL(g_nvmf_tprt != NULL);
for (i = 0; i < MAX_FC_UT_POLL_THREADS; i++) {
set_thread(i);
spdk_nvmf_poll_group_destroy(g_poll_groups[i]);
poll_thread(0);
}
SPDK_CU_ASSERT_FATAL(g_nvmf_tgt != NULL);
g_lld_fini_called = false;
spdk_nvmf_tgt_destroy(g_nvmf_tgt, NULL, NULL);
poll_threads();
CU_ASSERT(g_lld_fini_called == true);
}
static int
nvmf_fc_tests_init(void)
{
return 0;
}
static int
nvmf_fc_tests_fini(void)
{
free_threads();
return 0;
}
int main(int argc, char **argv)
{
unsigned int num_failures = 0;
CU_pSuite suite = NULL;
if (CU_initialize_registry() != CUE_SUCCESS) {
return CU_get_error();
}
suite = CU_add_suite("NVMf-FC", nvmf_fc_tests_init, nvmf_fc_tests_fini);
if (suite == NULL) {
CU_cleanup_registry();
return CU_get_error();
}
if (CU_add_test(suite, "Create Target & FC Transport",
create_transport_test) == NULL) {
CU_cleanup_registry();
return CU_get_error();
}
if (CU_add_test(suite, "Create Poll Groups",
create_poll_groups_test) == NULL) {
CU_cleanup_registry();
return CU_get_error();
}
if (CU_add_test(suite, "Create FC Port",
create_fc_port_test) == NULL) {
CU_cleanup_registry();
return CU_get_error();
}
if (CU_add_test(suite, "Online FC Port",
online_fc_port_test) == NULL) {
CU_cleanup_registry();
return CU_get_error();
}
if (CU_add_test(suite, "PG poll", poll_group_poll_test) == NULL) {
CU_cleanup_registry();
return CU_get_error();
}
if (CU_add_test(suite, "Remove HWQP's from PG's",
remove_hwqps_from_poll_groups_test) == NULL) {
CU_cleanup_registry();
return CU_get_error();
}
if (CU_add_test(suite, "Destroy Transport & Target",
destroy_transport_test) == NULL) {
CU_cleanup_registry();
return CU_get_error();
}
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
num_failures = CU_get_number_of_failures();
CU_cleanup_registry();
return num_failures;
}

1
test/unit/lib/nvmf/fc_ls.c/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
fc_ls_ut

View File

@ -0,0 +1,45 @@
#
# BSD LICENSE
#
# Copyright (c) 2018 Broadcom. All Rights Reserved.
# The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
#
# 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.
#
SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../../)
include $(SPDK_ROOT_DIR)/mk/config.mk
CFLAGS += -I$(SPDK_ROOT_DIR)/test/common/lib -I$(SPDK_ROOT_DIR)/lib/nvmf
ifneq ($(strip $(CONFIG_FC_PATH)),)
CFLAGS += -I$(CONFIG_FC_PATH)
endif
TEST_FILE = fc_ls_ut.c
include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk

File diff suppressed because it is too large Load Diff

View File

@ -165,6 +165,14 @@ $valgrind $testdir/lib/ftl/ftl_md/ftl_md_ut
$valgrind $testdir/lib/ftl/ftl_io.c/ftl_io_ut
fi
if [ -e $testdir/lib/nvmf/fc.c/fc_ut ]; then
$valgrind $testdir/lib/nvmf/fc.c/fc_ut
fi
if [ -e $testdir/lib/nvmf/fc_ls.c/fc_ls_ut ]; then
$valgrind $testdir/lib/nvmf/fc_ls.c/fc_ls_ut
fi
# local unit test coverage
if [ "$cov_avail" = "yes" ]; then
$LCOV -q -d . -c -t "$(hostname)" -o $UT_COVERAGE/ut_cov_test.info