nvme: add transport ID string parsing function
Change-Id: I33c15c8a56c25667567b373d21a117cca1f756c7 Signed-off-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
parent
57fbfa0abe
commit
be8a9d6966
@ -169,6 +169,29 @@ struct spdk_nvme_transport_id {
|
||||
char subnqn[SPDK_NVMF_NQN_MAX_LEN + 1];
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse the string representation of a transport ID.
|
||||
*
|
||||
* \param trid Output transport ID structure (must be allocated and initialized by caller).
|
||||
* \param str Input string representation of a transport ID to parse.
|
||||
* \return 0 if parsing was successful and trid is filled out, or negated errno values on failure.
|
||||
*
|
||||
* str must be a zero-terminated C string containing one or more key:value pairs separated by
|
||||
* whitespace.
|
||||
*
|
||||
* Key | Value
|
||||
* ------------ | -----
|
||||
* trtype | Transport type (e.g. PCIe, RDMA)
|
||||
* adrfam | Address family (e.g. IPv4, IPv6)
|
||||
* traddr | Transport address (e.g. 0000:04:00.0 for PCIe or 192.168.100.8 for RDMA)
|
||||
* trsvcid | Transport service identifier (e.g. 4420)
|
||||
* subnqn | Subsystem NQN
|
||||
*
|
||||
* Unspecified fields of trid are left unmodified, so the caller must initialize trid (for example,
|
||||
* memset() to 0) before calling this function.
|
||||
*/
|
||||
int spdk_nvme_transport_id_parse(struct spdk_nvme_transport_id *trid, const char *str);
|
||||
|
||||
/**
|
||||
* Determine whether the NVMe library can handle a specific NVMe over Fabrics transport type.
|
||||
*
|
||||
|
119
lib/nvme/nvme.c
119
lib/nvme/nvme.c
@ -443,4 +443,123 @@ spdk_nvme_probe(const struct spdk_nvme_transport_id *trid, void *cb_ctx,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_trtype(enum spdk_nvme_transport_type *trtype, const char *str)
|
||||
{
|
||||
if (strcasecmp(str, "PCIe") == 0) {
|
||||
*trtype = SPDK_NVME_TRANSPORT_PCIE;
|
||||
} else if (strcasecmp(str, "RDMA") == 0) {
|
||||
*trtype = SPDK_NVME_TRANSPORT_RDMA;
|
||||
} else {
|
||||
return -ENOENT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_adrfam(enum spdk_nvmf_adrfam *adrfam, const char *str)
|
||||
{
|
||||
if (strcasecmp(str, "IPv4") == 0) {
|
||||
*adrfam = SPDK_NVMF_ADRFAM_IPV4;
|
||||
} else if (strcasecmp(str, "IPv6") == 0) {
|
||||
*adrfam = SPDK_NVMF_ADRFAM_IPV6;
|
||||
} else if (strcasecmp(str, "IB") == 0) {
|
||||
*adrfam = SPDK_NVMF_ADRFAM_IB;
|
||||
} else if (strcasecmp(str, "FC") == 0) {
|
||||
*adrfam = SPDK_NVMF_ADRFAM_FC;
|
||||
} else {
|
||||
return -ENOENT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_nvme_transport_id_parse(struct spdk_nvme_transport_id *trid, const char *str)
|
||||
{
|
||||
const char *sep;
|
||||
const char *whitespace = " \t\n";
|
||||
size_t key_len, val_len;
|
||||
char key[32];
|
||||
char val[1024];
|
||||
|
||||
if (trid == NULL || str == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while (*str != '\0') {
|
||||
str += strspn(str, whitespace);
|
||||
|
||||
sep = strchr(str, ':');
|
||||
if (!sep) {
|
||||
SPDK_ERRLOG("Key without : separator\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
key_len = sep - str;
|
||||
if (key_len >= sizeof(key)) {
|
||||
SPDK_ERRLOG("Transport key length %zu greater than maximum allowed %zu\n",
|
||||
key_len, sizeof(key) - 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(key, str, key_len);
|
||||
key[key_len] = '\0';
|
||||
|
||||
str += key_len + 1; /* Skip key: */
|
||||
val_len = strcspn(str, whitespace);
|
||||
if (val_len == 0) {
|
||||
SPDK_ERRLOG("Key without value\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (val_len >= sizeof(val)) {
|
||||
SPDK_ERRLOG("Transport value length %zu greater than maximum allowed %zu\n",
|
||||
val_len, sizeof(val) - 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memcpy(val, str, val_len);
|
||||
val[val_len] = '\0';
|
||||
|
||||
str += val_len;
|
||||
|
||||
if (strcasecmp(key, "trtype") == 0) {
|
||||
if (parse_trtype(&trid->trtype, val) != 0) {
|
||||
SPDK_ERRLOG("Unknown trtype '%s'\n", val);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (strcasecmp(key, "adrfam") == 0) {
|
||||
if (parse_adrfam(&trid->adrfam, val) != 0) {
|
||||
SPDK_ERRLOG("Unknown adrfam '%s'\n", val);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (strcasecmp(key, "traddr") == 0) {
|
||||
if (val_len > SPDK_NVMF_TRADDR_MAX_LEN) {
|
||||
SPDK_ERRLOG("traddr length %zu greater than maximum allowed %u\n",
|
||||
val_len, SPDK_NVMF_TRADDR_MAX_LEN);
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(trid->traddr, val, val_len + 1);
|
||||
} else if (strcasecmp(key, "trsvcid") == 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(trid->trsvcid, val, val_len + 1);
|
||||
} else if (strcasecmp(key, "subnqn") == 0) {
|
||||
if (val_len > SPDK_NVMF_NQN_MAX_LEN) {
|
||||
SPDK_ERRLOG("subnqn length %zu greater than maximum allowed %u\n",
|
||||
val_len, SPDK_NVMF_NQN_MAX_LEN);
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(trid->subnqn, val, val_len + 1);
|
||||
} else {
|
||||
SPDK_ERRLOG("Unknown transport ID key '%s'\n", key);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPDK_LOG_REGISTER_TRACE_FLAG("nvme", SPDK_TRACE_NVME)
|
||||
|
@ -162,6 +162,30 @@ test_opc_data_transfer(void)
|
||||
CU_ASSERT(xfer == SPDK_NVME_DATA_CONTROLLER_TO_HOST);
|
||||
}
|
||||
|
||||
static void
|
||||
test_trid_parse(void)
|
||||
{
|
||||
struct spdk_nvme_transport_id trid;
|
||||
|
||||
memset(&trid, 0, sizeof(trid));
|
||||
CU_ASSERT(spdk_nvme_transport_id_parse(&trid,
|
||||
"trtype:rdma\n"
|
||||
"adrfam:ipv4\n"
|
||||
"traddr:192.168.100.8\n"
|
||||
"trsvcid:4420\n"
|
||||
"subnqn:nqn.2014-08.org.nvmexpress.discovery") == 0);
|
||||
CU_ASSERT(trid.trtype == SPDK_NVME_TRANSPORT_RDMA);
|
||||
CU_ASSERT(trid.adrfam == SPDK_NVMF_ADRFAM_IPV4);
|
||||
CU_ASSERT(strcmp(trid.traddr, "192.168.100.8") == 0);
|
||||
CU_ASSERT(strcmp(trid.trsvcid, "4420") == 0);
|
||||
CU_ASSERT(strcmp(trid.subnqn, "nqn.2014-08.org.nvmexpress.discovery") == 0);
|
||||
|
||||
memset(&trid, 0, sizeof(trid));
|
||||
CU_ASSERT(spdk_nvme_transport_id_parse(&trid, "trtype:PCIe traddr:0000:04:00.0") == 0);
|
||||
CU_ASSERT(trid.trtype == SPDK_NVME_TRANSPORT_PCIE);
|
||||
CU_ASSERT(strcmp(trid.traddr, "0000:04:00.0") == 0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
CU_pSuite suite = NULL;
|
||||
@ -178,7 +202,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (
|
||||
CU_add_test(suite, "test_opc_data_transfer", test_opc_data_transfer) == NULL
|
||||
CU_add_test(suite, "test_opc_data_transfer", test_opc_data_transfer) == NULL ||
|
||||
CU_add_test(suite, "test_trid_parse", test_trid_parse) == NULL
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
return CU_get_error();
|
||||
|
Loading…
x
Reference in New Issue
Block a user