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 #include "spdk_internal/thread.h" 39 40 #include "common/lib/ut_multithread.c" 41 #include "nvmf/ctrlr.c" 42 43 SPDK_LOG_REGISTER_COMPONENT("nvmf", SPDK_LOG_NVMF) 44 45 struct spdk_bdev { 46 int ut_mock; 47 uint64_t blockcnt; 48 }; 49 50 DEFINE_STUB(spdk_nvmf_tgt_find_subsystem, 51 struct spdk_nvmf_subsystem *, 52 (struct spdk_nvmf_tgt *tgt, const char *subnqn), 53 NULL); 54 55 DEFINE_STUB(spdk_nvmf_poll_group_create, 56 struct spdk_nvmf_poll_group *, 57 (struct spdk_nvmf_tgt *tgt), 58 NULL); 59 60 DEFINE_STUB_V(spdk_nvmf_poll_group_destroy, 61 (struct spdk_nvmf_poll_group *group)); 62 63 DEFINE_STUB_V(spdk_nvmf_transport_qpair_fini, 64 (struct spdk_nvmf_qpair *qpair)); 65 66 DEFINE_STUB(spdk_nvmf_poll_group_add, 67 int, 68 (struct spdk_nvmf_poll_group *group, struct spdk_nvmf_qpair *qpair), 69 0); 70 71 DEFINE_STUB(spdk_nvmf_subsystem_get_sn, 72 const char *, 73 (const struct spdk_nvmf_subsystem *subsystem), 74 NULL); 75 76 DEFINE_STUB(spdk_nvmf_subsystem_get_ns, 77 struct spdk_nvmf_ns *, 78 (struct spdk_nvmf_subsystem *subsystem, uint32_t nsid), 79 NULL); 80 81 DEFINE_STUB(spdk_nvmf_subsystem_get_first_ns, 82 struct spdk_nvmf_ns *, 83 (struct spdk_nvmf_subsystem *subsystem), 84 NULL); 85 86 DEFINE_STUB(spdk_nvmf_subsystem_get_next_ns, 87 struct spdk_nvmf_ns *, 88 (struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ns *prev_ns), 89 NULL); 90 91 DEFINE_STUB(spdk_nvmf_subsystem_host_allowed, 92 bool, 93 (struct spdk_nvmf_subsystem *subsystem, const char *hostnqn), 94 true); 95 96 DEFINE_STUB(spdk_nvmf_subsystem_add_ctrlr, 97 int, 98 (struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr), 99 0); 100 101 DEFINE_STUB_V(spdk_nvmf_subsystem_remove_ctrlr, 102 (struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr)); 103 104 DEFINE_STUB(spdk_nvmf_subsystem_get_ctrlr, 105 struct spdk_nvmf_ctrlr *, 106 (struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid), 107 NULL); 108 109 DEFINE_STUB(spdk_nvmf_ctrlr_dsm_supported, 110 bool, 111 (struct spdk_nvmf_ctrlr *ctrlr), 112 false); 113 114 DEFINE_STUB(spdk_nvmf_ctrlr_write_zeroes_supported, 115 bool, 116 (struct spdk_nvmf_ctrlr *ctrlr), 117 false); 118 119 DEFINE_STUB_V(spdk_nvmf_get_discovery_log_page, 120 (struct spdk_nvmf_tgt *tgt, struct iovec *iov, uint32_t iovcnt, uint64_t offset, uint32_t length)); 121 122 DEFINE_STUB(spdk_nvmf_request_complete, 123 int, 124 (struct spdk_nvmf_request *req), 125 -1); 126 127 DEFINE_STUB(spdk_nvmf_request_free, 128 int, 129 (struct spdk_nvmf_request *req), 130 -1); 131 132 DEFINE_STUB(spdk_nvmf_qpair_get_listen_trid, 133 int, 134 (struct spdk_nvmf_qpair *qpair, struct spdk_nvme_transport_id *trid), 135 0); 136 137 DEFINE_STUB(spdk_nvmf_subsystem_listener_allowed, 138 bool, 139 (struct spdk_nvmf_subsystem *subsystem, struct spdk_nvme_transport_id *trid), 140 true); 141 142 DEFINE_STUB(spdk_nvmf_transport_qpair_set_sqsize, 143 int, 144 (struct spdk_nvmf_qpair *qpair), 145 0); 146 147 void 148 spdk_nvmf_bdev_ctrlr_identify_ns(struct spdk_nvmf_ns *ns, struct spdk_nvme_ns_data *nsdata) 149 { 150 uint64_t num_blocks; 151 152 SPDK_CU_ASSERT_FATAL(ns->bdev != NULL); 153 num_blocks = ns->bdev->blockcnt; 154 nsdata->nsze = num_blocks; 155 nsdata->ncap = num_blocks; 156 nsdata->nuse = num_blocks; 157 nsdata->nlbaf = 0; 158 nsdata->flbas.format = 0; 159 nsdata->lbaf[0].lbads = spdk_u32log2(512); 160 } 161 162 static void 163 test_get_log_page(void) 164 { 165 struct spdk_nvmf_subsystem subsystem = {}; 166 struct spdk_nvmf_request req = {}; 167 struct spdk_nvmf_qpair qpair = {}; 168 struct spdk_nvmf_ctrlr ctrlr = {}; 169 union nvmf_h2c_msg cmd = {}; 170 union nvmf_c2h_msg rsp = {}; 171 char data[4096]; 172 173 subsystem.subtype = SPDK_NVMF_SUBTYPE_NVME; 174 175 ctrlr.subsys = &subsystem; 176 177 qpair.ctrlr = &ctrlr; 178 179 req.qpair = &qpair; 180 req.cmd = &cmd; 181 req.rsp = &rsp; 182 req.data = &data; 183 req.length = sizeof(data); 184 185 /* Get Log Page - all valid */ 186 memset(&cmd, 0, sizeof(cmd)); 187 memset(&rsp, 0, sizeof(rsp)); 188 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_LOG_PAGE; 189 cmd.nvme_cmd.cdw10 = SPDK_NVME_LOG_ERROR | (req.length / 4 - 1) << 16; 190 CU_ASSERT(spdk_nvmf_ctrlr_get_log_page(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 191 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 192 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 193 194 /* Get Log Page with invalid log ID */ 195 memset(&cmd, 0, sizeof(cmd)); 196 memset(&rsp, 0, sizeof(rsp)); 197 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_LOG_PAGE; 198 cmd.nvme_cmd.cdw10 = 0; 199 CU_ASSERT(spdk_nvmf_ctrlr_get_log_page(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 200 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 201 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 202 203 /* Get Log Page with invalid offset (not dword aligned) */ 204 memset(&cmd, 0, sizeof(cmd)); 205 memset(&rsp, 0, sizeof(rsp)); 206 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_LOG_PAGE; 207 cmd.nvme_cmd.cdw10 = SPDK_NVME_LOG_ERROR | (req.length / 4 - 1) << 16; 208 cmd.nvme_cmd.cdw12 = 2; 209 CU_ASSERT(spdk_nvmf_ctrlr_get_log_page(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 210 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 211 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 212 213 /* Get Log Page without data buffer */ 214 memset(&cmd, 0, sizeof(cmd)); 215 memset(&rsp, 0, sizeof(rsp)); 216 req.data = NULL; 217 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_LOG_PAGE; 218 cmd.nvme_cmd.cdw10 = SPDK_NVME_LOG_ERROR | (req.length / 4 - 1) << 16; 219 CU_ASSERT(spdk_nvmf_ctrlr_get_log_page(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 220 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 221 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 222 req.data = data; 223 } 224 225 static void 226 test_process_fabrics_cmd(void) 227 { 228 struct spdk_nvmf_request req = {}; 229 int ret; 230 struct spdk_nvmf_qpair req_qpair = {}; 231 union nvmf_h2c_msg req_cmd = {}; 232 union nvmf_c2h_msg req_rsp = {}; 233 234 req.qpair = &req_qpair; 235 req.cmd = &req_cmd; 236 req.rsp = &req_rsp; 237 req.qpair->ctrlr = NULL; 238 239 /* No ctrlr and invalid command check */ 240 req.cmd->nvmf_cmd.fctype = SPDK_NVMF_FABRIC_COMMAND_PROPERTY_GET; 241 ret = spdk_nvmf_ctrlr_process_fabrics_cmd(&req); 242 CU_ASSERT_EQUAL(req.rsp->nvme_cpl.status.sc, SPDK_NVME_SC_COMMAND_SEQUENCE_ERROR); 243 CU_ASSERT_EQUAL(ret, SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 244 } 245 246 static bool 247 nvme_status_success(const struct spdk_nvme_status *status) 248 { 249 return status->sct == SPDK_NVME_SCT_GENERIC && status->sc == SPDK_NVME_SC_SUCCESS; 250 } 251 252 static void 253 test_connect(void) 254 { 255 struct spdk_nvmf_fabric_connect_data connect_data; 256 struct spdk_nvmf_poll_group group; 257 struct spdk_nvmf_transport transport; 258 struct spdk_nvmf_subsystem subsystem; 259 struct spdk_nvmf_request req; 260 struct spdk_nvmf_qpair admin_qpair; 261 struct spdk_nvmf_qpair qpair; 262 struct spdk_nvmf_qpair qpair2; 263 struct spdk_nvmf_ctrlr ctrlr; 264 struct spdk_nvmf_tgt tgt; 265 union nvmf_h2c_msg cmd; 266 union nvmf_c2h_msg rsp; 267 const uint8_t hostid[16] = { 268 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 269 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F 270 }; 271 const char subnqn[] = "nqn.2016-06.io.spdk:subsystem1"; 272 const char hostnqn[] = "nqn.2016-06.io.spdk:host1"; 273 int rc; 274 275 memset(&group, 0, sizeof(group)); 276 group.thread = spdk_get_thread(); 277 278 memset(&ctrlr, 0, sizeof(ctrlr)); 279 ctrlr.subsys = &subsystem; 280 ctrlr.qpair_mask = spdk_bit_array_create(3); 281 SPDK_CU_ASSERT_FATAL(ctrlr.qpair_mask != NULL); 282 ctrlr.vcprop.cc.bits.en = 1; 283 ctrlr.vcprop.cc.bits.iosqes = 6; 284 ctrlr.vcprop.cc.bits.iocqes = 4; 285 286 memset(&admin_qpair, 0, sizeof(admin_qpair)); 287 admin_qpair.group = &group; 288 289 memset(&tgt, 0, sizeof(tgt)); 290 memset(&transport, 0, sizeof(transport)); 291 transport.opts.max_queue_depth = 64; 292 transport.opts.max_qpairs_per_ctrlr = 3; 293 transport.tgt = &tgt; 294 295 memset(&qpair, 0, sizeof(qpair)); 296 qpair.transport = &transport; 297 qpair.group = &group; 298 299 memset(&connect_data, 0, sizeof(connect_data)); 300 memcpy(connect_data.hostid, hostid, sizeof(hostid)); 301 connect_data.cntlid = 0xFFFF; 302 snprintf(connect_data.subnqn, sizeof(connect_data.subnqn), "%s", subnqn); 303 snprintf(connect_data.hostnqn, sizeof(connect_data.hostnqn), "%s", hostnqn); 304 305 memset(&subsystem, 0, sizeof(subsystem)); 306 subsystem.thread = spdk_get_thread(); 307 subsystem.id = 1; 308 TAILQ_INIT(&subsystem.ctrlrs); 309 subsystem.tgt = &tgt; 310 subsystem.subtype = SPDK_NVMF_SUBTYPE_NVME; 311 subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 312 snprintf(subsystem.subnqn, sizeof(subsystem.subnqn), "%s", subnqn); 313 314 memset(&cmd, 0, sizeof(cmd)); 315 cmd.connect_cmd.opcode = SPDK_NVME_OPC_FABRIC; 316 cmd.connect_cmd.cid = 1; 317 cmd.connect_cmd.fctype = SPDK_NVMF_FABRIC_COMMAND_CONNECT; 318 cmd.connect_cmd.recfmt = 0; 319 cmd.connect_cmd.qid = 0; 320 cmd.connect_cmd.sqsize = 31; 321 cmd.connect_cmd.cattr = 0; 322 cmd.connect_cmd.kato = 120000; 323 324 memset(&req, 0, sizeof(req)); 325 req.qpair = &qpair; 326 req.length = sizeof(connect_data); 327 req.xfer = SPDK_NVME_DATA_HOST_TO_CONTROLLER; 328 req.data = &connect_data; 329 req.cmd = &cmd; 330 req.rsp = &rsp; 331 332 MOCK_SET(spdk_nvmf_tgt_find_subsystem, &subsystem); 333 MOCK_SET(spdk_nvmf_poll_group_create, &group); 334 335 /* Valid admin connect command */ 336 memset(&rsp, 0, sizeof(rsp)); 337 rc = spdk_nvmf_ctrlr_connect(&req); 338 poll_threads(); 339 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 340 CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status)); 341 CU_ASSERT(qpair.ctrlr != NULL); 342 spdk_bit_array_free(&qpair.ctrlr->qpair_mask); 343 free(qpair.ctrlr); 344 qpair.ctrlr = NULL; 345 346 /* Invalid data length */ 347 memset(&rsp, 0, sizeof(rsp)); 348 req.length = sizeof(connect_data) - 1; 349 rc = spdk_nvmf_ctrlr_connect(&req); 350 poll_threads(); 351 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 352 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 353 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 354 CU_ASSERT(qpair.ctrlr == NULL); 355 req.length = sizeof(connect_data); 356 357 /* Invalid recfmt */ 358 memset(&rsp, 0, sizeof(rsp)); 359 cmd.connect_cmd.recfmt = 1234; 360 rc = spdk_nvmf_ctrlr_connect(&req); 361 poll_threads(); 362 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 363 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 364 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INCOMPATIBLE_FORMAT); 365 CU_ASSERT(qpair.ctrlr == NULL); 366 cmd.connect_cmd.recfmt = 0; 367 368 /* Unterminated subnqn */ 369 memset(&rsp, 0, sizeof(rsp)); 370 memset(connect_data.subnqn, 'a', sizeof(connect_data.subnqn)); 371 rc = spdk_nvmf_ctrlr_connect(&req); 372 poll_threads(); 373 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 374 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 375 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 376 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1); 377 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 256); 378 CU_ASSERT(qpair.ctrlr == NULL); 379 snprintf(connect_data.subnqn, sizeof(connect_data.subnqn), "%s", subnqn); 380 381 /* Subsystem not found */ 382 memset(&rsp, 0, sizeof(rsp)); 383 MOCK_SET(spdk_nvmf_tgt_find_subsystem, NULL); 384 rc = spdk_nvmf_ctrlr_connect(&req); 385 poll_threads(); 386 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 387 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 388 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 389 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1); 390 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 256); 391 CU_ASSERT(qpair.ctrlr == NULL); 392 MOCK_SET(spdk_nvmf_tgt_find_subsystem, &subsystem); 393 394 /* Unterminated hostnqn */ 395 memset(&rsp, 0, sizeof(rsp)); 396 memset(connect_data.hostnqn, 'b', sizeof(connect_data.hostnqn)); 397 rc = spdk_nvmf_ctrlr_connect(&req); 398 poll_threads(); 399 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 400 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 401 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 402 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1); 403 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 512); 404 CU_ASSERT(qpair.ctrlr == NULL); 405 snprintf(connect_data.hostnqn, sizeof(connect_data.hostnqn), "%s", hostnqn); 406 407 /* Host not allowed */ 408 memset(&rsp, 0, sizeof(rsp)); 409 MOCK_SET(spdk_nvmf_subsystem_host_allowed, false); 410 rc = spdk_nvmf_ctrlr_connect(&req); 411 poll_threads(); 412 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 413 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 414 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_HOST); 415 CU_ASSERT(qpair.ctrlr == NULL); 416 MOCK_SET(spdk_nvmf_subsystem_host_allowed, true); 417 418 /* Invalid sqsize == 0 */ 419 memset(&rsp, 0, sizeof(rsp)); 420 cmd.connect_cmd.sqsize = 0; 421 rc = spdk_nvmf_ctrlr_connect(&req); 422 poll_threads(); 423 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 424 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 425 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 426 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 427 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 44); 428 CU_ASSERT(qpair.ctrlr == NULL); 429 cmd.connect_cmd.sqsize = 31; 430 431 /* Invalid sqsize > max_queue_depth */ 432 memset(&rsp, 0, sizeof(rsp)); 433 cmd.connect_cmd.sqsize = 64; 434 rc = spdk_nvmf_ctrlr_connect(&req); 435 poll_threads(); 436 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 437 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 438 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 439 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 440 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 44); 441 CU_ASSERT(qpair.ctrlr == NULL); 442 cmd.connect_cmd.sqsize = 31; 443 444 /* Invalid cntlid for admin queue */ 445 memset(&rsp, 0, sizeof(rsp)); 446 connect_data.cntlid = 0x1234; 447 rc = spdk_nvmf_ctrlr_connect(&req); 448 poll_threads(); 449 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 450 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 451 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 452 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1); 453 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 16); 454 CU_ASSERT(qpair.ctrlr == NULL); 455 connect_data.cntlid = 0xFFFF; 456 457 ctrlr.admin_qpair = &admin_qpair; 458 ctrlr.subsys = &subsystem; 459 460 /* Valid I/O queue connect command */ 461 memset(&rsp, 0, sizeof(rsp)); 462 MOCK_SET(spdk_nvmf_subsystem_get_ctrlr, &ctrlr); 463 cmd.connect_cmd.qid = 1; 464 rc = spdk_nvmf_ctrlr_connect(&req); 465 poll_threads(); 466 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 467 CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status)); 468 CU_ASSERT(qpair.ctrlr == &ctrlr); 469 qpair.ctrlr = NULL; 470 471 /* Non-existent controller */ 472 memset(&rsp, 0, sizeof(rsp)); 473 MOCK_SET(spdk_nvmf_subsystem_get_ctrlr, NULL); 474 rc = spdk_nvmf_ctrlr_connect(&req); 475 poll_threads(); 476 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 477 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 478 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 479 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1); 480 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 16); 481 CU_ASSERT(qpair.ctrlr == NULL); 482 MOCK_SET(spdk_nvmf_subsystem_get_ctrlr, &ctrlr); 483 484 /* I/O connect to discovery controller */ 485 memset(&rsp, 0, sizeof(rsp)); 486 subsystem.subtype = SPDK_NVMF_SUBTYPE_DISCOVERY; 487 subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 488 rc = spdk_nvmf_ctrlr_connect(&req); 489 poll_threads(); 490 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 491 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 492 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 493 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 494 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42); 495 CU_ASSERT(qpair.ctrlr == NULL); 496 subsystem.subtype = SPDK_NVMF_SUBTYPE_NVME; 497 498 /* I/O connect to disabled controller */ 499 memset(&rsp, 0, sizeof(rsp)); 500 ctrlr.vcprop.cc.bits.en = 0; 501 rc = spdk_nvmf_ctrlr_connect(&req); 502 poll_threads(); 503 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 504 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 505 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 506 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 507 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42); 508 CU_ASSERT(qpair.ctrlr == NULL); 509 ctrlr.vcprop.cc.bits.en = 1; 510 511 /* I/O connect with invalid IOSQES */ 512 memset(&rsp, 0, sizeof(rsp)); 513 ctrlr.vcprop.cc.bits.iosqes = 3; 514 rc = spdk_nvmf_ctrlr_connect(&req); 515 poll_threads(); 516 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 517 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 518 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 519 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 520 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42); 521 CU_ASSERT(qpair.ctrlr == NULL); 522 ctrlr.vcprop.cc.bits.iosqes = 6; 523 524 /* I/O connect with invalid IOCQES */ 525 memset(&rsp, 0, sizeof(rsp)); 526 ctrlr.vcprop.cc.bits.iocqes = 3; 527 rc = spdk_nvmf_ctrlr_connect(&req); 528 poll_threads(); 529 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 530 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 531 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 532 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 533 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42); 534 CU_ASSERT(qpair.ctrlr == NULL); 535 ctrlr.vcprop.cc.bits.iocqes = 4; 536 537 /* I/O connect with too many existing qpairs */ 538 memset(&rsp, 0, sizeof(rsp)); 539 spdk_bit_array_set(ctrlr.qpair_mask, 0); 540 spdk_bit_array_set(ctrlr.qpair_mask, 1); 541 spdk_bit_array_set(ctrlr.qpair_mask, 2); 542 rc = spdk_nvmf_ctrlr_connect(&req); 543 poll_threads(); 544 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 545 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 546 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_QUEUE_IDENTIFIER); 547 CU_ASSERT(qpair.ctrlr == NULL); 548 spdk_bit_array_clear(ctrlr.qpair_mask, 0); 549 spdk_bit_array_clear(ctrlr.qpair_mask, 1); 550 spdk_bit_array_clear(ctrlr.qpair_mask, 2); 551 552 /* I/O connect with duplicate queue ID */ 553 memset(&rsp, 0, sizeof(rsp)); 554 memset(&qpair2, 0, sizeof(qpair2)); 555 qpair2.group = &group; 556 qpair2.qid = 1; 557 spdk_bit_array_set(ctrlr.qpair_mask, 1); 558 cmd.connect_cmd.qid = 1; 559 rc = spdk_nvmf_ctrlr_connect(&req); 560 poll_threads(); 561 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 562 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 563 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_QUEUE_IDENTIFIER); 564 CU_ASSERT(qpair.ctrlr == NULL); 565 566 /* Clean up globals */ 567 MOCK_CLEAR(spdk_nvmf_tgt_find_subsystem); 568 MOCK_CLEAR(spdk_nvmf_poll_group_create); 569 570 spdk_bit_array_free(&ctrlr.qpair_mask); 571 } 572 573 static void 574 test_get_ns_id_desc_list(void) 575 { 576 struct spdk_nvmf_subsystem subsystem; 577 struct spdk_nvmf_qpair qpair; 578 struct spdk_nvmf_ctrlr ctrlr; 579 struct spdk_nvmf_request req; 580 struct spdk_nvmf_ns *ns_ptrs[1]; 581 struct spdk_nvmf_ns ns; 582 union nvmf_h2c_msg cmd; 583 union nvmf_c2h_msg rsp; 584 struct spdk_bdev bdev; 585 uint8_t buf[4096]; 586 587 memset(&subsystem, 0, sizeof(subsystem)); 588 ns_ptrs[0] = &ns; 589 subsystem.ns = ns_ptrs; 590 subsystem.max_nsid = 1; 591 subsystem.subtype = SPDK_NVMF_SUBTYPE_NVME; 592 593 memset(&ns, 0, sizeof(ns)); 594 ns.opts.nsid = 1; 595 ns.bdev = &bdev; 596 597 memset(&qpair, 0, sizeof(qpair)); 598 qpair.ctrlr = &ctrlr; 599 600 memset(&ctrlr, 0, sizeof(ctrlr)); 601 ctrlr.subsys = &subsystem; 602 ctrlr.vcprop.cc.bits.en = 1; 603 604 memset(&req, 0, sizeof(req)); 605 req.qpair = &qpair; 606 req.cmd = &cmd; 607 req.rsp = &rsp; 608 req.xfer = SPDK_NVME_DATA_CONTROLLER_TO_HOST; 609 req.data = buf; 610 req.length = sizeof(buf); 611 612 memset(&cmd, 0, sizeof(cmd)); 613 cmd.nvme_cmd.opc = SPDK_NVME_OPC_IDENTIFY; 614 cmd.nvme_cmd.cdw10 = SPDK_NVME_IDENTIFY_NS_ID_DESCRIPTOR_LIST; 615 616 /* Invalid NSID */ 617 cmd.nvme_cmd.nsid = 0; 618 memset(&rsp, 0, sizeof(rsp)); 619 CU_ASSERT(spdk_nvmf_ctrlr_process_admin_cmd(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 620 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 621 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT); 622 623 /* Valid NSID, but ns has no IDs defined */ 624 cmd.nvme_cmd.nsid = 1; 625 memset(&rsp, 0, sizeof(rsp)); 626 CU_ASSERT(spdk_nvmf_ctrlr_process_admin_cmd(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 627 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 628 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 629 CU_ASSERT(spdk_mem_all_zero(buf, sizeof(buf))); 630 631 /* Valid NSID, only EUI64 defined */ 632 ns.opts.eui64[0] = 0x11; 633 ns.opts.eui64[7] = 0xFF; 634 memset(&rsp, 0, sizeof(rsp)); 635 CU_ASSERT(spdk_nvmf_ctrlr_process_admin_cmd(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 636 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 637 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 638 CU_ASSERT(buf[0] == SPDK_NVME_NIDT_EUI64); 639 CU_ASSERT(buf[1] == 8); 640 CU_ASSERT(buf[4] == 0x11); 641 CU_ASSERT(buf[11] == 0xFF); 642 CU_ASSERT(buf[13] == 0); 643 644 /* Valid NSID, only NGUID defined */ 645 memset(ns.opts.eui64, 0, sizeof(ns.opts.eui64)); 646 ns.opts.nguid[0] = 0x22; 647 ns.opts.nguid[15] = 0xEE; 648 memset(&rsp, 0, sizeof(rsp)); 649 CU_ASSERT(spdk_nvmf_ctrlr_process_admin_cmd(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 650 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 651 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 652 CU_ASSERT(buf[0] == SPDK_NVME_NIDT_NGUID); 653 CU_ASSERT(buf[1] == 16); 654 CU_ASSERT(buf[4] == 0x22); 655 CU_ASSERT(buf[19] == 0xEE); 656 CU_ASSERT(buf[21] == 0); 657 658 /* Valid NSID, both EUI64 and NGUID defined */ 659 ns.opts.eui64[0] = 0x11; 660 ns.opts.eui64[7] = 0xFF; 661 ns.opts.nguid[0] = 0x22; 662 ns.opts.nguid[15] = 0xEE; 663 memset(&rsp, 0, sizeof(rsp)); 664 CU_ASSERT(spdk_nvmf_ctrlr_process_admin_cmd(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 665 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 666 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 667 CU_ASSERT(buf[0] == SPDK_NVME_NIDT_EUI64); 668 CU_ASSERT(buf[1] == 8); 669 CU_ASSERT(buf[4] == 0x11); 670 CU_ASSERT(buf[11] == 0xFF); 671 CU_ASSERT(buf[12] == SPDK_NVME_NIDT_NGUID); 672 CU_ASSERT(buf[13] == 16); 673 CU_ASSERT(buf[16] == 0x22); 674 CU_ASSERT(buf[31] == 0xEE); 675 CU_ASSERT(buf[33] == 0); 676 677 /* Valid NSID, EUI64, NGUID, and UUID defined */ 678 ns.opts.eui64[0] = 0x11; 679 ns.opts.eui64[7] = 0xFF; 680 ns.opts.nguid[0] = 0x22; 681 ns.opts.nguid[15] = 0xEE; 682 ns.opts.uuid.u.raw[0] = 0x33; 683 ns.opts.uuid.u.raw[15] = 0xDD; 684 memset(&rsp, 0, sizeof(rsp)); 685 CU_ASSERT(spdk_nvmf_ctrlr_process_admin_cmd(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 686 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 687 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 688 CU_ASSERT(buf[0] == SPDK_NVME_NIDT_EUI64); 689 CU_ASSERT(buf[1] == 8); 690 CU_ASSERT(buf[4] == 0x11); 691 CU_ASSERT(buf[11] == 0xFF); 692 CU_ASSERT(buf[12] == SPDK_NVME_NIDT_NGUID); 693 CU_ASSERT(buf[13] == 16); 694 CU_ASSERT(buf[16] == 0x22); 695 CU_ASSERT(buf[31] == 0xEE); 696 CU_ASSERT(buf[32] == SPDK_NVME_NIDT_UUID); 697 CU_ASSERT(buf[33] == 16); 698 CU_ASSERT(buf[36] == 0x33); 699 CU_ASSERT(buf[51] == 0xDD); 700 CU_ASSERT(buf[53] == 0); 701 } 702 703 static void 704 test_identify_ns(void) 705 { 706 struct spdk_nvmf_subsystem subsystem = {}; 707 struct spdk_nvmf_transport transport = {}; 708 struct spdk_nvmf_qpair admin_qpair = { .transport = &transport}; 709 struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsystem, .admin_qpair = &admin_qpair }; 710 struct spdk_nvme_cmd cmd = {}; 711 struct spdk_nvme_cpl rsp = {}; 712 struct spdk_nvme_ns_data nsdata = {}; 713 struct spdk_bdev bdev[3] = {{.blockcnt = 1234}, {.blockcnt = 0}, {.blockcnt = 5678}}; 714 struct spdk_nvmf_ns ns[3] = {{.bdev = &bdev[0]}, {.bdev = NULL}, {.bdev = &bdev[2]}}; 715 struct spdk_nvmf_ns *ns_arr[3] = {&ns[0], NULL, &ns[2]}; 716 717 subsystem.ns = ns_arr; 718 subsystem.max_nsid = SPDK_COUNTOF(ns_arr); 719 720 /* Invalid NSID 0 */ 721 cmd.nsid = 0; 722 memset(&nsdata, 0, sizeof(nsdata)); 723 memset(&rsp, 0, sizeof(rsp)); 724 CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&ctrlr, &cmd, &rsp, 725 &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 726 CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); 727 CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT); 728 CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata))); 729 730 /* Valid NSID 1 */ 731 cmd.nsid = 1; 732 memset(&nsdata, 0, sizeof(nsdata)); 733 memset(&rsp, 0, sizeof(rsp)); 734 CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&ctrlr, &cmd, &rsp, 735 &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 736 CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); 737 CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS); 738 CU_ASSERT(nsdata.nsze == 1234); 739 740 /* Valid but inactive NSID 2 */ 741 cmd.nsid = 2; 742 memset(&nsdata, 0, sizeof(nsdata)); 743 memset(&rsp, 0, sizeof(rsp)); 744 CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&ctrlr, &cmd, &rsp, 745 &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 746 CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); 747 CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS); 748 CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata))); 749 750 /* Valid NSID 3 */ 751 cmd.nsid = 3; 752 memset(&nsdata, 0, sizeof(nsdata)); 753 memset(&rsp, 0, sizeof(rsp)); 754 CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&ctrlr, &cmd, &rsp, 755 &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 756 CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); 757 CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS); 758 CU_ASSERT(nsdata.nsze == 5678); 759 760 /* Invalid NSID 4 */ 761 cmd.nsid = 4; 762 memset(&nsdata, 0, sizeof(nsdata)); 763 memset(&rsp, 0, sizeof(rsp)); 764 CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&ctrlr, &cmd, &rsp, 765 &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 766 CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); 767 CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT); 768 CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata))); 769 770 /* Invalid NSID 0xFFFFFFFF (NS management not supported) */ 771 cmd.nsid = 0xFFFFFFFF; 772 memset(&nsdata, 0, sizeof(nsdata)); 773 memset(&rsp, 0, sizeof(rsp)); 774 CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&ctrlr, &cmd, &rsp, 775 &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 776 CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); 777 CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT); 778 CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata))); 779 } 780 781 int main(int argc, char **argv) 782 { 783 CU_pSuite suite = NULL; 784 unsigned int num_failures; 785 786 if (CU_initialize_registry() != CUE_SUCCESS) { 787 return CU_get_error(); 788 } 789 790 suite = CU_add_suite("nvmf", NULL, NULL); 791 if (suite == NULL) { 792 CU_cleanup_registry(); 793 return CU_get_error(); 794 } 795 796 if ( 797 CU_add_test(suite, "get_log_page", test_get_log_page) == NULL || 798 CU_add_test(suite, "process_fabrics_cmd", test_process_fabrics_cmd) == NULL || 799 CU_add_test(suite, "connect", test_connect) == NULL || 800 CU_add_test(suite, "get_ns_id_desc_list", test_get_ns_id_desc_list) == NULL || 801 CU_add_test(suite, "identify_ns", test_identify_ns) == NULL 802 ) { 803 CU_cleanup_registry(); 804 return CU_get_error(); 805 } 806 807 allocate_threads(1); 808 set_thread(0); 809 810 CU_basic_set_mode(CU_BRM_VERBOSE); 811 CU_basic_run_tests(); 812 num_failures = CU_get_number_of_failures(); 813 CU_cleanup_registry(); 814 815 free_threads(); 816 817 return num_failures; 818 } 819