Commit 020c4e11 authored by Konrad Sztyber's avatar Konrad Sztyber Committed by Tomasz Zawadzki
Browse files

nvmf: option to add NVM subsystem discovery log entries



It is now possible to add discovery log entries describing NVM
subsystems that aren't available in that NVMe-oF target.

Since this is fairly similar to the way discovery subsystem referrals
are handled, the nvmf_discovery_add_referral is also used for adding
such entries.  Users can now specify an NQN (which defaults to a
discovery subsystem NQN), which is then used to select a subtype.

Signed-off-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I608b98e93ae237d118c1a5feecbed713c774b1d8
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/20901


Reviewed-by: default avatarVasuki Manikarnike <vasuki.manikarnike@hpe.com>
Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Reviewed-by: default avatarAbhineet Pandey <abhineet.pandey@nutanix.com>
Reviewed-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent e3dde60a
Loading
Loading
Loading
Loading
+19 −6
Original line number Diff line number Diff line
@@ -72,6 +72,14 @@ spdk_nvmf_tgt_add_referral(struct spdk_nvmf_tgt *tgt,
	struct spdk_nvme_transport_id *trid = &opts.trid;

	memcpy(&opts, uopts, spdk_min(uopts->size, sizeof(opts)));
	if (trid->subnqn[0] == '\0') {
		snprintf(trid->subnqn, sizeof(trid->subnqn), "%s", SPDK_NVMF_DISCOVERY_NQN);
	}

	if (!nvmf_nqn_is_valid(trid->subnqn)) {
		SPDK_ERRLOG("Invalid subsystem NQN\n");
		return -EINVAL;
	}

	/* If the entry already exists, just ignore it. */
	if (nvmf_tgt_find_referral(tgt, trid)) {
@@ -84,16 +92,17 @@ spdk_nvmf_tgt_add_referral(struct spdk_nvmf_tgt *tgt,
		return -ENOMEM;
	}

	referral->entry.subtype = SPDK_NVMF_SUBTYPE_DISCOVERY;
	referral->entry.subtype = nvmf_nqn_is_discovery(trid->subnqn) ?
				  SPDK_NVMF_SUBTYPE_DISCOVERY :
				  SPDK_NVMF_SUBTYPE_NVME;
	referral->entry.treq.secure_channel = opts.secure_channel ?
					      SPDK_NVMF_TREQ_SECURE_CHANNEL_REQUIRED
					      : SPDK_NVMF_TREQ_SECURE_CHANNEL_NOT_REQUIRED;
	referral->entry.cntlid =
		0xffff; /* Discovery controller shall support the dynamic controller model */
					      SPDK_NVMF_TREQ_SECURE_CHANNEL_REQUIRED :
					      SPDK_NVMF_TREQ_SECURE_CHANNEL_NOT_REQUIRED;
	referral->entry.cntlid = 0xffff;
	referral->entry.trtype = trid->trtype;
	referral->entry.adrfam = trid->adrfam;
	snprintf(referral->entry.subnqn, sizeof(referral->entry.subnqn), "%s", SPDK_NVMF_DISCOVERY_NQN);
	memcpy(&referral->trid, trid, sizeof(struct spdk_nvme_transport_id));
	spdk_strcpy_pad(referral->entry.subnqn, trid->subnqn, sizeof(trid->subnqn), '\0');
	spdk_strcpy_pad(referral->entry.trsvcid, trid->trsvcid, sizeof(referral->entry.trsvcid), ' ');
	spdk_strcpy_pad(referral->entry.traddr, trid->traddr, sizeof(referral->entry.traddr), ' ');

@@ -109,8 +118,12 @@ spdk_nvmf_tgt_remove_referral(struct spdk_nvmf_tgt *tgt,
{
	struct spdk_nvmf_referral *referral;
	struct spdk_nvmf_referral_opts opts = {};
	struct spdk_nvme_transport_id *trid = &opts.trid;

	memcpy(&opts, uopts, spdk_min(uopts->size, sizeof(opts)));
	if (trid->subnqn[0] == '\0') {
		snprintf(trid->subnqn, sizeof(trid->subnqn), "%s", SPDK_NVMF_DISCOVERY_NQN);
	}

	referral = nvmf_tgt_find_referral(tgt, &opts.trid);
	if (referral == NULL) {
+5 −0
Original line number Diff line number Diff line
@@ -482,6 +482,11 @@ nvmf_qpair_is_admin_queue(struct spdk_nvmf_qpair *qpair)
 */
bool nvmf_nqn_is_valid(const char *nqn);

/*
 * Tests whether a given NQN describes a discovery subsystem.
 */
bool nvmf_nqn_is_discovery(const char *nqn);

/**
 * Initiates a zcopy start operation
 *
+25 −0
Original line number Diff line number Diff line
@@ -1006,18 +1006,21 @@ struct nvmf_rpc_referral_ctx {
	char				*tgt_name;
	struct rpc_listen_address	address;
	bool				secure_channel;
	char				*subnqn;
};

static const struct spdk_json_object_decoder nvmf_rpc_referral_decoder[] = {
	{"address", offsetof(struct nvmf_rpc_referral_ctx, address), decode_rpc_listen_address},
	{"tgt_name", offsetof(struct nvmf_rpc_referral_ctx, tgt_name), spdk_json_decode_string, true},
	{"secure_channel", offsetof(struct nvmf_rpc_referral_ctx, secure_channel), spdk_json_decode_bool, true},
	{"subnqn", offsetof(struct nvmf_rpc_referral_ctx, subnqn), spdk_json_decode_string, true},
};

static void
nvmf_rpc_referral_ctx_free(struct nvmf_rpc_referral_ctx *ctx)
{
	free(ctx->tgt_name);
	free(ctx->subnqn);
	free_rpc_listen_address(&ctx->address);
}

@@ -1056,6 +1059,16 @@ rpc_nvmf_add_referral(struct spdk_jsonrpc_request *request,
		return;
	}

	if (ctx.subnqn != NULL) {
		rc = snprintf(trid.subnqn, sizeof(trid.subnqn), "%s", ctx.subnqn);
		if (rc < 0 || (size_t)rc >= sizeof(trid.subnqn)) {
			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
							 "Invalid subsystem NQN");
			nvmf_rpc_referral_ctx_free(&ctx);
			return;
		}
	}

	if ((trid.trtype == SPDK_NVME_TRANSPORT_TCP ||
	     trid.trtype == SPDK_NVME_TRANSPORT_RDMA) &&
	    !strlen(trid.trsvcid)) {
@@ -1094,6 +1107,7 @@ rpc_nvmf_remove_referral(struct spdk_jsonrpc_request *request,
	struct spdk_nvme_transport_id trid = {};
	struct spdk_nvmf_referral_opts opts = {};
	struct spdk_nvmf_tgt *tgt;
	int rc;

	if (spdk_json_decode_object(params, nvmf_rpc_referral_decoder,
				    SPDK_COUNTOF(nvmf_rpc_referral_decoder),
@@ -1120,6 +1134,16 @@ rpc_nvmf_remove_referral(struct spdk_jsonrpc_request *request,
		return;
	}

	if (ctx.subnqn != NULL) {
		rc = snprintf(trid.subnqn, sizeof(trid.subnqn), "%s", ctx.subnqn);
		if (rc < 0 || (size_t)rc >= sizeof(trid.subnqn)) {
			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
							 "Invalid subsystem NQN");
			nvmf_rpc_referral_ctx_free(&ctx);
			return;
		}
	}

	opts.size = SPDK_SIZEOF(&opts, secure_channel);
	opts.trid = trid;

@@ -1150,6 +1174,7 @@ dump_nvmf_referral(struct spdk_json_write_ctx *w,
	spdk_json_write_object_end(w);
	spdk_json_write_named_bool(w, "secure_channel",
				   referral->entry.treq.secure_channel == SPDK_NVMF_TREQ_SECURE_CHANNEL_REQUIRED);
	spdk_json_write_named_string(w, "subnqn", referral->trid.subnqn);

	spdk_json_write_object_end(w);
}
+6 −0
Original line number Diff line number Diff line
@@ -3401,3 +3401,9 @@ spdk_nvmf_subsystem_is_discovery(struct spdk_nvmf_subsystem *subsystem)
	return subsystem->subtype == SPDK_NVMF_SUBTYPE_DISCOVERY_CURRENT ||
	       subsystem->subtype == SPDK_NVMF_SUBTYPE_DISCOVERY;
}

bool
nvmf_nqn_is_discovery(const char *nqn)
{
	return strcmp(nqn, SPDK_NVMF_DISCOVERY_NQN) == 0;
}
+12 −3
Original line number Diff line number Diff line
@@ -361,6 +361,7 @@ def nvmf_discovery_add_referral(client, **params):
        adrfam: Address family ("IPv4", "IPv6", "IB", or "FC").
        secure_channel: The connection to that discovery
            subsystem requires a secure channel (optional).
        subnqn: Subsystem NQN.

    Returns:
        True or False
@@ -371,6 +372,9 @@ def nvmf_discovery_add_referral(client, **params):
    group_as(params, 'address', ['trtype', 'traddr', 'trsvcid', 'adrfam'])
    remove_null(params)

    if params.get('subnqn') == 'discovery':
        params['subnqn'] = 'nqn.2014-08.org.nvmexpress.discovery'

    return client.call('nvmf_discovery_add_referral', params)


@@ -380,16 +384,17 @@ def nvmf_discovery_remove_referral(
        traddr,
        trsvcid,
        adrfam,
        tgt_name=None):
        tgt_name=None,
        subnqn=None):
    """Remove a discovery service referral

    Args:
        nqn: Subsystem NQN.
        trtype: Transport type ("RDMA").
        traddr: Transport address.
        trsvcid: Transport service ID.
        tgt_name: name of the parent NVMe-oF target (optional).
        adrfam: Address family ("IPv4", "IPv6", "IB", or "FC").
        tgt_name: name of the parent NVMe-oF target (optional).
        subnqn: Subsystem NQN.

    Returns:
            True or False
@@ -407,6 +412,10 @@ def nvmf_discovery_remove_referral(

    if tgt_name:
        params['tgt_name'] = tgt_name
    if subnqn is not None:
        if subnqn == 'discovery':
            subnqn = 'nqn.2014-08.org.nvmexpress.discovery'
        params['subnqn'] = subnqn

    return client.call('nvmf_discovery_remove_referral', params)

Loading