Commit 3d8904c6 authored by Alexey Marchuk's avatar Alexey Marchuk Committed by Jim Harris
Browse files

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: default avatarAlexey Marchuk <alexeymar@mellanox.com>
Change-Id: Ie981edebb29206793d3310940034dcbb22c52441
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/9185


Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
Community-CI: Mellanox Build Bot
parent e40bd531
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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.
+1 −0
Original line number Diff line number Diff line
@@ -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}

+15 −0
Original line number Diff line number Diff line
@@ -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 {
+9 −2
Original line number Diff line number Diff line
@@ -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);
			}
+55 −3
Original line number Diff line number Diff line
@@ -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) {
Loading