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 "subsystem.h" 38 39 const struct spdk_nvmf_ctrlr_ops spdk_nvmf_direct_ctrlr_ops; 40 const struct spdk_nvmf_ctrlr_ops spdk_nvmf_virtual_ctrlr_ops; 41 const struct spdk_nvmf_ctrlr_ops spdk_nvmf_discovery_ctrlr_ops; 42 43 #include "subsystem.c" 44 45 SPDK_LOG_REGISTER_TRACE_FLAG("nvmf", SPDK_TRACE_NVMF) 46 47 struct spdk_nvmf_tgt g_nvmf_tgt; 48 49 struct spdk_nvmf_listen_addr * 50 spdk_nvmf_listen_addr_create(const char *trname, enum spdk_nvmf_adrfam adrfam, const char *traddr, 51 const char *trsvcid) 52 { 53 struct spdk_nvmf_listen_addr *listen_addr; 54 55 listen_addr = calloc(1, sizeof(*listen_addr)); 56 if (!listen_addr) { 57 return NULL; 58 } 59 60 listen_addr->traddr = strdup(traddr); 61 if (!listen_addr->traddr) { 62 free(listen_addr); 63 return NULL; 64 } 65 66 listen_addr->trsvcid = strdup(trsvcid); 67 if (!listen_addr->trsvcid) { 68 free(listen_addr->traddr); 69 free(listen_addr); 70 return NULL; 71 } 72 73 listen_addr->trname = strdup(trname); 74 if (!listen_addr->trname) { 75 free(listen_addr->traddr); 76 free(listen_addr->trsvcid); 77 free(listen_addr); 78 return NULL; 79 } 80 81 listen_addr->adrfam = adrfam; 82 83 return listen_addr; 84 } 85 86 void 87 spdk_nvmf_listen_addr_destroy(struct spdk_nvmf_listen_addr *addr) 88 { 89 free(addr->trname); 90 free(addr->trsvcid); 91 free(addr->traddr); 92 free(addr); 93 } 94 95 void 96 spdk_nvmf_listen_addr_cleanup(struct spdk_nvmf_listen_addr *addr) 97 { 98 return; 99 } 100 101 static int 102 test_transport1_listen_addr_add(struct spdk_nvmf_listen_addr *listen_addr) 103 { 104 return 0; 105 } 106 107 static void 108 test_transport1_listen_addr_discover(struct spdk_nvmf_listen_addr *listen_addr, 109 struct spdk_nvmf_discovery_log_page_entry *entry) 110 { 111 entry->trtype = 42; 112 } 113 114 static const struct spdk_nvmf_transport test_transport1 = { 115 .listen_addr_add = test_transport1_listen_addr_add, 116 .listen_addr_discover = test_transport1_listen_addr_discover, 117 }; 118 119 const struct spdk_nvmf_transport * 120 spdk_nvmf_transport_get(const char *trname) 121 { 122 if (!strcasecmp(trname, "test_transport1")) { 123 return &test_transport1; 124 } 125 126 return NULL; 127 } 128 129 int32_t 130 spdk_nvme_ctrlr_process_admin_completions(struct spdk_nvme_ctrlr *ctrlr) 131 { 132 return -1; 133 } 134 135 int32_t 136 spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions) 137 { 138 return -1; 139 } 140 141 int 142 spdk_nvme_detach(struct spdk_nvme_ctrlr *ctrlr) 143 { 144 return -1; 145 } 146 147 void 148 spdk_nvmf_session_destruct(struct spdk_nvmf_session *session) 149 { 150 } 151 152 int 153 spdk_nvmf_session_poll(struct spdk_nvmf_session *session) 154 { 155 return -1; 156 } 157 158 int 159 spdk_bdev_open(struct spdk_bdev *bdev, bool write, spdk_bdev_remove_cb_t remove_cb, 160 void *remove_ctx, struct spdk_bdev_desc **desc) 161 { 162 return 0; 163 } 164 165 const char * 166 spdk_bdev_get_name(const struct spdk_bdev *bdev) 167 { 168 return "test"; 169 } 170 171 static void 172 test_spdk_nvmf_tgt_listen(void) 173 { 174 struct spdk_nvmf_listen_addr *listen_addr; 175 176 /* Invalid trname */ 177 const char *trname = "test_invalid_trname"; 178 enum spdk_nvmf_adrfam adrfam = SPDK_NVMF_ADRFAM_IPV4; 179 const char *traddr = "192.168.100.1"; 180 const char *trsvcid = "4420"; 181 CU_ASSERT(spdk_nvmf_tgt_listen(trname, adrfam, traddr, trsvcid) == NULL); 182 183 /* Listen addr is not create and create valid listen addr */ 184 trname = "test_transport1"; 185 adrfam = SPDK_NVMF_ADRFAM_IPV4; 186 traddr = "192.168.3.11"; 187 trsvcid = "3320"; 188 listen_addr = spdk_nvmf_tgt_listen(trname, adrfam, traddr, trsvcid); 189 SPDK_CU_ASSERT_FATAL(listen_addr != NULL); 190 CU_ASSERT(listen_addr->traddr != NULL); 191 CU_ASSERT(listen_addr->trsvcid != NULL); 192 spdk_nvmf_listen_addr_destroy(listen_addr); 193 194 } 195 196 static void 197 test_spdk_nvmf_subsystem_add_ns(void) 198 { 199 struct spdk_nvmf_subsystem subsystem = { 200 .mode = NVMF_SUBSYSTEM_MODE_VIRTUAL, 201 .dev.virt.max_nsid = 0, 202 .dev.virt.ns_list = {}, 203 }; 204 struct spdk_bdev bdev1 = {}, bdev2 = {}; 205 uint32_t nsid; 206 207 /* Allow NSID to be assigned automatically */ 208 nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev1, 0); 209 /* NSID 1 is the first unused ID */ 210 CU_ASSERT(nsid == 1); 211 CU_ASSERT(subsystem.dev.virt.max_nsid == 1); 212 CU_ASSERT(subsystem.dev.virt.ns_list[nsid - 1] == &bdev1); 213 214 /* Request a specific NSID */ 215 nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev2, 5); 216 CU_ASSERT(nsid == 5); 217 CU_ASSERT(subsystem.dev.virt.max_nsid == 5); 218 CU_ASSERT(subsystem.dev.virt.ns_list[nsid - 1] == &bdev2); 219 220 /* Request an NSID that is already in use */ 221 nsid = spdk_nvmf_subsystem_add_ns(&subsystem, &bdev2, 5); 222 CU_ASSERT(nsid == 0); 223 CU_ASSERT(subsystem.dev.virt.max_nsid == 5); 224 } 225 226 static void 227 nvmf_test_create_subsystem(void) 228 { 229 char nqn[256]; 230 struct spdk_nvmf_subsystem *subsystem; 231 TAILQ_INIT(&g_nvmf_tgt.subsystems); 232 233 strncpy(nqn, "nqn.2016-06.io.spdk:subsystem1", sizeof(nqn)); 234 subsystem = spdk_nvmf_create_subsystem(nqn, SPDK_NVMF_SUBTYPE_NVME, 235 NVMF_SUBSYSTEM_MODE_DIRECT, NULL, NULL, NULL); 236 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 237 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 238 spdk_nvmf_delete_subsystem(subsystem); 239 240 /* Longest valid name */ 241 strncpy(nqn, "nqn.2016-06.io.spdk:", sizeof(nqn)); 242 memset(nqn + strlen(nqn), 'a', 223 - strlen(nqn)); 243 nqn[223] = '\0'; 244 CU_ASSERT(strlen(nqn) == 223); 245 subsystem = spdk_nvmf_create_subsystem(nqn, SPDK_NVMF_SUBTYPE_NVME, 246 NVMF_SUBSYSTEM_MODE_DIRECT, NULL, NULL, NULL); 247 SPDK_CU_ASSERT_FATAL(subsystem != NULL); 248 CU_ASSERT_STRING_EQUAL(subsystem->subnqn, nqn); 249 spdk_nvmf_delete_subsystem(subsystem); 250 251 /* Name that is one byte longer than allowed */ 252 strncpy(nqn, "nqn.2016-06.io.spdk:", sizeof(nqn)); 253 memset(nqn + strlen(nqn), 'a', 224 - strlen(nqn)); 254 nqn[224] = '\0'; 255 CU_ASSERT(strlen(nqn) == 224); 256 subsystem = spdk_nvmf_create_subsystem(nqn, SPDK_NVMF_SUBTYPE_NVME, 257 NVMF_SUBSYSTEM_MODE_DIRECT, NULL, NULL, NULL); 258 CU_ASSERT(subsystem == NULL); 259 } 260 261 static void 262 nvmf_test_find_subsystem(void) 263 { 264 CU_ASSERT_PTR_NULL(spdk_nvmf_find_subsystem(NULL)); 265 CU_ASSERT_PTR_NULL(spdk_nvmf_find_subsystem("fake")); 266 } 267 268 int main(int argc, char **argv) 269 { 270 CU_pSuite suite = NULL; 271 unsigned int num_failures; 272 273 if (CU_initialize_registry() != CUE_SUCCESS) { 274 return CU_get_error(); 275 } 276 277 suite = CU_add_suite("nvmf", NULL, NULL); 278 if (suite == NULL) { 279 CU_cleanup_registry(); 280 return CU_get_error(); 281 } 282 283 if ( 284 CU_add_test(suite, "create_subsystem", nvmf_test_create_subsystem) == NULL || 285 CU_add_test(suite, "nvmf_tgt_listen", test_spdk_nvmf_tgt_listen) == NULL || 286 CU_add_test(suite, "nvmf_subsystem_add_ns", test_spdk_nvmf_subsystem_add_ns) == NULL || 287 CU_add_test(suite, "find_subsystem", nvmf_test_find_subsystem) == NULL) { 288 CU_cleanup_registry(); 289 return CU_get_error(); 290 } 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