1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "spdk_cunit.h" 37 #include "spdk_internal/mock.h" 38 39 #include "nvmf/ctrlr.c" 40 41 SPDK_LOG_REGISTER_COMPONENT("nvmf", SPDK_LOG_NVMF) 42 43 44 DEFINE_STUB(spdk_nvmf_tgt_find_subsystem, 45 struct spdk_nvmf_subsystem *, 46 (struct spdk_nvmf_tgt *tgt, const char *subnqn), 47 NULL) 48 49 DEFINE_STUB(spdk_nvmf_poll_group_create, 50 struct spdk_nvmf_poll_group *, 51 (struct spdk_nvmf_tgt *tgt), 52 NULL) 53 54 DEFINE_STUB_V(spdk_nvmf_poll_group_destroy, 55 (struct spdk_nvmf_poll_group *group)) 56 57 DEFINE_STUB_V(spdk_nvmf_transport_qpair_fini, 58 (struct spdk_nvmf_qpair *qpair)) 59 60 DEFINE_STUB(spdk_nvmf_poll_group_add, 61 int, 62 (struct spdk_nvmf_poll_group *group, struct spdk_nvmf_qpair *qpair), 63 0) 64 65 DEFINE_STUB(spdk_nvmf_poll_group_remove, 66 int, 67 (struct spdk_nvmf_poll_group *group, struct spdk_nvmf_qpair *qpair), 68 0) 69 70 DEFINE_STUB(spdk_nvmf_subsystem_get_sn, 71 const char *, 72 (const struct spdk_nvmf_subsystem *subsystem), 73 NULL) 74 75 DEFINE_STUB(spdk_nvmf_subsystem_get_ns, 76 struct spdk_nvmf_ns *, 77 (struct spdk_nvmf_subsystem *subsystem, uint32_t nsid), 78 NULL) 79 80 DEFINE_STUB(spdk_nvmf_subsystem_get_first_ns, 81 struct spdk_nvmf_ns *, 82 (struct spdk_nvmf_subsystem *subsystem), 83 NULL) 84 85 DEFINE_STUB(spdk_nvmf_subsystem_get_next_ns, 86 struct spdk_nvmf_ns *, 87 (struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ns *prev_ns), 88 NULL) 89 90 DEFINE_STUB(spdk_nvmf_subsystem_host_allowed, 91 bool, 92 (struct spdk_nvmf_subsystem *subsystem, const char *hostnqn), 93 true) 94 95 DEFINE_STUB(spdk_nvmf_subsystem_add_ctrlr, 96 int, 97 (struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr), 98 0) 99 100 DEFINE_STUB_V(spdk_nvmf_subsystem_remove_ctrlr, 101 (struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr)) 102 103 DEFINE_STUB(spdk_nvmf_subsystem_get_ctrlr, 104 struct spdk_nvmf_ctrlr *, 105 (struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid), 106 NULL) 107 108 DEFINE_STUB(spdk_nvmf_ctrlr_dsm_supported, 109 bool, 110 (struct spdk_nvmf_ctrlr *ctrlr), 111 false) 112 113 DEFINE_STUB(spdk_nvmf_ctrlr_write_zeroes_supported, 114 bool, 115 (struct spdk_nvmf_ctrlr *ctrlr), 116 false) 117 118 DEFINE_STUB(spdk_nvmf_bdev_ctrlr_identify_ns, 119 int, 120 (struct spdk_nvmf_ns *ns, struct spdk_nvme_ns_data *nsdata), 121 -1) 122 123 DEFINE_STUB_V(spdk_nvmf_get_discovery_log_page, 124 (struct spdk_nvmf_tgt *tgt, void *buffer, uint64_t offset, uint32_t length)) 125 126 DEFINE_STUB(spdk_nvmf_request_complete, 127 int, 128 (struct spdk_nvmf_request *req), 129 -1) 130 131 DEFINE_STUB(spdk_nvmf_request_abort, 132 int, 133 (struct spdk_nvmf_request *req), 134 -1) 135 136 static void 137 test_get_log_page(void) 138 { 139 struct spdk_nvmf_subsystem subsystem = {}; 140 struct spdk_nvmf_request req = {}; 141 struct spdk_nvmf_qpair qpair = {}; 142 struct spdk_nvmf_ctrlr ctrlr = {}; 143 union nvmf_h2c_msg cmd = {}; 144 union nvmf_c2h_msg rsp = {}; 145 char data[4096]; 146 147 subsystem.subtype = SPDK_NVMF_SUBTYPE_NVME; 148 149 ctrlr.subsys = &subsystem; 150 151 qpair.ctrlr = &ctrlr; 152 153 req.qpair = &qpair; 154 req.cmd = &cmd; 155 req.rsp = &rsp; 156 req.data = &data; 157 req.length = sizeof(data); 158 159 /* Get Log Page - all valid */ 160 memset(&cmd, 0, sizeof(cmd)); 161 memset(&rsp, 0, sizeof(rsp)); 162 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_LOG_PAGE; 163 cmd.nvme_cmd.cdw10 = SPDK_NVME_LOG_ERROR | (req.length / 4 - 1) << 16; 164 CU_ASSERT(spdk_nvmf_ctrlr_get_log_page(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 165 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 166 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 167 168 /* Get Log Page with invalid log ID */ 169 memset(&cmd, 0, sizeof(cmd)); 170 memset(&rsp, 0, sizeof(rsp)); 171 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_LOG_PAGE; 172 cmd.nvme_cmd.cdw10 = 0; 173 CU_ASSERT(spdk_nvmf_ctrlr_get_log_page(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 174 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 175 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 176 177 /* Get Log Page with invalid offset (not dword aligned) */ 178 memset(&cmd, 0, sizeof(cmd)); 179 memset(&rsp, 0, sizeof(rsp)); 180 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_LOG_PAGE; 181 cmd.nvme_cmd.cdw10 = SPDK_NVME_LOG_ERROR | (req.length / 4 - 1) << 16; 182 cmd.nvme_cmd.cdw12 = 2; 183 CU_ASSERT(spdk_nvmf_ctrlr_get_log_page(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 184 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 185 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 186 187 /* Get Log Page without data buffer */ 188 memset(&cmd, 0, sizeof(cmd)); 189 memset(&rsp, 0, sizeof(rsp)); 190 req.data = NULL; 191 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_LOG_PAGE; 192 cmd.nvme_cmd.cdw10 = SPDK_NVME_LOG_ERROR | (req.length / 4 - 1) << 16; 193 CU_ASSERT(spdk_nvmf_ctrlr_get_log_page(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 194 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 195 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 196 req.data = data; 197 } 198 199 static void 200 test_process_fabrics_cmd(void) 201 { 202 struct spdk_nvmf_request req = {}; 203 int ret; 204 struct spdk_nvmf_qpair req_qpair = {}; 205 union nvmf_h2c_msg req_cmd = {}; 206 union nvmf_c2h_msg req_rsp = {}; 207 208 req.qpair = &req_qpair; 209 req.cmd = &req_cmd; 210 req.rsp = &req_rsp; 211 req.qpair->ctrlr = NULL; 212 213 /* No ctrlr and invalid command check */ 214 req.cmd->nvmf_cmd.fctype = SPDK_NVMF_FABRIC_COMMAND_PROPERTY_GET; 215 ret = spdk_nvmf_ctrlr_process_fabrics_cmd(&req); 216 CU_ASSERT_EQUAL(req.rsp->nvme_cpl.status.sc, SPDK_NVME_SC_COMMAND_SEQUENCE_ERROR); 217 CU_ASSERT_EQUAL(ret, SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 218 } 219 220 static bool 221 nvme_status_success(const struct spdk_nvme_status *status) 222 { 223 return status->sct == SPDK_NVME_SCT_GENERIC && status->sc == SPDK_NVME_SC_SUCCESS; 224 } 225 226 void 227 spdk_thread_send_msg(const struct spdk_thread *thread, spdk_thread_fn fn, void *ctx) 228 { 229 fn(ctx); 230 } 231 232 static void 233 test_connect(void) 234 { 235 struct spdk_nvmf_fabric_connect_data connect_data; 236 struct spdk_nvmf_poll_group group; 237 struct spdk_nvmf_transport transport; 238 struct spdk_nvmf_subsystem subsystem; 239 struct spdk_nvmf_request req; 240 struct spdk_nvmf_qpair admin_qpair; 241 struct spdk_nvmf_qpair qpair; 242 struct spdk_nvmf_qpair qpair2; 243 struct spdk_nvmf_ctrlr ctrlr; 244 struct spdk_nvmf_tgt tgt; 245 union nvmf_h2c_msg cmd; 246 union nvmf_c2h_msg rsp; 247 const uint8_t hostid[16] = { 248 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 249 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F 250 }; 251 const char subnqn[] = "nqn.2016-06.io.spdk:subsystem1"; 252 const char hostnqn[] = "nqn.2016-06.io.spdk:host1"; 253 int rc; 254 255 memset(&group, 0, sizeof(group)); 256 257 memset(&ctrlr, 0, sizeof(ctrlr)); 258 TAILQ_INIT(&ctrlr.qpairs); 259 ctrlr.subsys = &subsystem; 260 ctrlr.vcprop.cc.bits.en = 1; 261 ctrlr.vcprop.cc.bits.iosqes = 6; 262 ctrlr.vcprop.cc.bits.iocqes = 4; 263 ctrlr.max_qpairs_allowed = 3; 264 265 memset(&admin_qpair, 0, sizeof(admin_qpair)); 266 TAILQ_INSERT_TAIL(&ctrlr.qpairs, &admin_qpair, link); 267 admin_qpair.group = &group; 268 269 memset(&tgt, 0, sizeof(tgt)); 270 tgt.opts.max_queue_depth = 64; 271 tgt.opts.max_qpairs_per_ctrlr = 3; 272 273 memset(&transport, 0, sizeof(transport)); 274 transport.tgt = &tgt; 275 276 memset(&qpair, 0, sizeof(qpair)); 277 qpair.transport = &transport; 278 qpair.group = &group; 279 280 memset(&connect_data, 0, sizeof(connect_data)); 281 memcpy(connect_data.hostid, hostid, sizeof(hostid)); 282 connect_data.cntlid = 0xFFFF; 283 strncpy(connect_data.subnqn, subnqn, sizeof(connect_data.subnqn)); 284 strncpy(connect_data.hostnqn, hostnqn, sizeof(connect_data.hostnqn)); 285 286 memset(&subsystem, 0, sizeof(subsystem)); 287 subsystem.id = 1; 288 TAILQ_INIT(&subsystem.ctrlrs); 289 subsystem.tgt = &tgt; 290 subsystem.subtype = SPDK_NVMF_SUBTYPE_NVME; 291 snprintf(subsystem.subnqn, sizeof(subsystem.subnqn), "%s", subnqn); 292 293 memset(&cmd, 0, sizeof(cmd)); 294 cmd.connect_cmd.opcode = SPDK_NVME_OPC_FABRIC; 295 cmd.connect_cmd.cid = 1; 296 cmd.connect_cmd.fctype = SPDK_NVMF_FABRIC_COMMAND_CONNECT; 297 cmd.connect_cmd.recfmt = 0; 298 cmd.connect_cmd.qid = 0; 299 cmd.connect_cmd.sqsize = 31; 300 cmd.connect_cmd.cattr = 0; 301 cmd.connect_cmd.kato = 120000; 302 303 memset(&req, 0, sizeof(req)); 304 req.qpair = &qpair; 305 req.length = sizeof(connect_data); 306 req.xfer = SPDK_NVME_DATA_HOST_TO_CONTROLLER; 307 req.data = &connect_data; 308 req.cmd = &cmd; 309 req.rsp = &rsp; 310 311 MOCK_SET(spdk_nvmf_tgt_find_subsystem, struct spdk_nvmf_subsystem *, &subsystem); 312 MOCK_SET(spdk_nvmf_poll_group_create, struct spdk_nvmf_poll_group *, &group); 313 314 /* Valid admin connect command */ 315 memset(&rsp, 0, sizeof(rsp)); 316 rc = spdk_nvmf_ctrlr_connect(&req); 317 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 318 CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status)); 319 CU_ASSERT(qpair.ctrlr != NULL); 320 free(qpair.ctrlr); 321 qpair.ctrlr = NULL; 322 323 /* Invalid data length */ 324 memset(&rsp, 0, sizeof(rsp)); 325 req.length = sizeof(connect_data) - 1; 326 rc = spdk_nvmf_ctrlr_connect(&req); 327 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 328 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 329 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 330 CU_ASSERT(qpair.ctrlr == NULL); 331 req.length = sizeof(connect_data); 332 333 /* Invalid recfmt */ 334 memset(&rsp, 0, sizeof(rsp)); 335 cmd.connect_cmd.recfmt = 1234; 336 rc = spdk_nvmf_ctrlr_connect(&req); 337 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 338 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 339 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INCOMPATIBLE_FORMAT); 340 CU_ASSERT(qpair.ctrlr == NULL); 341 cmd.connect_cmd.recfmt = 0; 342 343 /* Unterminated subnqn */ 344 memset(&rsp, 0, sizeof(rsp)); 345 memset(connect_data.subnqn, 'a', sizeof(connect_data.subnqn)); 346 rc = spdk_nvmf_ctrlr_connect(&req); 347 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 348 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 349 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 350 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1); 351 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 256); 352 CU_ASSERT(qpair.ctrlr == NULL); 353 strncpy(connect_data.subnqn, subnqn, sizeof(connect_data.subnqn)); 354 355 /* Subsystem not found */ 356 memset(&rsp, 0, sizeof(rsp)); 357 MOCK_SET(spdk_nvmf_tgt_find_subsystem, struct spdk_nvmf_subsystem *, NULL); 358 rc = spdk_nvmf_ctrlr_connect(&req); 359 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 360 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 361 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 362 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1); 363 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 256); 364 CU_ASSERT(qpair.ctrlr == NULL); 365 MOCK_SET(spdk_nvmf_tgt_find_subsystem, struct spdk_nvmf_subsystem *, &subsystem); 366 367 /* Unterminated hostnqn */ 368 memset(&rsp, 0, sizeof(rsp)); 369 memset(connect_data.hostnqn, 'b', sizeof(connect_data.hostnqn)); 370 rc = spdk_nvmf_ctrlr_connect(&req); 371 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 372 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 373 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 374 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1); 375 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 512); 376 CU_ASSERT(qpair.ctrlr == NULL); 377 strncpy(connect_data.hostnqn, hostnqn, sizeof(connect_data.hostnqn)); 378 379 /* Host not allowed */ 380 memset(&rsp, 0, sizeof(rsp)); 381 MOCK_SET(spdk_nvmf_subsystem_host_allowed, bool, false); 382 rc = spdk_nvmf_ctrlr_connect(&req); 383 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 384 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 385 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_HOST); 386 CU_ASSERT(qpair.ctrlr == NULL); 387 MOCK_SET(spdk_nvmf_subsystem_host_allowed, bool, true); 388 389 /* Invalid sqsize == 0 */ 390 memset(&rsp, 0, sizeof(rsp)); 391 cmd.connect_cmd.sqsize = 0; 392 rc = spdk_nvmf_ctrlr_connect(&req); 393 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 394 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 395 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 396 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 397 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 44); 398 CU_ASSERT(qpair.ctrlr == NULL); 399 cmd.connect_cmd.sqsize = 31; 400 401 /* Invalid sqsize > max_queue_depth */ 402 memset(&rsp, 0, sizeof(rsp)); 403 cmd.connect_cmd.sqsize = 64; 404 rc = spdk_nvmf_ctrlr_connect(&req); 405 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 406 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 407 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 408 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 409 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 44); 410 CU_ASSERT(qpair.ctrlr == NULL); 411 cmd.connect_cmd.sqsize = 31; 412 413 /* Invalid cntlid for admin queue */ 414 memset(&rsp, 0, sizeof(rsp)); 415 connect_data.cntlid = 0x1234; 416 rc = spdk_nvmf_ctrlr_connect(&req); 417 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 418 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 419 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 420 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1); 421 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 16); 422 CU_ASSERT(qpair.ctrlr == NULL); 423 connect_data.cntlid = 0xFFFF; 424 425 ctrlr.admin_qpair = &admin_qpair; 426 ctrlr.subsys = &subsystem; 427 428 /* Valid I/O queue connect command */ 429 memset(&rsp, 0, sizeof(rsp)); 430 MOCK_SET(spdk_nvmf_subsystem_get_ctrlr, struct spdk_nvmf_ctrlr *, &ctrlr); 431 cmd.connect_cmd.qid = 1; 432 rc = spdk_nvmf_ctrlr_connect(&req); 433 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 434 CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status)); 435 CU_ASSERT(qpair.ctrlr == &ctrlr); 436 qpair.ctrlr = NULL; 437 ctrlr.num_qpairs = 0; 438 TAILQ_INIT(&ctrlr.qpairs); 439 440 /* Non-existent controller */ 441 memset(&rsp, 0, sizeof(rsp)); 442 MOCK_SET(spdk_nvmf_subsystem_get_ctrlr, struct spdk_nvmf_ctrlr *, NULL); 443 rc = spdk_nvmf_ctrlr_connect(&req); 444 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 445 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 446 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 447 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1); 448 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 16); 449 CU_ASSERT(qpair.ctrlr == NULL); 450 MOCK_SET(spdk_nvmf_subsystem_get_ctrlr, struct spdk_nvmf_ctrlr *, &ctrlr); 451 452 /* I/O connect to discovery controller */ 453 memset(&rsp, 0, sizeof(rsp)); 454 subsystem.subtype = SPDK_NVMF_SUBTYPE_DISCOVERY; 455 rc = spdk_nvmf_ctrlr_connect(&req); 456 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 457 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 458 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 459 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 460 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42); 461 CU_ASSERT(qpair.ctrlr == NULL); 462 subsystem.subtype = SPDK_NVMF_SUBTYPE_NVME; 463 464 /* I/O connect to disabled controller */ 465 memset(&rsp, 0, sizeof(rsp)); 466 ctrlr.vcprop.cc.bits.en = 0; 467 rc = spdk_nvmf_ctrlr_connect(&req); 468 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 469 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 470 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 471 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 472 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42); 473 CU_ASSERT(qpair.ctrlr == NULL); 474 ctrlr.vcprop.cc.bits.en = 1; 475 476 /* I/O connect with invalid IOSQES */ 477 memset(&rsp, 0, sizeof(rsp)); 478 ctrlr.vcprop.cc.bits.iosqes = 3; 479 rc = spdk_nvmf_ctrlr_connect(&req); 480 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 481 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 482 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 483 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 484 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42); 485 CU_ASSERT(qpair.ctrlr == NULL); 486 ctrlr.vcprop.cc.bits.iosqes = 6; 487 488 /* I/O connect with invalid IOCQES */ 489 memset(&rsp, 0, sizeof(rsp)); 490 ctrlr.vcprop.cc.bits.iocqes = 3; 491 rc = spdk_nvmf_ctrlr_connect(&req); 492 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 493 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 494 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 495 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 496 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42); 497 CU_ASSERT(qpair.ctrlr == NULL); 498 ctrlr.vcprop.cc.bits.iocqes = 4; 499 500 /* I/O connect with too many existing qpairs */ 501 memset(&rsp, 0, sizeof(rsp)); 502 ctrlr.num_qpairs = 3; 503 rc = spdk_nvmf_ctrlr_connect(&req); 504 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 505 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 506 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_CONTROLLER_BUSY); 507 CU_ASSERT(qpair.ctrlr == NULL); 508 ctrlr.num_qpairs = 0; 509 510 /* I/O connect with duplicate queue ID */ 511 memset(&rsp, 0, sizeof(rsp)); 512 memset(&qpair2, 0, sizeof(qpair2)); 513 qpair2.group = &group; 514 qpair2.qid = 1; 515 TAILQ_INSERT_TAIL(&ctrlr.qpairs, &qpair, link); 516 cmd.connect_cmd.qid = 1; 517 rc = spdk_nvmf_ctrlr_connect(&req); 518 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 519 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 520 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_COMMAND_SEQUENCE_ERROR); 521 CU_ASSERT(qpair.ctrlr == NULL); 522 TAILQ_INIT(&ctrlr.qpairs); 523 524 /* Clean up globals */ 525 MOCK_SET(spdk_nvmf_tgt_find_subsystem, struct spdk_nvmf_subsystem *, NULL); 526 MOCK_SET(spdk_nvmf_poll_group_create, struct spdk_nvmf_poll_group *, NULL); 527 } 528 529 int main(int argc, char **argv) 530 { 531 CU_pSuite suite = NULL; 532 unsigned int num_failures; 533 534 if (CU_initialize_registry() != CUE_SUCCESS) { 535 return CU_get_error(); 536 } 537 538 suite = CU_add_suite("nvmf", NULL, NULL); 539 if (suite == NULL) { 540 CU_cleanup_registry(); 541 return CU_get_error(); 542 } 543 544 if ( 545 CU_add_test(suite, "get_log_page", test_get_log_page) == NULL || 546 CU_add_test(suite, "process_fabrics_cmd", test_process_fabrics_cmd) == NULL || 547 CU_add_test(suite, "connect", test_connect) == NULL 548 ) { 549 CU_cleanup_registry(); 550 return CU_get_error(); 551 } 552 553 CU_basic_set_mode(CU_BRM_VERBOSE); 554 CU_basic_run_tests(); 555 num_failures = CU_get_number_of_failures(); 556 CU_cleanup_registry(); 557 return num_failures; 558 } 559