diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
commit | 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch) | |
tree | e5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/spdk/test/unit/lib/vhost | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/spdk/test/unit/lib/vhost')
-rw-r--r-- | src/spdk/test/unit/lib/vhost/Makefile | 44 | ||||
-rw-r--r-- | src/spdk/test/unit/lib/vhost/test_vhost.c | 121 | ||||
-rw-r--r-- | src/spdk/test/unit/lib/vhost/vhost.c/.gitignore | 1 | ||||
-rw-r--r-- | src/spdk/test/unit/lib/vhost/vhost.c/Makefile | 42 | ||||
-rw-r--r-- | src/spdk/test/unit/lib/vhost/vhost.c/vhost_ut.c | 364 |
5 files changed, 572 insertions, 0 deletions
diff --git a/src/spdk/test/unit/lib/vhost/Makefile b/src/spdk/test/unit/lib/vhost/Makefile new file mode 100644 index 00000000..0f569f6d --- /dev/null +++ b/src/spdk/test/unit/lib/vhost/Makefile @@ -0,0 +1,44 @@ +# +# BSD LICENSE +# +# Copyright (c) Intel Corporation. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../..) +include $(SPDK_ROOT_DIR)/mk/spdk.common.mk + +DIRS-y = vhost.c + +.PHONY: all clean $(DIRS-y) + +all: $(DIRS-y) +clean: $(DIRS-y) + +include $(SPDK_ROOT_DIR)/mk/spdk.subdirs.mk diff --git a/src/spdk/test/unit/lib/vhost/test_vhost.c b/src/spdk/test/unit/lib/vhost/test_vhost.c new file mode 100644 index 00000000..437e1230 --- /dev/null +++ b/src/spdk/test/unit/lib/vhost/test_vhost.c @@ -0,0 +1,121 @@ +/*- + * BSD LICENSE + * + * Copyright(c) Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spdk/stdinc.h" + +#include "CUnit/Basic.h" +#include "spdk_cunit.h" +#include "spdk_internal/mock.h" +#include "spdk/thread.h" + +#include "unit/lib/json_mock.c" + +struct spdk_conf_section { + struct spdk_conf_section *next; + char *name; + int num; + struct spdk_conf_item *item; +}; + +DEFINE_STUB(spdk_vhost_vq_get_desc, int, (struct spdk_vhost_dev *vdev, + struct spdk_vhost_virtqueue *vq, uint16_t req_idx, struct vring_desc **desc, + struct vring_desc **desc_table, uint32_t *desc_table_size), 0); +DEFINE_STUB(spdk_vhost_vring_desc_is_wr, bool, (struct vring_desc *cur_desc), false); +DEFINE_STUB(spdk_vhost_vring_desc_to_iov, int, (struct spdk_vhost_dev *vdev, struct iovec *iov, + uint16_t *iov_index, const struct vring_desc *desc), 0); +DEFINE_STUB_V(spdk_vhost_vq_used_ring_enqueue, (struct spdk_vhost_dev *vdev, + struct spdk_vhost_virtqueue *vq, uint16_t id, uint32_t len)); +DEFINE_STUB(spdk_vhost_vring_desc_get_next, int, (struct vring_desc **desc, + struct vring_desc *desc_table, uint32_t desc_table_size), 0); +DEFINE_STUB(spdk_vhost_vq_avail_ring_get, uint16_t, (struct spdk_vhost_virtqueue *vq, + uint16_t *reqs, uint16_t reqs_len), 0); +DEFINE_STUB(spdk_vhost_vq_used_signal, int, (struct spdk_vhost_dev *vdev, + struct spdk_vhost_virtqueue *virtqueue), 0); +DEFINE_STUB_V(spdk_vhost_dev_used_signal, (struct spdk_vhost_dev *vdev)); +DEFINE_STUB_V(spdk_vhost_dev_mem_register, (struct spdk_vhost_dev *vdev)); +DEFINE_STUB_P(spdk_vhost_dev_find, struct spdk_vhost_dev, (const char *ctrlr_name), {0}); +DEFINE_STUB_P(spdk_conf_first_section, struct spdk_conf_section, (struct spdk_conf *cp), {0}); +DEFINE_STUB(spdk_conf_section_match_prefix, bool, (const struct spdk_conf_section *sp, + const char *name_prefix), false); +DEFINE_STUB_P(spdk_conf_next_section, struct spdk_conf_section, (struct spdk_conf_section *sp), {0}); +DEFINE_STUB_P(spdk_conf_section_get_name, const char, (const struct spdk_conf_section *sp), {0}); +DEFINE_STUB(spdk_conf_section_get_boolval, bool, (struct spdk_conf_section *sp, const char *key, + bool default_val), false); +DEFINE_STUB_P(spdk_conf_section_get_nmval, char, (struct spdk_conf_section *sp, const char *key, + int idx1, int idx2), {0}); +DEFINE_STUB_V(spdk_vhost_dev_mem_unregister, (struct spdk_vhost_dev *vdev)); +DEFINE_STUB(spdk_vhost_event_send, int, (struct spdk_vhost_dev *vdev, spdk_vhost_event_fn cb_fn, + void *arg, unsigned timeout_sec, const char *errmsg), 0); +DEFINE_STUB(spdk_env_get_socket_id, uint32_t, (uint32_t core), 0); +DEFINE_STUB_V(spdk_vhost_dev_backend_event_done, (void *event_ctx, int response)); +DEFINE_STUB_V(spdk_vhost_lock, (void)); +DEFINE_STUB_V(spdk_vhost_unlock, (void)); +DEFINE_STUB(spdk_env_get_current_core, uint32_t, (void), 0); +DEFINE_STUB_V(spdk_vhost_call_external_event, (const char *ctrlr_name, spdk_vhost_event_fn fn, + void *arg)); +DEFINE_STUB(spdk_vhost_vring_desc_has_next, bool, (struct vring_desc *cur_desc), false); +DEFINE_STUB_VP(spdk_vhost_gpa_to_vva, (struct spdk_vhost_dev *vdev, uint64_t addr, uint64_t len), +{0}); +DEFINE_STUB(spdk_scsi_dev_get_id, int, (const struct spdk_scsi_dev *dev), {0}); + +/* This sets spdk_vhost_dev_unregister to either to fail or success */ +DEFINE_STUB(spdk_vhost_dev_unregister_fail, bool, (void), false); +/* This sets spdk_vhost_dev_register to either to fail or success */ +DEFINE_STUB(spdk_vhost_dev_register_fail, bool, (void), false); + +static struct spdk_vhost_dev *g_spdk_vhost_device; +int +spdk_vhost_dev_register(struct spdk_vhost_dev *vdev, const char *name, const char *mask_str, + const struct spdk_vhost_dev_backend *backend) +{ + if (spdk_vhost_dev_register_fail()) { + return -1; + } + + vdev->backend = backend; + g_spdk_vhost_device = vdev; + vdev->registered = true; + return 0; +} + +int +spdk_vhost_dev_unregister(struct spdk_vhost_dev *vdev) +{ + if (spdk_vhost_dev_unregister_fail()) { + return -1; + } + + free(vdev->name); + g_spdk_vhost_device = NULL; + return 0; +} diff --git a/src/spdk/test/unit/lib/vhost/vhost.c/.gitignore b/src/spdk/test/unit/lib/vhost/vhost.c/.gitignore new file mode 100644 index 00000000..16cead8f --- /dev/null +++ b/src/spdk/test/unit/lib/vhost/vhost.c/.gitignore @@ -0,0 +1 @@ +vhost_ut diff --git a/src/spdk/test/unit/lib/vhost/vhost.c/Makefile b/src/spdk/test/unit/lib/vhost/vhost.c/Makefile new file mode 100644 index 00000000..3c30f5a8 --- /dev/null +++ b/src/spdk/test/unit/lib/vhost/vhost.c/Makefile @@ -0,0 +1,42 @@ +# +# BSD LICENSE +# +# Copyright (c) Intel Corporation. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../../../..) +include $(SPDK_ROOT_DIR)/mk/spdk.common.mk +include $(SPDK_ROOT_DIR)/mk/spdk.app.mk + +CFLAGS += -I$(SPDK_ROOT_DIR)/lib/vhost/rte_vhost +CFLAGS += $(ENV_CFLAGS) +TEST_FILE = vhost_ut.c + +include $(SPDK_ROOT_DIR)/mk/spdk.unittest.mk diff --git a/src/spdk/test/unit/lib/vhost/vhost.c/vhost_ut.c b/src/spdk/test/unit/lib/vhost/vhost.c/vhost_ut.c new file mode 100644 index 00000000..49e879ed --- /dev/null +++ b/src/spdk/test/unit/lib/vhost/vhost.c/vhost_ut.c @@ -0,0 +1,364 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spdk/stdinc.h" + +#include "CUnit/Basic.h" +#include "spdk_cunit.h" +#include "spdk/thread.h" +#include "spdk_internal/mock.h" +#include "common/lib/test_env.c" +#include "unit/lib/json_mock.c" + +#include "vhost/vhost.c" + +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); + +static struct spdk_cpuset *g_app_core_mask; +struct spdk_cpuset *spdk_app_get_core_mask(void) +{ + if (g_app_core_mask == NULL) { + g_app_core_mask = spdk_cpuset_alloc(); + spdk_cpuset_set_cpu(g_app_core_mask, 0, true); + } + return g_app_core_mask; +} + +int +spdk_app_parse_core_mask(const char *mask, struct spdk_cpuset *cpumask) +{ + int ret; + struct spdk_cpuset *validmask; + + ret = spdk_cpuset_parse(cpumask, mask); + if (ret < 0) { + return ret; + } + + validmask = spdk_app_get_core_mask(); + spdk_cpuset_and(cpumask, validmask); + + return 0; +} + +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_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, + (int vid, uint16_t vring_idx, struct rte_vhost_vring *vring), 0); +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_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) +{ + return cb(arg); +} + +static struct spdk_vhost_dev_backend g_vdev_backend; + +static int +test_setup(void) +{ + return 0; +} + +static int +alloc_vdev(struct spdk_vhost_dev **vdev_p, const char *name, const char *cpumask) +{ + struct spdk_vhost_dev *vdev = NULL; + int rc; + + /* spdk_vhost_dev must be allocated on a cache line boundary. */ + rc = posix_memalign((void **)&vdev, 64, sizeof(*vdev)); + CU_ASSERT(rc == 0); + SPDK_CU_ASSERT_FATAL(vdev != NULL); + memset(vdev, 0, sizeof(*vdev)); + rc = spdk_vhost_dev_register(vdev, name, cpumask, &g_vdev_backend); + if (rc == 0) { + *vdev_p = vdev; + } else { + free(vdev); + *vdev_p = NULL; + } + + return rc; +} + +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; +} + +static void +stop_vdev(struct spdk_vhost_dev *vdev) +{ + free(vdev->mem); + vdev->mem = NULL; + vdev->vid = -1; +} + +static void +cleanup_vdev(struct spdk_vhost_dev *vdev) +{ + stop_vdev(vdev); + spdk_vhost_dev_unregister(vdev); + free(vdev); +} + +static void +desc_to_iov_test(void) +{ + struct spdk_vhost_dev *vdev; + struct iovec iov[SPDK_VHOST_IOVS_MAX]; + uint16_t iov_index; + struct vring_desc desc; + int rc; + + rc = alloc_vdev(&vdev, "vdev_name_0", "0x1"); + SPDK_CU_ASSERT_FATAL(rc == 0 && vdev); + start_vdev(vdev); + + /* 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); + CU_ASSERT(rc == 0); + CU_ASSERT(iov_index == 1); + CU_ASSERT(iov[0].iov_base == (void *)0x1110000); + CU_ASSERT(iov[0].iov_len == 0x1000); + /* + * Always memset the iov to ensure each test validates data written by its call + * to the function under test. + */ + memset(iov, 0, sizeof(iov)); + + /* 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); + CU_ASSERT(rc == 0); + CU_ASSERT(iov_index == SPDK_VHOST_IOVS_MAX); + CU_ASSERT(iov[SPDK_VHOST_IOVS_MAX - 1].iov_base == (void *)0x1110000); + CU_ASSERT(iov[SPDK_VHOST_IOVS_MAX - 1].iov_len == 0x1000); + memset(iov, 0, sizeof(iov)); + + /* 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); + CU_ASSERT(rc != 0); + memset(iov, 0, sizeof(iov)); + + /* Test case where iov spans a 2MB boundary, but does not span a vhost memory region. */ + desc.addr = 0x1F0000; + desc.len = 0x20000; + iov_index = 0; + rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc); + CU_ASSERT(rc == 0); + CU_ASSERT(iov_index == 1); + CU_ASSERT(iov[0].iov_base == (void *)0x11F0000); + CU_ASSERT(iov[0].iov_len == 0x20000); + memset(iov, 0, sizeof(iov)); + + /* 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); + CU_ASSERT(rc == 0); + CU_ASSERT(iov_index == SPDK_VHOST_IOVS_MAX); + CU_ASSERT(iov[SPDK_VHOST_IOVS_MAX - 1].iov_base == (void *)0x11F0000); + CU_ASSERT(iov[SPDK_VHOST_IOVS_MAX - 1].iov_len == 0x20000); + memset(iov, 0, sizeof(iov)); + + /* Test case where iov spans a vhost memory region. */ + desc.addr = 0x3F0000; + desc.len = 0x20000; + iov_index = 0; + rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc); + CU_ASSERT(rc == 0); + CU_ASSERT(iov_index == 2); + CU_ASSERT(iov[0].iov_base == (void *)0x13F0000); + CU_ASSERT(iov[0].iov_len == 0x10000); + CU_ASSERT(iov[1].iov_base == (void *)0x2000000); + CU_ASSERT(iov[1].iov_len == 0x10000); + memset(iov, 0, sizeof(iov)); + + cleanup_vdev(vdev); + + CU_ASSERT(true); +} + +static void +create_controller_test(void) +{ + struct spdk_vhost_dev *vdev, *vdev2; + int ret; + char long_name[PATH_MAX]; + + /* NOTE: spdk_app_get_core_mask stub always sets coremask 0x01 */ + + /* Create device with no name */ + ret = alloc_vdev(&vdev, NULL, "0x1"); + CU_ASSERT(ret != 0); + + /* Create device with incorrect cpumask */ + ret = alloc_vdev(&vdev, "vdev_name_0", "0x2"); + CU_ASSERT(ret != 0); + + /* Create device with too long name and path */ + memset(long_name, 'x', sizeof(long_name)); + long_name[PATH_MAX - 1] = 0; + snprintf(dev_dirname, sizeof(dev_dirname), "some_path/"); + ret = alloc_vdev(&vdev, long_name, "0x1"); + CU_ASSERT(ret != 0); + dev_dirname[0] = 0; + + /* Create device when device name is already taken */ + ret = alloc_vdev(&vdev, "vdev_name_0", "0x1"); + SPDK_CU_ASSERT_FATAL(ret == 0 && vdev); + ret = alloc_vdev(&vdev2, "vdev_name_0", "0x1"); + CU_ASSERT(ret != 0); + cleanup_vdev(vdev); +} + +static void +dev_find_by_vid_test(void) +{ + struct spdk_vhost_dev *vdev, *tmp; + int rc; + + rc = alloc_vdev(&vdev, "vdev_name_0", "0x1"); + SPDK_CU_ASSERT_FATAL(rc == 0 && vdev); + + tmp = spdk_vhost_dev_find_by_vid(vdev->vid); + CU_ASSERT(tmp == vdev); + + /* Search for a device with incorrect vid */ + tmp = spdk_vhost_dev_find_by_vid(vdev->vid + 0xFF); + CU_ASSERT(tmp == NULL); + + cleanup_vdev(vdev); +} + +static void +remove_controller_test(void) +{ + struct spdk_vhost_dev *vdev; + int ret; + + ret = alloc_vdev(&vdev, "vdev_name_0", "0x1"); + SPDK_CU_ASSERT_FATAL(ret == 0 && vdev); + + /* Remove device when controller is in use */ + start_vdev(vdev); + ret = spdk_vhost_dev_unregister(vdev); + CU_ASSERT(ret != 0); + + cleanup_vdev(vdev); +} + +int +main(int argc, char **argv) +{ + CU_pSuite suite = NULL; + unsigned int num_failures; + + if (CU_initialize_registry() != CUE_SUCCESS) { + return CU_get_error(); + } + + suite = CU_add_suite("vhost_suite", test_setup, NULL); + if (suite == NULL) { + CU_cleanup_registry(); + return CU_get_error(); + } + + 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_cleanup_registry(); + return CU_get_error(); + } + + CU_basic_set_mode(CU_BRM_VERBOSE); + CU_basic_run_tests(); + num_failures = CU_get_number_of_failures(); + CU_cleanup_registry(); + + return num_failures; +} |