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