1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "spdk_cunit.h" 37 #include "spdk_internal/mock.h" 38 39 #include "common/lib/test_env.c" 40 #include "nvmf/ctrlr_discovery.c" 41 #include "nvmf/subsystem.c" 42 43 SPDK_LOG_REGISTER_COMPONENT(nvmf) 44 45 DEFINE_STUB_V(spdk_bdev_module_release_bdev, 46 (struct spdk_bdev *bdev)); 47 48 DEFINE_STUB(spdk_bdev_get_block_size, uint32_t, 49 (const struct spdk_bdev *bdev), 512); 50 51 DEFINE_STUB(spdk_nvmf_transport_stop_listen, 52 int, 53 (struct spdk_nvmf_transport *transport, 54 const struct spdk_nvme_transport_id *trid), 0); 55 56 DEFINE_STUB_V(spdk_bdev_close, (struct spdk_bdev_desc *desc)); 57 58 DEFINE_STUB(nvmf_ctrlr_async_event_discovery_log_change_notice, 59 int, 60 (struct spdk_nvmf_ctrlr *ctrlr), 0); 61 62 const char * 63 spdk_bdev_get_name(const struct spdk_bdev *bdev) 64 { 65 return "test"; 66 } 67 68 const struct spdk_uuid * 69 spdk_bdev_get_uuid(const struct spdk_bdev *bdev) 70 { 71 return &bdev->uuid; 72 } 73 74 int 75 spdk_nvmf_transport_listen(struct spdk_nvmf_transport *transport, 76 const struct spdk_nvme_transport_id *trid) 77 { 78 return 0; 79 } 80 81 static struct spdk_nvmf_listener g_listener = {}; 82 83 struct spdk_nvmf_listener * 84 nvmf_transport_find_listener(struct spdk_nvmf_transport *transport, 85 const struct spdk_nvme_transport_id *trid) 86 { 87 return &g_listener; 88 } 89 90 void 91 nvmf_transport_listener_discover(struct spdk_nvmf_transport *transport, 92 struct spdk_nvme_transport_id *trid, 93 struct spdk_nvmf_discovery_log_page_entry *entry) 94 { 95 entry->trtype = 42; 96 } 97 98 struct spdk_nvmf_transport_ops g_transport_ops = {}; 99 100 static struct spdk_nvmf_transport g_transport = { 101 .ops = &g_transport_ops 102 }; 103 104 struct spdk_nvmf_transport * 105 spdk_nvmf_transport_create(const char *transport_name, 106 struct spdk_nvmf_transport_opts *tprt_opts) 107 { 108 if (strcasecmp(transport_name, spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_RDMA))) { 109 return &g_transport; 110 } 111 112 return NULL; 113 } 114 115 struct spdk_nvmf_subsystem * 116 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn) 117 { 118 return NULL; 119 } 120 121 struct spdk_nvmf_transport * 122 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, const char *transport_name) 123 { 124 return &g_transport; 125 } 126 127 int 128 spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str) 129 { 130 if (trtype == NULL || str == NULL) { 131 return -EINVAL; 132 } 133 134 if (strcasecmp(str, "PCIe") == 0) { 135 *trtype = SPDK_NVME_TRANSPORT_PCIE; 136 } else if (strcasecmp(str, "RDMA") == 0) { 137 *trtype = SPDK_NVME_TRANSPORT_RDMA; 138 } else { 139 return -ENOENT; 140 } 141 return 0; 142 } 143 144 int 145 spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1, 146 const struct spdk_nvme_transport_id *trid2) 147 { 148 return 0; 149 } 150 151 void 152 nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid) 153 { 154 } 155 156 void 157 nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr) 158 { 159 } 160 161 int 162 nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group *group, 163 struct spdk_nvmf_subsystem *subsystem) 164 { 165 return 0; 166 } 167 168 int 169 nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group, 170 struct spdk_nvmf_subsystem *subsystem, 171 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 172 { 173 return 0; 174 } 175 176 void 177 nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group, 178 struct spdk_nvmf_subsystem *subsystem, 179 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 180 { 181 } 182 183 void 184 nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group *group, 185 struct spdk_nvmf_subsystem *subsystem, 186 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 187 { 188 } 189 190 void 191 nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group, 192 struct spdk_nvmf_subsystem *subsystem, 193 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 194 { 195 } 196 197 static void 198 _subsystem_add_listen_done(void *cb_arg, int status) 199 { 200 SPDK_CU_ASSERT_FATAL(status == 0); 201 } 202 203 static void 204 test_discovery_log(void) 205 { 206 struct spdk_nvmf_tgt tgt = {}; 207 struct spdk_nvmf_subsystem *subsystem; 208 uint8_t buffer[8192]; 209 struct iovec iov; 210 struct spdk_nvmf_discovery_log_page *disc_log; 211 struct spdk_nvmf_discovery_log_page_entry *entry; 212 struct spdk_nvme_transport_id trid = {}; 213 214 iov.iov_base = buffer; 215 iov.iov_len = 8192; 216 217 tgt.max_subsystems = 1024; 218 tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *)); 219 SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL); 220 221 /* Add one subsystem and verify that the discovery log contains it */ 222 subsystem = spdk_nvmf_subsystem_create(&tgt, "nqn.2016-06.io.spdk:subsystem1", 223 SPDK_NVMF_SUBTYPE_NVME, 0); 224 subsystem->flags.allow_any_host = true; 225 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 226 227 trid.trtype = SPDK_NVME_TRANSPORT_RDMA; 228 trid.adrfam = SPDK_NVMF_ADRFAM_IPV4; 229 snprintf(trid.traddr, sizeof(trid.traddr), "1234"); 230 snprintf(trid.trsvcid, sizeof(trid.trsvcid), "5678"); 231 spdk_nvmf_subsystem_add_listener(subsystem, &trid, _subsystem_add_listen_done, NULL); 232 subsystem->state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 233 234 /* Get only genctr (first field in the header) */ 235 memset(buffer, 0xCC, sizeof(buffer)); 236 disc_log = (struct spdk_nvmf_discovery_log_page *)buffer; 237 nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 238 sizeof(disc_log->genctr)); 239 CU_ASSERT(disc_log->genctr == 2); /* one added subsystem and listener */ 240 241 /* Get only the header, no entries */ 242 memset(buffer, 0xCC, sizeof(buffer)); 243 disc_log = (struct spdk_nvmf_discovery_log_page *)buffer; 244 nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, sizeof(*disc_log)); 245 CU_ASSERT(disc_log->genctr == 2); 246 CU_ASSERT(disc_log->numrec == 1); 247 248 /* Offset 0, exact size match */ 249 memset(buffer, 0xCC, sizeof(buffer)); 250 disc_log = (struct spdk_nvmf_discovery_log_page *)buffer; 251 nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 252 sizeof(*disc_log) + sizeof(disc_log->entries[0])); 253 CU_ASSERT(disc_log->genctr != 0); 254 CU_ASSERT(disc_log->numrec == 1); 255 CU_ASSERT(disc_log->entries[0].trtype == 42); 256 257 /* Offset 0, oversize buffer */ 258 memset(buffer, 0xCC, sizeof(buffer)); 259 disc_log = (struct spdk_nvmf_discovery_log_page *)buffer; 260 nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, sizeof(buffer)); 261 CU_ASSERT(disc_log->genctr != 0); 262 CU_ASSERT(disc_log->numrec == 1); 263 CU_ASSERT(disc_log->entries[0].trtype == 42); 264 CU_ASSERT(spdk_mem_all_zero(buffer + sizeof(*disc_log) + sizeof(disc_log->entries[0]), 265 sizeof(buffer) - (sizeof(*disc_log) + sizeof(disc_log->entries[0])))); 266 267 /* Get just the first entry, no header */ 268 memset(buffer, 0xCC, sizeof(buffer)); 269 entry = (struct spdk_nvmf_discovery_log_page_entry *)buffer; 270 nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 271 1, 272 offsetof(struct spdk_nvmf_discovery_log_page, entries[0]), 273 sizeof(*entry)); 274 CU_ASSERT(entry->trtype == 42); 275 subsystem->state = SPDK_NVMF_SUBSYSTEM_INACTIVE; 276 spdk_nvmf_subsystem_destroy(subsystem); 277 free(tgt.subsystems); 278 } 279 280 int main(int argc, char **argv) 281 { 282 CU_pSuite suite = NULL; 283 unsigned int num_failures; 284 285 CU_set_error_action(CUEA_ABORT); 286 CU_initialize_registry(); 287 288 suite = CU_add_suite("nvmf", NULL, NULL); 289 290 CU_ADD_TEST(suite, test_discovery_log); 291 292 CU_basic_set_mode(CU_BRM_VERBOSE); 293 CU_basic_run_tests(); 294 num_failures = CU_get_number_of_failures(); 295 CU_cleanup_registry(); 296 return num_failures; 297 } 298