1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "CUnit/Basic.h" 37 #include "spdk_cunit.h" 38 #include "spdk/io_channel.h" 39 #include "spdk_internal/mock.h" 40 #include "lib/test_env.c" 41 42 #include "vhost.c" 43 44 DEFINE_STUB(rte_vhost_driver_unregister, int, (const char *path), 0); 45 DEFINE_STUB(spdk_event_allocate, struct spdk_event *, 46 (uint32_t lcore, spdk_event_fn fn, void *arg1, void *arg2), NULL); 47 DEFINE_STUB(spdk_mem_register, int, (void *vaddr, size_t len), 0); 48 DEFINE_STUB(spdk_mem_unregister, int, (void *vaddr, size_t len), 0); 49 DEFINE_STUB(spdk_app_get_core_mask, uint64_t, (void), 0); 50 DEFINE_STUB_V(spdk_app_stop, (int rc)); 51 DEFINE_STUB_V(spdk_event_call, (struct spdk_event *event)); 52 DEFINE_STUB(spdk_poller_register, struct spdk_poller *, (spdk_poller_fn fn, void *arg, 53 uint64_t period_microseconds), NULL); 54 DEFINE_STUB_V(spdk_poller_unregister, (struct spdk_poller **ppoller)); 55 DEFINE_STUB(spdk_iommu_mem_unregister, int, (uint64_t addr, uint64_t len), 0); 56 DEFINE_STUB(rte_vhost_get_mem_table, int, (int vid, struct rte_vhost_memory **mem), 0); 57 DEFINE_STUB(rte_vhost_get_negotiated_features, int, (int vid, uint64_t *features), 0); 58 DEFINE_STUB(rte_vhost_get_vhost_vring, int, 59 (int vid, uint16_t vring_idx, struct rte_vhost_vring *vring), 0); 60 DEFINE_STUB(rte_vhost_enable_guest_notification, int, 61 (int vid, uint16_t queue_id, int enable), 0); 62 DEFINE_STUB(rte_vhost_get_ifname, int, (int vid, char *buf, size_t len), 0); 63 DEFINE_STUB(rte_vhost_get_vring_num, uint16_t, (int vid), 0); 64 DEFINE_STUB(rte_vhost_driver_start, int, (const char *name), 0); 65 DEFINE_STUB(rte_vhost_driver_callback_register, int, 66 (const char *path, struct vhost_device_ops const *const ops), 0); 67 DEFINE_STUB(rte_vhost_driver_disable_features, int, (const char *path, uint64_t features), 0); 68 DEFINE_STUB(rte_vhost_driver_set_features, int, (const char *path, uint64_t features), 0); 69 DEFINE_STUB(rte_vhost_driver_register, int, (const char *path, uint64_t flags), 0); 70 DEFINE_STUB(spdk_vhost_scsi_controller_construct, int, (void), 0); 71 DEFINE_STUB(spdk_vhost_blk_controller_construct, int, (void), 0); 72 DEFINE_STUB(rte_vhost_set_vhost_vring_last_idx, int, 73 (int vid, uint16_t vring_idx, uint16_t last_avail_idx, uint16_t last_used_idx), 0); 74 DEFINE_STUB(spdk_env_get_current_core, uint32_t, (void), 0); 75 76 static int 77 test_setup(void) 78 { 79 return 0; 80 } 81 82 static struct spdk_vhost_dev * 83 alloc_vdev(void) 84 { 85 struct spdk_vhost_dev *vdev = NULL; 86 int rc; 87 88 /* spdk_vhost_dev must be allocated on a cache line boundary. */ 89 rc = posix_memalign((void **)&vdev, 64, sizeof(*vdev)); 90 CU_ASSERT(rc == 0); 91 SPDK_CU_ASSERT_FATAL(vdev != NULL); 92 memset(vdev, 0, sizeof(*vdev)); 93 94 vdev->mem = calloc(1, sizeof(*vdev->mem) + 2 * sizeof(struct rte_vhost_mem_region)); 95 SPDK_CU_ASSERT_FATAL(vdev->mem != NULL); 96 vdev->mem->nregions = 2; 97 vdev->mem->regions[0].guest_phys_addr = 0; 98 vdev->mem->regions[0].size = 0x400000; /* 4 MB */ 99 vdev->mem->regions[0].host_user_addr = 0x1000000; 100 vdev->mem->regions[1].guest_phys_addr = 0x400000; 101 vdev->mem->regions[1].size = 0x400000; /* 4 MB */ 102 vdev->mem->regions[1].host_user_addr = 0x2000000; 103 vdev->vid = 0x10; 104 105 return vdev; 106 } 107 108 static void 109 free_vdev(struct spdk_vhost_dev *vdev) 110 { 111 free(vdev->name); 112 free(vdev->mem); 113 free(vdev); 114 } 115 116 static void 117 desc_to_iov_test(void) 118 { 119 struct spdk_vhost_dev *vdev; 120 struct iovec iov[SPDK_VHOST_IOVS_MAX]; 121 uint16_t iov_index; 122 struct vring_desc desc; 123 int rc; 124 125 vdev = alloc_vdev(); 126 127 /* Test simple case where iov falls fully within a 2MB page. */ 128 desc.addr = 0x110000; 129 desc.len = 0x1000; 130 iov_index = 0; 131 rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc); 132 CU_ASSERT(rc == 0); 133 CU_ASSERT(iov_index == 1); 134 CU_ASSERT(iov[0].iov_base == (void *)0x1110000); 135 CU_ASSERT(iov[0].iov_len == 0x1000); 136 /* 137 * Always memset the iov to ensure each test validates data written by its call 138 * to the function under test. 139 */ 140 memset(iov, 0, sizeof(iov)); 141 142 /* Same test, but ensure it respects the non-zero starting iov_index. */ 143 iov_index = SPDK_VHOST_IOVS_MAX - 1; 144 rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc); 145 CU_ASSERT(rc == 0); 146 CU_ASSERT(iov_index == SPDK_VHOST_IOVS_MAX); 147 CU_ASSERT(iov[SPDK_VHOST_IOVS_MAX - 1].iov_base == (void *)0x1110000); 148 CU_ASSERT(iov[SPDK_VHOST_IOVS_MAX - 1].iov_len == 0x1000); 149 memset(iov, 0, sizeof(iov)); 150 151 /* Test for failure if iov_index already equals SPDK_VHOST_IOVS_MAX. */ 152 iov_index = SPDK_VHOST_IOVS_MAX; 153 rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc); 154 CU_ASSERT(rc != 0); 155 memset(iov, 0, sizeof(iov)); 156 157 /* Test case where iov spans a 2MB boundary, but does not span a vhost memory region. */ 158 desc.addr = 0x1F0000; 159 desc.len = 0x20000; 160 iov_index = 0; 161 rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc); 162 CU_ASSERT(rc == 0); 163 CU_ASSERT(iov_index == 2); 164 CU_ASSERT(iov[0].iov_base == (void *)0x11F0000); 165 CU_ASSERT(iov[0].iov_len == 0x10000); 166 CU_ASSERT(iov[1].iov_base == (void *)0x1200000); 167 CU_ASSERT(iov[1].iov_len == 0x10000); 168 memset(iov, 0, sizeof(iov)); 169 170 /* Same test, but ensure it respects the non-zero starting iov_index. */ 171 iov_index = SPDK_VHOST_IOVS_MAX - 2; 172 rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc); 173 CU_ASSERT(rc == 0); 174 CU_ASSERT(iov_index == SPDK_VHOST_IOVS_MAX); 175 CU_ASSERT(iov[SPDK_VHOST_IOVS_MAX - 2].iov_base == (void *)0x11F0000); 176 CU_ASSERT(iov[SPDK_VHOST_IOVS_MAX - 2].iov_len == 0x10000); 177 CU_ASSERT(iov[SPDK_VHOST_IOVS_MAX - 1].iov_base == (void *)0x1200000); 178 CU_ASSERT(iov[SPDK_VHOST_IOVS_MAX - 1].iov_len == 0x10000); 179 memset(iov, 0, sizeof(iov)); 180 181 /* 182 * This test should fail. The first part of the descriptor will fit in the last 183 * iov, but the part after the 2MB boundary would overflow. 184 */ 185 iov_index = SPDK_VHOST_IOVS_MAX - 1; 186 rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc); 187 CU_ASSERT(rc != 0); 188 memset(iov, 0, sizeof(iov)); 189 190 /* Test case where iov spans a vhost memory region. */ 191 desc.addr = 0x3F0000; 192 desc.len = 0x20000; 193 iov_index = 0; 194 rc = spdk_vhost_vring_desc_to_iov(vdev, iov, &iov_index, &desc); 195 CU_ASSERT(rc == 0); 196 CU_ASSERT(iov_index == 2); 197 CU_ASSERT(iov[0].iov_base == (void *)0x13F0000); 198 CU_ASSERT(iov[0].iov_len == 0x10000); 199 CU_ASSERT(iov[1].iov_base == (void *)0x2000000); 200 CU_ASSERT(iov[1].iov_len == 0x10000); 201 memset(iov, 0, sizeof(iov)); 202 203 free_vdev(vdev); 204 205 CU_ASSERT(true); 206 } 207 208 static void 209 create_controller_test(void) 210 { 211 struct spdk_vhost_dev *vdev; 212 int ret; 213 unsigned ctrlr_num; 214 char long_name[PATH_MAX]; 215 struct spdk_vhost_dev_backend backend; 216 217 MOCK_SET(spdk_app_get_core_mask, uint64_t, 1); 218 219 /* Create device with no name */ 220 vdev = alloc_vdev(); 221 ret = spdk_vhost_dev_construct(vdev, NULL, "0x1", SPDK_VHOST_DEV_T_BLK, &backend); 222 CU_ASSERT(ret != 0); 223 224 /* Create device with incorrect cpumask */ 225 ret = spdk_vhost_dev_construct(vdev, "vdev_name_0", "0x2", SPDK_VHOST_DEV_T_BLK, &backend); 226 CU_ASSERT(ret != 0); 227 228 /* Create device with too long name and path */ 229 memset(long_name, 'x', sizeof(long_name)); 230 long_name[PATH_MAX - 1] = 0; 231 snprintf(dev_dirname, sizeof(dev_dirname), "some_path/"); 232 ret = spdk_vhost_dev_construct(vdev, long_name, "0x1", SPDK_VHOST_DEV_T_BLK, &backend); 233 CU_ASSERT(ret != 0); 234 dev_dirname[0] = 0; 235 236 /* Create device when device name is already taken */ 237 vdev->name = strdup("vdev_name_0"); 238 g_spdk_vhost_devices[0] = vdev; 239 ret = spdk_vhost_dev_construct(vdev, "vdev_name_0", "0x1", SPDK_VHOST_DEV_T_BLK, &backend); 240 CU_ASSERT(ret != 0); 241 242 /* Create device when max number of devices is reached */ 243 for (ctrlr_num = 0; ctrlr_num < MAX_VHOST_DEVICES; ctrlr_num ++) { 244 g_spdk_vhost_devices[ctrlr_num] = vdev; 245 } 246 247 ret = spdk_vhost_dev_construct(vdev, "vdev_name_1", "0x1", SPDK_VHOST_DEV_T_BLK, &backend); 248 CU_ASSERT(ret != 0); 249 250 free_vdev(vdev); 251 for (ctrlr_num = 0; ctrlr_num < MAX_VHOST_DEVICES; ctrlr_num++) { 252 g_spdk_vhost_devices[ctrlr_num] = NULL; 253 } 254 } 255 256 static void 257 dev_find_by_vid_test(void) 258 { 259 struct spdk_vhost_dev *vdev; 260 261 g_spdk_vhost_devices[0] = alloc_vdev(); 262 vdev = spdk_vhost_dev_find_by_vid(0x10); 263 CU_ASSERT(vdev != NULL); 264 265 /* Search for a device with incorrect vid */ 266 vdev = spdk_vhost_dev_find_by_vid(0xFF); 267 CU_ASSERT(vdev == NULL); 268 269 free_vdev(g_spdk_vhost_devices[0]); 270 g_spdk_vhost_devices[0] = NULL; 271 } 272 273 static void 274 remove_controller_test(void) 275 { 276 struct spdk_vhost_dev *vdev; 277 char long_name[PATH_MAX]; 278 int ret; 279 280 vdev = alloc_vdev(); 281 vdev->lcore = 0; 282 vdev->name = strdup("vdev_name_0"); 283 284 /* Remove device when controller is in use */ 285 ret = spdk_vhost_dev_remove(vdev); 286 CU_ASSERT(ret != 0); 287 if (ret == 0) { 288 vdev->name = strdup("vdev_name_0"); 289 } 290 291 /* Remove nonexistent device */ 292 vdev->lcore = -1; 293 ret = spdk_vhost_dev_remove(vdev); 294 CU_ASSERT(ret != 0); 295 if (ret != 0) { 296 free(vdev->name); 297 } 298 299 /* Remove device with too long name and path */ 300 memset(long_name, 'x', sizeof(long_name)); 301 long_name[PATH_MAX - 1] = 0; 302 snprintf(dev_dirname, sizeof(dev_dirname), "some_path/"); 303 vdev->name = strdup(long_name); 304 g_spdk_vhost_devices[0] = vdev; 305 ret = spdk_vhost_dev_remove(vdev); 306 CU_ASSERT(ret != 0); 307 if (ret == 0) { 308 vdev->name = NULL; 309 } 310 311 free_vdev(vdev); 312 g_spdk_vhost_devices[0] = NULL; 313 dev_dirname[0] = 0; 314 } 315 316 int 317 main(int argc, char **argv) 318 { 319 CU_pSuite suite = NULL; 320 unsigned int num_failures; 321 322 if (CU_initialize_registry() != CUE_SUCCESS) { 323 return CU_get_error(); 324 } 325 326 suite = CU_add_suite("vhost_suite", test_setup, NULL); 327 if (suite == NULL) { 328 CU_cleanup_registry(); 329 return CU_get_error(); 330 } 331 332 if ( 333 CU_add_test(suite, "desc_to_iov", desc_to_iov_test) == NULL || 334 CU_add_test(suite, "create_controller", create_controller_test) == NULL || 335 CU_add_test(suite, "dev_find_by_vid", dev_find_by_vid_test) == NULL || 336 CU_add_test(suite, "remove_controller", remove_controller_test) == NULL 337 ) { 338 CU_cleanup_registry(); 339 return CU_get_error(); 340 } 341 342 CU_basic_set_mode(CU_BRM_VERBOSE); 343 CU_basic_run_tests(); 344 num_failures = CU_get_number_of_failures(); 345 CU_cleanup_registry(); 346 347 return num_failures; 348 } 349