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/ut_multithread.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(spdk_nvmf_subsystem_get_sn, 61 const char *, 62 (const struct spdk_nvmf_subsystem *subsystem), 63 NULL); 64 65 DEFINE_STUB(spdk_nvmf_subsystem_get_mn, 66 const char *, 67 (const struct spdk_nvmf_subsystem *subsystem), 68 NULL); 69 70 DEFINE_STUB(spdk_nvmf_subsystem_get_first_ns, 71 struct spdk_nvmf_ns *, 72 (struct spdk_nvmf_subsystem *subsystem), 73 NULL); 74 75 DEFINE_STUB(spdk_nvmf_subsystem_get_next_ns, 76 struct spdk_nvmf_ns *, 77 (struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ns *prev_ns), 78 NULL); 79 80 DEFINE_STUB(spdk_nvmf_subsystem_host_allowed, 81 bool, 82 (struct spdk_nvmf_subsystem *subsystem, const char *hostnqn), 83 true); 84 85 DEFINE_STUB(spdk_nvmf_subsystem_add_ctrlr, 86 int, 87 (struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr), 88 0); 89 90 DEFINE_STUB(spdk_nvmf_subsystem_get_ctrlr, 91 struct spdk_nvmf_ctrlr *, 92 (struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid), 93 NULL); 94 95 DEFINE_STUB(spdk_nvmf_ctrlr_dsm_supported, 96 bool, 97 (struct spdk_nvmf_ctrlr *ctrlr), 98 false); 99 100 DEFINE_STUB(spdk_nvmf_ctrlr_write_zeroes_supported, 101 bool, 102 (struct spdk_nvmf_ctrlr *ctrlr), 103 false); 104 105 DEFINE_STUB_V(spdk_nvmf_get_discovery_log_page, 106 (struct spdk_nvmf_tgt *tgt, struct iovec *iov, uint32_t iovcnt, uint64_t offset, uint32_t length)); 107 108 DEFINE_STUB(spdk_nvmf_qpair_get_listen_trid, 109 int, 110 (struct spdk_nvmf_qpair *qpair, struct spdk_nvme_transport_id *trid), 111 0); 112 113 DEFINE_STUB(spdk_nvmf_subsystem_listener_allowed, 114 bool, 115 (struct spdk_nvmf_subsystem *subsystem, struct spdk_nvme_transport_id *trid), 116 true); 117 118 DEFINE_STUB(spdk_nvmf_transport_qpair_set_sqsize, 119 int, 120 (struct spdk_nvmf_qpair *qpair), 121 0); 122 123 DEFINE_STUB(spdk_nvmf_bdev_ctrlr_read_cmd, 124 int, 125 (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, 126 struct spdk_nvmf_request *req), 127 0); 128 129 DEFINE_STUB(spdk_nvmf_bdev_ctrlr_write_cmd, 130 int, 131 (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, 132 struct spdk_nvmf_request *req), 133 0); 134 135 DEFINE_STUB(spdk_nvmf_bdev_ctrlr_write_zeroes_cmd, 136 int, 137 (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, 138 struct spdk_nvmf_request *req), 139 0); 140 141 DEFINE_STUB(spdk_nvmf_bdev_ctrlr_flush_cmd, 142 int, 143 (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, 144 struct spdk_nvmf_request *req), 145 0); 146 147 DEFINE_STUB(spdk_nvmf_bdev_ctrlr_dsm_cmd, 148 int, 149 (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, 150 struct spdk_nvmf_request *req), 151 0); 152 153 DEFINE_STUB(spdk_nvmf_bdev_ctrlr_nvme_passthru_io, 154 int, 155 (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, 156 struct spdk_nvmf_request *req), 157 0); 158 159 DEFINE_STUB(spdk_nvmf_transport_req_complete, 160 int, 161 (struct spdk_nvmf_request *req), 162 0); 163 164 DEFINE_STUB_V(spdk_nvmf_ns_reservation_request, (void *ctx)); 165 166 int 167 spdk_nvmf_qpair_disconnect(struct spdk_nvmf_qpair *qpair, nvmf_qpair_disconnect_cb cb_fn, void *ctx) 168 { 169 return 0; 170 } 171 172 void 173 spdk_nvmf_bdev_ctrlr_identify_ns(struct spdk_nvmf_ns *ns, struct spdk_nvme_ns_data *nsdata) 174 { 175 uint64_t num_blocks; 176 177 SPDK_CU_ASSERT_FATAL(ns->bdev != NULL); 178 num_blocks = ns->bdev->blockcnt; 179 nsdata->nsze = num_blocks; 180 nsdata->ncap = num_blocks; 181 nsdata->nuse = num_blocks; 182 nsdata->nlbaf = 0; 183 nsdata->flbas.format = 0; 184 nsdata->lbaf[0].lbads = spdk_u32log2(512); 185 } 186 187 static void 188 test_get_log_page(void) 189 { 190 struct spdk_nvmf_subsystem subsystem = {}; 191 struct spdk_nvmf_request req = {}; 192 struct spdk_nvmf_qpair qpair = {}; 193 struct spdk_nvmf_ctrlr ctrlr = {}; 194 union nvmf_h2c_msg cmd = {}; 195 union nvmf_c2h_msg rsp = {}; 196 char data[4096]; 197 198 subsystem.subtype = SPDK_NVMF_SUBTYPE_NVME; 199 200 ctrlr.subsys = &subsystem; 201 202 qpair.ctrlr = &ctrlr; 203 204 req.qpair = &qpair; 205 req.cmd = &cmd; 206 req.rsp = &rsp; 207 req.data = &data; 208 req.length = sizeof(data); 209 210 /* Get Log Page - all valid */ 211 memset(&cmd, 0, sizeof(cmd)); 212 memset(&rsp, 0, sizeof(rsp)); 213 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_LOG_PAGE; 214 cmd.nvme_cmd.cdw10 = SPDK_NVME_LOG_ERROR | (req.length / 4 - 1) << 16; 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_SUCCESS); 218 219 /* Get Log Page with invalid log ID */ 220 memset(&cmd, 0, sizeof(cmd)); 221 memset(&rsp, 0, sizeof(rsp)); 222 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_LOG_PAGE; 223 cmd.nvme_cmd.cdw10 = 0; 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 228 /* Get Log Page with invalid offset (not dword aligned) */ 229 memset(&cmd, 0, sizeof(cmd)); 230 memset(&rsp, 0, sizeof(rsp)); 231 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_LOG_PAGE; 232 cmd.nvme_cmd.cdw10 = SPDK_NVME_LOG_ERROR | (req.length / 4 - 1) << 16; 233 cmd.nvme_cmd.cdw12 = 2; 234 CU_ASSERT(spdk_nvmf_ctrlr_get_log_page(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 235 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 236 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 237 238 /* Get Log Page without data buffer */ 239 memset(&cmd, 0, sizeof(cmd)); 240 memset(&rsp, 0, sizeof(rsp)); 241 req.data = NULL; 242 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_LOG_PAGE; 243 cmd.nvme_cmd.cdw10 = SPDK_NVME_LOG_ERROR | (req.length / 4 - 1) << 16; 244 CU_ASSERT(spdk_nvmf_ctrlr_get_log_page(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 245 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 246 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 247 req.data = data; 248 } 249 250 static void 251 test_process_fabrics_cmd(void) 252 { 253 struct spdk_nvmf_request req = {}; 254 int ret; 255 struct spdk_nvmf_qpair req_qpair = {}; 256 union nvmf_h2c_msg req_cmd = {}; 257 union nvmf_c2h_msg req_rsp = {}; 258 259 req.qpair = &req_qpair; 260 req.cmd = &req_cmd; 261 req.rsp = &req_rsp; 262 req.qpair->ctrlr = NULL; 263 264 /* No ctrlr and invalid command check */ 265 req.cmd->nvmf_cmd.fctype = SPDK_NVMF_FABRIC_COMMAND_PROPERTY_GET; 266 ret = spdk_nvmf_ctrlr_process_fabrics_cmd(&req); 267 CU_ASSERT_EQUAL(req.rsp->nvme_cpl.status.sc, SPDK_NVME_SC_COMMAND_SEQUENCE_ERROR); 268 CU_ASSERT_EQUAL(ret, SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 269 } 270 271 static bool 272 nvme_status_success(const struct spdk_nvme_status *status) 273 { 274 return status->sct == SPDK_NVME_SCT_GENERIC && status->sc == SPDK_NVME_SC_SUCCESS; 275 } 276 277 static void 278 test_connect(void) 279 { 280 struct spdk_nvmf_fabric_connect_data connect_data; 281 struct spdk_nvmf_poll_group group; 282 struct spdk_nvmf_transport transport; 283 struct spdk_nvmf_subsystem subsystem; 284 struct spdk_nvmf_request req; 285 struct spdk_nvmf_qpair admin_qpair; 286 struct spdk_nvmf_qpair qpair; 287 struct spdk_nvmf_qpair qpair2; 288 struct spdk_nvmf_ctrlr ctrlr; 289 struct spdk_nvmf_tgt tgt; 290 union nvmf_h2c_msg cmd; 291 union nvmf_c2h_msg rsp; 292 const uint8_t hostid[16] = { 293 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 294 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F 295 }; 296 const char subnqn[] = "nqn.2016-06.io.spdk:subsystem1"; 297 const char hostnqn[] = "nqn.2016-06.io.spdk:host1"; 298 int rc; 299 300 memset(&group, 0, sizeof(group)); 301 group.thread = spdk_get_thread(); 302 303 memset(&ctrlr, 0, sizeof(ctrlr)); 304 ctrlr.subsys = &subsystem; 305 ctrlr.qpair_mask = spdk_bit_array_create(3); 306 SPDK_CU_ASSERT_FATAL(ctrlr.qpair_mask != NULL); 307 ctrlr.vcprop.cc.bits.en = 1; 308 ctrlr.vcprop.cc.bits.iosqes = 6; 309 ctrlr.vcprop.cc.bits.iocqes = 4; 310 311 memset(&admin_qpair, 0, sizeof(admin_qpair)); 312 admin_qpair.group = &group; 313 314 memset(&tgt, 0, sizeof(tgt)); 315 memset(&transport, 0, sizeof(transport)); 316 transport.opts.max_aq_depth = 32; 317 transport.opts.max_queue_depth = 64; 318 transport.opts.max_qpairs_per_ctrlr = 3; 319 transport.tgt = &tgt; 320 321 memset(&qpair, 0, sizeof(qpair)); 322 qpair.transport = &transport; 323 qpair.group = &group; 324 qpair.state = SPDK_NVMF_QPAIR_ACTIVE; 325 TAILQ_INIT(&qpair.outstanding); 326 327 memset(&connect_data, 0, sizeof(connect_data)); 328 memcpy(connect_data.hostid, hostid, sizeof(hostid)); 329 connect_data.cntlid = 0xFFFF; 330 snprintf(connect_data.subnqn, sizeof(connect_data.subnqn), "%s", subnqn); 331 snprintf(connect_data.hostnqn, sizeof(connect_data.hostnqn), "%s", hostnqn); 332 333 memset(&subsystem, 0, sizeof(subsystem)); 334 subsystem.thread = spdk_get_thread(); 335 subsystem.id = 1; 336 TAILQ_INIT(&subsystem.ctrlrs); 337 subsystem.tgt = &tgt; 338 subsystem.subtype = SPDK_NVMF_SUBTYPE_NVME; 339 subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 340 snprintf(subsystem.subnqn, sizeof(subsystem.subnqn), "%s", subnqn); 341 342 memset(&cmd, 0, sizeof(cmd)); 343 cmd.connect_cmd.opcode = SPDK_NVME_OPC_FABRIC; 344 cmd.connect_cmd.cid = 1; 345 cmd.connect_cmd.fctype = SPDK_NVMF_FABRIC_COMMAND_CONNECT; 346 cmd.connect_cmd.recfmt = 0; 347 cmd.connect_cmd.qid = 0; 348 cmd.connect_cmd.sqsize = 31; 349 cmd.connect_cmd.cattr = 0; 350 cmd.connect_cmd.kato = 120000; 351 352 memset(&req, 0, sizeof(req)); 353 req.qpair = &qpair; 354 req.length = sizeof(connect_data); 355 req.xfer = SPDK_NVME_DATA_HOST_TO_CONTROLLER; 356 req.data = &connect_data; 357 req.cmd = &cmd; 358 req.rsp = &rsp; 359 360 MOCK_SET(spdk_nvmf_tgt_find_subsystem, &subsystem); 361 MOCK_SET(spdk_nvmf_poll_group_create, &group); 362 363 /* Valid admin connect command */ 364 memset(&rsp, 0, sizeof(rsp)); 365 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 366 rc = spdk_nvmf_ctrlr_connect(&req); 367 poll_threads(); 368 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 369 CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status)); 370 CU_ASSERT(qpair.ctrlr != NULL); 371 spdk_nvmf_ctrlr_stop_keep_alive_timer(qpair.ctrlr); 372 spdk_bit_array_free(&qpair.ctrlr->qpair_mask); 373 free(qpair.ctrlr); 374 qpair.ctrlr = NULL; 375 376 /* Valid admin connect command with kato = 0 */ 377 cmd.connect_cmd.kato = 0; 378 memset(&rsp, 0, sizeof(rsp)); 379 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 380 rc = spdk_nvmf_ctrlr_connect(&req); 381 poll_threads(); 382 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 383 CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status)); 384 CU_ASSERT(qpair.ctrlr != NULL && qpair.ctrlr->keep_alive_poller == NULL); 385 spdk_bit_array_free(&qpair.ctrlr->qpair_mask); 386 free(qpair.ctrlr); 387 qpair.ctrlr = NULL; 388 cmd.connect_cmd.kato = 120000; 389 390 /* Invalid data length */ 391 memset(&rsp, 0, sizeof(rsp)); 392 req.length = sizeof(connect_data) - 1; 393 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 394 rc = spdk_nvmf_ctrlr_connect(&req); 395 poll_threads(); 396 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 397 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 398 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 399 CU_ASSERT(qpair.ctrlr == NULL); 400 req.length = sizeof(connect_data); 401 402 /* Invalid recfmt */ 403 memset(&rsp, 0, sizeof(rsp)); 404 cmd.connect_cmd.recfmt = 1234; 405 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 406 rc = spdk_nvmf_ctrlr_connect(&req); 407 poll_threads(); 408 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 409 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 410 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INCOMPATIBLE_FORMAT); 411 CU_ASSERT(qpair.ctrlr == NULL); 412 cmd.connect_cmd.recfmt = 0; 413 414 /* Unterminated subnqn */ 415 memset(&rsp, 0, sizeof(rsp)); 416 memset(connect_data.subnqn, 'a', sizeof(connect_data.subnqn)); 417 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 418 rc = spdk_nvmf_ctrlr_connect(&req); 419 poll_threads(); 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 == 1); 424 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 256); 425 CU_ASSERT(qpair.ctrlr == NULL); 426 snprintf(connect_data.subnqn, sizeof(connect_data.subnqn), "%s", subnqn); 427 428 /* Subsystem not found */ 429 memset(&rsp, 0, sizeof(rsp)); 430 MOCK_SET(spdk_nvmf_tgt_find_subsystem, NULL); 431 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 432 rc = spdk_nvmf_ctrlr_connect(&req); 433 poll_threads(); 434 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 435 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 436 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 437 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1); 438 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 256); 439 CU_ASSERT(qpair.ctrlr == NULL); 440 MOCK_SET(spdk_nvmf_tgt_find_subsystem, &subsystem); 441 442 /* Unterminated hostnqn */ 443 memset(&rsp, 0, sizeof(rsp)); 444 memset(connect_data.hostnqn, 'b', sizeof(connect_data.hostnqn)); 445 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 446 rc = spdk_nvmf_ctrlr_connect(&req); 447 poll_threads(); 448 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 449 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 450 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 451 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1); 452 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 512); 453 CU_ASSERT(qpair.ctrlr == NULL); 454 snprintf(connect_data.hostnqn, sizeof(connect_data.hostnqn), "%s", hostnqn); 455 456 /* Host not allowed */ 457 memset(&rsp, 0, sizeof(rsp)); 458 MOCK_SET(spdk_nvmf_subsystem_host_allowed, false); 459 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 460 rc = spdk_nvmf_ctrlr_connect(&req); 461 poll_threads(); 462 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 463 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 464 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_HOST); 465 CU_ASSERT(qpair.ctrlr == NULL); 466 MOCK_SET(spdk_nvmf_subsystem_host_allowed, true); 467 468 /* Invalid sqsize == 0 */ 469 memset(&rsp, 0, sizeof(rsp)); 470 cmd.connect_cmd.sqsize = 0; 471 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 472 rc = spdk_nvmf_ctrlr_connect(&req); 473 poll_threads(); 474 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 475 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 476 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 477 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 478 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 44); 479 CU_ASSERT(qpair.ctrlr == NULL); 480 cmd.connect_cmd.sqsize = 31; 481 482 /* Invalid sqsize > max_queue_depth */ 483 memset(&rsp, 0, sizeof(rsp)); 484 cmd.connect_cmd.sqsize = 64; 485 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 486 rc = spdk_nvmf_ctrlr_connect(&req); 487 poll_threads(); 488 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 489 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 490 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 491 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 492 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 44); 493 CU_ASSERT(qpair.ctrlr == NULL); 494 cmd.connect_cmd.sqsize = 31; 495 496 /* Invalid cntlid for admin queue */ 497 memset(&rsp, 0, sizeof(rsp)); 498 connect_data.cntlid = 0x1234; 499 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 500 rc = spdk_nvmf_ctrlr_connect(&req); 501 poll_threads(); 502 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 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 == 1); 506 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 16); 507 CU_ASSERT(qpair.ctrlr == NULL); 508 connect_data.cntlid = 0xFFFF; 509 510 ctrlr.admin_qpair = &admin_qpair; 511 ctrlr.subsys = &subsystem; 512 513 /* Valid I/O queue connect command */ 514 memset(&rsp, 0, sizeof(rsp)); 515 MOCK_SET(spdk_nvmf_subsystem_get_ctrlr, &ctrlr); 516 cmd.connect_cmd.qid = 1; 517 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 518 rc = spdk_nvmf_ctrlr_connect(&req); 519 poll_threads(); 520 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 521 CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status)); 522 CU_ASSERT(qpair.ctrlr == &ctrlr); 523 qpair.ctrlr = NULL; 524 525 /* Non-existent controller */ 526 memset(&rsp, 0, sizeof(rsp)); 527 MOCK_SET(spdk_nvmf_subsystem_get_ctrlr, NULL); 528 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 529 rc = spdk_nvmf_ctrlr_connect(&req); 530 poll_threads(); 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_NVMF_FABRIC_SC_INVALID_PARAM); 534 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1); 535 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 16); 536 CU_ASSERT(qpair.ctrlr == NULL); 537 MOCK_SET(spdk_nvmf_subsystem_get_ctrlr, &ctrlr); 538 539 /* I/O connect to discovery controller */ 540 memset(&rsp, 0, sizeof(rsp)); 541 subsystem.subtype = SPDK_NVMF_SUBTYPE_DISCOVERY; 542 subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 543 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 544 rc = spdk_nvmf_ctrlr_connect(&req); 545 poll_threads(); 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_NVMF_FABRIC_SC_INVALID_PARAM); 549 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 550 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42); 551 CU_ASSERT(qpair.ctrlr == NULL); 552 553 /* I/O connect to discovery controller keep-alive-timeout should be 0 */ 554 cmd.connect_cmd.qid = 0; 555 memset(&rsp, 0, sizeof(rsp)); 556 subsystem.subtype = SPDK_NVMF_SUBTYPE_DISCOVERY; 557 subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 558 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 559 rc = spdk_nvmf_ctrlr_connect(&req); 560 poll_threads(); 561 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 562 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 563 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INTERNAL_DEVICE_ERROR); 564 CU_ASSERT(qpair.ctrlr == NULL); 565 cmd.connect_cmd.qid = 1; 566 subsystem.subtype = SPDK_NVMF_SUBTYPE_NVME; 567 568 /* I/O connect to disabled controller */ 569 memset(&rsp, 0, sizeof(rsp)); 570 ctrlr.vcprop.cc.bits.en = 0; 571 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 572 rc = spdk_nvmf_ctrlr_connect(&req); 573 poll_threads(); 574 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 575 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 576 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 577 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 578 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42); 579 CU_ASSERT(qpair.ctrlr == NULL); 580 ctrlr.vcprop.cc.bits.en = 1; 581 582 /* I/O connect with invalid IOSQES */ 583 memset(&rsp, 0, sizeof(rsp)); 584 ctrlr.vcprop.cc.bits.iosqes = 3; 585 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 586 rc = spdk_nvmf_ctrlr_connect(&req); 587 poll_threads(); 588 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 589 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 590 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 591 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 592 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42); 593 CU_ASSERT(qpair.ctrlr == NULL); 594 ctrlr.vcprop.cc.bits.iosqes = 6; 595 596 /* I/O connect with invalid IOCQES */ 597 memset(&rsp, 0, sizeof(rsp)); 598 ctrlr.vcprop.cc.bits.iocqes = 3; 599 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 600 rc = spdk_nvmf_ctrlr_connect(&req); 601 poll_threads(); 602 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 603 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 604 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 605 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 606 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42); 607 CU_ASSERT(qpair.ctrlr == NULL); 608 ctrlr.vcprop.cc.bits.iocqes = 4; 609 610 /* I/O connect with too many existing qpairs */ 611 memset(&rsp, 0, sizeof(rsp)); 612 spdk_bit_array_set(ctrlr.qpair_mask, 0); 613 spdk_bit_array_set(ctrlr.qpair_mask, 1); 614 spdk_bit_array_set(ctrlr.qpair_mask, 2); 615 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 616 rc = spdk_nvmf_ctrlr_connect(&req); 617 poll_threads(); 618 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 619 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 620 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_QUEUE_IDENTIFIER); 621 CU_ASSERT(qpair.ctrlr == NULL); 622 spdk_bit_array_clear(ctrlr.qpair_mask, 0); 623 spdk_bit_array_clear(ctrlr.qpair_mask, 1); 624 spdk_bit_array_clear(ctrlr.qpair_mask, 2); 625 626 /* I/O connect with duplicate queue ID */ 627 memset(&rsp, 0, sizeof(rsp)); 628 memset(&qpair2, 0, sizeof(qpair2)); 629 qpair2.group = &group; 630 qpair2.qid = 1; 631 spdk_bit_array_set(ctrlr.qpair_mask, 1); 632 cmd.connect_cmd.qid = 1; 633 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 634 rc = spdk_nvmf_ctrlr_connect(&req); 635 poll_threads(); 636 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 637 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 638 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_QUEUE_IDENTIFIER); 639 CU_ASSERT(qpair.ctrlr == NULL); 640 641 /* Clean up globals */ 642 MOCK_CLEAR(spdk_nvmf_tgt_find_subsystem); 643 MOCK_CLEAR(spdk_nvmf_poll_group_create); 644 645 spdk_bit_array_free(&ctrlr.qpair_mask); 646 } 647 648 static void 649 test_get_ns_id_desc_list(void) 650 { 651 struct spdk_nvmf_subsystem subsystem; 652 struct spdk_nvmf_qpair qpair; 653 struct spdk_nvmf_ctrlr ctrlr; 654 struct spdk_nvmf_request req; 655 struct spdk_nvmf_ns *ns_ptrs[1]; 656 struct spdk_nvmf_ns ns; 657 union nvmf_h2c_msg cmd; 658 union nvmf_c2h_msg rsp; 659 struct spdk_bdev bdev; 660 uint8_t buf[4096]; 661 662 memset(&subsystem, 0, sizeof(subsystem)); 663 ns_ptrs[0] = &ns; 664 subsystem.ns = ns_ptrs; 665 subsystem.max_nsid = 1; 666 subsystem.subtype = SPDK_NVMF_SUBTYPE_NVME; 667 668 memset(&ns, 0, sizeof(ns)); 669 ns.opts.nsid = 1; 670 ns.bdev = &bdev; 671 672 memset(&qpair, 0, sizeof(qpair)); 673 qpair.ctrlr = &ctrlr; 674 675 memset(&ctrlr, 0, sizeof(ctrlr)); 676 ctrlr.subsys = &subsystem; 677 ctrlr.vcprop.cc.bits.en = 1; 678 679 memset(&req, 0, sizeof(req)); 680 req.qpair = &qpair; 681 req.cmd = &cmd; 682 req.rsp = &rsp; 683 req.xfer = SPDK_NVME_DATA_CONTROLLER_TO_HOST; 684 req.data = buf; 685 req.length = sizeof(buf); 686 687 memset(&cmd, 0, sizeof(cmd)); 688 cmd.nvme_cmd.opc = SPDK_NVME_OPC_IDENTIFY; 689 cmd.nvme_cmd.cdw10 = SPDK_NVME_IDENTIFY_NS_ID_DESCRIPTOR_LIST; 690 691 /* Invalid NSID */ 692 cmd.nvme_cmd.nsid = 0; 693 memset(&rsp, 0, sizeof(rsp)); 694 CU_ASSERT(spdk_nvmf_ctrlr_process_admin_cmd(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 695 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 696 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT); 697 698 /* Valid NSID, but ns has no IDs defined */ 699 cmd.nvme_cmd.nsid = 1; 700 memset(&rsp, 0, sizeof(rsp)); 701 CU_ASSERT(spdk_nvmf_ctrlr_process_admin_cmd(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 702 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 703 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 704 CU_ASSERT(spdk_mem_all_zero(buf, sizeof(buf))); 705 706 /* Valid NSID, only EUI64 defined */ 707 ns.opts.eui64[0] = 0x11; 708 ns.opts.eui64[7] = 0xFF; 709 memset(&rsp, 0, sizeof(rsp)); 710 CU_ASSERT(spdk_nvmf_ctrlr_process_admin_cmd(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 711 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 712 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 713 CU_ASSERT(buf[0] == SPDK_NVME_NIDT_EUI64); 714 CU_ASSERT(buf[1] == 8); 715 CU_ASSERT(buf[4] == 0x11); 716 CU_ASSERT(buf[11] == 0xFF); 717 CU_ASSERT(buf[13] == 0); 718 719 /* Valid NSID, only NGUID defined */ 720 memset(ns.opts.eui64, 0, sizeof(ns.opts.eui64)); 721 ns.opts.nguid[0] = 0x22; 722 ns.opts.nguid[15] = 0xEE; 723 memset(&rsp, 0, sizeof(rsp)); 724 CU_ASSERT(spdk_nvmf_ctrlr_process_admin_cmd(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 725 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 726 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 727 CU_ASSERT(buf[0] == SPDK_NVME_NIDT_NGUID); 728 CU_ASSERT(buf[1] == 16); 729 CU_ASSERT(buf[4] == 0x22); 730 CU_ASSERT(buf[19] == 0xEE); 731 CU_ASSERT(buf[21] == 0); 732 733 /* Valid NSID, both EUI64 and NGUID defined */ 734 ns.opts.eui64[0] = 0x11; 735 ns.opts.eui64[7] = 0xFF; 736 ns.opts.nguid[0] = 0x22; 737 ns.opts.nguid[15] = 0xEE; 738 memset(&rsp, 0, sizeof(rsp)); 739 CU_ASSERT(spdk_nvmf_ctrlr_process_admin_cmd(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 740 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 741 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 742 CU_ASSERT(buf[0] == SPDK_NVME_NIDT_EUI64); 743 CU_ASSERT(buf[1] == 8); 744 CU_ASSERT(buf[4] == 0x11); 745 CU_ASSERT(buf[11] == 0xFF); 746 CU_ASSERT(buf[12] == SPDK_NVME_NIDT_NGUID); 747 CU_ASSERT(buf[13] == 16); 748 CU_ASSERT(buf[16] == 0x22); 749 CU_ASSERT(buf[31] == 0xEE); 750 CU_ASSERT(buf[33] == 0); 751 752 /* Valid NSID, EUI64, NGUID, and UUID defined */ 753 ns.opts.eui64[0] = 0x11; 754 ns.opts.eui64[7] = 0xFF; 755 ns.opts.nguid[0] = 0x22; 756 ns.opts.nguid[15] = 0xEE; 757 ns.opts.uuid.u.raw[0] = 0x33; 758 ns.opts.uuid.u.raw[15] = 0xDD; 759 memset(&rsp, 0, sizeof(rsp)); 760 CU_ASSERT(spdk_nvmf_ctrlr_process_admin_cmd(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 761 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 762 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 763 CU_ASSERT(buf[0] == SPDK_NVME_NIDT_EUI64); 764 CU_ASSERT(buf[1] == 8); 765 CU_ASSERT(buf[4] == 0x11); 766 CU_ASSERT(buf[11] == 0xFF); 767 CU_ASSERT(buf[12] == SPDK_NVME_NIDT_NGUID); 768 CU_ASSERT(buf[13] == 16); 769 CU_ASSERT(buf[16] == 0x22); 770 CU_ASSERT(buf[31] == 0xEE); 771 CU_ASSERT(buf[32] == SPDK_NVME_NIDT_UUID); 772 CU_ASSERT(buf[33] == 16); 773 CU_ASSERT(buf[36] == 0x33); 774 CU_ASSERT(buf[51] == 0xDD); 775 CU_ASSERT(buf[53] == 0); 776 } 777 778 static void 779 test_identify_ns(void) 780 { 781 struct spdk_nvmf_subsystem subsystem = {}; 782 struct spdk_nvmf_transport transport = {}; 783 struct spdk_nvmf_qpair admin_qpair = { .transport = &transport}; 784 struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsystem, .admin_qpair = &admin_qpair }; 785 struct spdk_nvme_cmd cmd = {}; 786 struct spdk_nvme_cpl rsp = {}; 787 struct spdk_nvme_ns_data nsdata = {}; 788 struct spdk_bdev bdev[3] = {{.blockcnt = 1234}, {.blockcnt = 0}, {.blockcnt = 5678}}; 789 struct spdk_nvmf_ns ns[3] = {{.bdev = &bdev[0]}, {.bdev = NULL}, {.bdev = &bdev[2]}}; 790 struct spdk_nvmf_ns *ns_arr[3] = {&ns[0], NULL, &ns[2]}; 791 792 subsystem.ns = ns_arr; 793 subsystem.max_nsid = SPDK_COUNTOF(ns_arr); 794 795 /* Invalid NSID 0 */ 796 cmd.nsid = 0; 797 memset(&nsdata, 0, sizeof(nsdata)); 798 memset(&rsp, 0, sizeof(rsp)); 799 CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&ctrlr, &cmd, &rsp, 800 &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 801 CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); 802 CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT); 803 CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata))); 804 805 /* Valid NSID 1 */ 806 cmd.nsid = 1; 807 memset(&nsdata, 0, sizeof(nsdata)); 808 memset(&rsp, 0, sizeof(rsp)); 809 CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&ctrlr, &cmd, &rsp, 810 &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 811 CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); 812 CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS); 813 CU_ASSERT(nsdata.nsze == 1234); 814 815 /* Valid but inactive NSID 2 */ 816 cmd.nsid = 2; 817 memset(&nsdata, 0, sizeof(nsdata)); 818 memset(&rsp, 0, sizeof(rsp)); 819 CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&ctrlr, &cmd, &rsp, 820 &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 821 CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); 822 CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS); 823 CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata))); 824 825 /* Valid NSID 3 */ 826 cmd.nsid = 3; 827 memset(&nsdata, 0, sizeof(nsdata)); 828 memset(&rsp, 0, sizeof(rsp)); 829 CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&ctrlr, &cmd, &rsp, 830 &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 831 CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); 832 CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS); 833 CU_ASSERT(nsdata.nsze == 5678); 834 835 /* Invalid NSID 4 */ 836 cmd.nsid = 4; 837 memset(&nsdata, 0, sizeof(nsdata)); 838 memset(&rsp, 0, sizeof(rsp)); 839 CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&ctrlr, &cmd, &rsp, 840 &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 841 CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); 842 CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT); 843 CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata))); 844 845 /* Invalid NSID 0xFFFFFFFF (NS management not supported) */ 846 cmd.nsid = 0xFFFFFFFF; 847 memset(&nsdata, 0, sizeof(nsdata)); 848 memset(&rsp, 0, sizeof(rsp)); 849 CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&ctrlr, &cmd, &rsp, 850 &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 851 CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); 852 CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT); 853 CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata))); 854 } 855 856 /* 857 * Reservation Unit Test Configuration 858 * -------- -------- -------- 859 * | Host A | | Host B | | Host C | 860 * -------- -------- -------- 861 * / \ | | 862 * -------- -------- ------- ------- 863 * |Ctrlr1_A| |Ctrlr2_A| |Ctrlr_B| |Ctrlr_C| 864 * -------- -------- ------- ------- 865 * \ \ / / 866 * \ \ / / 867 * \ \ / / 868 * -------------------------------------- 869 * | NAMESPACE 1 | 870 * -------------------------------------- 871 */ 872 873 static struct spdk_nvmf_ctrlr g_ctrlr1_A, g_ctrlr2_A, g_ctrlr_B, g_ctrlr_C; 874 struct spdk_nvmf_subsystem_pg_ns_info g_ns_info; 875 876 static void 877 ut_reservation_init(enum spdk_nvme_reservation_type rtype) 878 { 879 /* Host A has two controllers */ 880 spdk_uuid_generate(&g_ctrlr1_A.hostid); 881 spdk_uuid_copy(&g_ctrlr2_A.hostid, &g_ctrlr1_A.hostid); 882 883 /* Host B has 1 controller */ 884 spdk_uuid_generate(&g_ctrlr_B.hostid); 885 886 /* Host C has 1 controller */ 887 spdk_uuid_generate(&g_ctrlr_C.hostid); 888 889 memset(&g_ns_info, 0, sizeof(g_ns_info)); 890 g_ns_info.rtype = rtype; 891 g_ns_info.reg_hostid[0] = g_ctrlr1_A.hostid; 892 g_ns_info.reg_hostid[1] = g_ctrlr_B.hostid; 893 g_ns_info.reg_hostid[2] = g_ctrlr_C.hostid; 894 } 895 896 static void 897 test_reservation_write_exclusive(void) 898 { 899 struct spdk_nvmf_request req = {}; 900 union nvmf_h2c_msg cmd = {}; 901 union nvmf_c2h_msg rsp = {}; 902 int rc; 903 904 req.cmd = &cmd; 905 req.rsp = &rsp; 906 907 /* Host A holds reservation with type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE */ 908 ut_reservation_init(SPDK_NVME_RESERVE_WRITE_EXCLUSIVE); 909 g_ns_info.holder_id = g_ctrlr1_A.hostid; 910 911 /* Test Case: Issue a Read command from Host A and Host B */ 912 cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; 913 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr1_A, &req); 914 SPDK_CU_ASSERT_FATAL(rc == 0); 915 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); 916 SPDK_CU_ASSERT_FATAL(rc == 0); 917 918 /* Test Case: Issue a DSM Write command from Host A and Host B */ 919 cmd.nvme_cmd.opc = SPDK_NVME_OPC_DATASET_MANAGEMENT; 920 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr1_A, &req); 921 SPDK_CU_ASSERT_FATAL(rc == 0); 922 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); 923 SPDK_CU_ASSERT_FATAL(rc < 0); 924 SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 925 926 /* Test Case: Issue a Write command from Host C */ 927 cmd.nvme_cmd.opc = SPDK_NVME_OPC_WRITE; 928 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); 929 SPDK_CU_ASSERT_FATAL(rc < 0); 930 SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 931 932 /* Test Case: Issue a Read command from Host B */ 933 cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; 934 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); 935 SPDK_CU_ASSERT_FATAL(rc == 0); 936 937 /* Unregister Host C */ 938 memset(&g_ns_info.reg_hostid[2], 0, sizeof(struct spdk_uuid)); 939 940 /* Test Case: Read and Write commands from non-registrant Host C */ 941 cmd.nvme_cmd.opc = SPDK_NVME_OPC_WRITE; 942 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); 943 SPDK_CU_ASSERT_FATAL(rc < 0); 944 SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 945 cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; 946 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); 947 SPDK_CU_ASSERT_FATAL(rc == 0); 948 } 949 950 static void 951 test_reservation_exclusive_access(void) 952 { 953 struct spdk_nvmf_request req = {}; 954 union nvmf_h2c_msg cmd = {}; 955 union nvmf_c2h_msg rsp = {}; 956 int rc; 957 958 req.cmd = &cmd; 959 req.rsp = &rsp; 960 961 /* Host A holds reservation with type SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS */ 962 ut_reservation_init(SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS); 963 g_ns_info.holder_id = g_ctrlr1_A.hostid; 964 965 /* Test Case: Issue a Read command from Host B */ 966 cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; 967 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); 968 SPDK_CU_ASSERT_FATAL(rc < 0); 969 SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 970 971 /* Test Case: Issue a Reservation Release command from a valid Registrant */ 972 cmd.nvme_cmd.opc = SPDK_NVME_OPC_RESERVATION_RELEASE; 973 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); 974 SPDK_CU_ASSERT_FATAL(rc == 0); 975 } 976 977 static void 978 _test_reservation_write_exclusive_regs_only_and_all_regs(enum spdk_nvme_reservation_type rtype) 979 { 980 struct spdk_nvmf_request req = {}; 981 union nvmf_h2c_msg cmd = {}; 982 union nvmf_c2h_msg rsp = {}; 983 int rc; 984 985 req.cmd = &cmd; 986 req.rsp = &rsp; 987 988 /* SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY and SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS */ 989 ut_reservation_init(rtype); 990 g_ns_info.holder_id = g_ctrlr1_A.hostid; 991 992 /* Test Case: Issue a Read command from Host A and Host C */ 993 cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; 994 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr1_A, &req); 995 SPDK_CU_ASSERT_FATAL(rc == 0); 996 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); 997 SPDK_CU_ASSERT_FATAL(rc == 0); 998 999 /* Test Case: Issue a DSM Write command from Host A and Host C */ 1000 cmd.nvme_cmd.opc = SPDK_NVME_OPC_DATASET_MANAGEMENT; 1001 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr1_A, &req); 1002 SPDK_CU_ASSERT_FATAL(rc == 0); 1003 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); 1004 SPDK_CU_ASSERT_FATAL(rc == 0); 1005 1006 /* Unregister Host C */ 1007 memset(&g_ns_info.reg_hostid[2], 0, sizeof(struct spdk_uuid)); 1008 1009 /* Test Case: Read and Write commands from non-registrant Host C */ 1010 cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; 1011 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); 1012 SPDK_CU_ASSERT_FATAL(rc == 0); 1013 cmd.nvme_cmd.opc = SPDK_NVME_OPC_WRITE; 1014 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); 1015 SPDK_CU_ASSERT_FATAL(rc < 0); 1016 SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 1017 } 1018 1019 static void 1020 test_reservation_write_exclusive_regs_only_and_all_regs(void) 1021 { 1022 _test_reservation_write_exclusive_regs_only_and_all_regs( 1023 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1024 _test_reservation_write_exclusive_regs_only_and_all_regs( 1025 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 1026 } 1027 1028 static void 1029 _test_reservation_exclusive_access_regs_only_and_all_regs(enum spdk_nvme_reservation_type rtype) 1030 { 1031 struct spdk_nvmf_request req = {}; 1032 union nvmf_h2c_msg cmd = {}; 1033 union nvmf_c2h_msg rsp = {}; 1034 int rc; 1035 1036 req.cmd = &cmd; 1037 req.rsp = &rsp; 1038 1039 /* SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY and SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS */ 1040 ut_reservation_init(rtype); 1041 g_ns_info.holder_id = g_ctrlr1_A.hostid; 1042 1043 /* Test Case: Issue a Write command from Host B */ 1044 cmd.nvme_cmd.opc = SPDK_NVME_OPC_WRITE; 1045 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); 1046 SPDK_CU_ASSERT_FATAL(rc == 0); 1047 1048 /* Unregister Host B */ 1049 memset(&g_ns_info.reg_hostid[1], 0, sizeof(struct spdk_uuid)); 1050 1051 /* Test Case: Issue a Read command from Host B */ 1052 cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; 1053 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); 1054 SPDK_CU_ASSERT_FATAL(rc < 0); 1055 SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 1056 cmd.nvme_cmd.opc = SPDK_NVME_OPC_WRITE; 1057 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); 1058 SPDK_CU_ASSERT_FATAL(rc < 0); 1059 SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 1060 } 1061 1062 static void 1063 test_reservation_exclusive_access_regs_only_and_all_regs(void) 1064 { 1065 _test_reservation_exclusive_access_regs_only_and_all_regs( 1066 SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY); 1067 _test_reservation_exclusive_access_regs_only_and_all_regs( 1068 SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS); 1069 } 1070 1071 static void 1072 test_reservation_notification_log_page(void) 1073 { 1074 struct spdk_nvmf_ctrlr ctrlr; 1075 struct spdk_nvmf_qpair qpair; 1076 struct spdk_nvmf_ns ns; 1077 struct spdk_nvmf_request req; 1078 union nvmf_h2c_msg cmd; 1079 union nvmf_c2h_msg rsp; 1080 union spdk_nvme_async_event_completion event = {0}; 1081 struct spdk_nvme_reservation_notification_log logs[3]; 1082 1083 memset(&ctrlr, 0, sizeof(ctrlr)); 1084 ctrlr.thread = spdk_get_thread(); 1085 TAILQ_INIT(&ctrlr.log_head); 1086 ns.nsid = 1; 1087 1088 /* Test Case: Mask all the reservation notifications */ 1089 ns.mask = SPDK_NVME_REGISTRATION_PREEMPTED_MASK | 1090 SPDK_NVME_RESERVATION_RELEASED_MASK | 1091 SPDK_NVME_RESERVATION_PREEMPTED_MASK; 1092 spdk_nvmf_ctrlr_reservation_notice_log(&ctrlr, &ns, 1093 SPDK_NVME_REGISTRATION_PREEMPTED); 1094 spdk_nvmf_ctrlr_reservation_notice_log(&ctrlr, &ns, 1095 SPDK_NVME_RESERVATION_RELEASED); 1096 spdk_nvmf_ctrlr_reservation_notice_log(&ctrlr, &ns, 1097 SPDK_NVME_RESERVATION_PREEMPTED); 1098 poll_threads(); 1099 SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&ctrlr.log_head)); 1100 1101 /* Test Case: Unmask all the reservation notifications, 1102 * 3 log pages are generated, and AER was triggered. 1103 */ 1104 ns.mask = 0; 1105 ctrlr.num_avail_log_pages = 0; 1106 req.cmd = &cmd; 1107 req.rsp = &rsp; 1108 ctrlr.aer_req = &req; 1109 req.qpair = &qpair; 1110 TAILQ_INIT(&qpair.outstanding); 1111 qpair.state = SPDK_NVMF_QPAIR_ACTIVE; 1112 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 1113 1114 spdk_nvmf_ctrlr_reservation_notice_log(&ctrlr, &ns, 1115 SPDK_NVME_REGISTRATION_PREEMPTED); 1116 spdk_nvmf_ctrlr_reservation_notice_log(&ctrlr, &ns, 1117 SPDK_NVME_RESERVATION_RELEASED); 1118 spdk_nvmf_ctrlr_reservation_notice_log(&ctrlr, &ns, 1119 SPDK_NVME_RESERVATION_PREEMPTED); 1120 poll_threads(); 1121 event.raw = rsp.nvme_cpl.cdw0; 1122 SPDK_CU_ASSERT_FATAL(event.bits.async_event_type == SPDK_NVME_ASYNC_EVENT_TYPE_IO); 1123 SPDK_CU_ASSERT_FATAL(event.bits.async_event_info == SPDK_NVME_ASYNC_EVENT_RESERVATION_LOG_AVAIL); 1124 SPDK_CU_ASSERT_FATAL(event.bits.log_page_identifier == SPDK_NVME_LOG_RESERVATION_NOTIFICATION); 1125 SPDK_CU_ASSERT_FATAL(ctrlr.num_avail_log_pages == 3); 1126 1127 /* Test Case: Get Log Page to clear the log pages */ 1128 spdk_nvmf_get_reservation_notification_log_page(&ctrlr, (void *)logs, 0, sizeof(logs)); 1129 SPDK_CU_ASSERT_FATAL(ctrlr.num_avail_log_pages == 0); 1130 } 1131 1132 int main(int argc, char **argv) 1133 { 1134 CU_pSuite suite = NULL; 1135 unsigned int num_failures; 1136 1137 if (CU_initialize_registry() != CUE_SUCCESS) { 1138 return CU_get_error(); 1139 } 1140 1141 suite = CU_add_suite("nvmf", NULL, NULL); 1142 if (suite == NULL) { 1143 CU_cleanup_registry(); 1144 return CU_get_error(); 1145 } 1146 1147 if ( 1148 CU_add_test(suite, "get_log_page", test_get_log_page) == NULL || 1149 CU_add_test(suite, "process_fabrics_cmd", test_process_fabrics_cmd) == NULL || 1150 CU_add_test(suite, "connect", test_connect) == NULL || 1151 CU_add_test(suite, "get_ns_id_desc_list", test_get_ns_id_desc_list) == NULL || 1152 CU_add_test(suite, "identify_ns", test_identify_ns) == NULL || 1153 CU_add_test(suite, "reservation_write_exclusive", test_reservation_write_exclusive) == NULL || 1154 CU_add_test(suite, "reservation_exclusive_access", test_reservation_exclusive_access) == NULL || 1155 CU_add_test(suite, "reservation_write_exclusive_regs_only_and_all_regs", 1156 test_reservation_write_exclusive_regs_only_and_all_regs) == NULL || 1157 CU_add_test(suite, "reservation_exclusive_access_regs_only_and_all_regs", 1158 test_reservation_exclusive_access_regs_only_and_all_regs) == NULL || 1159 CU_add_test(suite, "reservation_notification_log_page", 1160 test_reservation_notification_log_page) == NULL 1161 ) { 1162 CU_cleanup_registry(); 1163 return CU_get_error(); 1164 } 1165 1166 allocate_threads(1); 1167 set_thread(0); 1168 1169 CU_basic_set_mode(CU_BRM_VERBOSE); 1170 CU_basic_run_tests(); 1171 num_failures = CU_get_number_of_failures(); 1172 CU_cleanup_registry(); 1173 1174 free_threads(); 1175 1176 return num_failures; 1177 } 1178