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