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