diff --git a/app/nvmf_tgt/conf.c b/app/nvmf_tgt/conf.c index 4017c4b2c..618cddf39 100644 --- a/app/nvmf_tgt/conf.c +++ b/app/nvmf_tgt/conf.c @@ -451,6 +451,7 @@ spdk_nvmf_construct_subsystem(const char *name, { struct spdk_nvmf_subsystem *subsystem; struct nvmf_tgt_subsystem *app_subsys; + struct spdk_nvmf_listen_addr *listen_addr; enum spdk_nvmf_subsystem_mode mode; int i; uint64_t mask; @@ -519,8 +520,10 @@ spdk_nvmf_construct_subsystem(const char *name, } } - spdk_nvmf_subsystem_add_listener(subsystem, addresses[i].transport, addresses[i].traddr, - addresses[i].trsvcid); + listen_addr = spdk_nvmf_tgt_listen(addresses[i].transport, + addresses[i].traddr, addresses[i].trsvcid); + assert(listen_addr != NULL); + spdk_nvmf_subsystem_add_listener(subsystem, listen_addr); } /* Parse Host sections */ diff --git a/app/nvmf_tgt/nvmf_rpc.c b/app/nvmf_tgt/nvmf_rpc.c index 79b783ec7..c02f38c67 100644 --- a/app/nvmf_tgt/nvmf_rpc.c +++ b/app/nvmf_tgt/nvmf_rpc.c @@ -50,6 +50,7 @@ dump_nvmf_subsystem(struct spdk_json_write_ctx *w, struct nvmf_tgt_subsystem *tg struct spdk_nvmf_listen_addr *listen_addr; struct spdk_nvmf_host *host; struct spdk_nvmf_subsystem *subsystem = tgt_subsystem->subsystem; + struct spdk_nvmf_subsystem_allowed_listener *allowed_listener; spdk_json_write_object_begin(w); @@ -76,7 +77,8 @@ dump_nvmf_subsystem(struct spdk_json_write_ctx *w, struct nvmf_tgt_subsystem *tg spdk_json_write_name(w, "listen_addresses"); spdk_json_write_array_begin(w); - TAILQ_FOREACH(listen_addr, &subsystem->listen_addrs, link) { + TAILQ_FOREACH(allowed_listener, &subsystem->allowed_listeners, link) { + listen_addr = allowed_listener->listen_addr; spdk_json_write_object_begin(w); spdk_json_write_name(w, "transport"); spdk_json_write_string(w, listen_addr->trname); diff --git a/include/spdk/nvmf.h b/include/spdk/nvmf.h index 8b314bbaf..5540f1b7a 100644 --- a/include/spdk/nvmf.h +++ b/include/spdk/nvmf.h @@ -115,6 +115,11 @@ struct spdk_nvmf_ctrlr_ops { void (*detach)(struct spdk_nvmf_subsystem *subsystem); }; +struct spdk_nvmf_subsystem_allowed_listener { + struct spdk_nvmf_listen_addr *listen_addr; + TAILQ_ENTRY(spdk_nvmf_subsystem_allowed_listener) link; +}; + /* * The NVMf subsystem, as indicated in the specification, is a collection * of virtual controller sessions. Any individual controller session has @@ -149,12 +154,11 @@ struct spdk_nvmf_subsystem { TAILQ_HEAD(, spdk_nvmf_session) sessions; - TAILQ_HEAD(, spdk_nvmf_listen_addr) listen_addrs; - uint32_t num_listen_addrs; - TAILQ_HEAD(, spdk_nvmf_host) hosts; uint32_t num_hosts; + TAILQ_HEAD(, spdk_nvmf_subsystem_allowed_listener) allowed_listeners; + TAILQ_ENTRY(spdk_nvmf_subsystem) entries; }; @@ -181,9 +185,16 @@ bool spdk_nvmf_subsystem_exists(const char *subnqn); bool spdk_nvmf_subsystem_host_allowed(struct spdk_nvmf_subsystem *subsystem, const char *hostnqn); +struct spdk_nvmf_listen_addr * +spdk_nvmf_tgt_listen(const char *trname, const char *traddr, const char *trsvcid); + int spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem, - const char *trname, const char *traddr, const char *trsvcid); + struct spdk_nvmf_listen_addr *listen_addr); + +bool +spdk_nvmf_subsystem_listener_allowed(struct spdk_nvmf_subsystem *subsystem, + struct spdk_nvmf_listen_addr *listen_addr); int spdk_nvmf_subsystem_add_host(struct spdk_nvmf_subsystem *subsystem, diff --git a/lib/nvmf/nvmf.c b/lib/nvmf/nvmf.c index 02ea956ae..db3bb68de 100644 --- a/lib/nvmf/nvmf.c +++ b/lib/nvmf/nvmf.c @@ -62,6 +62,7 @@ spdk_nvmf_tgt_init(uint16_t max_queue_depth, uint16_t max_queues_per_sess, g_nvmf_tgt.discovery_log_page = NULL; g_nvmf_tgt.discovery_log_page_size = 0; TAILQ_INIT(&g_nvmf_tgt.subsystems); + TAILQ_INIT(&g_nvmf_tgt.listen_addrs); SPDK_TRACELOG(SPDK_TRACE_NVMF, "Max Queues Per Session: %d\n", max_queues_per_sess); SPDK_TRACELOG(SPDK_TRACE_NVMF, "Max Queue Depth: %d\n", max_queue_depth); @@ -80,6 +81,15 @@ spdk_nvmf_tgt_init(uint16_t max_queue_depth, uint16_t max_queues_per_sess, int spdk_nvmf_tgt_fini(void) { + struct spdk_nvmf_listen_addr *listen_addr, *listen_addr_tmp; + + TAILQ_FOREACH_SAFE(listen_addr, &g_nvmf_tgt.listen_addrs, link, listen_addr_tmp) { + TAILQ_REMOVE(&g_nvmf_tgt.listen_addrs, listen_addr, link); + g_nvmf_tgt.discovery_genctr++; + + spdk_nvmf_listen_addr_destroy(listen_addr); + } + spdk_nvmf_transport_fini(); return 0; diff --git a/lib/nvmf/nvmf_internal.h b/lib/nvmf/nvmf_internal.h index 191080680..e87f2c8c7 100644 --- a/lib/nvmf/nvmf_internal.h +++ b/lib/nvmf/nvmf_internal.h @@ -55,6 +55,7 @@ struct spdk_nvmf_tgt { TAILQ_HEAD(, spdk_nvmf_subsystem) subsystems; struct spdk_nvmf_discovery_log_page *discovery_log_page; size_t discovery_log_page_size; + TAILQ_HEAD(, spdk_nvmf_listen_addr) listen_addrs; }; extern struct spdk_nvmf_tgt g_nvmf_tgt; diff --git a/lib/nvmf/subsystem.c b/lib/nvmf/subsystem.c index de952c6fc..ed647d0ee 100644 --- a/lib/nvmf/subsystem.c +++ b/lib/nvmf/subsystem.c @@ -199,7 +199,7 @@ spdk_nvmf_create_subsystem(const char *nqn, subsystem->connect_cb = connect_cb; subsystem->disconnect_cb = disconnect_cb; snprintf(subsystem->subnqn, sizeof(subsystem->subnqn), "%s", nqn); - TAILQ_INIT(&subsystem->listen_addrs); + TAILQ_INIT(&subsystem->allowed_listeners); TAILQ_INIT(&subsystem->hosts); TAILQ_INIT(&subsystem->sessions); @@ -218,7 +218,7 @@ spdk_nvmf_create_subsystem(const char *nqn, void spdk_nvmf_delete_subsystem(struct spdk_nvmf_subsystem *subsystem) { - struct spdk_nvmf_listen_addr *listen_addr, *listen_addr_tmp; + struct spdk_nvmf_subsystem_allowed_listener *allowed_listener, *allowed_listener_tmp; struct spdk_nvmf_host *host, *host_tmp; struct spdk_nvmf_session *session, *session_tmp; @@ -228,10 +228,11 @@ spdk_nvmf_delete_subsystem(struct spdk_nvmf_subsystem *subsystem) SPDK_TRACELOG(SPDK_TRACE_NVMF, "subsystem is %p\n", subsystem); - TAILQ_FOREACH_SAFE(listen_addr, &subsystem->listen_addrs, link, listen_addr_tmp) { - TAILQ_REMOVE(&subsystem->listen_addrs, listen_addr, link); - spdk_nvmf_listen_addr_destroy(listen_addr); - subsystem->num_listen_addrs--; + TAILQ_FOREACH_SAFE(allowed_listener, + &subsystem->allowed_listeners, link, allowed_listener_tmp) { + TAILQ_REMOVE(&subsystem->allowed_listeners, allowed_listener, link); + + free(allowed_listener); } TAILQ_FOREACH_SAFE(host, &subsystem->hosts, link, host_tmp) { @@ -255,38 +256,84 @@ spdk_nvmf_delete_subsystem(struct spdk_nvmf_subsystem *subsystem) free(subsystem); } -int -spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem, - const char *trname, const char *traddr, const char *trsvcid) +struct spdk_nvmf_listen_addr * +spdk_nvmf_tgt_listen(const char *trname, const char *traddr, const char *trsvcid) { struct spdk_nvmf_listen_addr *listen_addr; const struct spdk_nvmf_transport *transport; int rc; + TAILQ_FOREACH(listen_addr, &g_nvmf_tgt.listen_addrs, link) { + if ((strcmp(listen_addr->trname, trname) == 0) && + (strcmp(listen_addr->traddr, traddr) == 0) && + (strcmp(listen_addr->trsvcid, trsvcid) == 0)) { + return listen_addr; + } + } + transport = spdk_nvmf_transport_get(trname); if (!transport) { - return -1; + return NULL; } listen_addr = spdk_nvmf_listen_addr_create(trname, traddr, trsvcid); if (!listen_addr) { - return -1; + return NULL; } rc = transport->listen_addr_add(listen_addr); if (rc < 0) { spdk_nvmf_listen_addr_cleanup(listen_addr); SPDK_ERRLOG("Unable to listen on address '%s'\n", traddr); + return NULL; + } + + TAILQ_INSERT_HEAD(&g_nvmf_tgt.listen_addrs, listen_addr, link); + g_nvmf_tgt.discovery_genctr++; + + return listen_addr; +} + +int +spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem, + struct spdk_nvmf_listen_addr *listen_addr) +{ + struct spdk_nvmf_subsystem_allowed_listener *allowed_listener; + + allowed_listener = calloc(1, sizeof(*allowed_listener)); + if (!allowed_listener) { return -1; } - TAILQ_INSERT_HEAD(&subsystem->listen_addrs, listen_addr, link); - subsystem->num_listen_addrs++; - g_nvmf_tgt.discovery_genctr++; + allowed_listener->listen_addr = listen_addr; + + TAILQ_INSERT_HEAD(&subsystem->allowed_listeners, allowed_listener, link); return 0; } +/* + * TODO: this is the whitelist and will be called during connection setup + */ +bool +spdk_nvmf_subsystem_listener_allowed(struct spdk_nvmf_subsystem *subsystem, + struct spdk_nvmf_listen_addr *listen_addr) +{ + struct spdk_nvmf_subsystem_allowed_listener *allowed_listener; + + if (TAILQ_EMPTY(&subsystem->allowed_listeners)) { + return true; + } + + TAILQ_FOREACH(allowed_listener, &subsystem->allowed_listeners, link) { + if (allowed_listener->listen_addr == listen_addr) { + return true; + } + } + + return false; +} + int spdk_nvmf_subsystem_add_host(struct spdk_nvmf_subsystem *subsystem, const char *host_nqn) { @@ -324,6 +371,7 @@ nvmf_update_discovery_log(void) { uint64_t numrec = 0; struct spdk_nvmf_subsystem *subsystem; + struct spdk_nvmf_subsystem_allowed_listener *allowed_listener; struct spdk_nvmf_listen_addr *listen_addr; struct spdk_nvmf_discovery_log_page_entry *entry; const struct spdk_nvmf_transport *transport; @@ -345,7 +393,7 @@ nvmf_update_discovery_log(void) continue; } - TAILQ_FOREACH(listen_addr, &subsystem->listen_addrs, link) { + TAILQ_FOREACH(allowed_listener, &subsystem->allowed_listeners, link) { size_t new_size = cur_size + sizeof(*entry); void *new_log_page = realloc(disc_log, new_size); @@ -354,6 +402,8 @@ nvmf_update_discovery_log(void) break; } + listen_addr = allowed_listener->listen_addr; + disc_log = new_log_page; cur_size = new_size; diff --git a/test/lib/nvmf/subsystem/subsystem_ut.c b/test/lib/nvmf/subsystem/subsystem_ut.c index f9b5e8020..45083deac 100644 --- a/test/lib/nvmf/subsystem/subsystem_ut.c +++ b/test/lib/nvmf/subsystem/subsystem_ut.c @@ -225,6 +225,7 @@ test_discovery_log(void) uint8_t buffer[8192]; struct spdk_nvmf_discovery_log_page *disc_log; struct spdk_nvmf_discovery_log_page_entry *entry; + struct spdk_nvmf_listen_addr *listen_addr; /* Reset discovery-related globals */ g_nvmf_tgt.discovery_genctr = 0; @@ -237,8 +238,10 @@ test_discovery_log(void) NVMF_SUBSYSTEM_MODE_DIRECT, NULL, NULL, NULL); SPDK_CU_ASSERT_FATAL(subsystem != NULL); - SPDK_CU_ASSERT_FATAL(spdk_nvmf_subsystem_add_listener(subsystem, "test_transport1", - "1234", "5678") == 0); + listen_addr = spdk_nvmf_tgt_listen("test_transport1", "1234", "5678"); + SPDK_CU_ASSERT_FATAL(listen_addr != NULL); + + SPDK_CU_ASSERT_FATAL(spdk_nvmf_subsystem_add_listener(subsystem, listen_addr) == 0); /* Get only genctr (first field in the header) */ memset(buffer, 0xCC, sizeof(buffer));