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 int 57 spdk_bdev_open(struct spdk_bdev *bdev, bool write, spdk_bdev_remove_cb_t remove_cb, 58 void *remove_ctx, struct spdk_bdev_desc **desc) 59 { 60 return 0; 61 } 62 63 void 64 spdk_bdev_close(struct spdk_bdev_desc *desc) 65 { 66 } 67 68 const char * 69 spdk_bdev_get_name(const struct spdk_bdev *bdev) 70 { 71 return "test"; 72 } 73 74 const struct spdk_uuid * 75 spdk_bdev_get_uuid(const struct spdk_bdev *bdev) 76 { 77 return &bdev->uuid; 78 } 79 80 int 81 spdk_nvmf_transport_listen(struct spdk_nvmf_transport *transport, 82 const struct spdk_nvme_transport_id *trid) 83 { 84 return 0; 85 } 86 87 static struct spdk_nvmf_listener g_listener = {}; 88 89 struct spdk_nvmf_listener * 90 nvmf_transport_find_listener(struct spdk_nvmf_transport *transport, 91 const struct spdk_nvme_transport_id *trid) 92 { 93 return &g_listener; 94 } 95 96 void 97 nvmf_transport_listener_discover(struct spdk_nvmf_transport *transport, 98 struct spdk_nvme_transport_id *trid, 99 struct spdk_nvmf_discovery_log_page_entry *entry) 100 { 101 entry->trtype = 42; 102 } 103 104 struct spdk_nvmf_transport_ops g_transport_ops = {}; 105 106 static struct spdk_nvmf_transport g_transport = { 107 .ops = &g_transport_ops 108 }; 109 110 struct spdk_nvmf_transport * 111 spdk_nvmf_transport_create(const char *transport_name, 112 struct spdk_nvmf_transport_opts *tprt_opts) 113 { 114 if (strcasecmp(transport_name, spdk_nvme_transport_id_trtype_str(SPDK_NVME_TRANSPORT_RDMA))) { 115 return &g_transport; 116 } 117 118 return NULL; 119 } 120 121 struct spdk_nvmf_subsystem * 122 spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn) 123 { 124 return NULL; 125 } 126 127 struct spdk_nvmf_transport * 128 spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, const char *transport_name) 129 { 130 return &g_transport; 131 } 132 133 int 134 spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str) 135 { 136 if (trtype == NULL || str == NULL) { 137 return -EINVAL; 138 } 139 140 if (strcasecmp(str, "PCIe") == 0) { 141 *trtype = SPDK_NVME_TRANSPORT_PCIE; 142 } else if (strcasecmp(str, "RDMA") == 0) { 143 *trtype = SPDK_NVME_TRANSPORT_RDMA; 144 } else { 145 return -ENOENT; 146 } 147 return 0; 148 } 149 150 int 151 spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1, 152 const struct spdk_nvme_transport_id *trid2) 153 { 154 return 0; 155 } 156 157 void 158 nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid) 159 { 160 } 161 162 void 163 nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr) 164 { 165 } 166 167 int 168 nvmf_poll_group_update_subsystem(struct spdk_nvmf_poll_group *group, 169 struct spdk_nvmf_subsystem *subsystem) 170 { 171 return 0; 172 } 173 174 int 175 nvmf_poll_group_add_subsystem(struct spdk_nvmf_poll_group *group, 176 struct spdk_nvmf_subsystem *subsystem, 177 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 178 { 179 return 0; 180 } 181 182 void 183 nvmf_poll_group_remove_subsystem(struct spdk_nvmf_poll_group *group, 184 struct spdk_nvmf_subsystem *subsystem, 185 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 186 { 187 } 188 189 void 190 nvmf_poll_group_pause_subsystem(struct spdk_nvmf_poll_group *group, 191 struct spdk_nvmf_subsystem *subsystem, 192 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 193 { 194 } 195 196 void 197 nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group, 198 struct spdk_nvmf_subsystem *subsystem, 199 spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg) 200 { 201 } 202 203 static void 204 _subsystem_add_listen_done(void *cb_arg, int status) 205 { 206 SPDK_CU_ASSERT_FATAL(status == 0); 207 } 208 209 static void 210 test_discovery_log(void) 211 { 212 struct spdk_nvmf_tgt tgt = {}; 213 struct spdk_nvmf_subsystem *subsystem; 214 uint8_t buffer[8192]; 215 struct iovec iov; 216 struct spdk_nvmf_discovery_log_page *disc_log; 217 struct spdk_nvmf_discovery_log_page_entry *entry; 218 struct spdk_nvme_transport_id trid = {}; 219 220 iov.iov_base = buffer; 221 iov.iov_len = 8192; 222 223 tgt.max_subsystems = 1024; 224 tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *)); 225 SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL); 226 227 /* Add one subsystem and verify that the discovery log contains it */ 228 subsystem = spdk_nvmf_subsystem_create(&tgt, "nqn.2016-06.io.spdk:subsystem1", 229 SPDK_NVMF_SUBTYPE_NVME, 0); 230 subsystem->flags.allow_any_host = true; 231 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 232 233 trid.trtype = SPDK_NVME_TRANSPORT_RDMA; 234 trid.adrfam = SPDK_NVMF_ADRFAM_IPV4; 235 snprintf(trid.traddr, sizeof(trid.traddr), "1234"); 236 snprintf(trid.trsvcid, sizeof(trid.trsvcid), "5678"); 237 spdk_nvmf_subsystem_add_listener(subsystem, &trid, _subsystem_add_listen_done, NULL); 238 subsystem->state = SPDK_NVMF_SUBSYSTEM_ACTIVE; 239 240 /* Get only genctr (first field in the header) */ 241 memset(buffer, 0xCC, sizeof(buffer)); 242 disc_log = (struct spdk_nvmf_discovery_log_page *)buffer; 243 nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 244 sizeof(disc_log->genctr)); 245 CU_ASSERT(disc_log->genctr == 2); /* one added subsystem and listener */ 246 247 /* Get only the header, no entries */ 248 memset(buffer, 0xCC, sizeof(buffer)); 249 disc_log = (struct spdk_nvmf_discovery_log_page *)buffer; 250 nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, sizeof(*disc_log)); 251 CU_ASSERT(disc_log->genctr == 2); 252 CU_ASSERT(disc_log->numrec == 1); 253 254 /* Offset 0, exact size match */ 255 memset(buffer, 0xCC, sizeof(buffer)); 256 disc_log = (struct spdk_nvmf_discovery_log_page *)buffer; 257 nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 258 sizeof(*disc_log) + sizeof(disc_log->entries[0])); 259 CU_ASSERT(disc_log->genctr != 0); 260 CU_ASSERT(disc_log->numrec == 1); 261 CU_ASSERT(disc_log->entries[0].trtype == 42); 262 263 /* Offset 0, oversize buffer */ 264 memset(buffer, 0xCC, sizeof(buffer)); 265 disc_log = (struct spdk_nvmf_discovery_log_page *)buffer; 266 nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, sizeof(buffer)); 267 CU_ASSERT(disc_log->genctr != 0); 268 CU_ASSERT(disc_log->numrec == 1); 269 CU_ASSERT(disc_log->entries[0].trtype == 42); 270 CU_ASSERT(spdk_mem_all_zero(buffer + sizeof(*disc_log) + sizeof(disc_log->entries[0]), 271 sizeof(buffer) - (sizeof(*disc_log) + sizeof(disc_log->entries[0])))); 272 273 /* Get just the first entry, no header */ 274 memset(buffer, 0xCC, sizeof(buffer)); 275 entry = (struct spdk_nvmf_discovery_log_page_entry *)buffer; 276 nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 277 1, 278 offsetof(struct spdk_nvmf_discovery_log_page, entries[0]), 279 sizeof(*entry)); 280 CU_ASSERT(entry->trtype == 42); 281 subsystem->state = SPDK_NVMF_SUBSYSTEM_INACTIVE; 282 spdk_nvmf_subsystem_destroy(subsystem); 283 free(tgt.subsystems); 284 } 285 286 int main(int argc, char **argv) 287 { 288 CU_pSuite suite = NULL; 289 unsigned int num_failures; 290 291 CU_set_error_action(CUEA_ABORT); 292 CU_initialize_registry(); 293 294 suite = CU_add_suite("nvmf", NULL, NULL); 295 296 CU_ADD_TEST(suite, test_discovery_log); 297 298 CU_basic_set_mode(CU_BRM_VERBOSE); 299 CU_basic_run_tests(); 300 num_failures = CU_get_number_of_failures(); 301 CU_cleanup_registry(); 302 return num_failures; 303 } 304