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