nvme_mi_admin_xfer;
nvme_mi_admin_security_send;
nvme_mi_admin_security_recv;
+ nvme_mi_endpoint_desc;
nvme_mi_open_mctp;
local:
*;
free(ep->transport_data);
}
+static int nvme_mi_mctp_desc_ep(struct nvme_mi_ep *ep, char *buf, size_t len)
+{
+ struct nvme_mi_transport_mctp *mctp;
+
+ if (ep->transport != &nvme_mi_transport_mctp)
+ return -1;
+
+ mctp = ep->transport_data;
+
+ snprintf(buf, len, "net %d eid %d", mctp->net, mctp->eid);
+
+ return 0;
+}
+
static const struct nvme_mi_transport nvme_mi_transport_mctp = {
.name = "mctp",
.mic_enabled = true,
.submit = nvme_mi_mctp_submit,
.close = nvme_mi_mctp_close,
+ .desc_ep = nvme_mi_mctp_desc_ep,
};
nvme_mi_ep_t nvme_mi_open_mctp(nvme_root_t root, unsigned int netid, __u8 eid)
#include <errno.h>
#include <stdlib.h>
#include <stdlib.h>
+#include <stdio.h>
#include <ccan/endian/endian.h>
{
free(ctrl);
}
+
+char *nvme_mi_endpoint_desc(nvme_mi_ep_t ep)
+{
+ char tsbuf[101], *s = NULL;
+ size_t tslen;
+ int rc;
+
+ rc = -1;
+ memset(tsbuf, 0, sizeof(tsbuf));
+ if (ep->transport->desc_ep)
+ rc = ep->transport->desc_ep(ep, tsbuf, sizeof(tsbuf) - 1);
+
+ if (!rc) {
+ /* don't overflow if the transport gives us an invalid string */
+ tsbuf[sizeof(tsbuf)-1] = '\0';
+ tslen = strlen(tsbuf);
+ } else {
+ tslen = 0;
+ }
+
+ if (tslen)
+ rc = asprintf(&s, "%s: %s", ep->transport->name, tsbuf);
+ else
+ rc = asprintf(&s, "%s endpoint", ep->transport->name);
+
+ if (rc < 0)
+ return NULL;
+
+ return s;
+}
*/
void nvme_mi_close_ctrl(nvme_mi_ctrl_t ctrl);
+/**
+ * nvme_mi_endpoint_desc - Get a string describing a MI endpoint.
+ * @ep: endpoint to describe
+ *
+ * Generates a human-readable string describing the endpoint, with possibly
+ * transport-specific data. The string is allocated during the call, and the
+ * caller is responsible for free()-ing the string.
+ *
+ * Return: a newly-allocated string containing the endpoint description, or
+ * NULL on failure.
+ */
+char *nvme_mi_endpoint_desc(nvme_mi_ep_t ep);
+
/* MI Command API: nvme_mi_mi_ prefix */
/**
struct nvme_mi_req *req,
struct nvme_mi_resp *resp);
void (*close)(struct nvme_mi_ep *ep);
+ int (*desc_ep)(struct nvme_mi_ep *ep, char *buf, size_t len);
};
struct nvme_mi_ep {
struct test_transport_data {
unsigned int magic;
+ bool named;
test_submit_cb submit_cb;
void *submit_cb_data;
};
free(tpd);
}
+static int test_transport_desc_ep(struct nvme_mi_ep *ep,
+ char *buf, size_t len)
+{
+ struct test_transport_data *tpd = ep->transport_data;
+
+ assert(tpd->magic == test_transport_magic);
+
+ if (!tpd->named)
+ return -1;
+
+ snprintf(buf, len, "test endpoint 0x%x", tpd->magic);
+
+ return 0;
+}
+
/* internal test helper to generate correct response crc */
static void test_transport_resp_calc_mic(struct nvme_mi_resp *resp)
{
.mic_enabled = true,
.submit = test_transport_submit,
.close = test_transport_close,
+ .desc_ep = test_transport_desc_ep,
};
static void test_set_transport_callback(nvme_mi_ep_t ep, test_submit_cb cb,
assert(tpd);
tpd->magic = test_transport_magic;
+ tpd->named = true;
ep->transport = &test_transport;
ep->transport_data = tpd;
assert(rc != 0);
}
+static void test_transport_describe(nvme_mi_ep_t ep)
+{
+ struct test_transport_data *tpd;
+ char *str;
+
+ tpd = (struct test_transport_data *)ep->transport_data;
+
+ tpd->named = false;
+ str = nvme_mi_endpoint_desc(ep);
+ assert(str);
+ assert(!strcmp(str, "test-mi endpoint"));
+ free(str);
+
+ tpd->named = true;
+ str = nvme_mi_endpoint_desc(ep);
+ assert(str);
+ assert(!strcmp(str, "test-mi: test endpoint 0x74657374"));
+ free(str);
+}
+
/* test: invalid crc */
static int test_invalid_crc_cb(struct nvme_mi_ep *ep,
struct nvme_mi_req *req,
} tests[] = {
DEFINE_TEST(read_mi_data),
DEFINE_TEST(transport_fail),
+ DEFINE_TEST(transport_describe),
DEFINE_TEST(invalid_crc),
DEFINE_TEST(admin_id),
DEFINE_TEST(admin_err_resp),