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