diff --git a/include/spdk/nvmf.h b/include/spdk/nvmf.h index 0706fd25e..1ed403fb1 100644 --- a/include/spdk/nvmf.h +++ b/include/spdk/nvmf.h @@ -60,6 +60,7 @@ struct spdk_nvmf_request; struct spdk_nvmf_host; struct spdk_nvmf_listener; struct spdk_nvmf_poll_group; +struct spdk_json_write_ctx; struct spdk_nvmf_tgt_opts { uint16_t max_queue_depth; @@ -96,6 +97,13 @@ void spdk_nvmf_tgt_destroy(struct spdk_nvmf_tgt *tgt, spdk_nvmf_tgt_destroy_done_fn cb_fn, void *cb_arg); +/** + * Write NVMe-oF target configuration into provided JSON context. + * \param w JSON write context + * \param tgt The NVMe-oF target + */ +void spdk_nvmf_tgt_write_config_json(struct spdk_json_write_ctx *w, struct spdk_nvmf_tgt *tgt); + /** * Function to be called once the target is listening. * diff --git a/lib/event/subsystems/nvmf/nvmf_tgt.c b/lib/event/subsystems/nvmf/nvmf_tgt.c index 73234efad..0b197a548 100644 --- a/lib/event/subsystems/nvmf/nvmf_tgt.c +++ b/lib/event/subsystems/nvmf/nvmf_tgt.c @@ -329,10 +329,30 @@ spdk_nvmf_subsystem_init(void) nvmf_tgt_advance_state(); } +static void +spdk_nvmf_subsystem_write_config_json(struct spdk_json_write_ctx *w, struct spdk_event *done_ev) +{ + spdk_json_write_array_begin(w); + + spdk_json_write_object_begin(w); + spdk_json_write_named_string(w, "method", "set_nvmf_target_config"); + + spdk_json_write_named_object_begin(w, "params"); + spdk_json_write_named_uint32(w, "acceptor_poll_rate", g_spdk_nvmf_tgt_conf->acceptor_poll_rate); + spdk_json_write_object_end(w); + spdk_json_write_object_end(w); + + spdk_nvmf_tgt_write_config_json(w, g_spdk_nvmf_tgt); + spdk_json_write_array_end(w); + + spdk_event_call(done_ev); +} + static struct spdk_subsystem g_spdk_subsystem_nvmf = { .name = "nvmf", .init = spdk_nvmf_subsystem_init, .fini = spdk_nvmf_subsystem_fini, + .write_config_json = spdk_nvmf_subsystem_write_config_json, }; SPDK_SUBSYSTEM_REGISTER(g_spdk_subsystem_nvmf) diff --git a/lib/nvmf/nvmf.c b/lib/nvmf/nvmf.c index f9906b859..b87f5c55e 100644 --- a/lib/nvmf/nvmf.c +++ b/lib/nvmf/nvmf.c @@ -38,6 +38,8 @@ #include "spdk/thread.h" #include "spdk/nvmf.h" #include "spdk/trace.h" +#include "spdk/endian.h" +#include "spdk/string.h" #include "spdk_internal/log.h" @@ -259,6 +261,139 @@ struct spdk_nvmf_tgt_listen_ctx { void *cb_arg; }; +static void +spdk_nvmf_write_subsystem_config_json(struct spdk_json_write_ctx *w, + struct spdk_nvmf_subsystem *subsystem) +{ + struct spdk_nvmf_host *host; + struct spdk_nvmf_listener *listener; + const struct spdk_nvme_transport_id *trid; + struct spdk_nvmf_ns *ns; + struct spdk_nvmf_ns_opts ns_opts; + uint32_t max_namespaces; + char uuid_str[SPDK_UUID_STRING_LEN]; + const char *trtype; + const char *adrfam; + + if (spdk_nvmf_subsystem_get_type(subsystem) != SPDK_NVMF_SUBTYPE_NVME) { + return; + } + + /* { */ + spdk_json_write_object_begin(w); + spdk_json_write_named_string(w, "method", "construct_nvmf_subsystem"); + + /* "params" : { */ + spdk_json_write_named_object_begin(w, "params"); + spdk_json_write_named_string(w, "nqn", spdk_nvmf_subsystem_get_nqn(subsystem)); + spdk_json_write_named_bool(w, "allow_any_host", spdk_nvmf_subsystem_get_allow_any_host(subsystem)); + + /* "listen_addresses" : [ */ + spdk_json_write_named_array_begin(w, "listen_addresses"); + for (listener = spdk_nvmf_subsystem_get_first_listener(subsystem); listener != NULL; + listener = spdk_nvmf_subsystem_get_next_listener(subsystem, listener)) { + trid = spdk_nvmf_listener_get_trid(listener); + + trtype = spdk_nvme_transport_id_trtype_str(trid->trtype); + adrfam = spdk_nvme_transport_id_adrfam_str(trid->adrfam); + + /* { */ + spdk_json_write_object_begin(w); + spdk_json_write_named_string(w, "trtype", trtype); + if (adrfam) { + spdk_json_write_named_string(w, "adrfam", adrfam); + } + + spdk_json_write_named_string(w, "traddr", trid->traddr); + spdk_json_write_named_string(w, "trsvcid", trid->trsvcid); + spdk_json_write_object_end(w); + /* } */ + } + spdk_json_write_array_end(w); + /* ] "listen_addresses" */ + + /* "hosts" : [ */ + spdk_json_write_named_array_begin(w, "hosts"); + for (host = spdk_nvmf_subsystem_get_first_host(subsystem); host != NULL; + host = spdk_nvmf_subsystem_get_next_host(subsystem, host)) { + spdk_json_write_named_string(w, "nqn", spdk_nvmf_host_get_nqn(host)); + } + spdk_json_write_array_end(w); + /* ] "hosts" */ + + spdk_json_write_named_string(w, "serial_number", spdk_nvmf_subsystem_get_sn(subsystem)); + + max_namespaces = spdk_nvmf_subsystem_get_max_namespaces(subsystem); + if (max_namespaces != 0) { + spdk_json_write_named_uint32(w, "max_namespaces", max_namespaces); + } + + /* "namespaces" : [ */ + spdk_json_write_named_array_begin(w, "namespaces"); + for (ns = spdk_nvmf_subsystem_get_first_ns(subsystem); ns != NULL; + ns = spdk_nvmf_subsystem_get_next_ns(subsystem, ns)) { + spdk_nvmf_ns_get_opts(ns, &ns_opts, sizeof(ns_opts)); + + /* { */ + spdk_json_write_object_begin(w); + spdk_json_write_named_uint32(w, "nsid", spdk_nvmf_ns_get_id(ns)); + spdk_json_write_named_string(w, "bdev_name", spdk_bdev_get_name(spdk_nvmf_ns_get_bdev(ns))); + + if (!spdk_mem_all_zero(ns_opts.nguid, sizeof(ns_opts.nguid))) { + SPDK_STATIC_ASSERT(sizeof(ns_opts.nguid) == sizeof(uint64_t) * 2, "size mismatch"); + spdk_json_write_named_string_fmt(w, "nguid", "%016"PRIX64"%016"PRIX64, from_be64(&ns_opts.nguid[0]), + from_be64(&ns_opts.nguid[8])); + } + + if (!spdk_mem_all_zero(ns_opts.eui64, sizeof(ns_opts.eui64))) { + SPDK_STATIC_ASSERT(sizeof(ns_opts.eui64) == sizeof(uint64_t), "size mismatch"); + spdk_json_write_named_string_fmt(w, "eui64", "%016"PRIX64, from_be64(&ns_opts.eui64)); + } + + if (!spdk_mem_all_zero(&ns_opts.uuid, sizeof(ns_opts.uuid))) { + spdk_uuid_fmt_lower(uuid_str, sizeof(uuid_str), &ns_opts.uuid); + spdk_json_write_named_string(w, "uuid", uuid_str); + } + /* } */ + spdk_json_write_object_end(w); + } + + /* ] "namespaces" */ + spdk_json_write_array_end(w); + + /* } "params" */ + spdk_json_write_object_end(w); + + /* } */ + spdk_json_write_object_end(w); +} + +void +spdk_nvmf_tgt_write_config_json(struct spdk_json_write_ctx *w, struct spdk_nvmf_tgt *tgt) +{ + struct spdk_nvmf_subsystem *subsystem; + + spdk_json_write_object_begin(w); + spdk_json_write_named_string(w, "method", "set_nvmf_target_options"); + + spdk_json_write_named_object_begin(w, "params"); + spdk_json_write_named_uint32(w, "max_queue_depth", tgt->opts.max_queue_depth); + spdk_json_write_named_uint32(w, "max_qpairs_per_ctrlr", tgt->opts.max_qpairs_per_ctrlr); + spdk_json_write_named_uint32(w, "in_capsule_data_size", tgt->opts.in_capsule_data_size); + spdk_json_write_named_uint32(w, "max_io_size", tgt->opts.max_io_size); + spdk_json_write_named_uint32(w, "max_subsystems", tgt->opts.max_subsystems); + spdk_json_write_named_uint32(w, "io_unit_size", tgt->opts.io_unit_size); + spdk_json_write_object_end(w); + + spdk_json_write_object_end(w); + + subsystem = spdk_nvmf_subsystem_get_first(tgt); + while (subsystem) { + spdk_nvmf_write_subsystem_config_json(w, subsystem); + subsystem = spdk_nvmf_subsystem_get_next(subsystem); + } +} + static void spdk_nvmf_tgt_listen_done(struct spdk_io_channel_iter *i, int status) {