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