1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. All rights reserved. 5 * Copyright (c) 2019 Mellanox Technologies LTD. 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 const char subsystem_default_sn[SPDK_NVME_CTRLR_SN_LEN + 1] = "subsys_default_sn"; 51 const char subsystem_default_mn[SPDK_NVME_CTRLR_MN_LEN + 1] = "subsys_default_mn"; 52 53 DEFINE_STUB(spdk_nvmf_tgt_find_subsystem, 54 struct spdk_nvmf_subsystem *, 55 (struct spdk_nvmf_tgt *tgt, const char *subnqn), 56 NULL); 57 58 DEFINE_STUB(spdk_nvmf_poll_group_create, 59 struct spdk_nvmf_poll_group *, 60 (struct spdk_nvmf_tgt *tgt), 61 NULL); 62 63 DEFINE_STUB(spdk_nvmf_subsystem_get_sn, 64 const char *, 65 (const struct spdk_nvmf_subsystem *subsystem), 66 subsystem_default_sn); 67 68 DEFINE_STUB(spdk_nvmf_subsystem_get_mn, 69 const char *, 70 (const struct spdk_nvmf_subsystem *subsystem), 71 subsystem_default_mn); 72 73 DEFINE_STUB(spdk_nvmf_subsystem_get_first_ns, 74 struct spdk_nvmf_ns *, 75 (struct spdk_nvmf_subsystem *subsystem), 76 NULL); 77 78 DEFINE_STUB(spdk_nvmf_subsystem_get_next_ns, 79 struct spdk_nvmf_ns *, 80 (struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ns *prev_ns), 81 NULL); 82 83 DEFINE_STUB(spdk_nvmf_subsystem_host_allowed, 84 bool, 85 (struct spdk_nvmf_subsystem *subsystem, const char *hostnqn), 86 true); 87 88 DEFINE_STUB(spdk_nvmf_subsystem_add_ctrlr, 89 int, 90 (struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr), 91 0); 92 93 DEFINE_STUB(spdk_nvmf_subsystem_get_ctrlr, 94 struct spdk_nvmf_ctrlr *, 95 (struct spdk_nvmf_subsystem *subsystem, uint16_t cntlid), 96 NULL); 97 98 DEFINE_STUB(spdk_nvmf_ctrlr_dsm_supported, 99 bool, 100 (struct spdk_nvmf_ctrlr *ctrlr), 101 false); 102 103 DEFINE_STUB(spdk_nvmf_ctrlr_write_zeroes_supported, 104 bool, 105 (struct spdk_nvmf_ctrlr *ctrlr), 106 false); 107 108 DEFINE_STUB_V(spdk_nvmf_get_discovery_log_page, 109 (struct spdk_nvmf_tgt *tgt, const char *hostnqn, struct iovec *iov, 110 uint32_t iovcnt, uint64_t offset, uint32_t length)); 111 112 DEFINE_STUB(spdk_nvmf_qpair_get_listen_trid, 113 int, 114 (struct spdk_nvmf_qpair *qpair, struct spdk_nvme_transport_id *trid), 115 0); 116 117 DEFINE_STUB(spdk_nvmf_subsystem_listener_allowed, 118 bool, 119 (struct spdk_nvmf_subsystem *subsystem, const struct spdk_nvme_transport_id *trid), 120 true); 121 122 DEFINE_STUB(spdk_nvmf_bdev_ctrlr_read_cmd, 123 int, 124 (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, 125 struct spdk_nvmf_request *req), 126 0); 127 128 DEFINE_STUB(spdk_nvmf_bdev_ctrlr_write_cmd, 129 int, 130 (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, 131 struct spdk_nvmf_request *req), 132 0); 133 134 DEFINE_STUB(spdk_nvmf_bdev_ctrlr_compare_cmd, 135 int, 136 (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, 137 struct spdk_nvmf_request *req), 138 0); 139 140 DEFINE_STUB(spdk_nvmf_bdev_ctrlr_compare_and_write_cmd, 141 int, 142 (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, 143 struct spdk_nvmf_request *cmp_req, struct spdk_nvmf_request *write_req), 144 0); 145 146 DEFINE_STUB(spdk_nvmf_bdev_ctrlr_write_zeroes_cmd, 147 int, 148 (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, 149 struct spdk_nvmf_request *req), 150 0); 151 152 DEFINE_STUB(spdk_nvmf_bdev_ctrlr_flush_cmd, 153 int, 154 (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, 155 struct spdk_nvmf_request *req), 156 0); 157 158 DEFINE_STUB(spdk_nvmf_bdev_ctrlr_dsm_cmd, 159 int, 160 (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, 161 struct spdk_nvmf_request *req), 162 0); 163 164 DEFINE_STUB(spdk_nvmf_bdev_ctrlr_nvme_passthru_io, 165 int, 166 (struct spdk_bdev *bdev, struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, 167 struct spdk_nvmf_request *req), 168 0); 169 170 DEFINE_STUB(spdk_nvmf_transport_req_complete, 171 int, 172 (struct spdk_nvmf_request *req), 173 0); 174 175 DEFINE_STUB_V(spdk_nvmf_ns_reservation_request, (void *ctx)); 176 177 DEFINE_STUB(spdk_nvmf_bdev_ctrlr_get_dif_ctx, bool, 178 (struct spdk_bdev *bdev, struct spdk_nvme_cmd *cmd, 179 struct spdk_dif_ctx *dif_ctx), 180 true); 181 182 int 183 spdk_nvmf_qpair_disconnect(struct spdk_nvmf_qpair *qpair, nvmf_qpair_disconnect_cb cb_fn, void *ctx) 184 { 185 return 0; 186 } 187 188 void 189 spdk_nvmf_bdev_ctrlr_identify_ns(struct spdk_nvmf_ns *ns, struct spdk_nvme_ns_data *nsdata, 190 bool dif_insert_or_strip) 191 { 192 uint64_t num_blocks; 193 194 SPDK_CU_ASSERT_FATAL(ns->bdev != NULL); 195 num_blocks = ns->bdev->blockcnt; 196 nsdata->nsze = num_blocks; 197 nsdata->ncap = num_blocks; 198 nsdata->nuse = num_blocks; 199 nsdata->nlbaf = 0; 200 nsdata->flbas.format = 0; 201 nsdata->lbaf[0].lbads = spdk_u32log2(512); 202 } 203 204 static void 205 test_get_log_page(void) 206 { 207 struct spdk_nvmf_subsystem subsystem = {}; 208 struct spdk_nvmf_request req = {}; 209 struct spdk_nvmf_qpair qpair = {}; 210 struct spdk_nvmf_ctrlr ctrlr = {}; 211 union nvmf_h2c_msg cmd = {}; 212 union nvmf_c2h_msg rsp = {}; 213 char data[4096]; 214 215 subsystem.subtype = SPDK_NVMF_SUBTYPE_NVME; 216 217 ctrlr.subsys = &subsystem; 218 219 qpair.ctrlr = &ctrlr; 220 221 req.qpair = &qpair; 222 req.cmd = &cmd; 223 req.rsp = &rsp; 224 req.data = &data; 225 req.length = sizeof(data); 226 227 /* Get Log Page - all valid */ 228 memset(&cmd, 0, sizeof(cmd)); 229 memset(&rsp, 0, sizeof(rsp)); 230 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_LOG_PAGE; 231 cmd.nvme_cmd.cdw10_bits.get_log_page.lid = SPDK_NVME_LOG_ERROR; 232 cmd.nvme_cmd.cdw10_bits.get_log_page.numdl = (req.length / 4 - 1); 233 CU_ASSERT(spdk_nvmf_ctrlr_get_log_page(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 234 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 235 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 236 237 /* Get Log Page with invalid log ID */ 238 memset(&cmd, 0, sizeof(cmd)); 239 memset(&rsp, 0, sizeof(rsp)); 240 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_LOG_PAGE; 241 cmd.nvme_cmd.cdw10 = 0; 242 CU_ASSERT(spdk_nvmf_ctrlr_get_log_page(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 243 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 244 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 245 246 /* Get Log Page with invalid offset (not dword aligned) */ 247 memset(&cmd, 0, sizeof(cmd)); 248 memset(&rsp, 0, sizeof(rsp)); 249 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_LOG_PAGE; 250 cmd.nvme_cmd.cdw10_bits.get_log_page.lid = SPDK_NVME_LOG_ERROR; 251 cmd.nvme_cmd.cdw10_bits.get_log_page.numdl = (req.length / 4 - 1); 252 cmd.nvme_cmd.cdw12 = 2; 253 CU_ASSERT(spdk_nvmf_ctrlr_get_log_page(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 254 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 255 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 256 257 /* Get Log Page without data buffer */ 258 memset(&cmd, 0, sizeof(cmd)); 259 memset(&rsp, 0, sizeof(rsp)); 260 req.data = NULL; 261 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_LOG_PAGE; 262 cmd.nvme_cmd.cdw10_bits.get_log_page.lid = SPDK_NVME_LOG_ERROR; 263 cmd.nvme_cmd.cdw10_bits.get_log_page.numdl = (req.length / 4 - 1); 264 CU_ASSERT(spdk_nvmf_ctrlr_get_log_page(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 265 CU_ASSERT(req.rsp->nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 266 CU_ASSERT(req.rsp->nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 267 req.data = data; 268 } 269 270 static void 271 test_process_fabrics_cmd(void) 272 { 273 struct spdk_nvmf_request req = {}; 274 int ret; 275 struct spdk_nvmf_qpair req_qpair = {}; 276 union nvmf_h2c_msg req_cmd = {}; 277 union nvmf_c2h_msg req_rsp = {}; 278 279 req.qpair = &req_qpair; 280 req.cmd = &req_cmd; 281 req.rsp = &req_rsp; 282 req.qpair->ctrlr = NULL; 283 284 /* No ctrlr and invalid command check */ 285 req.cmd->nvmf_cmd.fctype = SPDK_NVMF_FABRIC_COMMAND_PROPERTY_GET; 286 ret = spdk_nvmf_ctrlr_process_fabrics_cmd(&req); 287 CU_ASSERT_EQUAL(req.rsp->nvme_cpl.status.sc, SPDK_NVME_SC_COMMAND_SEQUENCE_ERROR); 288 CU_ASSERT_EQUAL(ret, SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 289 } 290 291 static bool 292 nvme_status_success(const struct spdk_nvme_status *status) 293 { 294 return status->sct == SPDK_NVME_SCT_GENERIC && status->sc == SPDK_NVME_SC_SUCCESS; 295 } 296 297 static void 298 test_connect(void) 299 { 300 struct spdk_nvmf_fabric_connect_data connect_data; 301 struct spdk_nvmf_poll_group group; 302 struct spdk_nvmf_subsystem_poll_group *sgroups; 303 struct spdk_nvmf_transport transport; 304 struct spdk_nvmf_subsystem subsystem; 305 struct spdk_nvmf_request req; 306 struct spdk_nvmf_qpair admin_qpair; 307 struct spdk_nvmf_qpair qpair; 308 struct spdk_nvmf_qpair qpair2; 309 struct spdk_nvmf_ctrlr ctrlr; 310 struct spdk_nvmf_tgt tgt; 311 union nvmf_h2c_msg cmd; 312 union nvmf_c2h_msg rsp; 313 const uint8_t hostid[16] = { 314 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 315 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F 316 }; 317 const char subnqn[] = "nqn.2016-06.io.spdk:subsystem1"; 318 const char hostnqn[] = "nqn.2016-06.io.spdk:host1"; 319 int rc; 320 321 memset(&group, 0, sizeof(group)); 322 group.thread = spdk_get_thread(); 323 324 memset(&ctrlr, 0, sizeof(ctrlr)); 325 ctrlr.subsys = &subsystem; 326 ctrlr.qpair_mask = spdk_bit_array_create(3); 327 SPDK_CU_ASSERT_FATAL(ctrlr.qpair_mask != NULL); 328 ctrlr.vcprop.cc.bits.en = 1; 329 ctrlr.vcprop.cc.bits.iosqes = 6; 330 ctrlr.vcprop.cc.bits.iocqes = 4; 331 332 memset(&admin_qpair, 0, sizeof(admin_qpair)); 333 admin_qpair.group = &group; 334 335 memset(&tgt, 0, sizeof(tgt)); 336 memset(&transport, 0, sizeof(transport)); 337 transport.opts.max_aq_depth = 32; 338 transport.opts.max_queue_depth = 64; 339 transport.opts.max_qpairs_per_ctrlr = 3; 340 transport.tgt = &tgt; 341 342 memset(&qpair, 0, sizeof(qpair)); 343 qpair.transport = &transport; 344 qpair.group = &group; 345 qpair.state = SPDK_NVMF_QPAIR_ACTIVE; 346 TAILQ_INIT(&qpair.outstanding); 347 348 memset(&connect_data, 0, sizeof(connect_data)); 349 memcpy(connect_data.hostid, hostid, sizeof(hostid)); 350 connect_data.cntlid = 0xFFFF; 351 snprintf(connect_data.subnqn, sizeof(connect_data.subnqn), "%s", subnqn); 352 snprintf(connect_data.hostnqn, sizeof(connect_data.hostnqn), "%s", hostnqn); 353 354 memset(&subsystem, 0, sizeof(subsystem)); 355 subsystem.thread = spdk_get_thread(); 356 subsystem.id = 1; 357 TAILQ_INIT(&subsystem.ctrlrs); 358 subsystem.tgt = &tgt; 359 subsystem.subtype = SPDK_NVMF_SUBTYPE_NVME; 360 subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 361 snprintf(subsystem.subnqn, sizeof(subsystem.subnqn), "%s", subnqn); 362 363 sgroups = calloc(subsystem.id + 1, sizeof(struct spdk_nvmf_subsystem_poll_group)); 364 group.sgroups = sgroups; 365 366 memset(&cmd, 0, sizeof(cmd)); 367 cmd.connect_cmd.opcode = SPDK_NVME_OPC_FABRIC; 368 cmd.connect_cmd.cid = 1; 369 cmd.connect_cmd.fctype = SPDK_NVMF_FABRIC_COMMAND_CONNECT; 370 cmd.connect_cmd.recfmt = 0; 371 cmd.connect_cmd.qid = 0; 372 cmd.connect_cmd.sqsize = 31; 373 cmd.connect_cmd.cattr = 0; 374 cmd.connect_cmd.kato = 120000; 375 376 memset(&req, 0, sizeof(req)); 377 req.qpair = &qpair; 378 req.length = sizeof(connect_data); 379 req.xfer = SPDK_NVME_DATA_HOST_TO_CONTROLLER; 380 req.data = &connect_data; 381 req.cmd = &cmd; 382 req.rsp = &rsp; 383 384 MOCK_SET(spdk_nvmf_tgt_find_subsystem, &subsystem); 385 MOCK_SET(spdk_nvmf_poll_group_create, &group); 386 387 /* Valid admin connect command */ 388 memset(&rsp, 0, sizeof(rsp)); 389 sgroups[subsystem.id].io_outstanding++; 390 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 391 rc = spdk_nvmf_ctrlr_cmd_connect(&req); 392 poll_threads(); 393 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 394 CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status)); 395 CU_ASSERT(qpair.ctrlr != NULL); 396 CU_ASSERT(sgroups[subsystem.id].io_outstanding == 0); 397 spdk_nvmf_ctrlr_stop_keep_alive_timer(qpair.ctrlr); 398 spdk_bit_array_free(&qpair.ctrlr->qpair_mask); 399 free(qpair.ctrlr); 400 qpair.ctrlr = NULL; 401 402 /* Valid admin connect command with kato = 0 */ 403 cmd.connect_cmd.kato = 0; 404 memset(&rsp, 0, sizeof(rsp)); 405 sgroups[subsystem.id].io_outstanding++; 406 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 407 rc = spdk_nvmf_ctrlr_cmd_connect(&req); 408 poll_threads(); 409 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 410 CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status)); 411 CU_ASSERT(qpair.ctrlr != NULL && qpair.ctrlr->keep_alive_poller == NULL); 412 CU_ASSERT(sgroups[subsystem.id].io_outstanding == 0); 413 spdk_bit_array_free(&qpair.ctrlr->qpair_mask); 414 free(qpair.ctrlr); 415 qpair.ctrlr = NULL; 416 cmd.connect_cmd.kato = 120000; 417 418 /* Invalid data length */ 419 memset(&rsp, 0, sizeof(rsp)); 420 req.length = sizeof(connect_data) - 1; 421 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 422 rc = spdk_nvmf_ctrlr_cmd_connect(&req); 423 poll_threads(); 424 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 425 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 426 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 427 CU_ASSERT(qpair.ctrlr == NULL); 428 req.length = sizeof(connect_data); 429 430 /* Invalid recfmt */ 431 memset(&rsp, 0, sizeof(rsp)); 432 cmd.connect_cmd.recfmt = 1234; 433 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 434 rc = spdk_nvmf_ctrlr_cmd_connect(&req); 435 poll_threads(); 436 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 437 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 438 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INCOMPATIBLE_FORMAT); 439 CU_ASSERT(qpair.ctrlr == NULL); 440 cmd.connect_cmd.recfmt = 0; 441 442 /* Subsystem not found */ 443 memset(&rsp, 0, sizeof(rsp)); 444 MOCK_SET(spdk_nvmf_tgt_find_subsystem, NULL); 445 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 446 rc = spdk_nvmf_ctrlr_cmd_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 == 256); 453 CU_ASSERT(qpair.ctrlr == NULL); 454 MOCK_SET(spdk_nvmf_tgt_find_subsystem, &subsystem); 455 456 /* Unterminated hostnqn */ 457 memset(&rsp, 0, sizeof(rsp)); 458 memset(connect_data.hostnqn, 'b', sizeof(connect_data.hostnqn)); 459 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 460 rc = spdk_nvmf_ctrlr_cmd_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_PARAM); 465 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1); 466 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 512); 467 CU_ASSERT(qpair.ctrlr == NULL); 468 snprintf(connect_data.hostnqn, sizeof(connect_data.hostnqn), "%s", hostnqn); 469 470 /* Host not allowed */ 471 memset(&rsp, 0, sizeof(rsp)); 472 MOCK_SET(spdk_nvmf_subsystem_host_allowed, false); 473 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 474 rc = spdk_nvmf_ctrlr_cmd_connect(&req); 475 poll_threads(); 476 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 477 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 478 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_HOST); 479 CU_ASSERT(qpair.ctrlr == NULL); 480 MOCK_SET(spdk_nvmf_subsystem_host_allowed, true); 481 482 /* Invalid sqsize == 0 */ 483 memset(&rsp, 0, sizeof(rsp)); 484 cmd.connect_cmd.sqsize = 0; 485 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 486 rc = spdk_nvmf_ctrlr_cmd_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 admin sqsize > max_aq_depth */ 497 memset(&rsp, 0, sizeof(rsp)); 498 cmd.connect_cmd.sqsize = 32; 499 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 500 rc = spdk_nvmf_ctrlr_cmd_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 == 0); 506 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 44); 507 CU_ASSERT(qpair.ctrlr == NULL); 508 cmd.connect_cmd.sqsize = 31; 509 510 /* Invalid I/O sqsize > max_queue_depth */ 511 memset(&rsp, 0, sizeof(rsp)); 512 cmd.connect_cmd.qid = 1; 513 cmd.connect_cmd.sqsize = 64; 514 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 515 rc = spdk_nvmf_ctrlr_cmd_connect(&req); 516 poll_threads(); 517 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 518 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 519 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 520 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 521 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 44); 522 CU_ASSERT(qpair.ctrlr == NULL); 523 cmd.connect_cmd.qid = 0; 524 cmd.connect_cmd.sqsize = 31; 525 526 /* Invalid cntlid for admin queue */ 527 memset(&rsp, 0, sizeof(rsp)); 528 connect_data.cntlid = 0x1234; 529 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 530 rc = spdk_nvmf_ctrlr_cmd_connect(&req); 531 poll_threads(); 532 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 533 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 534 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 535 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1); 536 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 16); 537 CU_ASSERT(qpair.ctrlr == NULL); 538 connect_data.cntlid = 0xFFFF; 539 540 ctrlr.admin_qpair = &admin_qpair; 541 ctrlr.subsys = &subsystem; 542 543 /* Valid I/O queue connect command */ 544 memset(&rsp, 0, sizeof(rsp)); 545 MOCK_SET(spdk_nvmf_subsystem_get_ctrlr, &ctrlr); 546 cmd.connect_cmd.qid = 1; 547 cmd.connect_cmd.sqsize = 63; 548 sgroups[subsystem.id].io_outstanding++; 549 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 550 rc = spdk_nvmf_ctrlr_cmd_connect(&req); 551 poll_threads(); 552 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 553 CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status)); 554 CU_ASSERT(qpair.ctrlr == &ctrlr); 555 CU_ASSERT(sgroups[subsystem.id].io_outstanding == 0); 556 qpair.ctrlr = NULL; 557 cmd.connect_cmd.sqsize = 31; 558 559 /* Non-existent controller */ 560 memset(&rsp, 0, sizeof(rsp)); 561 MOCK_SET(spdk_nvmf_subsystem_get_ctrlr, NULL); 562 sgroups[subsystem.id].io_outstanding++; 563 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 564 rc = spdk_nvmf_ctrlr_cmd_connect(&req); 565 poll_threads(); 566 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 567 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 568 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 569 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 1); 570 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 16); 571 CU_ASSERT(qpair.ctrlr == NULL); 572 CU_ASSERT(sgroups[subsystem.id].io_outstanding == 0); 573 MOCK_SET(spdk_nvmf_subsystem_get_ctrlr, &ctrlr); 574 575 /* I/O connect to discovery controller */ 576 memset(&rsp, 0, sizeof(rsp)); 577 subsystem.subtype = SPDK_NVMF_SUBTYPE_DISCOVERY; 578 subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 579 sgroups[subsystem.id].io_outstanding++; 580 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 581 rc = spdk_nvmf_ctrlr_cmd_connect(&req); 582 poll_threads(); 583 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 584 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 585 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 586 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 587 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42); 588 CU_ASSERT(qpair.ctrlr == NULL); 589 CU_ASSERT(sgroups[subsystem.id].io_outstanding == 0); 590 591 /* I/O connect to discovery controller with keep-alive-timeout != 0 */ 592 cmd.connect_cmd.qid = 0; 593 cmd.connect_cmd.kato = 120000; 594 memset(&rsp, 0, sizeof(rsp)); 595 subsystem.subtype = SPDK_NVMF_SUBTYPE_DISCOVERY; 596 subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 597 sgroups[subsystem.id].io_outstanding++; 598 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 599 rc = spdk_nvmf_ctrlr_cmd_connect(&req); 600 poll_threads(); 601 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 602 CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status)); 603 CU_ASSERT(qpair.ctrlr != NULL); 604 CU_ASSERT(qpair.ctrlr->keep_alive_poller != NULL); 605 CU_ASSERT(sgroups[subsystem.id].io_outstanding == 0); 606 spdk_nvmf_ctrlr_stop_keep_alive_timer(qpair.ctrlr); 607 spdk_bit_array_free(&qpair.ctrlr->qpair_mask); 608 free(qpair.ctrlr); 609 qpair.ctrlr = NULL; 610 611 /* I/O connect to discovery controller with keep-alive-timeout == 0. 612 * Then, a fixed timeout value is set to keep-alive-timeout. 613 */ 614 cmd.connect_cmd.kato = 0; 615 memset(&rsp, 0, sizeof(rsp)); 616 subsystem.subtype = SPDK_NVMF_SUBTYPE_DISCOVERY; 617 subsystem.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 618 sgroups[subsystem.id].io_outstanding++; 619 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 620 rc = spdk_nvmf_ctrlr_cmd_connect(&req); 621 poll_threads(); 622 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 623 CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status)); 624 CU_ASSERT(qpair.ctrlr != NULL); 625 CU_ASSERT(qpair.ctrlr->keep_alive_poller != NULL); 626 CU_ASSERT(sgroups[subsystem.id].io_outstanding == 0); 627 spdk_nvmf_ctrlr_stop_keep_alive_timer(qpair.ctrlr); 628 spdk_bit_array_free(&qpair.ctrlr->qpair_mask); 629 free(qpair.ctrlr); 630 qpair.ctrlr = NULL; 631 cmd.connect_cmd.qid = 1; 632 cmd.connect_cmd.kato = 120000; 633 subsystem.subtype = SPDK_NVMF_SUBTYPE_NVME; 634 635 /* I/O connect to disabled controller */ 636 memset(&rsp, 0, sizeof(rsp)); 637 ctrlr.vcprop.cc.bits.en = 0; 638 sgroups[subsystem.id].io_outstanding++; 639 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 640 rc = spdk_nvmf_ctrlr_cmd_connect(&req); 641 poll_threads(); 642 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 643 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 644 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 645 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 646 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42); 647 CU_ASSERT(qpair.ctrlr == NULL); 648 CU_ASSERT(sgroups[subsystem.id].io_outstanding == 0); 649 ctrlr.vcprop.cc.bits.en = 1; 650 651 /* I/O connect with invalid IOSQES */ 652 memset(&rsp, 0, sizeof(rsp)); 653 ctrlr.vcprop.cc.bits.iosqes = 3; 654 sgroups[subsystem.id].io_outstanding++; 655 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 656 rc = spdk_nvmf_ctrlr_cmd_connect(&req); 657 poll_threads(); 658 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 659 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 660 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 661 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 662 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42); 663 CU_ASSERT(qpair.ctrlr == NULL); 664 CU_ASSERT(sgroups[subsystem.id].io_outstanding == 0); 665 ctrlr.vcprop.cc.bits.iosqes = 6; 666 667 /* I/O connect with invalid IOCQES */ 668 memset(&rsp, 0, sizeof(rsp)); 669 ctrlr.vcprop.cc.bits.iocqes = 3; 670 sgroups[subsystem.id].io_outstanding++; 671 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 672 rc = spdk_nvmf_ctrlr_cmd_connect(&req); 673 poll_threads(); 674 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 675 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 676 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVMF_FABRIC_SC_INVALID_PARAM); 677 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.iattr == 0); 678 CU_ASSERT(rsp.connect_rsp.status_code_specific.invalid.ipo == 42); 679 CU_ASSERT(qpair.ctrlr == NULL); 680 CU_ASSERT(sgroups[subsystem.id].io_outstanding == 0); 681 ctrlr.vcprop.cc.bits.iocqes = 4; 682 683 /* I/O connect with too many existing qpairs */ 684 memset(&rsp, 0, sizeof(rsp)); 685 spdk_bit_array_set(ctrlr.qpair_mask, 0); 686 spdk_bit_array_set(ctrlr.qpair_mask, 1); 687 spdk_bit_array_set(ctrlr.qpair_mask, 2); 688 sgroups[subsystem.id].io_outstanding++; 689 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 690 rc = spdk_nvmf_ctrlr_cmd_connect(&req); 691 poll_threads(); 692 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 693 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 694 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_QUEUE_IDENTIFIER); 695 CU_ASSERT(qpair.ctrlr == NULL); 696 CU_ASSERT(sgroups[subsystem.id].io_outstanding == 0); 697 spdk_bit_array_clear(ctrlr.qpair_mask, 0); 698 spdk_bit_array_clear(ctrlr.qpair_mask, 1); 699 spdk_bit_array_clear(ctrlr.qpair_mask, 2); 700 701 /* I/O connect with duplicate queue ID */ 702 memset(&rsp, 0, sizeof(rsp)); 703 memset(&qpair2, 0, sizeof(qpair2)); 704 qpair2.group = &group; 705 qpair2.qid = 1; 706 spdk_bit_array_set(ctrlr.qpair_mask, 1); 707 cmd.connect_cmd.qid = 1; 708 sgroups[subsystem.id].io_outstanding++; 709 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 710 rc = spdk_nvmf_ctrlr_cmd_connect(&req); 711 poll_threads(); 712 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_ASYNCHRONOUS); 713 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 714 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_QUEUE_IDENTIFIER); 715 CU_ASSERT(qpair.ctrlr == NULL); 716 CU_ASSERT(sgroups[subsystem.id].io_outstanding == 0); 717 718 /* Clean up globals */ 719 MOCK_CLEAR(spdk_nvmf_tgt_find_subsystem); 720 MOCK_CLEAR(spdk_nvmf_poll_group_create); 721 722 spdk_bit_array_free(&ctrlr.qpair_mask); 723 free(sgroups); 724 } 725 726 static void 727 test_get_ns_id_desc_list(void) 728 { 729 struct spdk_nvmf_subsystem subsystem; 730 struct spdk_nvmf_qpair qpair; 731 struct spdk_nvmf_ctrlr ctrlr; 732 struct spdk_nvmf_request req; 733 struct spdk_nvmf_ns *ns_ptrs[1]; 734 struct spdk_nvmf_ns ns; 735 union nvmf_h2c_msg cmd; 736 union nvmf_c2h_msg rsp; 737 struct spdk_bdev bdev; 738 uint8_t buf[4096]; 739 740 memset(&subsystem, 0, sizeof(subsystem)); 741 ns_ptrs[0] = &ns; 742 subsystem.ns = ns_ptrs; 743 subsystem.max_nsid = 1; 744 subsystem.subtype = SPDK_NVMF_SUBTYPE_NVME; 745 746 memset(&ns, 0, sizeof(ns)); 747 ns.opts.nsid = 1; 748 ns.bdev = &bdev; 749 750 memset(&qpair, 0, sizeof(qpair)); 751 qpair.ctrlr = &ctrlr; 752 753 memset(&ctrlr, 0, sizeof(ctrlr)); 754 ctrlr.subsys = &subsystem; 755 ctrlr.vcprop.cc.bits.en = 1; 756 757 memset(&req, 0, sizeof(req)); 758 req.qpair = &qpair; 759 req.cmd = &cmd; 760 req.rsp = &rsp; 761 req.xfer = SPDK_NVME_DATA_CONTROLLER_TO_HOST; 762 req.data = buf; 763 req.length = sizeof(buf); 764 765 memset(&cmd, 0, sizeof(cmd)); 766 cmd.nvme_cmd.opc = SPDK_NVME_OPC_IDENTIFY; 767 cmd.nvme_cmd.cdw10_bits.identify.cns = SPDK_NVME_IDENTIFY_NS_ID_DESCRIPTOR_LIST; 768 769 /* Invalid NSID */ 770 cmd.nvme_cmd.nsid = 0; 771 memset(&rsp, 0, sizeof(rsp)); 772 CU_ASSERT(spdk_nvmf_ctrlr_process_admin_cmd(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 773 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 774 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT); 775 776 /* Valid NSID, but ns has no IDs defined */ 777 cmd.nvme_cmd.nsid = 1; 778 memset(&rsp, 0, sizeof(rsp)); 779 CU_ASSERT(spdk_nvmf_ctrlr_process_admin_cmd(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 780 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 781 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 782 CU_ASSERT(spdk_mem_all_zero(buf, sizeof(buf))); 783 784 /* Valid NSID, only EUI64 defined */ 785 ns.opts.eui64[0] = 0x11; 786 ns.opts.eui64[7] = 0xFF; 787 memset(&rsp, 0, sizeof(rsp)); 788 CU_ASSERT(spdk_nvmf_ctrlr_process_admin_cmd(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 789 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 790 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 791 CU_ASSERT(buf[0] == SPDK_NVME_NIDT_EUI64); 792 CU_ASSERT(buf[1] == 8); 793 CU_ASSERT(buf[4] == 0x11); 794 CU_ASSERT(buf[11] == 0xFF); 795 CU_ASSERT(buf[13] == 0); 796 797 /* Valid NSID, only NGUID defined */ 798 memset(ns.opts.eui64, 0, sizeof(ns.opts.eui64)); 799 ns.opts.nguid[0] = 0x22; 800 ns.opts.nguid[15] = 0xEE; 801 memset(&rsp, 0, sizeof(rsp)); 802 CU_ASSERT(spdk_nvmf_ctrlr_process_admin_cmd(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 803 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 804 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 805 CU_ASSERT(buf[0] == SPDK_NVME_NIDT_NGUID); 806 CU_ASSERT(buf[1] == 16); 807 CU_ASSERT(buf[4] == 0x22); 808 CU_ASSERT(buf[19] == 0xEE); 809 CU_ASSERT(buf[21] == 0); 810 811 /* Valid NSID, both EUI64 and NGUID defined */ 812 ns.opts.eui64[0] = 0x11; 813 ns.opts.eui64[7] = 0xFF; 814 ns.opts.nguid[0] = 0x22; 815 ns.opts.nguid[15] = 0xEE; 816 memset(&rsp, 0, sizeof(rsp)); 817 CU_ASSERT(spdk_nvmf_ctrlr_process_admin_cmd(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 818 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 819 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 820 CU_ASSERT(buf[0] == SPDK_NVME_NIDT_EUI64); 821 CU_ASSERT(buf[1] == 8); 822 CU_ASSERT(buf[4] == 0x11); 823 CU_ASSERT(buf[11] == 0xFF); 824 CU_ASSERT(buf[12] == SPDK_NVME_NIDT_NGUID); 825 CU_ASSERT(buf[13] == 16); 826 CU_ASSERT(buf[16] == 0x22); 827 CU_ASSERT(buf[31] == 0xEE); 828 CU_ASSERT(buf[33] == 0); 829 830 /* Valid NSID, EUI64, NGUID, and UUID defined */ 831 ns.opts.eui64[0] = 0x11; 832 ns.opts.eui64[7] = 0xFF; 833 ns.opts.nguid[0] = 0x22; 834 ns.opts.nguid[15] = 0xEE; 835 ns.opts.uuid.u.raw[0] = 0x33; 836 ns.opts.uuid.u.raw[15] = 0xDD; 837 memset(&rsp, 0, sizeof(rsp)); 838 CU_ASSERT(spdk_nvmf_ctrlr_process_admin_cmd(&req) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 839 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 840 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 841 CU_ASSERT(buf[0] == SPDK_NVME_NIDT_EUI64); 842 CU_ASSERT(buf[1] == 8); 843 CU_ASSERT(buf[4] == 0x11); 844 CU_ASSERT(buf[11] == 0xFF); 845 CU_ASSERT(buf[12] == SPDK_NVME_NIDT_NGUID); 846 CU_ASSERT(buf[13] == 16); 847 CU_ASSERT(buf[16] == 0x22); 848 CU_ASSERT(buf[31] == 0xEE); 849 CU_ASSERT(buf[32] == SPDK_NVME_NIDT_UUID); 850 CU_ASSERT(buf[33] == 16); 851 CU_ASSERT(buf[36] == 0x33); 852 CU_ASSERT(buf[51] == 0xDD); 853 CU_ASSERT(buf[53] == 0); 854 } 855 856 static void 857 test_identify_ns(void) 858 { 859 struct spdk_nvmf_subsystem subsystem = {}; 860 struct spdk_nvmf_transport transport = {}; 861 struct spdk_nvmf_qpair admin_qpair = { .transport = &transport}; 862 struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsystem, .admin_qpair = &admin_qpair }; 863 struct spdk_nvme_cmd cmd = {}; 864 struct spdk_nvme_cpl rsp = {}; 865 struct spdk_nvme_ns_data nsdata = {}; 866 struct spdk_bdev bdev[3] = {{.blockcnt = 1234}, {.blockcnt = 0}, {.blockcnt = 5678}}; 867 struct spdk_nvmf_ns ns[3] = {{.bdev = &bdev[0]}, {.bdev = NULL}, {.bdev = &bdev[2]}}; 868 struct spdk_nvmf_ns *ns_arr[3] = {&ns[0], NULL, &ns[2]}; 869 870 subsystem.ns = ns_arr; 871 subsystem.max_nsid = SPDK_COUNTOF(ns_arr); 872 873 /* Invalid NSID 0 */ 874 cmd.nsid = 0; 875 memset(&nsdata, 0, sizeof(nsdata)); 876 memset(&rsp, 0, sizeof(rsp)); 877 CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&ctrlr, &cmd, &rsp, 878 &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 879 CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); 880 CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT); 881 CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata))); 882 883 /* Valid NSID 1 */ 884 cmd.nsid = 1; 885 memset(&nsdata, 0, sizeof(nsdata)); 886 memset(&rsp, 0, sizeof(rsp)); 887 CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&ctrlr, &cmd, &rsp, 888 &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 889 CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); 890 CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS); 891 CU_ASSERT(nsdata.nsze == 1234); 892 893 /* Valid but inactive NSID 2 */ 894 cmd.nsid = 2; 895 memset(&nsdata, 0, sizeof(nsdata)); 896 memset(&rsp, 0, sizeof(rsp)); 897 CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&ctrlr, &cmd, &rsp, 898 &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 899 CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); 900 CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS); 901 CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata))); 902 903 /* Valid NSID 3 */ 904 cmd.nsid = 3; 905 memset(&nsdata, 0, sizeof(nsdata)); 906 memset(&rsp, 0, sizeof(rsp)); 907 CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&ctrlr, &cmd, &rsp, 908 &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 909 CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); 910 CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_SUCCESS); 911 CU_ASSERT(nsdata.nsze == 5678); 912 913 /* Invalid NSID 4 */ 914 cmd.nsid = 4; 915 memset(&nsdata, 0, sizeof(nsdata)); 916 memset(&rsp, 0, sizeof(rsp)); 917 CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&ctrlr, &cmd, &rsp, 918 &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 919 CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); 920 CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT); 921 CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata))); 922 923 /* Invalid NSID 0xFFFFFFFF (NS management not supported) */ 924 cmd.nsid = 0xFFFFFFFF; 925 memset(&nsdata, 0, sizeof(nsdata)); 926 memset(&rsp, 0, sizeof(rsp)); 927 CU_ASSERT(spdk_nvmf_ctrlr_identify_ns(&ctrlr, &cmd, &rsp, 928 &nsdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 929 CU_ASSERT(rsp.status.sct == SPDK_NVME_SCT_GENERIC); 930 CU_ASSERT(rsp.status.sc == SPDK_NVME_SC_INVALID_NAMESPACE_OR_FORMAT); 931 CU_ASSERT(spdk_mem_all_zero(&nsdata, sizeof(nsdata))); 932 } 933 934 static void 935 test_set_get_features(void) 936 { 937 struct spdk_nvmf_subsystem subsystem = {}; 938 struct spdk_nvmf_qpair admin_qpair = {}; 939 struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsystem, .admin_qpair = &admin_qpair }; 940 union nvmf_h2c_msg cmd = {}; 941 union nvmf_c2h_msg rsp = {}; 942 struct spdk_nvmf_ns ns[3]; 943 struct spdk_nvmf_ns *ns_arr[3] = {&ns[0], NULL, &ns[2]};; 944 struct spdk_nvmf_request req; 945 int rc; 946 947 subsystem.ns = ns_arr; 948 subsystem.max_nsid = SPDK_COUNTOF(ns_arr); 949 admin_qpair.ctrlr = &ctrlr; 950 req.qpair = &admin_qpair; 951 cmd.nvme_cmd.nsid = 1; 952 req.cmd = &cmd; 953 req.rsp = &rsp; 954 955 /* Set SPDK_NVME_FEAT_HOST_RESERVE_PERSIST feature */ 956 cmd.nvme_cmd.opc = SPDK_NVME_OPC_SET_FEATURES; 957 cmd.nvme_cmd.cdw11_bits.feat_rsv_persistence.bits.ptpl = 1; 958 ns[0].ptpl_file = "testcfg"; 959 rc = spdk_nvmf_ctrlr_set_features_reservation_persistence(&req); 960 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 961 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC); 962 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_FEATURE_ID_NOT_SAVEABLE); 963 CU_ASSERT(ns[0].ptpl_activated == true); 964 965 /* Get SPDK_NVME_FEAT_HOST_RESERVE_PERSIST feature */ 966 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_FEATURES; 967 cmd.nvme_cmd.cdw10_bits.get_features.fid = SPDK_NVME_FEAT_HOST_RESERVE_PERSIST; 968 rc = spdk_nvmf_ctrlr_get_features_reservation_persistence(&req); 969 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 970 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 971 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 972 CU_ASSERT(rsp.nvme_cpl.cdw0 == 1); 973 974 975 /* Get SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD - valid TMPSEL */ 976 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_FEATURES; 977 cmd.nvme_cmd.cdw11 = 0x42; 978 cmd.nvme_cmd.cdw10_bits.get_features.fid = SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD; 979 980 rc = spdk_nvmf_ctrlr_get_features(&req); 981 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 982 983 /* Get SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD - invalid TMPSEL */ 984 cmd.nvme_cmd.opc = SPDK_NVME_OPC_GET_FEATURES; 985 cmd.nvme_cmd.cdw11 = 0x42 | 1 << 16 | 1 << 19; /* Set reserved value */ 986 cmd.nvme_cmd.cdw10_bits.get_features.fid = SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD; 987 988 rc = spdk_nvmf_ctrlr_get_features(&req); 989 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 990 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 991 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 992 993 /* Set SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD - valid TMPSEL */ 994 cmd.nvme_cmd.opc = SPDK_NVME_OPC_SET_FEATURES; 995 cmd.nvme_cmd.cdw11 = 0x42; 996 cmd.nvme_cmd.cdw10_bits.set_features.fid = SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD; 997 998 rc = spdk_nvmf_ctrlr_set_features(&req); 999 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 1000 1001 /* Set SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD - invalid TMPSEL */ 1002 cmd.nvme_cmd.opc = SPDK_NVME_OPC_SET_FEATURES; 1003 cmd.nvme_cmd.cdw11 = 0x42 | 1 << 16 | 1 << 19; /* Set reserved value */ 1004 cmd.nvme_cmd.cdw10_bits.set_features.fid = SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD; 1005 1006 rc = spdk_nvmf_ctrlr_set_features(&req); 1007 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 1008 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 1009 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 1010 1011 /* Set SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD - invalid THSEL */ 1012 cmd.nvme_cmd.opc = SPDK_NVME_OPC_SET_FEATURES; 1013 cmd.nvme_cmd.cdw11 = 0x42; 1014 cmd.nvme_cmd.cdw11_bits.feat_temp_threshold.bits.thsel = 0x3; /* Set reserved value */ 1015 cmd.nvme_cmd.cdw10_bits.set_features.fid = SPDK_NVME_FEAT_TEMPERATURE_THRESHOLD; 1016 1017 rc = spdk_nvmf_ctrlr_set_features(&req); 1018 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 1019 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 1020 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 1021 1022 1023 /* get SPDK_NVME_FEAT_ERROR_RECOVERY - generic */ 1024 cmd.nvme_cmd.opc = SPDK_NVME_OPC_SET_FEATURES; 1025 cmd.nvme_cmd.cdw10_bits.get_features.fid = SPDK_NVME_FEAT_ERROR_RECOVERY; 1026 1027 rc = spdk_nvmf_ctrlr_get_features(&req); 1028 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 1029 1030 /* Set SPDK_NVME_FEAT_ERROR_RECOVERY - DULBE set */ 1031 cmd.nvme_cmd.opc = SPDK_NVME_OPC_SET_FEATURES; 1032 cmd.nvme_cmd.cdw11 = 0x42; 1033 cmd.nvme_cmd.cdw11_bits.feat_error_recovery.bits.dulbe = 0x1; 1034 cmd.nvme_cmd.cdw10_bits.set_features.fid = SPDK_NVME_FEAT_ERROR_RECOVERY; 1035 1036 rc = spdk_nvmf_ctrlr_set_features(&req); 1037 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 1038 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 1039 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_FIELD); 1040 1041 /* Set SPDK_NVME_FEAT_ERROR_RECOVERY - DULBE cleared */ 1042 cmd.nvme_cmd.opc = SPDK_NVME_OPC_SET_FEATURES; 1043 cmd.nvme_cmd.cdw11 = 0x42; 1044 cmd.nvme_cmd.cdw11_bits.feat_error_recovery.bits.dulbe = 0x0; 1045 cmd.nvme_cmd.cdw10_bits.set_features.fid = SPDK_NVME_FEAT_ERROR_RECOVERY; 1046 1047 rc = spdk_nvmf_ctrlr_set_features(&req); 1048 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 1049 } 1050 1051 /* 1052 * Reservation Unit Test Configuration 1053 * -------- -------- -------- 1054 * | Host A | | Host B | | Host C | 1055 * -------- -------- -------- 1056 * / \ | | 1057 * -------- -------- ------- ------- 1058 * |Ctrlr1_A| |Ctrlr2_A| |Ctrlr_B| |Ctrlr_C| 1059 * -------- -------- ------- ------- 1060 * \ \ / / 1061 * \ \ / / 1062 * \ \ / / 1063 * -------------------------------------- 1064 * | NAMESPACE 1 | 1065 * -------------------------------------- 1066 */ 1067 1068 static struct spdk_nvmf_ctrlr g_ctrlr1_A, g_ctrlr2_A, g_ctrlr_B, g_ctrlr_C; 1069 struct spdk_nvmf_subsystem_pg_ns_info g_ns_info; 1070 1071 static void 1072 ut_reservation_init(enum spdk_nvme_reservation_type rtype) 1073 { 1074 /* Host A has two controllers */ 1075 spdk_uuid_generate(&g_ctrlr1_A.hostid); 1076 spdk_uuid_copy(&g_ctrlr2_A.hostid, &g_ctrlr1_A.hostid); 1077 1078 /* Host B has 1 controller */ 1079 spdk_uuid_generate(&g_ctrlr_B.hostid); 1080 1081 /* Host C has 1 controller */ 1082 spdk_uuid_generate(&g_ctrlr_C.hostid); 1083 1084 memset(&g_ns_info, 0, sizeof(g_ns_info)); 1085 g_ns_info.rtype = rtype; 1086 g_ns_info.reg_hostid[0] = g_ctrlr1_A.hostid; 1087 g_ns_info.reg_hostid[1] = g_ctrlr_B.hostid; 1088 g_ns_info.reg_hostid[2] = g_ctrlr_C.hostid; 1089 } 1090 1091 static void 1092 test_reservation_write_exclusive(void) 1093 { 1094 struct spdk_nvmf_request req = {}; 1095 union nvmf_h2c_msg cmd = {}; 1096 union nvmf_c2h_msg rsp = {}; 1097 int rc; 1098 1099 req.cmd = &cmd; 1100 req.rsp = &rsp; 1101 1102 /* Host A holds reservation with type SPDK_NVME_RESERVE_WRITE_EXCLUSIVE */ 1103 ut_reservation_init(SPDK_NVME_RESERVE_WRITE_EXCLUSIVE); 1104 g_ns_info.holder_id = g_ctrlr1_A.hostid; 1105 1106 /* Test Case: Issue a Read command from Host A and Host B */ 1107 cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; 1108 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr1_A, &req); 1109 SPDK_CU_ASSERT_FATAL(rc == 0); 1110 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); 1111 SPDK_CU_ASSERT_FATAL(rc == 0); 1112 1113 /* Test Case: Issue a DSM Write command from Host A and Host B */ 1114 cmd.nvme_cmd.opc = SPDK_NVME_OPC_DATASET_MANAGEMENT; 1115 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr1_A, &req); 1116 SPDK_CU_ASSERT_FATAL(rc == 0); 1117 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); 1118 SPDK_CU_ASSERT_FATAL(rc < 0); 1119 SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 1120 1121 /* Test Case: Issue a Write command from Host C */ 1122 cmd.nvme_cmd.opc = SPDK_NVME_OPC_WRITE; 1123 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); 1124 SPDK_CU_ASSERT_FATAL(rc < 0); 1125 SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 1126 1127 /* Test Case: Issue a Read command from Host B */ 1128 cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; 1129 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); 1130 SPDK_CU_ASSERT_FATAL(rc == 0); 1131 1132 /* Unregister Host C */ 1133 memset(&g_ns_info.reg_hostid[2], 0, sizeof(struct spdk_uuid)); 1134 1135 /* Test Case: Read and Write commands from non-registrant Host C */ 1136 cmd.nvme_cmd.opc = SPDK_NVME_OPC_WRITE; 1137 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); 1138 SPDK_CU_ASSERT_FATAL(rc < 0); 1139 SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 1140 cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; 1141 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); 1142 SPDK_CU_ASSERT_FATAL(rc == 0); 1143 } 1144 1145 static void 1146 test_reservation_exclusive_access(void) 1147 { 1148 struct spdk_nvmf_request req = {}; 1149 union nvmf_h2c_msg cmd = {}; 1150 union nvmf_c2h_msg rsp = {}; 1151 int rc; 1152 1153 req.cmd = &cmd; 1154 req.rsp = &rsp; 1155 1156 /* Host A holds reservation with type SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS */ 1157 ut_reservation_init(SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS); 1158 g_ns_info.holder_id = g_ctrlr1_A.hostid; 1159 1160 /* Test Case: Issue a Read command from Host B */ 1161 cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; 1162 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); 1163 SPDK_CU_ASSERT_FATAL(rc < 0); 1164 SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 1165 1166 /* Test Case: Issue a Reservation Release command from a valid Registrant */ 1167 cmd.nvme_cmd.opc = SPDK_NVME_OPC_RESERVATION_RELEASE; 1168 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); 1169 SPDK_CU_ASSERT_FATAL(rc == 0); 1170 } 1171 1172 static void 1173 _test_reservation_write_exclusive_regs_only_and_all_regs(enum spdk_nvme_reservation_type rtype) 1174 { 1175 struct spdk_nvmf_request req = {}; 1176 union nvmf_h2c_msg cmd = {}; 1177 union nvmf_c2h_msg rsp = {}; 1178 int rc; 1179 1180 req.cmd = &cmd; 1181 req.rsp = &rsp; 1182 1183 /* SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY and SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS */ 1184 ut_reservation_init(rtype); 1185 g_ns_info.holder_id = g_ctrlr1_A.hostid; 1186 1187 /* Test Case: Issue a Read command from Host A and Host C */ 1188 cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; 1189 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr1_A, &req); 1190 SPDK_CU_ASSERT_FATAL(rc == 0); 1191 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); 1192 SPDK_CU_ASSERT_FATAL(rc == 0); 1193 1194 /* Test Case: Issue a DSM Write command from Host A and Host C */ 1195 cmd.nvme_cmd.opc = SPDK_NVME_OPC_DATASET_MANAGEMENT; 1196 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr1_A, &req); 1197 SPDK_CU_ASSERT_FATAL(rc == 0); 1198 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); 1199 SPDK_CU_ASSERT_FATAL(rc == 0); 1200 1201 /* Unregister Host C */ 1202 memset(&g_ns_info.reg_hostid[2], 0, sizeof(struct spdk_uuid)); 1203 1204 /* Test Case: Read and Write commands from non-registrant Host C */ 1205 cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; 1206 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); 1207 SPDK_CU_ASSERT_FATAL(rc == 0); 1208 cmd.nvme_cmd.opc = SPDK_NVME_OPC_WRITE; 1209 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_C, &req); 1210 SPDK_CU_ASSERT_FATAL(rc < 0); 1211 SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 1212 } 1213 1214 static void 1215 test_reservation_write_exclusive_regs_only_and_all_regs(void) 1216 { 1217 _test_reservation_write_exclusive_regs_only_and_all_regs( 1218 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_REG_ONLY); 1219 _test_reservation_write_exclusive_regs_only_and_all_regs( 1220 SPDK_NVME_RESERVE_WRITE_EXCLUSIVE_ALL_REGS); 1221 } 1222 1223 static void 1224 _test_reservation_exclusive_access_regs_only_and_all_regs(enum spdk_nvme_reservation_type rtype) 1225 { 1226 struct spdk_nvmf_request req = {}; 1227 union nvmf_h2c_msg cmd = {}; 1228 union nvmf_c2h_msg rsp = {}; 1229 int rc; 1230 1231 req.cmd = &cmd; 1232 req.rsp = &rsp; 1233 1234 /* SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY and SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS */ 1235 ut_reservation_init(rtype); 1236 g_ns_info.holder_id = g_ctrlr1_A.hostid; 1237 1238 /* Test Case: Issue a Write command from Host B */ 1239 cmd.nvme_cmd.opc = SPDK_NVME_OPC_WRITE; 1240 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); 1241 SPDK_CU_ASSERT_FATAL(rc == 0); 1242 1243 /* Unregister Host B */ 1244 memset(&g_ns_info.reg_hostid[1], 0, sizeof(struct spdk_uuid)); 1245 1246 /* Test Case: Issue a Read command from Host B */ 1247 cmd.nvme_cmd.opc = SPDK_NVME_OPC_READ; 1248 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); 1249 SPDK_CU_ASSERT_FATAL(rc < 0); 1250 SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 1251 cmd.nvme_cmd.opc = SPDK_NVME_OPC_WRITE; 1252 rc = nvmf_ns_reservation_request_check(&g_ns_info, &g_ctrlr_B, &req); 1253 SPDK_CU_ASSERT_FATAL(rc < 0); 1254 SPDK_CU_ASSERT_FATAL(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_RESERVATION_CONFLICT); 1255 } 1256 1257 static void 1258 test_reservation_exclusive_access_regs_only_and_all_regs(void) 1259 { 1260 _test_reservation_exclusive_access_regs_only_and_all_regs( 1261 SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_REG_ONLY); 1262 _test_reservation_exclusive_access_regs_only_and_all_regs( 1263 SPDK_NVME_RESERVE_EXCLUSIVE_ACCESS_ALL_REGS); 1264 } 1265 1266 static void 1267 test_reservation_notification_log_page(void) 1268 { 1269 struct spdk_nvmf_ctrlr ctrlr; 1270 struct spdk_nvmf_qpair qpair; 1271 struct spdk_nvmf_ns ns; 1272 struct spdk_nvmf_request req; 1273 union nvmf_h2c_msg cmd = {}; 1274 union nvmf_c2h_msg rsp = {}; 1275 union spdk_nvme_async_event_completion event = {}; 1276 struct spdk_nvme_reservation_notification_log logs[3]; 1277 1278 memset(&ctrlr, 0, sizeof(ctrlr)); 1279 ctrlr.thread = spdk_get_thread(); 1280 TAILQ_INIT(&ctrlr.log_head); 1281 ns.nsid = 1; 1282 1283 /* Test Case: Mask all the reservation notifications */ 1284 ns.mask = SPDK_NVME_REGISTRATION_PREEMPTED_MASK | 1285 SPDK_NVME_RESERVATION_RELEASED_MASK | 1286 SPDK_NVME_RESERVATION_PREEMPTED_MASK; 1287 spdk_nvmf_ctrlr_reservation_notice_log(&ctrlr, &ns, 1288 SPDK_NVME_REGISTRATION_PREEMPTED); 1289 spdk_nvmf_ctrlr_reservation_notice_log(&ctrlr, &ns, 1290 SPDK_NVME_RESERVATION_RELEASED); 1291 spdk_nvmf_ctrlr_reservation_notice_log(&ctrlr, &ns, 1292 SPDK_NVME_RESERVATION_PREEMPTED); 1293 poll_threads(); 1294 SPDK_CU_ASSERT_FATAL(TAILQ_EMPTY(&ctrlr.log_head)); 1295 1296 /* Test Case: Unmask all the reservation notifications, 1297 * 3 log pages are generated, and AER was triggered. 1298 */ 1299 ns.mask = 0; 1300 ctrlr.num_avail_log_pages = 0; 1301 req.cmd = &cmd; 1302 req.rsp = &rsp; 1303 ctrlr.aer_req = &req; 1304 req.qpair = &qpair; 1305 TAILQ_INIT(&qpair.outstanding); 1306 qpair.ctrlr = NULL; 1307 qpair.state = SPDK_NVMF_QPAIR_ACTIVE; 1308 TAILQ_INSERT_TAIL(&qpair.outstanding, &req, link); 1309 1310 spdk_nvmf_ctrlr_reservation_notice_log(&ctrlr, &ns, 1311 SPDK_NVME_REGISTRATION_PREEMPTED); 1312 spdk_nvmf_ctrlr_reservation_notice_log(&ctrlr, &ns, 1313 SPDK_NVME_RESERVATION_RELEASED); 1314 spdk_nvmf_ctrlr_reservation_notice_log(&ctrlr, &ns, 1315 SPDK_NVME_RESERVATION_PREEMPTED); 1316 poll_threads(); 1317 event.raw = rsp.nvme_cpl.cdw0; 1318 SPDK_CU_ASSERT_FATAL(event.bits.async_event_type == SPDK_NVME_ASYNC_EVENT_TYPE_IO); 1319 SPDK_CU_ASSERT_FATAL(event.bits.async_event_info == SPDK_NVME_ASYNC_EVENT_RESERVATION_LOG_AVAIL); 1320 SPDK_CU_ASSERT_FATAL(event.bits.log_page_identifier == SPDK_NVME_LOG_RESERVATION_NOTIFICATION); 1321 SPDK_CU_ASSERT_FATAL(ctrlr.num_avail_log_pages == 3); 1322 1323 /* Test Case: Get Log Page to clear the log pages */ 1324 spdk_nvmf_get_reservation_notification_log_page(&ctrlr, (void *)logs, 0, sizeof(logs)); 1325 SPDK_CU_ASSERT_FATAL(ctrlr.num_avail_log_pages == 0); 1326 } 1327 1328 static void 1329 test_get_dif_ctx(void) 1330 { 1331 struct spdk_nvmf_subsystem subsystem = {}; 1332 struct spdk_nvmf_request req = {}; 1333 struct spdk_nvmf_qpair qpair = {}; 1334 struct spdk_nvmf_ctrlr ctrlr = {}; 1335 struct spdk_nvmf_ns ns = {}; 1336 struct spdk_nvmf_ns *_ns = NULL; 1337 struct spdk_bdev bdev = {}; 1338 union nvmf_h2c_msg cmd = {}; 1339 struct spdk_dif_ctx dif_ctx = {}; 1340 bool ret; 1341 1342 ctrlr.subsys = &subsystem; 1343 1344 qpair.ctrlr = &ctrlr; 1345 1346 req.qpair = &qpair; 1347 req.cmd = &cmd; 1348 1349 ns.bdev = &bdev; 1350 1351 ctrlr.dif_insert_or_strip = false; 1352 1353 ret = spdk_nvmf_request_get_dif_ctx(&req, &dif_ctx); 1354 CU_ASSERT(ret == false); 1355 1356 ctrlr.dif_insert_or_strip = true; 1357 qpair.state = SPDK_NVMF_QPAIR_UNINITIALIZED; 1358 1359 ret = spdk_nvmf_request_get_dif_ctx(&req, &dif_ctx); 1360 CU_ASSERT(ret == false); 1361 1362 qpair.state = SPDK_NVMF_QPAIR_ACTIVE; 1363 cmd.nvmf_cmd.opcode = SPDK_NVME_OPC_FABRIC; 1364 1365 ret = spdk_nvmf_request_get_dif_ctx(&req, &dif_ctx); 1366 CU_ASSERT(ret == false); 1367 1368 cmd.nvmf_cmd.opcode = SPDK_NVME_OPC_FLUSH; 1369 1370 ret = spdk_nvmf_request_get_dif_ctx(&req, &dif_ctx); 1371 CU_ASSERT(ret == false); 1372 1373 qpair.qid = 1; 1374 1375 ret = spdk_nvmf_request_get_dif_ctx(&req, &dif_ctx); 1376 CU_ASSERT(ret == false); 1377 1378 cmd.nvme_cmd.nsid = 1; 1379 1380 ret = spdk_nvmf_request_get_dif_ctx(&req, &dif_ctx); 1381 CU_ASSERT(ret == false); 1382 1383 subsystem.max_nsid = 1; 1384 subsystem.ns = &_ns; 1385 subsystem.ns[0] = &ns; 1386 1387 ret = spdk_nvmf_request_get_dif_ctx(&req, &dif_ctx); 1388 CU_ASSERT(ret == false); 1389 1390 cmd.nvmf_cmd.opcode = SPDK_NVME_OPC_WRITE; 1391 1392 ret = spdk_nvmf_request_get_dif_ctx(&req, &dif_ctx); 1393 CU_ASSERT(ret == true); 1394 } 1395 1396 static void 1397 test_identify_ctrlr(void) 1398 { 1399 struct spdk_nvmf_subsystem subsystem = { 1400 .subtype = SPDK_NVMF_SUBTYPE_NVME 1401 }; 1402 struct spdk_nvmf_transport_ops tops = {}; 1403 struct spdk_nvmf_transport transport = { 1404 .ops = &tops, 1405 .opts = { 1406 .in_capsule_data_size = 4096, 1407 }, 1408 }; 1409 struct spdk_nvmf_qpair admin_qpair = { .transport = &transport}; 1410 struct spdk_nvmf_ctrlr ctrlr = { .subsys = &subsystem, .admin_qpair = &admin_qpair }; 1411 struct spdk_nvme_ctrlr_data cdata = {}; 1412 uint32_t expected_ioccsz; 1413 1414 spdk_nvmf_ctrlr_data_init(&transport.opts, &transport.cdata); 1415 1416 /* Check ioccsz, TCP transport */ 1417 tops.type = SPDK_NVME_TRANSPORT_TCP; 1418 expected_ioccsz = sizeof(struct spdk_nvme_cmd) / 16 + transport.opts.in_capsule_data_size / 16; 1419 CU_ASSERT(spdk_nvmf_ctrlr_identify_ctrlr(&ctrlr, &cdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 1420 CU_ASSERT(cdata.nvmf_specific.ioccsz == expected_ioccsz); 1421 1422 /* Check ioccsz, RDMA transport */ 1423 tops.type = SPDK_NVME_TRANSPORT_RDMA; 1424 expected_ioccsz = sizeof(struct spdk_nvme_cmd) / 16 + transport.opts.in_capsule_data_size / 16; 1425 CU_ASSERT(spdk_nvmf_ctrlr_identify_ctrlr(&ctrlr, &cdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 1426 CU_ASSERT(cdata.nvmf_specific.ioccsz == expected_ioccsz); 1427 1428 /* Check ioccsz, TCP transport with dif_insert_or_strip */ 1429 tops.type = SPDK_NVME_TRANSPORT_TCP; 1430 ctrlr.dif_insert_or_strip = true; 1431 expected_ioccsz = sizeof(struct spdk_nvme_cmd) / 16 + transport.opts.in_capsule_data_size / 16; 1432 CU_ASSERT(spdk_nvmf_ctrlr_identify_ctrlr(&ctrlr, &cdata) == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 1433 CU_ASSERT(cdata.nvmf_specific.ioccsz == expected_ioccsz); 1434 } 1435 1436 static int 1437 custom_admin_cmd_hdlr(struct spdk_nvmf_request *req) 1438 { 1439 req->rsp->nvme_cpl.status.sc = SPDK_NVME_SC_SUCCESS; 1440 1441 return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE; 1442 }; 1443 1444 static void 1445 test_custom_admin_cmd(void) 1446 { 1447 struct spdk_nvmf_subsystem subsystem; 1448 struct spdk_nvmf_qpair qpair; 1449 struct spdk_nvmf_ctrlr ctrlr; 1450 struct spdk_nvmf_request req; 1451 struct spdk_nvmf_ns *ns_ptrs[1]; 1452 struct spdk_nvmf_ns ns; 1453 union nvmf_h2c_msg cmd; 1454 union nvmf_c2h_msg rsp; 1455 struct spdk_bdev bdev; 1456 uint8_t buf[4096]; 1457 int rc; 1458 1459 memset(&subsystem, 0, sizeof(subsystem)); 1460 ns_ptrs[0] = &ns; 1461 subsystem.ns = ns_ptrs; 1462 subsystem.max_nsid = 1; 1463 subsystem.subtype = SPDK_NVMF_SUBTYPE_NVME; 1464 1465 memset(&ns, 0, sizeof(ns)); 1466 ns.opts.nsid = 1; 1467 ns.bdev = &bdev; 1468 1469 memset(&qpair, 0, sizeof(qpair)); 1470 qpair.ctrlr = &ctrlr; 1471 1472 memset(&ctrlr, 0, sizeof(ctrlr)); 1473 ctrlr.subsys = &subsystem; 1474 ctrlr.vcprop.cc.bits.en = 1; 1475 1476 memset(&req, 0, sizeof(req)); 1477 req.qpair = &qpair; 1478 req.cmd = &cmd; 1479 req.rsp = &rsp; 1480 req.xfer = SPDK_NVME_DATA_CONTROLLER_TO_HOST; 1481 req.data = buf; 1482 req.length = sizeof(buf); 1483 1484 memset(&cmd, 0, sizeof(cmd)); 1485 cmd.nvme_cmd.opc = 0xc1; 1486 cmd.nvme_cmd.nsid = 0; 1487 memset(&rsp, 0, sizeof(rsp)); 1488 1489 spdk_nvmf_set_custom_admin_cmd_hdlr(cmd.nvme_cmd.opc, custom_admin_cmd_hdlr); 1490 1491 /* Ensure that our hdlr is being called */ 1492 rc = spdk_nvmf_ctrlr_process_admin_cmd(&req); 1493 CU_ASSERT(rc == SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE); 1494 CU_ASSERT(rsp.nvme_cpl.status.sct == SPDK_NVME_SCT_GENERIC); 1495 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_SUCCESS); 1496 } 1497 1498 static void 1499 test_fused_compare_and_write(void) 1500 { 1501 struct spdk_nvmf_request req = {}; 1502 struct spdk_nvmf_qpair qpair = {}; 1503 struct spdk_nvme_cmd cmd = {}; 1504 union nvmf_c2h_msg rsp = {}; 1505 struct spdk_nvmf_ctrlr ctrlr = {}; 1506 struct spdk_nvmf_subsystem subsystem = {}; 1507 struct spdk_nvmf_ns ns = {}; 1508 struct spdk_nvmf_ns *subsys_ns[1] = {}; 1509 struct spdk_bdev bdev = {}; 1510 1511 struct spdk_nvmf_poll_group group = {}; 1512 struct spdk_nvmf_subsystem_poll_group sgroups = {}; 1513 struct spdk_nvmf_subsystem_pg_ns_info ns_info = {}; 1514 1515 ns.bdev = &bdev; 1516 1517 subsystem.id = 0; 1518 subsystem.max_nsid = 1; 1519 subsys_ns[0] = &ns; 1520 subsystem.ns = (struct spdk_nvmf_ns **)&subsys_ns; 1521 1522 /* Enable controller */ 1523 ctrlr.vcprop.cc.bits.en = 1; 1524 ctrlr.subsys = (struct spdk_nvmf_subsystem *)&subsystem; 1525 1526 group.num_sgroups = 1; 1527 sgroups.state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 1528 sgroups.num_ns = 1; 1529 sgroups.ns_info = &ns_info; 1530 TAILQ_INIT(&sgroups.queued); 1531 group.sgroups = &sgroups; 1532 TAILQ_INIT(&qpair.outstanding); 1533 1534 qpair.ctrlr = &ctrlr; 1535 qpair.group = &group; 1536 qpair.qid = 1; 1537 qpair.state = SPDK_NVMF_QPAIR_ACTIVE; 1538 1539 cmd.nsid = 1; 1540 1541 req.qpair = &qpair; 1542 req.cmd = (union nvmf_h2c_msg *)&cmd; 1543 req.rsp = &rsp; 1544 1545 /* SUCCESS/SUCCESS */ 1546 cmd.fuse = SPDK_NVME_CMD_FUSE_FIRST; 1547 cmd.opc = SPDK_NVME_OPC_COMPARE; 1548 1549 spdk_nvmf_request_exec(&req); 1550 CU_ASSERT(qpair.first_fused_req != NULL); 1551 CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status)); 1552 1553 cmd.fuse = SPDK_NVME_CMD_FUSE_SECOND; 1554 cmd.opc = SPDK_NVME_OPC_WRITE; 1555 1556 spdk_nvmf_request_exec(&req); 1557 CU_ASSERT(qpair.first_fused_req == NULL); 1558 CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status)); 1559 1560 /* Wrong sequence */ 1561 cmd.fuse = SPDK_NVME_CMD_FUSE_SECOND; 1562 cmd.opc = SPDK_NVME_OPC_WRITE; 1563 1564 spdk_nvmf_request_exec(&req); 1565 CU_ASSERT(!nvme_status_success(&rsp.nvme_cpl.status)); 1566 CU_ASSERT(qpair.first_fused_req == NULL); 1567 1568 /* Write as FUSE_FIRST (Wrong op code) */ 1569 cmd.fuse = SPDK_NVME_CMD_FUSE_FIRST; 1570 cmd.opc = SPDK_NVME_OPC_WRITE; 1571 1572 spdk_nvmf_request_exec(&req); 1573 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_OPCODE); 1574 CU_ASSERT(qpair.first_fused_req == NULL); 1575 1576 /* Compare as FUSE_SECOND (Wrong op code) */ 1577 cmd.fuse = SPDK_NVME_CMD_FUSE_FIRST; 1578 cmd.opc = SPDK_NVME_OPC_COMPARE; 1579 1580 spdk_nvmf_request_exec(&req); 1581 CU_ASSERT(qpair.first_fused_req != NULL); 1582 CU_ASSERT(nvme_status_success(&rsp.nvme_cpl.status)); 1583 1584 cmd.fuse = SPDK_NVME_CMD_FUSE_SECOND; 1585 cmd.opc = SPDK_NVME_OPC_COMPARE; 1586 1587 spdk_nvmf_request_exec(&req); 1588 CU_ASSERT(rsp.nvme_cpl.status.sc == SPDK_NVME_SC_INVALID_OPCODE); 1589 CU_ASSERT(qpair.first_fused_req == NULL); 1590 } 1591 1592 int main(int argc, char **argv) 1593 { 1594 CU_pSuite suite = NULL; 1595 unsigned int num_failures; 1596 1597 CU_set_error_action(CUEA_ABORT); 1598 CU_initialize_registry(); 1599 1600 suite = CU_add_suite("nvmf", NULL, NULL); 1601 CU_ADD_TEST(suite, test_get_log_page); 1602 CU_ADD_TEST(suite, test_process_fabrics_cmd); 1603 CU_ADD_TEST(suite, test_connect); 1604 CU_ADD_TEST(suite, test_get_ns_id_desc_list); 1605 CU_ADD_TEST(suite, test_identify_ns); 1606 CU_ADD_TEST(suite, test_reservation_write_exclusive); 1607 CU_ADD_TEST(suite, test_reservation_exclusive_access); 1608 CU_ADD_TEST(suite, test_reservation_write_exclusive_regs_only_and_all_regs); 1609 CU_ADD_TEST(suite, test_reservation_exclusive_access_regs_only_and_all_regs); 1610 CU_ADD_TEST(suite, test_reservation_notification_log_page); 1611 CU_ADD_TEST(suite, test_get_dif_ctx); 1612 CU_ADD_TEST(suite, test_set_get_features); 1613 CU_ADD_TEST(suite, test_identify_ctrlr); 1614 CU_ADD_TEST(suite, test_custom_admin_cmd); 1615 CU_ADD_TEST(suite, test_fused_compare_and_write); 1616 1617 allocate_threads(1); 1618 set_thread(0); 1619 1620 CU_basic_set_mode(CU_BRM_VERBOSE); 1621 CU_basic_run_tests(); 1622 num_failures = CU_get_number_of_failures(); 1623 CU_cleanup_registry(); 1624 1625 free_threads(); 1626 1627 return num_failures; 1628 } 1629