#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)
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,
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)
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);
}
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;
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);
/* 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);
/* 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));
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);
/* 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);
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);
}
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);
/* 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)
{
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();