]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/spdk/test/unit/lib/vhost/vhost.c/vhost_ut.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / test / unit / lib / vhost / vhost.c / vhost_ut.c
index 49e879ed5136ce98445afd0937bb06e4b51489e4..ce040e61942717749828dca4c73c60e60e43d943 100644 (file)
 
 #include "vhost/vhost.c"
 
+DEFINE_STUB(rte_vhost_set_vring_base, int, (int vid, uint16_t queue_id,
+               uint16_t last_avail_idx, uint16_t last_used_idx), 0);
+DEFINE_STUB(rte_vhost_get_vring_base, int, (int vid, uint16_t queue_id,
+               uint16_t *last_avail_idx, uint16_t *last_used_idx), 0);
+DEFINE_STUB_V(spdk_vhost_session_install_rte_compat_hooks,
+             (struct spdk_vhost_session *vsession));
+DEFINE_STUB_V(spdk_vhost_dev_install_rte_compat_hooks,
+             (struct spdk_vhost_dev *vdev));
 DEFINE_STUB(rte_vhost_driver_unregister, int, (const char *path), 0);
 DEFINE_STUB(spdk_event_allocate, struct spdk_event *,
            (uint32_t lcore, spdk_event_fn fn, void *arg1, void *arg2), NULL);
 DEFINE_STUB(spdk_mem_register, int, (void *vaddr, size_t len), 0);
 DEFINE_STUB(spdk_mem_unregister, int, (void *vaddr, size_t len), 0);
+DEFINE_STUB(rte_vhost_vring_call, int, (int vid, uint16_t vring_idx), 0);
 
 static struct spdk_cpuset *g_app_core_mask;
 struct spdk_cpuset *spdk_app_get_core_mask(void)
@@ -77,13 +86,8 @@ spdk_app_parse_core_mask(const char *mask, struct spdk_cpuset *cpumask)
 
 DEFINE_STUB(spdk_env_get_first_core, uint32_t, (void), 0);
 DEFINE_STUB(spdk_env_get_next_core, uint32_t, (uint32_t prev_core), 0);
-DEFINE_STUB(spdk_env_get_last_core, uint32_t, (void), 0);
-DEFINE_STUB_V(spdk_app_stop, (int rc));
+DEFINE_STUB(spdk_env_get_current_core, uint32_t, (void), 0);
 DEFINE_STUB_V(spdk_event_call, (struct spdk_event *event));
-DEFINE_STUB(spdk_poller_register, struct spdk_poller *, (spdk_poller_fn fn, void *arg,
-               uint64_t period_microseconds), NULL);
-DEFINE_STUB_V(spdk_poller_unregister, (struct spdk_poller **ppoller));
-DEFINE_STUB(spdk_iommu_mem_unregister, int, (uint64_t addr, uint64_t len), 0);
 DEFINE_STUB(rte_vhost_get_mem_table, int, (int vid, struct rte_vhost_memory **mem), 0);
 DEFINE_STUB(rte_vhost_get_negotiated_features, int, (int vid, uint64_t *features), 0);
 DEFINE_STUB(rte_vhost_get_vhost_vring, int,
@@ -91,25 +95,16 @@ DEFINE_STUB(rte_vhost_get_vhost_vring, int,
 DEFINE_STUB(rte_vhost_enable_guest_notification, int,
            (int vid, uint16_t queue_id, int enable), 0);
 DEFINE_STUB(rte_vhost_get_ifname, int, (int vid, char *buf, size_t len), 0);
-DEFINE_STUB(rte_vhost_get_vring_num, uint16_t, (int vid), 0);
 DEFINE_STUB(rte_vhost_driver_start, int, (const char *name), 0);
 DEFINE_STUB(rte_vhost_driver_callback_register, int,
            (const char *path, struct vhost_device_ops const *const ops), 0);
 DEFINE_STUB(rte_vhost_driver_disable_features, int, (const char *path, uint64_t features), 0);
 DEFINE_STUB(rte_vhost_driver_set_features, int, (const char *path, uint64_t features), 0);
 DEFINE_STUB(rte_vhost_driver_register, int, (const char *path, uint64_t flags), 0);
-DEFINE_STUB_V(rte_vhost_log_used_vring, (int vid, uint16_t vring_idx, uint64_t offset,
-               uint64_t len));
-DEFINE_STUB_V(rte_vhost_log_write, (int vid, uint64_t addr, uint64_t len));
-DEFINE_STUB(spdk_vhost_scsi_controller_construct, int, (void), 0);
-DEFINE_STUB(spdk_vhost_blk_controller_construct, int, (void), 0);
 DEFINE_STUB(spdk_vhost_nvme_admin_passthrough, int, (int vid, void *cmd, void *cqe, void *buf), 0);
 DEFINE_STUB(spdk_vhost_nvme_set_cq_call, int, (int vid, uint16_t qid, int fd), 0);
+DEFINE_STUB(spdk_vhost_nvme_set_bar_mr, int, (int vid, void *bar, uint64_t bar_size), 0);
 DEFINE_STUB(spdk_vhost_nvme_get_cap, int, (int vid, uint64_t *cap), 0);
-DEFINE_STUB(spdk_vhost_nvme_controller_construct, int, (void), 0);
-DEFINE_STUB(rte_vhost_set_vhost_vring_last_idx, int,
-           (int vid, uint16_t vring_idx, uint16_t last_avail_idx, uint16_t last_used_idx), 0);
-DEFINE_STUB(spdk_env_get_current_core, uint32_t, (void), 0);
 
 void *
 spdk_call_unaffinitized(void *cb(void *arg), void *arg)
@@ -150,31 +145,48 @@ alloc_vdev(struct spdk_vhost_dev **vdev_p, const char *name, const char *cpumask
 static void
 start_vdev(struct spdk_vhost_dev *vdev)
 {
-       vdev->vid = 0;
-       vdev->lcore = 0;
-       vdev->mem = calloc(1, sizeof(*vdev->mem) + 2 * sizeof(struct rte_vhost_mem_region));
-       SPDK_CU_ASSERT_FATAL(vdev->mem != NULL);
-       vdev->mem->nregions = 2;
-       vdev->mem->regions[0].guest_phys_addr = 0;
-       vdev->mem->regions[0].size = 0x400000; /* 4 MB */
-       vdev->mem->regions[0].host_user_addr = 0x1000000;
-       vdev->mem->regions[1].guest_phys_addr = 0x400000;
-       vdev->mem->regions[1].size = 0x400000; /* 4 MB */
-       vdev->mem->regions[1].host_user_addr = 0x2000000;
+       struct rte_vhost_memory *mem;
+       struct spdk_vhost_session *vsession = NULL;
+       int rc;
+
+       mem = calloc(1, sizeof(*mem) + 2 * sizeof(struct rte_vhost_mem_region));
+       SPDK_CU_ASSERT_FATAL(mem != NULL);
+       mem->nregions = 2;
+       mem->regions[0].guest_phys_addr = 0;
+       mem->regions[0].size = 0x400000; /* 4 MB */
+       mem->regions[0].host_user_addr = 0x1000000;
+       mem->regions[1].guest_phys_addr = 0x400000;
+       mem->regions[1].size = 0x400000; /* 4 MB */
+       mem->regions[1].host_user_addr = 0x2000000;
+
+       assert(TAILQ_EMPTY(&vdev->vsessions));
+       /* spdk_vhost_dev must be allocated on a cache line boundary. */
+       rc = posix_memalign((void **)&vsession, 64, sizeof(*vsession));
+       CU_ASSERT(rc == 0);
+       SPDK_CU_ASSERT_FATAL(vsession != NULL);
+       vsession->lcore = 0;
+       vsession->started = true;
+       vsession->vid = 0;
+       vsession->mem = mem;
+       TAILQ_INSERT_TAIL(&vdev->vsessions, vsession, tailq);
 }
 
 static void
 stop_vdev(struct spdk_vhost_dev *vdev)
 {
-       free(vdev->mem);
-       vdev->mem = NULL;
-       vdev->vid = -1;
+       struct spdk_vhost_session *vsession = TAILQ_FIRST(&vdev->vsessions);
+
+       TAILQ_REMOVE(&vdev->vsessions, vsession, tailq);
+       free(vsession->mem);
+       free(vsession);
 }
 
 static void
 cleanup_vdev(struct spdk_vhost_dev *vdev)
 {
-       stop_vdev(vdev);
+       if (!TAILQ_EMPTY(&vdev->vsessions)) {
+               stop_vdev(vdev);
+       }
        spdk_vhost_dev_unregister(vdev);
        free(vdev);
 }
@@ -183,6 +195,7 @@ static void
 desc_to_iov_test(void)
 {
        struct spdk_vhost_dev *vdev;
+       struct spdk_vhost_session *vsession;
        struct iovec iov[SPDK_VHOST_IOVS_MAX];
        uint16_t iov_index;
        struct vring_desc desc;
@@ -192,11 +205,13 @@ desc_to_iov_test(void)
        SPDK_CU_ASSERT_FATAL(rc == 0 && vdev);
        start_vdev(vdev);
 
+       vsession = TAILQ_FIRST(&vdev->vsessions);
+
        /* Test simple case where iov falls fully within a 2MB page. */
        desc.addr = 0x110000;
        desc.len = 0x1000;
        iov_index = 0;
-       rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc);
+       rc = spdk_vhost_vring_desc_to_iov(vsession, iov, &iov_index, &desc);
        CU_ASSERT(rc == 0);
        CU_ASSERT(iov_index == 1);
        CU_ASSERT(iov[0].iov_base == (void *)0x1110000);
@@ -209,7 +224,7 @@ desc_to_iov_test(void)
 
        /* Same test, but ensure it respects the non-zero starting iov_index. */
        iov_index = SPDK_VHOST_IOVS_MAX - 1;
-       rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc);
+       rc = spdk_vhost_vring_desc_to_iov(vsession, iov, &iov_index, &desc);
        CU_ASSERT(rc == 0);
        CU_ASSERT(iov_index == SPDK_VHOST_IOVS_MAX);
        CU_ASSERT(iov[SPDK_VHOST_IOVS_MAX - 1].iov_base == (void *)0x1110000);
@@ -218,7 +233,7 @@ desc_to_iov_test(void)
 
        /* Test for failure if iov_index already equals SPDK_VHOST_IOVS_MAX. */
        iov_index = SPDK_VHOST_IOVS_MAX;
-       rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc);
+       rc = spdk_vhost_vring_desc_to_iov(vsession, iov, &iov_index, &desc);
        CU_ASSERT(rc != 0);
        memset(iov, 0, sizeof(iov));
 
@@ -226,7 +241,7 @@ desc_to_iov_test(void)
        desc.addr = 0x1F0000;
        desc.len = 0x20000;
        iov_index = 0;
-       rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc);
+       rc = spdk_vhost_vring_desc_to_iov(vsession, iov, &iov_index, &desc);
        CU_ASSERT(rc == 0);
        CU_ASSERT(iov_index == 1);
        CU_ASSERT(iov[0].iov_base == (void *)0x11F0000);
@@ -235,7 +250,7 @@ desc_to_iov_test(void)
 
        /* Same test, but ensure it respects the non-zero starting iov_index. */
        iov_index = SPDK_VHOST_IOVS_MAX - 1;
-       rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc);
+       rc = spdk_vhost_vring_desc_to_iov(vsession, iov, &iov_index, &desc);
        CU_ASSERT(rc == 0);
        CU_ASSERT(iov_index == SPDK_VHOST_IOVS_MAX);
        CU_ASSERT(iov[SPDK_VHOST_IOVS_MAX - 1].iov_base == (void *)0x11F0000);
@@ -246,7 +261,7 @@ desc_to_iov_test(void)
        desc.addr = 0x3F0000;
        desc.len = 0x20000;
        iov_index = 0;
-       rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc);
+       rc = spdk_vhost_vring_desc_to_iov(vsession, iov, &iov_index, &desc);
        CU_ASSERT(rc == 0);
        CU_ASSERT(iov_index == 2);
        CU_ASSERT(iov[0].iov_base == (void *)0x13F0000);
@@ -294,19 +309,24 @@ create_controller_test(void)
 }
 
 static void
-dev_find_by_vid_test(void)
+session_find_by_vid_test(void)
 {
-       struct spdk_vhost_dev *vdev, *tmp;
+       struct spdk_vhost_dev *vdev;
+       struct spdk_vhost_session *vsession;
+       struct spdk_vhost_session *tmp;
        int rc;
 
        rc = alloc_vdev(&vdev, "vdev_name_0", "0x1");
        SPDK_CU_ASSERT_FATAL(rc == 0 && vdev);
+       start_vdev(vdev);
+
+       vsession = TAILQ_FIRST(&vdev->vsessions);
 
-       tmp = spdk_vhost_dev_find_by_vid(vdev->vid);
-       CU_ASSERT(tmp == vdev);
+       tmp = spdk_vhost_session_find_by_vid(vsession->vid);
+       CU_ASSERT(tmp == vsession);
 
        /* Search for a device with incorrect vid */
-       tmp = spdk_vhost_dev_find_by_vid(vdev->vid + 0xFF);
+       tmp = spdk_vhost_session_find_by_vid(vsession->vid + 0xFF);
        CU_ASSERT(tmp == NULL);
 
        cleanup_vdev(vdev);
@@ -323,12 +343,72 @@ remove_controller_test(void)
 
        /* Remove device when controller is in use */
        start_vdev(vdev);
+       SPDK_CU_ASSERT_FATAL(!TAILQ_EMPTY(&vdev->vsessions));
        ret = spdk_vhost_dev_unregister(vdev);
        CU_ASSERT(ret != 0);
 
        cleanup_vdev(vdev);
 }
 
+static void
+vq_avail_ring_get_test(void)
+{
+       struct spdk_vhost_virtqueue vq;
+       uint16_t avail_mem[34];
+       uint16_t reqs[32];
+       uint16_t reqs_len, ret, i;
+
+       /* Basic example reap all requests */
+       vq.vring.avail = (struct vring_avail *)avail_mem;
+       vq.vring.size = 32;
+       vq.last_avail_idx = 24;
+       vq.vring.avail->idx = 29;
+       reqs_len = 6;
+
+       for (i = 0; i < 32; i++) {
+               vq.vring.avail->ring[i] = i;
+       }
+
+       ret = spdk_vhost_vq_avail_ring_get(&vq, reqs, reqs_len);
+       CU_ASSERT(ret == 5);
+       CU_ASSERT(vq.last_avail_idx == 29);
+       for (i = 0; i < ret; i++) {
+               CU_ASSERT(reqs[i] == vq.vring.avail->ring[i + 24]);
+       }
+
+       /* Basic example reap only some requests */
+       vq.last_avail_idx = 20;
+       vq.vring.avail->idx = 29;
+       reqs_len = 6;
+
+       ret = spdk_vhost_vq_avail_ring_get(&vq, reqs, reqs_len);
+       CU_ASSERT(ret == reqs_len);
+       CU_ASSERT(vq.last_avail_idx == 26);
+       for (i = 0; i < ret; i++) {
+               CU_ASSERT(reqs[i] == vq.vring.avail->ring[i + 20]);
+       }
+
+       /* Test invalid example */
+       vq.last_avail_idx = 20;
+       vq.vring.avail->idx = 156;
+       reqs_len = 6;
+
+       ret = spdk_vhost_vq_avail_ring_get(&vq, reqs, reqs_len);
+       CU_ASSERT(ret == 0);
+
+       /* Test overflow in the avail->idx variable. */
+       vq.last_avail_idx = 65535;
+       vq.vring.avail->idx = 4;
+       reqs_len = 6;
+       ret = spdk_vhost_vq_avail_ring_get(&vq, reqs, reqs_len);
+       CU_ASSERT(ret == 5);
+       CU_ASSERT(vq.last_avail_idx == 4);
+       CU_ASSERT(reqs[0] == vq.vring.avail->ring[31])
+       for (i = 1; i < ret; i++) {
+               CU_ASSERT(reqs[i] == vq.vring.avail->ring[i - 1]);
+       }
+}
+
 int
 main(int argc, char **argv)
 {
@@ -348,8 +428,9 @@ main(int argc, char **argv)
        if (
                CU_add_test(suite, "desc_to_iov", desc_to_iov_test) == NULL ||
                CU_add_test(suite, "create_controller", create_controller_test) == NULL ||
-               CU_add_test(suite, "dev_find_by_vid", dev_find_by_vid_test) == NULL ||
-               CU_add_test(suite, "remove_controller", remove_controller_test) == NULL
+               CU_add_test(suite, "session_find_by_vid", session_find_by_vid_test) == NULL ||
+               CU_add_test(suite, "remove_controller", remove_controller_test) == NULL ||
+               CU_add_test(suite, "vq_avail_ring_get", vq_avail_ring_get_test) == NULL
        ) {
                CU_cleanup_registry();
                return CU_get_error();