Commit 675c5592 authored by Seth Howell's avatar Seth Howell Committed by Jim Harris
Browse files

nvme_bdev: add parsing for hostaddr and hostsvcid



This allows us to specify the host-side configuration for each
controller to which we connect.

Change-Id: Iac2aed3934d4a326f45546f2f541e374308e2589
Signed-off-by: default avatarSeth Howell <seth.howell@intel.com>
Reviewed-on: https://review.gerrithub.io/436219


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent b035e2b8
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -25,6 +25,9 @@ same TCP/IP support.
Added API, spdk_nvme_ctrlr_is_discovery(), to indicate whether the ctrlr
arg refers to a Discovery Controller or not.

Added an API function `spdk_nvme_host_id_parse` and corresponding object `spdk_nvme_host_id`
for parsing host address and host service ID arguments on a per connection basis.

### NVMe-oF Target

The `spdk_nvmf_tgt_opts` struct has been deprecated in favor of `spdk_nvmf_transport_opts`.
+1 −0
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@
  TransportID "trtype:PCIe traddr:0000:01:00.0" Nvme1
  TransportID "trtype:PCIe traddr:0000:02:00.0" Nvme2
  TransportID "trtype:PCIe traddr:0000:03:00.0" Nvme3
  TransportID "trtypr:RDMA traddr:192.168.100.8 trsvcid:4420 hostaddr:192.168.100.9" Nvme4

  # The number of attempts per I/O when an I/O fails. Do not include
  # this key to get the default behavior.
+54 −0
Original line number Diff line number Diff line
@@ -279,6 +279,35 @@ struct spdk_nvme_transport_id {
	char subnqn[SPDK_NVMF_NQN_MAX_LEN + 1];
};

/**
 * NVMe host identifier
 *
 * Used for defining the host identity for an NVMe-oF connection.
 *
 * In terms of configuration, this object can be considered a subtype of TransportID
 * Please see etc/spdk/nvmf.conf.in for more details.
 *
 * A string representation of this type may be converted to this type using
 * spdk_nvme_host_id_parse().
 */
struct spdk_nvme_host_id {
	/**
	 * Transport address to be used by the host when connecting to the NVMe-oF endpoint.
	 * May be an IP address or a zero length string for transports which
	 * use IP addressing (e.g. RDMA).
	 * For PCIe and FC this is always a zero length string.
	 */
	char hostaddr[SPDK_NVMF_TRADDR_MAX_LEN + 1];

	/**
	 * Transport service ID used by the host when connecting to the NVMe.
	 * May be a port number or a zero length string for transports which
	 * use IP addressing (e.g. RDMA).
	 * For PCIe and FC this is always a zero length string.
	 */
	char hostsvcid[SPDK_NVMF_TRSVCID_MAX_LEN + 1];
};

/**
 * Parse the string representation of a transport ID.
 *
@@ -304,6 +333,31 @@ struct spdk_nvme_transport_id {
 */
int spdk_nvme_transport_id_parse(struct spdk_nvme_transport_id *trid, const char *str);

/**
 * Parse the string representation of a host ID.
 *
 * \param hostid Output host ID structure (must be allocated and initialized by caller).
 * \param str Input string representation of a transport ID to parse (hostid is a sub-configuration).
 *
 * str must be a zero-terminated C string containing one or more key:value pairs
 * separated by whitespace.
 *
 * Key            | Value
 * -------------- | -----
 * hostaddr       | Transport address (e.g. 192.168.100.8 for RDMA)
 * hostsvcid      | Transport service identifier (e.g. 4420)
 *
 * Unspecified fields of trid are left unmodified, so the caller must initialize
 * hostid (for example, memset() to 0) before calling this function.
 *
 * This function should not be used with Fiber Channel or PCIe as these transports
 * do not require host information for connections.
 *
 * \return 0 if parsing was successful and hostid is filled out, or negated errno
 * values on failure.
 */
int spdk_nvme_host_id_parse(struct spdk_nvme_host_id *hostid, const char *str);

/**
 * Parse the string representation of a transport ID tranport type.
 *
+16 −0
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ enum data_direction {
struct nvme_probe_ctx {
	size_t count;
	struct spdk_nvme_transport_id trids[NVME_MAX_CONTROLLERS];
	struct spdk_nvme_host_id hostids[NVME_MAX_CONTROLLERS];
	const char *names[NVME_MAX_CONTROLLERS];
	const char *hostnqn;
};
@@ -1384,6 +1385,13 @@ bdev_nvme_library_init(void)
			goto end;
		}

		rc = spdk_nvme_host_id_parse(&probe_ctx->hostids[i], val);
		if (rc < 0) {
			SPDK_ERRLOG("Unable to parse HostID: %s\n", val);
			rc = -1;
			goto end;
		}

		val = spdk_conf_section_get_nmval(sp, "TransportID", i, 1);
		if (val == NULL) {
			SPDK_ERRLOG("No name provided for TransportID\n");
@@ -1417,6 +1425,14 @@ bdev_nvme_library_init(void)
				snprintf(opts.hostnqn, sizeof(opts.hostnqn), "%s", probe_ctx->hostnqn);
			}

			if (probe_ctx->hostids[i].hostaddr[0] != '\0') {
				snprintf(opts.src_addr, sizeof(opts.src_addr), "%s", probe_ctx->hostids[i].hostaddr);
			}

			if (probe_ctx->hostids[i].hostsvcid[0] != '\0') {
				snprintf(opts.src_svcid, sizeof(opts.src_svcid), "%s", probe_ctx->hostids[i].hostsvcid);
			}

			ctrlr = spdk_nvme_connect(&probe_ctx->trids[i], &opts, sizeof(opts));
			if (ctrlr == NULL) {
				SPDK_ERRLOG("Unable to connect to provided trid (traddr: %s)\n",
+63 −0
Original line number Diff line number Diff line
@@ -828,6 +828,10 @@ spdk_nvme_transport_id_parse(struct spdk_nvme_transport_id *trid, const char *st
				return -EINVAL;
			}
			memcpy(trid->subnqn, val, val_len + 1);
		} else if (strcasecmp(key, "hostaddr") == 0) {
			continue;
		} else if (strcasecmp(key, "hostsvcid") == 0) {
			continue;
		} else if (strcasecmp(key, "ns") == 0) {
			/*
			 * Special case.  The namespace id parameter may
@@ -848,6 +852,65 @@ spdk_nvme_transport_id_parse(struct spdk_nvme_transport_id *trid, const char *st
	return 0;
}

int
spdk_nvme_host_id_parse(struct spdk_nvme_host_id *hostid, const char *str)
{

	size_t key_size = 32;
	size_t val_size = 1024;
	size_t val_len;
	char key[key_size];
	char val[val_size];

	if (hostid == NULL || str == NULL) {
		return -EINVAL;
	}

	while (*str != '\0') {

		val_len = parse_next_key(&str, key, val, key_size, val_size);

		if (val_len == 0) {
			SPDK_ERRLOG("Failed to parse host ID\n");
			return val_len;
		}

		/* Ignore the rest of the options from the transport ID. */
		if (strcasecmp(key, "trtype") == 0) {
			continue;
		} else if (strcasecmp(key, "adrfam") == 0) {
			continue;
		} else if (strcasecmp(key, "traddr") == 0) {
			continue;
		} else if (strcasecmp(key, "trsvcid") == 0) {
			continue;
		} else if (strcasecmp(key, "subnqn") == 0) {
			continue;
		} else if (strcasecmp(key, "ns") == 0) {
			continue;
		} else if (strcasecmp(key, "hostaddr") == 0) {
			if (val_len > SPDK_NVMF_TRADDR_MAX_LEN) {
				SPDK_ERRLOG("hostaddr length %zu greater than maximum allowed %u\n",
					    val_len, SPDK_NVMF_TRADDR_MAX_LEN);
				return -EINVAL;
			}
			memcpy(hostid->hostaddr, val, val_len + 1);

		} else if (strcasecmp(key, "hostsvcid") == 0) {
			if (val_len > SPDK_NVMF_TRSVCID_MAX_LEN) {
				SPDK_ERRLOG("trsvcid length %zu greater than maximum allowed %u\n",
					    val_len, SPDK_NVMF_TRSVCID_MAX_LEN);
				return -EINVAL;
			}
			memcpy(hostid->hostsvcid, val, val_len + 1);
		} else {
			SPDK_ERRLOG("Unknown transport ID key '%s'\n", key);
		}
	}

	return 0;
}

static int
cmp_int(int a, int b)
{
Loading