diff --git a/CHANGELOG.md b/CHANGELOG.md index e0bcf65e7..8f26be655 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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. diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index a3525251e..59d61788f 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -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} diff --git a/include/spdk/nvmf.h b/include/spdk/nvmf.h index 6f7987cc3..3bf44c47f 100644 --- a/include/spdk/nvmf.h +++ b/include/spdk/nvmf.h @@ -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 { diff --git a/lib/nvmf/ctrlr.c b/lib/nvmf/ctrlr.c index e40db404b..154a1b2e3 100644 --- a/lib/nvmf/ctrlr.c +++ b/lib/nvmf/ctrlr.c @@ -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); } diff --git a/lib/nvmf/ctrlr_discovery.c b/lib/nvmf/ctrlr_discovery.c index a24538165..331d4ab0c 100644 --- a/lib/nvmf/ctrlr_discovery.c +++ b/lib/nvmf/ctrlr_discovery.c @@ -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) { diff --git a/lib/nvmf/nvmf.c b/lib/nvmf/nvmf.c index 7af3a9da1..337803a7d 100644 --- a/lib/nvmf/nvmf.c +++ b/lib/nvmf/nvmf.c @@ -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); diff --git a/lib/nvmf/nvmf_internal.h b/lib/nvmf/nvmf_internal.h index 22b679f59..37dd389d1 100644 --- a/lib/nvmf/nvmf_internal.h +++ b/lib/nvmf/nvmf_internal.h @@ -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); diff --git a/lib/nvmf/nvmf_rpc.c b/lib/nvmf/nvmf_rpc.c index 532521fa8..7ab557df3 100644 --- a/lib/nvmf/nvmf_rpc.c +++ b/lib/nvmf/nvmf_rpc.c @@ -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); diff --git a/module/event/subsystems/nvmf/event_nvmf.h b/module/event/subsystems/nvmf/event_nvmf.h index 9c796f9bb..82b81627e 100644 --- a/module/event/subsystems/nvmf/event_nvmf.h +++ b/module/event/subsystems/nvmf/event_nvmf.h @@ -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; diff --git a/module/event/subsystems/nvmf/nvmf_rpc.c b/module/event/subsystems/nvmf/nvmf_rpc.c index c18efeb0f..f138dc689 100644 --- a/module/event/subsystems/nvmf/nvmf_rpc.c +++ b/module/event/subsystems/nvmf/nvmf_rpc.c @@ -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 diff --git a/module/event/subsystems/nvmf/nvmf_tgt.c b/module/event/subsystems/nvmf/nvmf_tgt.c index 321ab765b..29c1a92ce 100644 --- a/module/event/subsystems/nvmf/nvmf_tgt.c +++ b/module/event/subsystems/nvmf/nvmf_tgt.c @@ -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); diff --git a/scripts/rpc.py b/scripts/rpc.py index 35fec3a95..5c707e9b7 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -1917,7 +1917,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') @@ -1926,6 +1927,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): diff --git a/scripts/rpc/nvmf.py b/scripts/rpc/nvmf.py index 4f1dd7358..915c04b4b 100644 --- a/scripts/rpc/nvmf.py +++ b/scripts/rpc/nvmf.py @@ -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) diff --git a/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c b/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c index d942ace9e..16a15b14b 100644 --- a/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c +++ b/test/unit/lib/nvmf/ctrlr.c/ctrlr_ut.c @@ -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, diff --git a/test/unit/lib/nvmf/ctrlr_discovery.c/ctrlr_discovery_ut.c b/test/unit/lib/nvmf/ctrlr_discovery.c/ctrlr_discovery_ut.c index 9ca17aee1..095bc0943 100644 --- a/test/unit/lib/nvmf/ctrlr_discovery.c/ctrlr_discovery_ut.c +++ b/test/unit/lib/nvmf/ctrlr_discovery.c/ctrlr_discovery_ut.c @@ -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(); diff --git a/test/unit/lib/nvmf/tcp.c/tcp_ut.c b/test/unit/lib/nvmf/tcp.c/tcp_ut.c index 93d5d6546..d609fbb4e 100644 --- a/test/unit/lib/nvmf/tcp.c/tcp_ut.c +++ b/test/unit/lib/nvmf/tcp.c/tcp_ut.c @@ -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));