ut/nvmf/ctrlr: add Connect command unit tests
Change-Id: I4d3cced91e804fbbb96a15a09b575ff85960ddef Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com> Reviewed-on: https://review.gerrithub.io/390661 Tested-by: SPDK Automated Test System <sys_sgsw@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
2d630f9b75
commit
fab9349fdc
@ -217,6 +217,285 @@ test_process_fabrics_cmd(void)
|
||||
CU_ASSERT_EQUAL(ret, SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
|
||||
}
|
||||
|
||||
static bool
|
||||
nvme_status_success(const struct spdk_nvme_status *status)
|
||||
{
|
||||
return status->sct == SPDK_NVME_SCT_GENERIC && status->sc == SPDK_NVME_SC_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
test_connect(void)
|
||||
{
|
||||
struct spdk_nvmf_fabric_connect_data connect_data;
|
||||
struct spdk_nvmf_poll_group group;
|
||||
struct spdk_nvmf_transport transport;
|
||||
struct spdk_nvmf_subsystem subsystem;
|
||||
struct spdk_nvmf_request req;
|
||||
struct spdk_nvmf_qpair qpair;
|
||||
struct spdk_nvmf_ctrlr ctrlr;
|
||||
struct spdk_nvmf_tgt tgt;
|
||||
union nvmf_h2c_msg cmd;
|
||||
union nvmf_c2h_msg rsp;
|
||||
const uint8_t hostid[16] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
|
||||
};
|
||||
const char subnqn[] = "nqn.2016-06.io.spdk:subsystem1";
|
||||
const char hostnqn[] = "nqn.2016-06.io.spdk:host1";
|
||||
int rc;
|
||||
|
||||
memset(&group, 0, sizeof(group));
|
||||
|
||||
memset(&ctrlr, 0, sizeof(ctrlr));
|
||||
TAILQ_INIT(&ctrlr.qpairs);
|
||||
ctrlr.subsys = &subsystem;
|
||||
ctrlr.vcprop.cc.bits.en = 1;
|
||||
ctrlr.vcprop.cc.bits.iosqes = 6;
|
||||
ctrlr.vcprop.cc.bits.iocqes = 4;
|
||||
ctrlr.max_qpairs_allowed = 3;
|
||||
|
||||
memset(&tgt, 0, sizeof(tgt));
|
||||
tgt.opts.max_queue_depth = 64;
|
||||
tgt.opts.max_qpairs_per_ctrlr = 3;
|
||||
|
||||
memset(&transport, 0, sizeof(transport));
|
||||
transport.tgt = &tgt;
|
||||
|
||||
memset(&qpair, 0, sizeof(qpair));
|
||||
qpair.transport = &transport;
|
||||
|
||||
memset(&connect_data, 0, sizeof(connect_data));
|
||||
memcpy(connect_data.hostid, hostid, sizeof(hostid));
|
||||
connect_data.cntlid = 0xFFFF;
|
||||
strncpy(connect_data.subnqn, subnqn, sizeof(connect_data.subnqn));
|
||||
strncpy(connect_data.hostnqn, hostnqn, sizeof(connect_data.hostnqn));
|
||||
|
||||
memset(&subsystem, 0, sizeof(subsystem));
|
||||
subsystem.id = 1;
|
||||
TAILQ_INIT(&subsystem.ctrlrs);
|
||||
subsystem.tgt = &tgt;
|
||||
subsystem.subtype = SPDK_NVMF_SUBTYPE_NVME;
|
||||
snprintf(subsystem.subnqn, sizeof(subsystem.subnqn), "%s", subnqn);
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.connect_cmd.opcode = SPDK_NVME_OPC_FABRIC;
|
||||
cmd.connect_cmd.cid = 1;
|
||||
cmd.connect_cmd.fctype = SPDK_NVMF_FABRIC_COMMAND_CONNECT;
|
||||
cmd.connect_cmd.recfmt = 0;
|
||||
cmd.connect_cmd.qid = 0;
|
||||
cmd.connect_cmd.sqsize = 31;
|
||||
cmd.connect_cmd.cattr = 0;
|
||||
cmd.connect_cmd.kato = 120000;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.qpair = &qpair;
|
||||
req.length = sizeof(connect_data);
|
||||
req.xfer = SPDK_NVME_DATA_HOST_TO_CONTROLLER;
|
||||
req.data = &connect_data;
|
||||
req.cmd = &cmd;
|
||||
req.rsp = &rsp;
|
||||
|
||||
MOCK_SET(spdk_nvmf_tgt_find_subsystem, struct spdk_nvmf_subsystem *, &subsystem);
|
||||
MOCK_SET(spdk_nvmf_poll_group_create, struct spdk_nvmf_poll_group *, &group);
|
||||
|
||||
/* Valid admin connect command */
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
rc = spdk_nvmf_ctrlr_connect(&req);
|
||||
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
|
||||
CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status));
|
||||
CU_ASSERT(qpair.ctrlr != NULL);
|
||||
free(qpair.ctrlr);
|
||||
qpair.ctrlr = NULL;
|
||||
|
||||
/* Invalid data length */
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
req.length = sizeof(connect_data) - 1;
|
||||
rc = spdk_nvmf_ctrlr_connect(&req);
|
||||
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD);
|
||||
CU_ASSERT(qpair.ctrlr == NULL);
|
||||
req.length = sizeof(connect_data);
|
||||
|
||||
/* Invalid recfmt */
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
cmd.connect_cmd.recfmt = 1234;
|
||||
rc = spdk_nvmf_ctrlr_connect(&req);
|
||||
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INCOMPATIBLE_FORMAT);
|
||||
CU_ASSERT(qpair.ctrlr == NULL);
|
||||
cmd.connect_cmd.recfmt = 0;
|
||||
|
||||
/* Unterminated subnqn */
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
memset(connect_data.subnqn, 'a', sizeof(connect_data.subnqn));
|
||||
rc = spdk_nvmf_ctrlr_connect(&req);
|
||||
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 256);
|
||||
CU_ASSERT(qpair.ctrlr == NULL);
|
||||
strncpy(connect_data.subnqn, subnqn, sizeof(connect_data.subnqn));
|
||||
|
||||
/* Subsystem not found */
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
MOCK_SET(spdk_nvmf_tgt_find_subsystem, struct spdk_nvmf_subsystem *, NULL);
|
||||
rc = spdk_nvmf_ctrlr_connect(&req);
|
||||
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 256);
|
||||
CU_ASSERT(qpair.ctrlr == NULL);
|
||||
MOCK_SET(spdk_nvmf_tgt_find_subsystem, struct spdk_nvmf_subsystem *, &subsystem);
|
||||
|
||||
/* Unterminated hostnqn */
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
memset(connect_data.hostnqn, 'b', sizeof(connect_data.hostnqn));
|
||||
rc = spdk_nvmf_ctrlr_connect(&req);
|
||||
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 512);
|
||||
CU_ASSERT(qpair.ctrlr == NULL);
|
||||
strncpy(connect_data.hostnqn, hostnqn, sizeof(connect_data.hostnqn));
|
||||
|
||||
/* Host not allowed */
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
MOCK_SET(spdk_nvmf_subsystem_host_allowed, bool, false);
|
||||
rc = spdk_nvmf_ctrlr_connect(&req);
|
||||
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_HOST);
|
||||
CU_ASSERT(qpair.ctrlr == NULL);
|
||||
MOCK_SET(spdk_nvmf_subsystem_host_allowed, bool, true);
|
||||
|
||||
/* Invalid sqsize == 0 */
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
cmd.connect_cmd.sqsize = 0;
|
||||
rc = spdk_nvmf_ctrlr_connect(&req);
|
||||
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 44);
|
||||
CU_ASSERT(qpair.ctrlr == NULL);
|
||||
cmd.connect_cmd.sqsize = 31;
|
||||
|
||||
/* Invalid sqsize > max_queue_depth */
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
cmd.connect_cmd.sqsize = 64;
|
||||
rc = spdk_nvmf_ctrlr_connect(&req);
|
||||
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 44);
|
||||
CU_ASSERT(qpair.ctrlr == NULL);
|
||||
cmd.connect_cmd.sqsize = 31;
|
||||
|
||||
/* Invalid cntlid for admin queue */
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
connect_data.cntlid = 0x1234;
|
||||
rc = spdk_nvmf_ctrlr_connect(&req);
|
||||
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 16);
|
||||
CU_ASSERT(qpair.ctrlr == NULL);
|
||||
connect_data.cntlid = 0xFFFF;
|
||||
|
||||
/* Valid I/O queue connect command */
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
MOCK_SET(spdk_nvmf_subsystem_get_ctrlr, struct spdk_nvmf_ctrlr *, &ctrlr);
|
||||
cmd.connect_cmd.qid = 1;
|
||||
rc = spdk_nvmf_ctrlr_connect(&req);
|
||||
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
|
||||
CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status));
|
||||
CU_ASSERT(qpair.ctrlr == &ctrlr);
|
||||
qpair.ctrlr = NULL;
|
||||
ctrlr.num_qpairs = 0;
|
||||
TAILQ_INIT(&ctrlr.qpairs);
|
||||
|
||||
/* Non-existent controller */
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
MOCK_SET(spdk_nvmf_subsystem_get_ctrlr, struct spdk_nvmf_ctrlr *, NULL);
|
||||
rc = spdk_nvmf_ctrlr_connect(&req);
|
||||
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 16);
|
||||
CU_ASSERT(qpair.ctrlr == NULL);
|
||||
MOCK_SET(spdk_nvmf_subsystem_get_ctrlr, struct spdk_nvmf_ctrlr *, &ctrlr);
|
||||
|
||||
/* I/O connect to discovery controller */
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
subsystem.subtype = SPDK_NVMF_SUBTYPE_DISCOVERY;
|
||||
rc = spdk_nvmf_ctrlr_connect(&req);
|
||||
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42);
|
||||
CU_ASSERT(qpair.ctrlr == NULL);
|
||||
subsystem.subtype = SPDK_NVMF_SUBTYPE_NVME;
|
||||
|
||||
/* I/O connect to disabled controller */
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
ctrlr.vcprop.cc.bits.en = 0;
|
||||
rc = spdk_nvmf_ctrlr_connect(&req);
|
||||
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42);
|
||||
CU_ASSERT(qpair.ctrlr == NULL);
|
||||
ctrlr.vcprop.cc.bits.en = 1;
|
||||
|
||||
/* I/O connect with invalid IOSQES */
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
ctrlr.vcprop.cc.bits.iosqes = 3;
|
||||
rc = spdk_nvmf_ctrlr_connect(&req);
|
||||
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42);
|
||||
CU_ASSERT(qpair.ctrlr == NULL);
|
||||
ctrlr.vcprop.cc.bits.iosqes = 6;
|
||||
|
||||
/* I/O connect with invalid IOCQES */
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
ctrlr.vcprop.cc.bits.iocqes = 3;
|
||||
rc = spdk_nvmf_ctrlr_connect(&req);
|
||||
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0);
|
||||
CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42);
|
||||
CU_ASSERT(qpair.ctrlr == NULL);
|
||||
ctrlr.vcprop.cc.bits.iocqes = 4;
|
||||
|
||||
/* I/O connect with too many existing qpairs */
|
||||
memset(&rsp, 0, sizeof(rsp));
|
||||
ctrlr.num_qpairs = 3;
|
||||
rc = spdk_nvmf_ctrlr_connect(&req);
|
||||
CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC);
|
||||
CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_CONTROLLER_BUSY);
|
||||
CU_ASSERT(qpair.ctrlr == NULL);
|
||||
ctrlr.num_qpairs = 0;
|
||||
|
||||
/* Clean up globals */
|
||||
MOCK_SET(spdk_nvmf_tgt_find_subsystem, struct spdk_nvmf_subsystem *, NULL);
|
||||
MOCK_SET(spdk_nvmf_poll_group_create, struct spdk_nvmf_poll_group *, NULL);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CU_pSuite suite = NULL;
|
||||
@ -234,7 +513,8 @@ int main(int argc, char **argv)
|
||||
|
||||
if (
|
||||
CU_add_test(suite, "get_log_page", test_get_log_page) == NULL ||
|
||||
CU_add_test(suite, "process_fabrics_cmd", test_process_fabrics_cmd) == NULL
|
||||
CU_add_test(suite, "process_fabrics_cmd", test_process_fabrics_cmd) == NULL ||
|
||||
CU_add_test(suite, "connect", test_connect) == NULL
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
|
Loading…
Reference in New Issue
Block a user