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: Seth Howell <seth.howell@intel.com>
Reviewed-on: https://review.gerrithub.io/436219
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Seth Howell 2018-12-04 15:09:31 -07:00 committed by Jim Harris
parent b035e2b848
commit 675c5592e7
6 changed files with 138 additions and 1 deletions

View File

@ -25,6 +25,9 @@ same TCP/IP support.
Added API, spdk_nvme_ctrlr_is_discovery(), to indicate whether the ctrlr Added API, spdk_nvme_ctrlr_is_discovery(), to indicate whether the ctrlr
arg refers to a Discovery Controller or not. 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 ### NVMe-oF Target
The `spdk_nvmf_tgt_opts` struct has been deprecated in favor of `spdk_nvmf_transport_opts`. The `spdk_nvmf_tgt_opts` struct has been deprecated in favor of `spdk_nvmf_transport_opts`.

View File

@ -102,6 +102,7 @@
TransportID "trtype:PCIe traddr:0000:01:00.0" Nvme1 TransportID "trtype:PCIe traddr:0000:01:00.0" Nvme1
TransportID "trtype:PCIe traddr:0000:02:00.0" Nvme2 TransportID "trtype:PCIe traddr:0000:02:00.0" Nvme2
TransportID "trtype:PCIe traddr:0000:03:00.0" Nvme3 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 # The number of attempts per I/O when an I/O fails. Do not include
# this key to get the default behavior. # this key to get the default behavior.

View File

@ -279,6 +279,35 @@ struct spdk_nvme_transport_id {
char subnqn[SPDK_NVMF_NQN_MAX_LEN + 1]; 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. * 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); 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. * Parse the string representation of a transport ID tranport type.
* *

View File

@ -90,6 +90,7 @@ enum data_direction {
struct nvme_probe_ctx { struct nvme_probe_ctx {
size_t count; size_t count;
struct spdk_nvme_transport_id trids[NVME_MAX_CONTROLLERS]; 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 *names[NVME_MAX_CONTROLLERS];
const char *hostnqn; const char *hostnqn;
}; };
@ -1384,6 +1385,13 @@ bdev_nvme_library_init(void)
goto end; 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); val = spdk_conf_section_get_nmval(sp, "TransportID", i, 1);
if (val == NULL) { if (val == NULL) {
SPDK_ERRLOG("No name provided for TransportID\n"); 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); 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)); ctrlr = spdk_nvme_connect(&probe_ctx->trids[i], &opts, sizeof(opts));
if (ctrlr == NULL) { if (ctrlr == NULL) {
SPDK_ERRLOG("Unable to connect to provided trid (traddr: %s)\n", SPDK_ERRLOG("Unable to connect to provided trid (traddr: %s)\n",

View File

@ -828,6 +828,10 @@ spdk_nvme_transport_id_parse(struct spdk_nvme_transport_id *trid, const char *st
return -EINVAL; return -EINVAL;
} }
memcpy(trid->subnqn, val, val_len + 1); 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) { } else if (strcasecmp(key, "ns") == 0) {
/* /*
* Special case. The namespace id parameter may * 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; 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 static int
cmp_int(int a, int b) cmp_int(int a, int b)
{ {

View File

@ -56,7 +56,7 @@ do
done done
$rpc_py nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode$i -t rdma -a $NVMF_FIRST_TARGET_IP -s $NVMF_PORT $rpc_py nvmf_subsystem_add_listener nqn.2016-06.io.spdk:cnode$i -t rdma -a $NVMF_FIRST_TARGET_IP -s $NVMF_PORT
echo " TransportID \"trtype:RDMA adrfam:IPv4 subnqn:nqn.2016-06.io.spdk:cnode$i traddr:$NVMF_FIRST_TARGET_IP trsvcid:$NVMF_PORT\" Nvme$i" >> $testdir/bdevperf.conf echo " TransportID \"trtype:RDMA adrfam:IPv4 subnqn:nqn.2016-06.io.spdk:cnode$i traddr:$NVMF_FIRST_TARGET_IP trsvcid:$NVMF_PORT hostaddr:$NVMF_FIRST_TARGET_IP\" Nvme$i" >> $testdir/bdevperf.conf
done done
# Test 1: Kill the initiator unexpectedly with no I/O outstanding # Test 1: Kill the initiator unexpectedly with no I/O outstanding