assert(rc != 0);
}
+/* test: simple NVMe admin request/response */
+static int test_admin_id_cb(struct nvme_mi_ep *ep,
+ struct nvme_mi_req *req,
+ struct nvme_mi_resp *resp,
+ void *data)
+{
+ __u8 ror, mt, *hdr;
+ __u32 dlen, cdw10;
+ __u16 ctrl_id;
+ __u8 flags;
+
+ assert(req->hdr->type == NVME_MI_MSGTYPE_NVME);
+
+ ror = req->hdr->nmp >> 7;
+ mt = req->hdr->nmp >> 3 & 0x7;
+ assert(ror == NVME_MI_ROR_REQ);
+ assert(mt == NVME_MI_MT_ADMIN);
+
+ /* do we have enough for a mi header? */
+ assert(req->hdr_len == sizeof(struct nvme_mi_admin_req_hdr));
+
+ /* inspect response as raw bytes */
+ hdr = (__u8 *)req->hdr;
+ assert(hdr[4] == nvme_admin_identify);
+ flags = hdr[5];
+
+ ctrl_id = hdr[7] << 8 | hdr[6];
+ assert(ctrl_id == 0x5); /* controller id */
+
+ /* we requested a full id; if we've set the length flag,
+ * ensure the length matches */
+ dlen = hdr[35] << 24 | hdr[34] << 16 | hdr[33] << 8 | hdr[32];
+ if (flags & 0x1) {
+ assert(dlen == sizeof(struct nvme_id_ctrl));
+ }
+ assert(!(flags & 0x2));
+
+ /* CNS value of 1 in cdw10 field */
+ cdw10 = hdr[47] << 24 | hdr[46] << 16 | hdr[45] << 8 | hdr[44];
+ assert(cdw10 == 0x1);
+
+ /* create valid (but somewhat empty) response */
+ hdr = (__u8 *)resp->hdr;
+ memset(resp->hdr, 0, resp->hdr_len);
+ memset(resp->data, 0, resp->data_len);
+ hdr[4] = 0x00; /* status: success */
+
+ test_transport_resp_calc_mic(resp);
+
+ return 0;
+}
+
+static void test_admin_id(nvme_mi_ep_t ep)
+{
+ struct nvme_id_ctrl id;
+ nvme_mi_ctrl_t ctrl;
+ int rc;
+
+ test_set_transport_callback(ep, test_admin_id_cb, NULL);
+
+ ctrl = nvme_mi_init_ctrl(ep, 5);
+ assert(ctrl);
+
+ rc = nvme_mi_admin_identify_ctrl(ctrl, &id);
+ assert(rc == 0);
+}
+
#define DEFINE_TEST(name) { #name, test_ ## name }
struct test {
const char *name;
DEFINE_TEST(read_mi_data),
DEFINE_TEST(transport_fail),
DEFINE_TEST(invalid_crc),
+ DEFINE_TEST(admin_id),
};
static void print_log_buf(FILE *logfd)