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:
Alexey Marchuk 2021-08-12 19:01:39 +03:00 committed by Jim Harris
parent e40bd53175
commit 3d8904c66b
16 changed files with 576 additions and 42 deletions

View File

@ -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.

View File

@ -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}

View File

@ -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 {

View File

@ -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);
}

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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):

View File

@ -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)

View File

@ -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,

View File

@ -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();

View File

@ -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));