nvmf: Add discovery filtering rules
SPDK nvmf target reports all listeners on all subsystems in discovery pages, kernel target reports only subsystems listening on a port where discovery command is received. NVMEoF specification allows to specify any addresses/ transport types. Ch 5: The set of Discovery Log entries should include all applicable addresses on the same fabric as the Discovery Service and may include addresses on other fabrics. To align SPDK and kernel targets behaviour, add filtering rules to allow flexible configuration of what should be listed in discovery log page entries. Fixes #2082 Signed-off-by: Alexey Marchuk <alexeymar@mellanox.com> Change-Id: Ie981edebb29206793d3310940034dcbb22c52441 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9185 Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com> Community-CI: Mellanox Build Bot
This commit is contained in:
parent
e40bd53175
commit
3d8904c66b
@ -4,6 +4,9 @@
|
||||
|
||||
## v21.10
|
||||
|
||||
Structure `spdk_nvmf_target_opts` has been extended with new member `discovery_filter` which allows to specify
|
||||
filtering rules applied during discovery log generation. Refer to `enum spdk_nvmf_tgt_discovery_filter` for more info.
|
||||
|
||||
### bdev
|
||||
|
||||
New API `spdk_bdev_get_memory_domains` has been added, it allows to get SPDK memory domains used by bdev.
|
||||
|
@ -6736,6 +6736,7 @@ Name | Optional | Type | Description
|
||||
acceptor_poll_rate | Optional | number | Polling interval of the acceptor for incoming connections (microseconds)
|
||||
admin_cmd_passthru | Optional | object | Admin command passthru configuration
|
||||
poll_groups_mask | Optional | string | Set cpumask for NVMf poll groups
|
||||
discovery_filter | Optional | string | Set discovery filter, possible values are: `match_any` (default) or comma separated values: `transport`, `address`, `svcid`
|
||||
|
||||
#### admin_cmd_passthru {#spdk_nvmf_admin_passthru_conf}
|
||||
|
||||
|
@ -67,11 +67,26 @@ struct spdk_json_write_ctx;
|
||||
struct spdk_json_val;
|
||||
struct spdk_nvmf_transport;
|
||||
|
||||
/**
|
||||
* Specify filter rules which are applied during discovery log generation.
|
||||
*/
|
||||
enum spdk_nvmf_tgt_discovery_filter {
|
||||
/** Log all listeners in discovery log page */
|
||||
SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY = 0,
|
||||
/** Only log listeners with the same transport type on which the DISCOVERY command was received */
|
||||
SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE = 1u << 0u,
|
||||
/** Only log listeners with the same transport address on which the DISCOVERY command was received */
|
||||
SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS = 1u << 1u,
|
||||
/** Only log listeners with the same transport svcid on which the DISCOVERY command was received */
|
||||
SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID = 1u << 2u
|
||||
};
|
||||
|
||||
struct spdk_nvmf_target_opts {
|
||||
char name[NVMF_TGT_NAME_MAX_LENGTH];
|
||||
uint32_t max_subsystems;
|
||||
uint32_t acceptor_poll_rate;
|
||||
uint16_t crdt[3];
|
||||
enum spdk_nvmf_tgt_discovery_filter discovery_filter;
|
||||
};
|
||||
|
||||
struct spdk_nvmf_transport_opts {
|
||||
|
@ -2271,6 +2271,7 @@ nvmf_ctrlr_get_log_page(struct spdk_nvmf_request *req)
|
||||
struct spdk_nvmf_subsystem *subsystem = ctrlr->subsys;
|
||||
struct spdk_nvme_cmd *cmd = &req->cmd->nvme_cmd;
|
||||
struct spdk_nvme_cpl *response = &req->rsp->nvme_cpl;
|
||||
struct spdk_nvme_transport_id cmd_source_trid;
|
||||
uint64_t offset, len;
|
||||
uint32_t rae, numdl, numdu;
|
||||
uint8_t lid;
|
||||
@ -2309,8 +2310,14 @@ nvmf_ctrlr_get_log_page(struct spdk_nvmf_request *req)
|
||||
if (subsystem->subtype == SPDK_NVMF_SUBTYPE_DISCOVERY) {
|
||||
switch (lid) {
|
||||
case SPDK_NVME_LOG_DISCOVERY:
|
||||
nvmf_get_discovery_log_page(subsystem->tgt, ctrlr->hostnqn, req->iov, req->iovcnt, offset,
|
||||
len);
|
||||
if (spdk_nvmf_qpair_get_listen_trid(req->qpair, &cmd_source_trid)) {
|
||||
SPDK_ERRLOG("Failed to get LOG_DISCOVERY source trid\n");
|
||||
response->status.sct = SPDK_NVME_SCT_GENERIC;
|
||||
response->status.sc = SPDK_NVME_SC_INTERNAL_DEVICE_ERROR;
|
||||
return SPDK_NVMF_REQUEST_EXEC_STATUS_COMPLETE;
|
||||
}
|
||||
nvmf_get_discovery_log_page(subsystem->tgt, ctrlr->hostnqn, req->iov, req->iovcnt,
|
||||
offset, len, &cmd_source_trid);
|
||||
if (!rae) {
|
||||
nvmf_ctrlr_unmask_aen(ctrlr, SPDK_NVME_ASYNC_EVENT_DISCOVERY_LOG_CHANGE_MASK_BIT);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -43,6 +44,7 @@
|
||||
#include "spdk/string.h"
|
||||
#include "spdk/trace.h"
|
||||
#include "spdk/nvmf_spec.h"
|
||||
#include "spdk_internal/assert.h"
|
||||
|
||||
#include "spdk/log.h"
|
||||
|
||||
@ -65,8 +67,34 @@ nvmf_update_discovery_log(struct spdk_nvmf_tgt *tgt, const char *hostnqn)
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
nvmf_discovery_compare_trtype(const struct spdk_nvme_transport_id *trid1,
|
||||
const struct spdk_nvme_transport_id *trid2)
|
||||
{
|
||||
if (trid1->trtype == SPDK_NVME_TRANSPORT_CUSTOM) {
|
||||
return strcasecmp(trid1->trstring, trid2->trstring) == 0;
|
||||
} else {
|
||||
return trid1->trtype == trid2->trtype;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
nvmf_discovery_compare_tr_addr(const struct spdk_nvme_transport_id *trid1,
|
||||
const struct spdk_nvme_transport_id *trid2)
|
||||
{
|
||||
return trid1->adrfam == trid2->adrfam && strcasecmp(trid1->traddr, trid2->traddr) == 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
nvmf_discovery_compare_tr_svcid(const struct spdk_nvme_transport_id *trid1,
|
||||
const struct spdk_nvme_transport_id *trid2)
|
||||
{
|
||||
return strcasecmp(trid1->trsvcid, trid2->trsvcid) == 0;
|
||||
}
|
||||
|
||||
static struct spdk_nvmf_discovery_log_page *
|
||||
nvmf_generate_discovery_log(struct spdk_nvmf_tgt *tgt, const char *hostnqn, size_t *log_page_size)
|
||||
nvmf_generate_discovery_log(struct spdk_nvmf_tgt *tgt, const char *hostnqn, size_t *log_page_size,
|
||||
struct spdk_nvme_transport_id *cmd_source_trid)
|
||||
{
|
||||
uint64_t numrec = 0;
|
||||
struct spdk_nvmf_subsystem *subsystem;
|
||||
@ -104,6 +132,29 @@ nvmf_generate_discovery_log(struct spdk_nvmf_tgt *tgt, const char *hostnqn, size
|
||||
|
||||
for (listener = spdk_nvmf_subsystem_get_first_listener(subsystem); listener != NULL;
|
||||
listener = spdk_nvmf_subsystem_get_next_listener(subsystem, listener)) {
|
||||
|
||||
if ((tgt->discovery_filter & SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE) != 0 &&
|
||||
!nvmf_discovery_compare_trtype(listener->trid, cmd_source_trid)) {
|
||||
SPDK_DEBUGLOG(nvmf, "ignore listener type %d (%s) due to type mismatch\n",
|
||||
listener->trid->trtype, listener->trid->trstring);
|
||||
continue;
|
||||
}
|
||||
if ((tgt->discovery_filter & SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS) != 0 &&
|
||||
!nvmf_discovery_compare_tr_addr(listener->trid, cmd_source_trid)) {
|
||||
SPDK_DEBUGLOG(nvmf, "ignore listener addr %s due to addr mismatch\n",
|
||||
listener->trid->traddr);
|
||||
continue;
|
||||
}
|
||||
if ((tgt->discovery_filter & SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID) != 0 &&
|
||||
!nvmf_discovery_compare_tr_svcid(listener->trid, cmd_source_trid)) {
|
||||
SPDK_DEBUGLOG(nvmf, "ignore listener svcid %s due to svcid mismatch\n",
|
||||
listener->trid->trsvcid);
|
||||
continue;
|
||||
}
|
||||
|
||||
SPDK_DEBUGLOG(nvmf, "listener %s:%s trtype %s\n", listener->trid->traddr, listener->trid->trsvcid,
|
||||
listener->trid->trstring);
|
||||
|
||||
size_t new_size = cur_size + sizeof(*entry);
|
||||
void *new_log_page = realloc(disc_log, new_size);
|
||||
|
||||
@ -138,7 +189,8 @@ nvmf_generate_discovery_log(struct spdk_nvmf_tgt *tgt, const char *hostnqn, size
|
||||
|
||||
void
|
||||
nvmf_get_discovery_log_page(struct spdk_nvmf_tgt *tgt, const char *hostnqn, struct iovec *iov,
|
||||
uint32_t iovcnt, uint64_t offset, uint32_t length)
|
||||
uint32_t iovcnt, uint64_t offset, uint32_t length,
|
||||
struct spdk_nvme_transport_id *cmd_source_trid)
|
||||
{
|
||||
size_t copy_len = 0;
|
||||
size_t zero_len = 0;
|
||||
@ -146,7 +198,7 @@ nvmf_get_discovery_log_page(struct spdk_nvmf_tgt *tgt, const char *hostnqn, stru
|
||||
size_t log_page_size = 0;
|
||||
struct spdk_nvmf_discovery_log_page *discovery_log_page;
|
||||
|
||||
discovery_log_page = nvmf_generate_discovery_log(tgt, hostnqn, &log_page_size);
|
||||
discovery_log_page = nvmf_generate_discovery_log(tgt, hostnqn, &log_page_size, cmd_source_trid);
|
||||
|
||||
/* Copy the valid part of the discovery log page, if any */
|
||||
if (discovery_log_page) {
|
||||
|
@ -303,6 +303,12 @@ spdk_nvmf_tgt_create(struct spdk_nvmf_target_opts *opts)
|
||||
tgt->crdt[2] = opts->crdt[2];
|
||||
}
|
||||
|
||||
if (!opts) {
|
||||
tgt->discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY;
|
||||
} else {
|
||||
tgt->discovery_filter = opts->discovery_filter;
|
||||
}
|
||||
|
||||
tgt->discovery_genctr = 0;
|
||||
TAILQ_INIT(&tgt->transports);
|
||||
TAILQ_INIT(&tgt->poll_groups);
|
||||
|
@ -76,6 +76,8 @@ struct spdk_nvmf_tgt {
|
||||
|
||||
uint32_t max_subsystems;
|
||||
|
||||
enum spdk_nvmf_tgt_discovery_filter discovery_filter;
|
||||
|
||||
/* Array of subsystem pointers of size max_subsystems indexed by sid */
|
||||
struct spdk_nvmf_subsystem **subsystems;
|
||||
|
||||
@ -350,9 +352,9 @@ void nvmf_poll_group_resume_subsystem(struct spdk_nvmf_poll_group *group,
|
||||
struct spdk_nvmf_subsystem *subsystem, spdk_nvmf_poll_group_mod_done cb_fn, void *cb_arg);
|
||||
|
||||
void nvmf_update_discovery_log(struct spdk_nvmf_tgt *tgt, const char *hostnqn);
|
||||
void nvmf_get_discovery_log_page(struct spdk_nvmf_tgt *tgt, const char *hostnqn,
|
||||
struct iovec *iov,
|
||||
uint32_t iovcnt, uint64_t offset, uint32_t length);
|
||||
void nvmf_get_discovery_log_page(struct spdk_nvmf_tgt *tgt, const char *hostnqn, struct iovec *iov,
|
||||
uint32_t iovcnt, uint64_t offset, uint32_t length,
|
||||
struct spdk_nvme_transport_id *cmd_source_trid);
|
||||
|
||||
void nvmf_ctrlr_destruct(struct spdk_nvmf_ctrlr *ctrlr);
|
||||
int nvmf_ctrlr_process_admin_cmd(struct spdk_nvmf_request *req);
|
||||
|
@ -1657,11 +1657,63 @@ SPDK_RPC_REGISTER("nvmf_subsystem_allow_any_host", rpc_nvmf_subsystem_allow_any_
|
||||
struct nvmf_rpc_target_ctx {
|
||||
char *name;
|
||||
uint32_t max_subsystems;
|
||||
char *discovery_filter;
|
||||
};
|
||||
|
||||
static int
|
||||
decode_discovery_filter(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
enum spdk_nvmf_tgt_discovery_filter *_filter = (enum spdk_nvmf_tgt_discovery_filter *)out;
|
||||
enum spdk_nvmf_tgt_discovery_filter filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY;
|
||||
char *tokens = spdk_json_strdup(val);
|
||||
char *tok;
|
||||
int rc = -EINVAL;
|
||||
bool all_specified = false;
|
||||
|
||||
if (!tokens) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tok = strtok(tokens, ",");
|
||||
while (tok) {
|
||||
if (strncmp(tok, "match_any", 9) == 0) {
|
||||
if (filter != SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY) {
|
||||
goto out;
|
||||
}
|
||||
filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY;
|
||||
all_specified = true;
|
||||
} else {
|
||||
if (all_specified) {
|
||||
goto out;
|
||||
}
|
||||
if (strncmp(tok, "transport", 9) == 0) {
|
||||
filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE;
|
||||
} else if (strncmp(tok, "address", 7) == 0) {
|
||||
filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS;
|
||||
} else if (strncmp(tok, "svcid", 5) == 0) {
|
||||
filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID;
|
||||
} else {
|
||||
SPDK_ERRLOG("Invalid value %s\n", tok);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
tok = strtok(NULL, ",");
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
*_filter = filter;
|
||||
|
||||
out:
|
||||
free(tokens);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct spdk_json_object_decoder nvmf_rpc_create_target_decoder[] = {
|
||||
{"name", offsetof(struct nvmf_rpc_target_ctx, name), spdk_json_decode_string},
|
||||
{"max_subsystems", offsetof(struct nvmf_rpc_target_ctx, max_subsystems), spdk_json_decode_uint32, true},
|
||||
{"discovery_filter", offsetof(struct nvmf_rpc_target_ctx, discovery_filter), decode_discovery_filter, true}
|
||||
};
|
||||
|
||||
static void
|
||||
@ -1679,8 +1731,7 @@ rpc_nvmf_create_target(struct spdk_jsonrpc_request *request,
|
||||
&ctx)) {
|
||||
SPDK_ERRLOG("spdk_json_decode_object failed\n");
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
|
||||
free(ctx.name);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
snprintf(opts.name, NVMF_TGT_NAME_MAX_LENGTH, "%s", ctx.name);
|
||||
@ -1689,8 +1740,7 @@ rpc_nvmf_create_target(struct spdk_jsonrpc_request *request,
|
||||
if (spdk_nvmf_get_tgt(opts.name) != NULL) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
|
||||
"Target already exists.");
|
||||
free(ctx.name);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tgt = spdk_nvmf_tgt_create(&opts);
|
||||
@ -1698,14 +1748,15 @@ rpc_nvmf_create_target(struct spdk_jsonrpc_request *request,
|
||||
if (tgt == NULL) {
|
||||
spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
|
||||
"Unable to create the requested target.");
|
||||
free(ctx.name);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
w = spdk_jsonrpc_begin_result(request);
|
||||
spdk_json_write_string(w, spdk_nvmf_tgt_get_name(tgt));
|
||||
spdk_jsonrpc_end_result(request, w);
|
||||
out:
|
||||
free(ctx.name);
|
||||
free(ctx.discovery_filter);
|
||||
}
|
||||
/* private */ SPDK_RPC_REGISTER("nvmf_create_target", rpc_nvmf_create_target, SPDK_RPC_RUNTIME);
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -52,6 +53,7 @@ struct spdk_nvmf_tgt_conf {
|
||||
uint32_t acceptor_poll_rate;
|
||||
uint32_t conn_sched; /* Deprecated. */
|
||||
struct spdk_nvmf_admin_passthru_conf admin_passthru;
|
||||
enum spdk_nvmf_tgt_discovery_filter discovery_filter;
|
||||
};
|
||||
|
||||
extern struct spdk_nvmf_tgt_conf g_spdk_nvmf_tgt_conf;
|
||||
|
@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright (c) Intel Corporation. All rights reserved.
|
||||
* Copyright (c) 2018-2019 Mellanox Technologies LTD. All rights reserved.
|
||||
* Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -99,6 +100,56 @@ static int decode_admin_passthru(const struct spdk_json_val *val, void *out)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
decode_discovery_filter(const struct spdk_json_val *val, void *out)
|
||||
{
|
||||
enum spdk_nvmf_tgt_discovery_filter *_filter = (enum spdk_nvmf_tgt_discovery_filter *)out;
|
||||
enum spdk_nvmf_tgt_discovery_filter filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY;
|
||||
char *tokens = spdk_json_strdup(val);
|
||||
char *tok;
|
||||
int rc = -EINVAL;
|
||||
bool all_specified = false;
|
||||
|
||||
if (!tokens) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tok = strtok(tokens, ",");
|
||||
while (tok) {
|
||||
if (strncmp(tok, "match_any", 9) == 0) {
|
||||
if (filter != SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY) {
|
||||
goto out;
|
||||
}
|
||||
filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY;
|
||||
all_specified = true;
|
||||
} else {
|
||||
if (all_specified) {
|
||||
goto out;
|
||||
}
|
||||
if (strncmp(tok, "transport", 9) == 0) {
|
||||
filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE;
|
||||
} else if (strncmp(tok, "address", 7) == 0) {
|
||||
filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS;
|
||||
} else if (strncmp(tok, "svcid", 5) == 0) {
|
||||
filter |= SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID;
|
||||
} else {
|
||||
SPDK_ERRLOG("Invalid value %s\n", tok);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
tok = strtok(NULL, ",");
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
*_filter = filter;
|
||||
|
||||
out:
|
||||
free(tokens);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
nvmf_is_subset_of_env_core_mask(const struct spdk_cpuset *set)
|
||||
{
|
||||
@ -149,7 +200,8 @@ static const struct spdk_json_object_decoder nvmf_rpc_subsystem_tgt_conf_decoder
|
||||
{"acceptor_poll_rate", offsetof(struct spdk_nvmf_tgt_conf, acceptor_poll_rate), spdk_json_decode_uint32, true},
|
||||
{"conn_sched", offsetof(struct spdk_nvmf_tgt_conf, conn_sched), decode_conn_sched, true},
|
||||
{"admin_cmd_passthru", offsetof(struct spdk_nvmf_tgt_conf, admin_passthru), decode_admin_passthru, true},
|
||||
{"poll_groups_mask", 0, nvmf_decode_poll_groups_mask, true}
|
||||
{"poll_groups_mask", 0, nvmf_decode_poll_groups_mask, true},
|
||||
{"discovery_filter", offsetof(struct spdk_nvmf_tgt_conf, discovery_filter), decode_discovery_filter, true}
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -307,6 +307,7 @@ nvmf_tgt_create_target(void)
|
||||
opts.crdt[0] = g_spdk_nvmf_tgt_crdt[0];
|
||||
opts.crdt[1] = g_spdk_nvmf_tgt_crdt[1];
|
||||
opts.crdt[2] = g_spdk_nvmf_tgt_crdt[2];
|
||||
opts.discovery_filter = g_spdk_nvmf_tgt_conf.discovery_filter;
|
||||
g_spdk_nvmf_tgt = spdk_nvmf_tgt_create(&opts);
|
||||
if (!g_spdk_nvmf_tgt) {
|
||||
SPDK_ERRLOG("spdk_nvmf_tgt_create() failed\n");
|
||||
@ -485,6 +486,31 @@ nvmf_subsystem_init(void)
|
||||
nvmf_tgt_advance_state();
|
||||
}
|
||||
|
||||
static void
|
||||
nvmf_subsystem_dump_discover_filter(struct spdk_json_write_ctx *w)
|
||||
{
|
||||
static char const *const answers[] = {
|
||||
"match_any",
|
||||
"transport",
|
||||
"address",
|
||||
"transport,address",
|
||||
"svcid",
|
||||
"transport,svcid",
|
||||
"address,svcid",
|
||||
"transport,address,svcid"
|
||||
};
|
||||
|
||||
if ((g_spdk_nvmf_tgt_conf.discovery_filter & ~(SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE |
|
||||
SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS |
|
||||
SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID)) != 0) {
|
||||
SPDK_ERRLOG("Incorrect discovery filter %d\n", g_spdk_nvmf_tgt_conf.discovery_filter);
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
spdk_json_write_named_string(w, "discovery_filter", answers[g_spdk_nvmf_tgt_conf.discovery_filter]);
|
||||
}
|
||||
|
||||
static void
|
||||
nvmf_subsystem_write_config_json(struct spdk_json_write_ctx *w)
|
||||
{
|
||||
@ -495,6 +521,7 @@ nvmf_subsystem_write_config_json(struct spdk_json_write_ctx *w)
|
||||
|
||||
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);
|
||||
nvmf_subsystem_dump_discover_filter(w);
|
||||
spdk_json_write_named_object_begin(w, "admin_cmd_passthru");
|
||||
spdk_json_write_named_bool(w, "identify_ctrlr",
|
||||
g_spdk_nvmf_tgt_conf.admin_passthru.identify_ctrlr);
|
||||
|
@ -1908,7 +1908,8 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
|
||||
acceptor_poll_rate=args.acceptor_poll_rate,
|
||||
conn_sched=args.conn_sched,
|
||||
passthru_identify_ctrlr=args.passthru_identify_ctrlr,
|
||||
poll_groups_mask=args.poll_groups_mask)
|
||||
poll_groups_mask=args.poll_groups_mask,
|
||||
discovery_filter=args.discovery_filter)
|
||||
|
||||
p = subparsers.add_parser('nvmf_set_config', aliases=['set_nvmf_target_config'],
|
||||
help='Set NVMf target config')
|
||||
@ -1917,6 +1918,8 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse
|
||||
p.add_argument('-i', '--passthru-identify-ctrlr', help="""Passthrough fields like serial number and model number
|
||||
when the controller has a single namespace that is an NVMe bdev""", action='store_true')
|
||||
p.add_argument('-m', '--poll-groups-mask', help='Set cpumask for NVMf poll groups (optional)', type=str)
|
||||
p.add_argument('-d', '--discovery-filter', help="""Set discovery filter (optional), possible values are: `match_any` (default) or
|
||||
comma separated values: `transport`, `address`, `svcid`""", type=str)
|
||||
p.set_defaults(func=nvmf_set_config)
|
||||
|
||||
def nvmf_create_transport(args):
|
||||
|
@ -24,12 +24,15 @@ def nvmf_set_config(client,
|
||||
acceptor_poll_rate=None,
|
||||
conn_sched=None,
|
||||
passthru_identify_ctrlr=None,
|
||||
poll_groups_mask=None):
|
||||
poll_groups_mask=None,
|
||||
discovery_filter=None):
|
||||
"""Set NVMe-oF target subsystem configuration.
|
||||
|
||||
Args:
|
||||
acceptor_poll_rate: Acceptor poll period in microseconds (optional)
|
||||
conn_sched: (Deprecated) Ignored
|
||||
discovery_filter: Set discovery filter (optional), possible values are: `match_any` (default) or
|
||||
comma separated values: `transport`, `address`, `svcid`
|
||||
|
||||
Returns:
|
||||
True or False
|
||||
@ -46,18 +49,23 @@ def nvmf_set_config(client,
|
||||
params['admin_cmd_passthru'] = admin_cmd_passthru
|
||||
if poll_groups_mask:
|
||||
params['poll_groups_mask'] = poll_groups_mask
|
||||
if discovery_filter:
|
||||
params['discovery_filter'] = discovery_filter
|
||||
|
||||
return client.call('nvmf_set_config', params)
|
||||
|
||||
|
||||
def nvmf_create_target(client,
|
||||
name,
|
||||
max_subsystems=0):
|
||||
max_subsystems=0,
|
||||
discovery_filter="match_any"):
|
||||
"""Create a new NVMe-oF Target.
|
||||
|
||||
Args:
|
||||
name: Must be unique within the application
|
||||
max_subsystems: Maximum number of NVMe-oF subsystems (e.g. 1024). default: 0 (Uses SPDK_NVMF_DEFAULT_MAX_SUBSYSTEMS).
|
||||
discovery_filter: Set discovery filter (optional), possible values are: `match_any` (default) or
|
||||
comma separated values: `transport`, `address`, `svcid`
|
||||
|
||||
Returns:
|
||||
The name of the new target.
|
||||
@ -66,6 +74,7 @@ def nvmf_create_target(client,
|
||||
|
||||
params['name'] = name
|
||||
params['max_subsystems'] = max_subsystems
|
||||
params['discovery_filter'] = discovery_filter
|
||||
return client.call("nvmf_create_target", params)
|
||||
|
||||
|
||||
|
@ -104,7 +104,7 @@ DEFINE_STUB(nvmf_ctrlr_write_zeroes_supported,
|
||||
|
||||
DEFINE_STUB_V(nvmf_get_discovery_log_page,
|
||||
(struct spdk_nvmf_tgt *tgt, const char *hostnqn, struct iovec *iov,
|
||||
uint32_t iovcnt, uint64_t offset, uint32_t length));
|
||||
uint32_t iovcnt, uint64_t offset, uint32_t length, struct spdk_nvme_transport_id *cmd_src_trid));
|
||||
|
||||
DEFINE_STUB(spdk_nvmf_qpair_get_listen_trid,
|
||||
int,
|
||||
|
@ -118,6 +118,14 @@ spdk_bdev_get_uuid(const struct spdk_bdev *bdev)
|
||||
return &bdev->uuid;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1,
|
||||
const struct spdk_nvme_transport_id *trid2)
|
||||
{
|
||||
return !(trid1->trtype == trid2->trtype && strcasecmp(trid1->traddr, trid2->traddr) == 0 &&
|
||||
strcasecmp(trid1->trsvcid, trid2->trsvcid) == 0);
|
||||
}
|
||||
|
||||
int
|
||||
spdk_nvmf_transport_listen(struct spdk_nvmf_transport *transport,
|
||||
const struct spdk_nvme_transport_id *trid, struct spdk_nvmf_listen_opts *opts)
|
||||
@ -131,18 +139,37 @@ struct spdk_nvmf_listener *
|
||||
nvmf_transport_find_listener(struct spdk_nvmf_transport *transport,
|
||||
const struct spdk_nvme_transport_id *trid)
|
||||
{
|
||||
return &g_listener;
|
||||
struct spdk_nvmf_listener *listener;
|
||||
|
||||
if (TAILQ_EMPTY(&transport->listeners)) {
|
||||
return &g_listener;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(listener, &transport->listeners, link) {
|
||||
if (spdk_nvme_transport_id_compare(&listener->trid, trid) == 0) {
|
||||
return listener;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
nvmf_transport_listener_discover(struct spdk_nvmf_transport *transport,
|
||||
struct spdk_nvme_transport_id *trid,
|
||||
struct spdk_nvmf_discovery_log_page_entry *entry)
|
||||
{
|
||||
transport->ops->listener_discover(transport, trid, entry);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dummy_listener_discover(struct spdk_nvmf_transport *transport,
|
||||
struct spdk_nvme_transport_id *trid, struct spdk_nvmf_discovery_log_page_entry *entry)
|
||||
{
|
||||
entry->trtype = 42;
|
||||
}
|
||||
|
||||
struct spdk_nvmf_transport_ops g_transport_ops = {};
|
||||
struct spdk_nvmf_transport_ops g_transport_ops = { .listener_discover = test_dummy_listener_discover };
|
||||
|
||||
static struct spdk_nvmf_transport g_transport = {
|
||||
.ops = &g_transport_ops
|
||||
@ -165,9 +192,11 @@ spdk_nvmf_tgt_find_subsystem(struct spdk_nvmf_tgt *tgt, const char *subnqn)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEFINE_RETURN_MOCK(spdk_nvmf_tgt_get_transport, struct spdk_nvmf_transport *);
|
||||
struct spdk_nvmf_transport *
|
||||
spdk_nvmf_tgt_get_transport(struct spdk_nvmf_tgt *tgt, const char *transport_name)
|
||||
{
|
||||
HANDLE_RETURN_MOCK(spdk_nvmf_tgt_get_transport);
|
||||
return &g_transport;
|
||||
}
|
||||
|
||||
@ -188,13 +217,6 @@ spdk_nvme_transport_id_parse_trtype(enum spdk_nvme_transport_type *trtype, const
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_nvme_transport_id_compare(const struct spdk_nvme_transport_id *trid1,
|
||||
const struct spdk_nvme_transport_id *trid2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nvmf_ctrlr_ns_changed(struct spdk_nvmf_ctrlr *ctrlr, uint32_t nsid)
|
||||
{
|
||||
@ -248,6 +270,26 @@ _subsystem_add_listen_done(void *cb_arg, int status)
|
||||
SPDK_CU_ASSERT_FATAL(status == 0);
|
||||
}
|
||||
|
||||
static void
|
||||
test_gen_trid(struct spdk_nvme_transport_id *trid, enum spdk_nvme_transport_type trtype,
|
||||
enum spdk_nvmf_adrfam adrfam, const char *tradd, const char *trsvcid)
|
||||
{
|
||||
snprintf(trid->traddr, sizeof(trid->traddr), "%s", tradd);
|
||||
snprintf(trid->trsvcid, sizeof(trid->trsvcid), "%s", trsvcid);
|
||||
trid->adrfam = adrfam;
|
||||
trid->trtype = trtype;
|
||||
switch (trtype) {
|
||||
case SPDK_NVME_TRANSPORT_RDMA:
|
||||
snprintf(trid->trstring, SPDK_NVMF_TRSTRING_MAX_LEN, "%s", SPDK_NVME_TRANSPORT_NAME_RDMA);
|
||||
break;
|
||||
case SPDK_NVME_TRANSPORT_TCP:
|
||||
snprintf(trid->trstring, SPDK_NVMF_TRSTRING_MAX_LEN, "%s", SPDK_NVME_TRANSPORT_NAME_TCP);
|
||||
break;
|
||||
default:
|
||||
SPDK_CU_ASSERT_FATAL(0 && "not supported by test");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_discovery_log(void)
|
||||
{
|
||||
@ -273,24 +315,22 @@ test_discovery_log(void)
|
||||
subsystem->flags.allow_any_host = true;
|
||||
SPDK_CU_ASSERT_FATAL(subsystem != NULL);
|
||||
|
||||
trid.trtype = SPDK_NVME_TRANSPORT_RDMA;
|
||||
trid.adrfam = SPDK_NVMF_ADRFAM_IPV4;
|
||||
snprintf(trid.traddr, sizeof(trid.traddr), "1234");
|
||||
snprintf(trid.trsvcid, sizeof(trid.trsvcid), "5678");
|
||||
test_gen_trid(&trid, SPDK_NVME_TRANSPORT_RDMA, SPDK_NVMF_ADRFAM_IPV4, "1234", "5678");
|
||||
spdk_nvmf_subsystem_add_listener(subsystem, &trid, _subsystem_add_listen_done, NULL);
|
||||
subsystem->state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
|
||||
|
||||
/* Get only genctr (first field in the header) */
|
||||
memset(buffer, 0xCC, sizeof(buffer));
|
||||
disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0,
|
||||
sizeof(disc_log->genctr));
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, sizeof(disc_log->genctr),
|
||||
&trid);
|
||||
CU_ASSERT(disc_log->genctr == 2); /* one added subsystem and listener */
|
||||
|
||||
/* Get only the header, no entries */
|
||||
memset(buffer, 0xCC, sizeof(buffer));
|
||||
disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, sizeof(*disc_log));
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, sizeof(*disc_log),
|
||||
&trid);
|
||||
CU_ASSERT(disc_log->genctr == 2);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
|
||||
@ -298,7 +338,7 @@ test_discovery_log(void)
|
||||
memset(buffer, 0xCC, sizeof(buffer));
|
||||
disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0,
|
||||
sizeof(*disc_log) + sizeof(disc_log->entries[0]));
|
||||
sizeof(*disc_log) + sizeof(disc_log->entries[0]), &trid);
|
||||
CU_ASSERT(disc_log->genctr != 0);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == 42);
|
||||
@ -306,7 +346,7 @@ test_discovery_log(void)
|
||||
/* Offset 0, oversize buffer */
|
||||
memset(buffer, 0xCC, sizeof(buffer));
|
||||
disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, sizeof(buffer));
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, sizeof(buffer), &trid);
|
||||
CU_ASSERT(disc_log->genctr != 0);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == 42);
|
||||
@ -316,10 +356,8 @@ test_discovery_log(void)
|
||||
/* Get just the first entry, no header */
|
||||
memset(buffer, 0xCC, sizeof(buffer));
|
||||
entry = (struct spdk_nvmf_discovery_log_page_entry *)buffer;
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov,
|
||||
1,
|
||||
offsetof(struct spdk_nvmf_discovery_log_page, entries[0]),
|
||||
sizeof(*entry));
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1,
|
||||
offsetof(struct spdk_nvmf_discovery_log_page, entries[0]), sizeof(*entry), &trid);
|
||||
CU_ASSERT(entry->trtype == 42);
|
||||
subsystem->state = SPDK_NVMF_SUBSYSTEM_INACTIVE;
|
||||
rc = spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
|
||||
@ -327,6 +365,270 @@ test_discovery_log(void)
|
||||
free(tgt.subsystems);
|
||||
}
|
||||
|
||||
static void
|
||||
test_rdma_discover(struct spdk_nvmf_transport *transport, struct spdk_nvme_transport_id *trid,
|
||||
struct spdk_nvmf_discovery_log_page_entry *entry)
|
||||
{
|
||||
entry->trtype = SPDK_NVMF_TRTYPE_RDMA;
|
||||
entry->adrfam = trid->adrfam;
|
||||
memcpy(entry->traddr, trid->traddr, sizeof(entry->traddr));
|
||||
memcpy(entry->trsvcid, trid->trsvcid, sizeof(entry->trsvcid));
|
||||
}
|
||||
|
||||
static void
|
||||
test_tcp_discover(struct spdk_nvmf_transport *transport, struct spdk_nvme_transport_id *trid,
|
||||
struct spdk_nvmf_discovery_log_page_entry *entry)
|
||||
{
|
||||
entry->trtype = SPDK_NVMF_TRTYPE_TCP;
|
||||
entry->adrfam = trid->adrfam;
|
||||
memcpy(entry->traddr, trid->traddr, sizeof(entry->traddr));
|
||||
memcpy(entry->trsvcid, trid->trsvcid, sizeof(entry->trsvcid));
|
||||
}
|
||||
|
||||
static void
|
||||
test_discovery_log_with_filters(void)
|
||||
{
|
||||
struct spdk_nvmf_tgt tgt = {};
|
||||
struct spdk_nvmf_transport_ops rdma_tr_ops = { .listener_discover = test_rdma_discover }, tcp_tr_ops
|
||||
= { .listener_discover = test_tcp_discover };
|
||||
struct spdk_nvmf_transport rdma_tr = {.ops = &rdma_tr_ops }, tcp_tr = { .ops = &tcp_tr_ops };
|
||||
struct spdk_nvmf_subsystem *subsystem;
|
||||
uint8_t buffer[8192];
|
||||
struct iovec iov;
|
||||
struct spdk_nvmf_discovery_log_page *disc_log;
|
||||
struct spdk_nvmf_listener rdma_listener_1 = {}, rdma_listener_2 = {}, rdma_listener_3 = {},
|
||||
tcp_listener_1 = {}, tcp_listener_2 = {}, tcp_listener_3 = {};
|
||||
struct spdk_nvme_transport_id rdma_trid_1 = {}, rdma_trid_2 = {}, rdma_trid_3 = {}, tcp_trid_1 = {},
|
||||
tcp_trid_2 = {}, tcp_trid_3 = {};
|
||||
|
||||
iov.iov_base = buffer;
|
||||
iov.iov_len = 8192;
|
||||
|
||||
tgt.max_subsystems = 4;
|
||||
tgt.subsystems = calloc(tgt.max_subsystems, sizeof(struct spdk_nvmf_subsystem *));
|
||||
SPDK_CU_ASSERT_FATAL(tgt.subsystems != NULL);
|
||||
|
||||
subsystem = spdk_nvmf_subsystem_create(&tgt, "nqn.2016-06.io.spdk:subsystem1",
|
||||
SPDK_NVMF_SUBTYPE_NVME, 0);
|
||||
subsystem->flags.allow_any_host = true;
|
||||
SPDK_CU_ASSERT_FATAL(subsystem != NULL);
|
||||
|
||||
test_gen_trid(&rdma_trid_1, SPDK_NVME_TRANSPORT_RDMA, SPDK_NVMF_ADRFAM_IPV4, "10.10.10.10", "4420");
|
||||
test_gen_trid(&rdma_trid_2, SPDK_NVME_TRANSPORT_RDMA, SPDK_NVMF_ADRFAM_IPV4, "11.11.11.11", "4420");
|
||||
test_gen_trid(&rdma_trid_3, SPDK_NVME_TRANSPORT_RDMA, SPDK_NVMF_ADRFAM_IPV4, "10.10.10.10", "4421");
|
||||
test_gen_trid(&tcp_trid_1, SPDK_NVME_TRANSPORT_TCP, SPDK_NVMF_ADRFAM_IPV4, "11.11.11.11", "4421");
|
||||
test_gen_trid(&tcp_trid_2, SPDK_NVME_TRANSPORT_TCP, SPDK_NVMF_ADRFAM_IPV4, "10.10.10.10", "4422");
|
||||
test_gen_trid(&tcp_trid_3, SPDK_NVME_TRANSPORT_TCP, SPDK_NVMF_ADRFAM_IPV4, "11.11.11.11", "4422");
|
||||
|
||||
rdma_listener_1.trid = rdma_trid_1;
|
||||
rdma_listener_2.trid = rdma_trid_2;
|
||||
rdma_listener_3.trid = rdma_trid_3;
|
||||
TAILQ_INIT(&rdma_tr.listeners);
|
||||
TAILQ_INSERT_TAIL(&rdma_tr.listeners, &rdma_listener_1, link);
|
||||
TAILQ_INSERT_TAIL(&rdma_tr.listeners, &rdma_listener_2, link);
|
||||
TAILQ_INSERT_TAIL(&rdma_tr.listeners, &rdma_listener_3, link);
|
||||
|
||||
tcp_listener_1.trid = tcp_trid_1;
|
||||
tcp_listener_2.trid = tcp_trid_2;
|
||||
tcp_listener_3.trid = tcp_trid_3;
|
||||
TAILQ_INIT(&tcp_tr.listeners);
|
||||
TAILQ_INSERT_TAIL(&tcp_tr.listeners, &tcp_listener_1, link);
|
||||
TAILQ_INSERT_TAIL(&tcp_tr.listeners, &tcp_listener_2, link);
|
||||
TAILQ_INSERT_TAIL(&tcp_tr.listeners, &tcp_listener_3, link);
|
||||
|
||||
MOCK_SET(spdk_nvmf_tgt_get_transport, &rdma_tr);
|
||||
spdk_nvmf_subsystem_add_listener(subsystem, &rdma_trid_1, _subsystem_add_listen_done, NULL);
|
||||
spdk_nvmf_subsystem_add_listener(subsystem, &rdma_trid_2, _subsystem_add_listen_done, NULL);
|
||||
spdk_nvmf_subsystem_add_listener(subsystem, &rdma_trid_3, _subsystem_add_listen_done, NULL);
|
||||
MOCK_SET(spdk_nvmf_tgt_get_transport, &tcp_tr);
|
||||
spdk_nvmf_subsystem_add_listener(subsystem, &tcp_trid_1, _subsystem_add_listen_done, NULL);
|
||||
spdk_nvmf_subsystem_add_listener(subsystem, &tcp_trid_2, _subsystem_add_listen_done, NULL);
|
||||
spdk_nvmf_subsystem_add_listener(subsystem, &tcp_trid_3, _subsystem_add_listen_done, NULL);
|
||||
MOCK_CLEAR(spdk_nvmf_tgt_get_transport);
|
||||
|
||||
subsystem->state = SPDK_NVMF_SUBSYSTEM_ACTIVE;
|
||||
|
||||
disc_log = (struct spdk_nvmf_discovery_log_page *)buffer;
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
/* Test case 1 - check that all trids are reported */
|
||||
tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_ANY;
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &rdma_trid_1);
|
||||
CU_ASSERT(disc_log->numrec == 6);
|
||||
|
||||
/* Test case 2 - check that only entries of the same transport type are returned */
|
||||
tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE;
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &rdma_trid_1);
|
||||
CU_ASSERT(disc_log->numrec == 3);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
|
||||
CU_ASSERT(disc_log->entries[1].trtype == rdma_trid_1.trtype);
|
||||
CU_ASSERT(disc_log->entries[2].trtype == rdma_trid_1.trtype);
|
||||
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &tcp_trid_1);
|
||||
CU_ASSERT(disc_log->numrec == 3);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
|
||||
CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_1.trtype);
|
||||
CU_ASSERT(disc_log->entries[2].trtype == tcp_trid_1.trtype);
|
||||
|
||||
/* Test case 3 - check that only entries of the same transport address are returned */
|
||||
tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS;
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &rdma_trid_1);
|
||||
CU_ASSERT(disc_log->numrec == 3);
|
||||
/* one tcp and 2 rdma */
|
||||
CU_ASSERT((disc_log->entries[0].trtype ^ disc_log->entries[1].trtype ^ disc_log->entries[2].trtype)
|
||||
!= 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_1.traddr) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, rdma_trid_1.traddr) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, rdma_trid_1.traddr) == 0);
|
||||
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &tcp_trid_1);
|
||||
CU_ASSERT(disc_log->numrec == 3);
|
||||
/* one rdma and two tcp */
|
||||
CU_ASSERT((disc_log->entries[0].trtype ^ disc_log->entries[1].trtype ^ disc_log->entries[2].trtype)
|
||||
!= 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_1.traddr) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_1.traddr) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[2].traddr, tcp_trid_1.traddr) == 0);
|
||||
|
||||
/* Test case 4 - check that only entries of the same transport address and type returned */
|
||||
tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE |
|
||||
SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS;
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &rdma_trid_1);
|
||||
CU_ASSERT(disc_log->numrec == 2);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_1.traddr) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, rdma_trid_1.traddr) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
|
||||
CU_ASSERT(disc_log->entries[1].trtype == rdma_trid_1.trtype);
|
||||
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &rdma_trid_2);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_2.traddr) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_2.trtype);
|
||||
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &tcp_trid_1);
|
||||
CU_ASSERT(disc_log->numrec == 2);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_1.traddr) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[1].traddr, tcp_trid_1.traddr) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
|
||||
CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_1.trtype);
|
||||
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &rdma_trid_2);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_2.traddr) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_2.trtype);
|
||||
|
||||
/* Test case 5 - check that only entries of the same transport address and type returned */
|
||||
tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE |
|
||||
SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID;
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &rdma_trid_1);
|
||||
CU_ASSERT(disc_log->numrec == 2);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_1.trsvcid) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, rdma_trid_2.trsvcid) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
|
||||
CU_ASSERT(disc_log->entries[1].trtype == rdma_trid_2.trtype);
|
||||
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &rdma_trid_3);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_3.trsvcid) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_3.trtype);
|
||||
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &tcp_trid_1);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_1.trsvcid) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
|
||||
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &tcp_trid_2);
|
||||
CU_ASSERT(disc_log->numrec == 2);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_2.trsvcid) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[1].trsvcid, tcp_trid_2.trsvcid) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_2.trtype);
|
||||
CU_ASSERT(disc_log->entries[1].trtype == tcp_trid_2.trtype);
|
||||
|
||||
/* Test case 6 - check that only entries of the same transport address and type returned.
|
||||
* That also implies trtype since RDMA and TCP listeners can't occupy the same socket */
|
||||
tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS |
|
||||
SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID;
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &rdma_trid_1);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_1.traddr) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_1.trsvcid) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
|
||||
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &rdma_trid_2);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_2.traddr) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_2.trsvcid) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_2.trtype);
|
||||
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &rdma_trid_3);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_3.traddr) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_3.trsvcid) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_3.trtype);
|
||||
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &tcp_trid_1);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_1.traddr) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_1.trsvcid) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
|
||||
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &tcp_trid_2);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_2.traddr) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_2.trsvcid) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_2.trtype);
|
||||
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &tcp_trid_3);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_3.traddr) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_3.trsvcid) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_3.trtype);
|
||||
|
||||
/* Test case 7 - check that only entries of the same transport address, svcid and type returned */
|
||||
tgt.discovery_filter = SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_TYPE |
|
||||
SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_ADDRESS |
|
||||
SPDK_NVMF_TGT_DISCOVERY_MATCH_TRANSPORT_SVCID;
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &rdma_trid_1);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_1.traddr) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_1.trsvcid) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_1.trtype);
|
||||
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &rdma_trid_2);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_2.traddr) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_2.trsvcid) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_2.trtype);
|
||||
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &rdma_trid_3);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, rdma_trid_3.traddr) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, rdma_trid_3.trsvcid) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == rdma_trid_3.trtype);
|
||||
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &tcp_trid_1);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_1.traddr) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_1.trsvcid) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_1.trtype);
|
||||
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &tcp_trid_2);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_2.traddr) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_2.trsvcid) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_2.trtype);
|
||||
|
||||
nvmf_get_discovery_log_page(&tgt, "nqn.2016-06.io.spdk:host1", &iov, 1, 0, 8192, &tcp_trid_3);
|
||||
CU_ASSERT(disc_log->numrec == 1);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].traddr, tcp_trid_3.traddr) == 0);
|
||||
CU_ASSERT(strcasecmp(disc_log->entries[0].trsvcid, tcp_trid_3.trsvcid) == 0);
|
||||
CU_ASSERT(disc_log->entries[0].trtype == tcp_trid_3.trtype);
|
||||
|
||||
subsystem->state = SPDK_NVMF_SUBSYSTEM_INACTIVE;
|
||||
spdk_nvmf_subsystem_destroy(subsystem, NULL, NULL);
|
||||
free(tgt.subsystems);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CU_pSuite suite = NULL;
|
||||
@ -338,6 +640,7 @@ int main(int argc, char **argv)
|
||||
suite = CU_add_suite("nvmf", NULL, NULL);
|
||||
|
||||
CU_ADD_TEST(suite, test_discovery_log);
|
||||
CU_ADD_TEST(suite, test_discovery_log_with_filters);
|
||||
|
||||
CU_basic_set_mode(CU_BRM_VERBOSE);
|
||||
CU_basic_run_tests();
|
||||
|
@ -3,6 +3,7 @@
|
||||
*
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -92,7 +93,7 @@ DEFINE_STUB(nvmf_subsystem_find_listener,
|
||||
|
||||
DEFINE_STUB_V(nvmf_get_discovery_log_page,
|
||||
(struct spdk_nvmf_tgt *tgt, const char *hostnqn, struct iovec *iov,
|
||||
uint32_t iovcnt, uint64_t offset, uint32_t length));
|
||||
uint32_t iovcnt, uint64_t offset, uint32_t length, struct spdk_nvme_transport_id *cmd_src_trid));
|
||||
|
||||
DEFINE_STUB_V(nvmf_subsystem_remove_ctrlr,
|
||||
(struct spdk_nvmf_subsystem *subsystem, struct spdk_nvmf_ctrlr *ctrlr));
|
||||
|
Loading…
Reference in New Issue
Block a user