qapi: document DisplayType enum
[qemu/ericb.git] / tests / vhost-user-test.c
blobd961bd09d1ff735cc351a616e6e5752220af2809
1 /*
2 * QTest testcase for the vhost-user
4 * Copyright (c) 2014 Virtual Open Systems Sarl.
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
9 */
11 #include "qemu/osdep.h"
13 #include "libqtest.h"
14 #include "qapi/error.h"
15 #include "qapi/qmp/qdict.h"
16 #include "qemu/config-file.h"
17 #include "qemu/option.h"
18 #include "qemu/range.h"
19 #include "qemu/sockets.h"
20 #include "chardev/char-fe.h"
21 #include "qemu/memfd.h"
22 #include "sysemu/sysemu.h"
23 #include "libqos/libqos.h"
24 #include "libqos/pci-pc.h"
25 #include "libqos/virtio-pci.h"
27 #include "libqos/malloc-pc.h"
28 #include "hw/virtio/virtio-net.h"
30 #include <linux/vhost.h>
31 #include <linux/virtio_ids.h>
32 #include <linux/virtio_net.h>
33 #include <sys/vfs.h>
36 #define QEMU_CMD_MEM " -m %d -object memory-backend-file,id=mem,size=%dM," \
37 "mem-path=%s,share=on -numa node,memdev=mem"
38 #define QEMU_CMD_MEMFD " -m %d -object memory-backend-memfd,id=mem,size=%dM," \
39 " -numa node,memdev=mem"
40 #define QEMU_CMD_CHR " -chardev socket,id=%s,path=%s%s"
41 #define QEMU_CMD_NETDEV " -netdev vhost-user,id=net0,chardev=%s,vhostforce"
42 #define QEMU_CMD_NET " -device virtio-net-pci,netdev=net0"
44 #define HUGETLBFS_MAGIC 0x958458f6
46 /*********** FROM hw/virtio/vhost-user.c *************************************/
48 #define VHOST_MEMORY_MAX_NREGIONS 8
49 #define VHOST_MAX_VIRTQUEUES 0x100
51 #define VHOST_USER_F_PROTOCOL_FEATURES 30
52 #define VHOST_USER_PROTOCOL_F_MQ 0
53 #define VHOST_USER_PROTOCOL_F_LOG_SHMFD 1
54 #define VHOST_USER_PROTOCOL_F_CROSS_ENDIAN 6
56 #define VHOST_LOG_PAGE 0x1000
58 typedef enum VhostUserRequest {
59 VHOST_USER_NONE = 0,
60 VHOST_USER_GET_FEATURES = 1,
61 VHOST_USER_SET_FEATURES = 2,
62 VHOST_USER_SET_OWNER = 3,
63 VHOST_USER_RESET_OWNER = 4,
64 VHOST_USER_SET_MEM_TABLE = 5,
65 VHOST_USER_SET_LOG_BASE = 6,
66 VHOST_USER_SET_LOG_FD = 7,
67 VHOST_USER_SET_VRING_NUM = 8,
68 VHOST_USER_SET_VRING_ADDR = 9,
69 VHOST_USER_SET_VRING_BASE = 10,
70 VHOST_USER_GET_VRING_BASE = 11,
71 VHOST_USER_SET_VRING_KICK = 12,
72 VHOST_USER_SET_VRING_CALL = 13,
73 VHOST_USER_SET_VRING_ERR = 14,
74 VHOST_USER_GET_PROTOCOL_FEATURES = 15,
75 VHOST_USER_SET_PROTOCOL_FEATURES = 16,
76 VHOST_USER_GET_QUEUE_NUM = 17,
77 VHOST_USER_SET_VRING_ENABLE = 18,
78 VHOST_USER_MAX
79 } VhostUserRequest;
81 typedef struct VhostUserMemoryRegion {
82 uint64_t guest_phys_addr;
83 uint64_t memory_size;
84 uint64_t userspace_addr;
85 uint64_t mmap_offset;
86 } VhostUserMemoryRegion;
88 typedef struct VhostUserMemory {
89 uint32_t nregions;
90 uint32_t padding;
91 VhostUserMemoryRegion regions[VHOST_MEMORY_MAX_NREGIONS];
92 } VhostUserMemory;
94 typedef struct VhostUserLog {
95 uint64_t mmap_size;
96 uint64_t mmap_offset;
97 } VhostUserLog;
99 typedef struct VhostUserMsg {
100 VhostUserRequest request;
102 #define VHOST_USER_VERSION_MASK (0x3)
103 #define VHOST_USER_REPLY_MASK (0x1<<2)
104 uint32_t flags;
105 uint32_t size; /* the following payload size */
106 union {
107 #define VHOST_USER_VRING_IDX_MASK (0xff)
108 #define VHOST_USER_VRING_NOFD_MASK (0x1<<8)
109 uint64_t u64;
110 struct vhost_vring_state state;
111 struct vhost_vring_addr addr;
112 VhostUserMemory memory;
113 VhostUserLog log;
114 } payload;
115 } QEMU_PACKED VhostUserMsg;
117 static VhostUserMsg m __attribute__ ((unused));
118 #define VHOST_USER_HDR_SIZE (sizeof(m.request) \
119 + sizeof(m.flags) \
120 + sizeof(m.size))
122 #define VHOST_USER_PAYLOAD_SIZE (sizeof(m) - VHOST_USER_HDR_SIZE)
124 /* The version of the protocol we support */
125 #define VHOST_USER_VERSION (0x1)
126 /*****************************************************************************/
128 enum {
129 TEST_FLAGS_OK,
130 TEST_FLAGS_DISCONNECT,
131 TEST_FLAGS_BAD,
132 TEST_FLAGS_END,
135 typedef struct TestServer {
136 QPCIBus *bus;
137 QVirtioPCIDevice *dev;
138 QVirtQueue *vq[VHOST_MAX_VIRTQUEUES];
139 gchar *socket_path;
140 gchar *mig_path;
141 gchar *chr_name;
142 CharBackend chr;
143 int fds_num;
144 int fds[VHOST_MEMORY_MAX_NREGIONS];
145 VhostUserMemory memory;
146 GMutex data_mutex;
147 GCond data_cond;
148 int log_fd;
149 uint64_t rings;
150 bool test_fail;
151 int test_flags;
152 int queues;
153 QGuestAllocator *alloc;
154 } TestServer;
156 static TestServer *test_server_new(const gchar *name);
157 static void test_server_free(TestServer *server);
158 static void test_server_listen(TestServer *server);
160 static const char *tmpfs;
161 static const char *root;
163 enum test_memfd {
164 TEST_MEMFD_AUTO,
165 TEST_MEMFD_YES,
166 TEST_MEMFD_NO,
169 static char *get_qemu_cmd(TestServer *s,
170 int mem, enum test_memfd memfd, const char *mem_path,
171 const char *chr_opts, const char *extra)
173 if (memfd == TEST_MEMFD_AUTO && qemu_memfd_check(0)) {
174 memfd = TEST_MEMFD_YES;
177 if (memfd == TEST_MEMFD_YES) {
178 return g_strdup_printf(QEMU_CMD_MEMFD QEMU_CMD_CHR
179 QEMU_CMD_NETDEV QEMU_CMD_NET "%s", mem, mem,
180 s->chr_name, s->socket_path,
181 chr_opts, s->chr_name, extra);
182 } else {
183 return g_strdup_printf(QEMU_CMD_MEM QEMU_CMD_CHR
184 QEMU_CMD_NETDEV QEMU_CMD_NET "%s", mem, mem,
185 mem_path, s->chr_name, s->socket_path,
186 chr_opts, s->chr_name, extra);
190 static void init_virtio_dev(QTestState *qts, TestServer *s, uint32_t features_mask)
192 uint32_t features;
193 int i;
195 s->bus = qpci_init_pc(qts, NULL);
196 g_assert_nonnull(s->bus);
198 s->dev = qvirtio_pci_device_find(s->bus, VIRTIO_ID_NET);
199 g_assert_nonnull(s->dev);
201 qvirtio_pci_device_enable(s->dev);
202 qvirtio_reset(&s->dev->vdev);
203 qvirtio_set_acknowledge(&s->dev->vdev);
204 qvirtio_set_driver(&s->dev->vdev);
206 s->alloc = pc_alloc_init(qts);
208 for (i = 0; i < s->queues * 2; i++) {
209 s->vq[i] = qvirtqueue_setup(&s->dev->vdev, s->alloc, i);
212 features = qvirtio_get_features(&s->dev->vdev);
213 features = features & features_mask;
214 qvirtio_set_features(&s->dev->vdev, features);
216 qvirtio_set_driver_ok(&s->dev->vdev);
219 static void uninit_virtio_dev(TestServer *s)
221 int i;
223 for (i = 0; i < s->queues * 2; i++) {
224 qvirtqueue_cleanup(s->dev->vdev.bus, s->vq[i], s->alloc);
226 pc_alloc_uninit(s->alloc);
228 qvirtio_pci_device_free(s->dev);
231 static bool wait_for_fds(TestServer *s)
233 gint64 end_time;
234 bool got_region;
235 int i;
237 g_mutex_lock(&s->data_mutex);
239 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
240 while (!s->fds_num) {
241 if (!g_cond_wait_until(&s->data_cond, &s->data_mutex, end_time)) {
242 /* timeout has passed */
243 g_assert(s->fds_num);
244 break;
248 /* check for sanity */
249 g_assert_cmpint(s->fds_num, >, 0);
250 g_assert_cmpint(s->fds_num, ==, s->memory.nregions);
252 g_mutex_unlock(&s->data_mutex);
254 got_region = false;
255 for (i = 0; i < s->memory.nregions; ++i) {
256 VhostUserMemoryRegion *reg = &s->memory.regions[i];
257 if (reg->guest_phys_addr == 0) {
258 got_region = true;
259 break;
262 if (!got_region) {
263 g_test_skip("No memory at address 0x0");
265 return got_region;
268 static void read_guest_mem_server(QTestState *qts, TestServer *s)
270 uint8_t *guest_mem;
271 int i, j;
272 size_t size;
274 g_mutex_lock(&s->data_mutex);
276 /* iterate all regions */
277 for (i = 0; i < s->fds_num; i++) {
279 /* We'll check only the region statring at 0x0*/
280 if (s->memory.regions[i].guest_phys_addr != 0x0) {
281 continue;
284 g_assert_cmpint(s->memory.regions[i].memory_size, >, 1024);
286 size = s->memory.regions[i].memory_size +
287 s->memory.regions[i].mmap_offset;
289 guest_mem = mmap(0, size, PROT_READ | PROT_WRITE,
290 MAP_SHARED, s->fds[i], 0);
292 g_assert(guest_mem != MAP_FAILED);
293 guest_mem += (s->memory.regions[i].mmap_offset / sizeof(*guest_mem));
295 for (j = 0; j < 1024; j++) {
296 uint32_t a = qtest_readb(qts, s->memory.regions[i].guest_phys_addr + j);
297 uint32_t b = guest_mem[j];
299 g_assert_cmpint(a, ==, b);
302 munmap(guest_mem, s->memory.regions[i].memory_size);
305 g_mutex_unlock(&s->data_mutex);
308 static void *thread_function(void *data)
310 GMainLoop *loop = data;
311 g_main_loop_run(loop);
312 return NULL;
315 static int chr_can_read(void *opaque)
317 return VHOST_USER_HDR_SIZE;
320 static void chr_read(void *opaque, const uint8_t *buf, int size)
322 TestServer *s = opaque;
323 CharBackend *chr = &s->chr;
324 VhostUserMsg msg;
325 uint8_t *p = (uint8_t *) &msg;
326 int fd = -1;
328 if (s->test_fail) {
329 qemu_chr_fe_disconnect(chr);
330 /* now switch to non-failure */
331 s->test_fail = false;
334 if (size != VHOST_USER_HDR_SIZE) {
335 g_test_message("Wrong message size received %d\n", size);
336 return;
339 g_mutex_lock(&s->data_mutex);
340 memcpy(p, buf, VHOST_USER_HDR_SIZE);
342 if (msg.size) {
343 p += VHOST_USER_HDR_SIZE;
344 size = qemu_chr_fe_read_all(chr, p, msg.size);
345 if (size != msg.size) {
346 g_test_message("Wrong message size received %d != %d\n",
347 size, msg.size);
348 return;
352 switch (msg.request) {
353 case VHOST_USER_GET_FEATURES:
354 /* send back features to qemu */
355 msg.flags |= VHOST_USER_REPLY_MASK;
356 msg.size = sizeof(m.payload.u64);
357 msg.payload.u64 = 0x1ULL << VHOST_F_LOG_ALL |
358 0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES;
359 if (s->queues > 1) {
360 msg.payload.u64 |= 0x1ULL << VIRTIO_NET_F_MQ;
362 if (s->test_flags >= TEST_FLAGS_BAD) {
363 msg.payload.u64 = 0;
364 s->test_flags = TEST_FLAGS_END;
366 p = (uint8_t *) &msg;
367 qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
368 break;
370 case VHOST_USER_SET_FEATURES:
371 g_assert_cmpint(msg.payload.u64 & (0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES),
372 !=, 0ULL);
373 if (s->test_flags == TEST_FLAGS_DISCONNECT) {
374 qemu_chr_fe_disconnect(chr);
375 s->test_flags = TEST_FLAGS_BAD;
377 break;
379 case VHOST_USER_GET_PROTOCOL_FEATURES:
380 /* send back features to qemu */
381 msg.flags |= VHOST_USER_REPLY_MASK;
382 msg.size = sizeof(m.payload.u64);
383 msg.payload.u64 = 1 << VHOST_USER_PROTOCOL_F_LOG_SHMFD;
384 msg.payload.u64 |= 1 << VHOST_USER_PROTOCOL_F_CROSS_ENDIAN;
385 if (s->queues > 1) {
386 msg.payload.u64 |= 1 << VHOST_USER_PROTOCOL_F_MQ;
388 p = (uint8_t *) &msg;
389 qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
390 break;
392 case VHOST_USER_GET_VRING_BASE:
393 /* send back vring base to qemu */
394 msg.flags |= VHOST_USER_REPLY_MASK;
395 msg.size = sizeof(m.payload.state);
396 msg.payload.state.num = 0;
397 p = (uint8_t *) &msg;
398 qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
400 assert(msg.payload.state.index < s->queues * 2);
401 s->rings &= ~(0x1ULL << msg.payload.state.index);
402 g_cond_broadcast(&s->data_cond);
403 break;
405 case VHOST_USER_SET_MEM_TABLE:
406 /* received the mem table */
407 memcpy(&s->memory, &msg.payload.memory, sizeof(msg.payload.memory));
408 s->fds_num = qemu_chr_fe_get_msgfds(chr, s->fds,
409 G_N_ELEMENTS(s->fds));
411 /* signal the test that it can continue */
412 g_cond_broadcast(&s->data_cond);
413 break;
415 case VHOST_USER_SET_VRING_KICK:
416 case VHOST_USER_SET_VRING_CALL:
417 /* consume the fd */
418 qemu_chr_fe_get_msgfds(chr, &fd, 1);
420 * This is a non-blocking eventfd.
421 * The receive function forces it to be blocking,
422 * so revert it back to non-blocking.
424 qemu_set_nonblock(fd);
425 break;
427 case VHOST_USER_SET_LOG_BASE:
428 if (s->log_fd != -1) {
429 close(s->log_fd);
430 s->log_fd = -1;
432 qemu_chr_fe_get_msgfds(chr, &s->log_fd, 1);
433 msg.flags |= VHOST_USER_REPLY_MASK;
434 msg.size = 0;
435 p = (uint8_t *) &msg;
436 qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE);
438 g_cond_broadcast(&s->data_cond);
439 break;
441 case VHOST_USER_SET_VRING_BASE:
442 assert(msg.payload.state.index < s->queues * 2);
443 s->rings |= 0x1ULL << msg.payload.state.index;
444 g_cond_broadcast(&s->data_cond);
445 break;
447 case VHOST_USER_GET_QUEUE_NUM:
448 msg.flags |= VHOST_USER_REPLY_MASK;
449 msg.size = sizeof(m.payload.u64);
450 msg.payload.u64 = s->queues;
451 p = (uint8_t *) &msg;
452 qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
453 break;
455 default:
456 break;
459 g_mutex_unlock(&s->data_mutex);
462 static const char *init_hugepagefs(const char *path)
464 struct statfs fs;
465 int ret;
467 if (access(path, R_OK | W_OK | X_OK)) {
468 g_test_message("access on path (%s): %s\n", path, strerror(errno));
469 return NULL;
472 do {
473 ret = statfs(path, &fs);
474 } while (ret != 0 && errno == EINTR);
476 if (ret != 0) {
477 g_test_message("statfs on path (%s): %s\n", path, strerror(errno));
478 return NULL;
481 if (fs.f_type != HUGETLBFS_MAGIC) {
482 g_test_message("Warning: path not on HugeTLBFS: %s\n", path);
483 return NULL;
486 return path;
489 static TestServer *test_server_new(const gchar *name)
491 TestServer *server = g_new0(TestServer, 1);
493 server->socket_path = g_strdup_printf("%s/%s.sock", tmpfs, name);
494 server->mig_path = g_strdup_printf("%s/%s.mig", tmpfs, name);
495 server->chr_name = g_strdup_printf("chr-%s", name);
497 g_mutex_init(&server->data_mutex);
498 g_cond_init(&server->data_cond);
500 server->log_fd = -1;
501 server->queues = 1;
503 return server;
506 static void chr_event(void *opaque, int event)
508 TestServer *s = opaque;
510 if (s->test_flags == TEST_FLAGS_END &&
511 event == CHR_EVENT_CLOSED) {
512 s->test_flags = TEST_FLAGS_OK;
516 static void test_server_create_chr(TestServer *server, const gchar *opt)
518 gchar *chr_path;
519 Chardev *chr;
521 chr_path = g_strdup_printf("unix:%s%s", server->socket_path, opt);
522 chr = qemu_chr_new(server->chr_name, chr_path, NULL);
523 g_free(chr_path);
525 g_assert_nonnull(chr);
526 qemu_chr_fe_init(&server->chr, chr, &error_abort);
527 qemu_chr_fe_set_handlers(&server->chr, chr_can_read, chr_read,
528 chr_event, NULL, server, NULL, true);
531 static void test_server_listen(TestServer *server)
533 test_server_create_chr(server, ",server,nowait");
536 static gboolean _test_server_free(TestServer *server)
538 int i;
540 qemu_chr_fe_deinit(&server->chr, true);
542 for (i = 0; i < server->fds_num; i++) {
543 close(server->fds[i]);
546 if (server->log_fd != -1) {
547 close(server->log_fd);
550 unlink(server->socket_path);
551 g_free(server->socket_path);
553 unlink(server->mig_path);
554 g_free(server->mig_path);
556 g_free(server->chr_name);
557 g_assert(server->bus);
558 qpci_free_pc(server->bus);
560 g_free(server);
562 return FALSE;
565 static void test_server_free(TestServer *server)
567 g_idle_add((GSourceFunc)_test_server_free, server);
570 static void wait_for_log_fd(TestServer *s)
572 gint64 end_time;
574 g_mutex_lock(&s->data_mutex);
575 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
576 while (s->log_fd == -1) {
577 if (!g_cond_wait_until(&s->data_cond, &s->data_mutex, end_time)) {
578 /* timeout has passed */
579 g_assert(s->log_fd != -1);
580 break;
584 g_mutex_unlock(&s->data_mutex);
587 static void write_guest_mem(TestServer *s, uint32_t seed)
589 uint32_t *guest_mem;
590 int i, j;
591 size_t size;
593 /* iterate all regions */
594 for (i = 0; i < s->fds_num; i++) {
596 /* We'll write only the region statring at 0x0 */
597 if (s->memory.regions[i].guest_phys_addr != 0x0) {
598 continue;
601 g_assert_cmpint(s->memory.regions[i].memory_size, >, 1024);
603 size = s->memory.regions[i].memory_size +
604 s->memory.regions[i].mmap_offset;
606 guest_mem = mmap(0, size, PROT_READ | PROT_WRITE,
607 MAP_SHARED, s->fds[i], 0);
609 g_assert(guest_mem != MAP_FAILED);
610 guest_mem += (s->memory.regions[i].mmap_offset / sizeof(*guest_mem));
612 for (j = 0; j < 256; j++) {
613 guest_mem[j] = seed + j;
616 munmap(guest_mem, s->memory.regions[i].memory_size);
617 break;
621 static guint64 get_log_size(TestServer *s)
623 guint64 log_size = 0;
624 int i;
626 for (i = 0; i < s->memory.nregions; ++i) {
627 VhostUserMemoryRegion *reg = &s->memory.regions[i];
628 guint64 last = range_get_last(reg->guest_phys_addr,
629 reg->memory_size);
630 log_size = MAX(log_size, last / (8 * VHOST_LOG_PAGE) + 1);
633 return log_size;
636 typedef struct TestMigrateSource {
637 GSource source;
638 TestServer *src;
639 TestServer *dest;
640 } TestMigrateSource;
642 static gboolean
643 test_migrate_source_check(GSource *source)
645 TestMigrateSource *t = (TestMigrateSource *)source;
646 gboolean overlap = t->src->rings && t->dest->rings;
648 g_assert(!overlap);
650 return FALSE;
653 GSourceFuncs test_migrate_source_funcs = {
654 .check = test_migrate_source_check,
657 static void test_read_guest_mem(const void *arg)
659 enum test_memfd memfd = GPOINTER_TO_INT(arg);
660 TestServer *server = NULL;
661 char *qemu_cmd = NULL;
662 QTestState *s = NULL;
664 server = test_server_new(memfd == TEST_MEMFD_YES ?
665 "read-guest-memfd" : "read-guest-mem");
666 test_server_listen(server);
668 qemu_cmd = get_qemu_cmd(server, 512, memfd, root, "", "");
670 s = qtest_start(qemu_cmd);
671 g_free(qemu_cmd);
673 init_virtio_dev(global_qtest, server, 1u << VIRTIO_NET_F_MAC);
675 if (!wait_for_fds(server)) {
676 goto exit;
679 read_guest_mem_server(global_qtest, server);
681 exit:
682 uninit_virtio_dev(server);
684 qtest_quit(s);
685 test_server_free(server);
688 static void test_migrate(void)
690 TestServer *s = test_server_new("src");
691 TestServer *dest = test_server_new("dest");
692 char *uri = g_strdup_printf("%s%s", "unix:", dest->mig_path);
693 QTestState *from, *to;
694 GSource *source;
695 gchar *cmd, *tmp;
696 QDict *rsp;
697 guint8 *log;
698 guint64 size;
700 test_server_listen(s);
701 test_server_listen(dest);
703 cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, "", "");
704 from = qtest_start(cmd);
705 g_free(cmd);
707 init_virtio_dev(from, s, 1u << VIRTIO_NET_F_MAC);
708 if (!wait_for_fds(s)) {
709 goto exit;
712 size = get_log_size(s);
713 g_assert_cmpint(size, ==, (2 * 1024 * 1024) / (VHOST_LOG_PAGE * 8));
715 tmp = g_strdup_printf(" -incoming %s", uri);
716 cmd = get_qemu_cmd(dest, 2, TEST_MEMFD_AUTO, root, "", tmp);
717 g_free(tmp);
718 to = qtest_init(cmd);
719 g_free(cmd);
720 init_virtio_dev(to, dest, 1u << VIRTIO_NET_F_MAC);
722 source = g_source_new(&test_migrate_source_funcs,
723 sizeof(TestMigrateSource));
724 ((TestMigrateSource *)source)->src = s;
725 ((TestMigrateSource *)source)->dest = dest;
726 g_source_attach(source, NULL);
728 /* slow down migration to have time to fiddle with log */
729 /* TODO: qtest could learn to break on some places */
730 rsp = qmp("{ 'execute': 'migrate_set_speed',"
731 "'arguments': { 'value': 10 } }");
732 g_assert(qdict_haskey(rsp, "return"));
733 qobject_unref(rsp);
735 rsp = qmp("{ 'execute': 'migrate', 'arguments': { 'uri': %s } }", uri);
736 g_assert(qdict_haskey(rsp, "return"));
737 qobject_unref(rsp);
739 wait_for_log_fd(s);
741 log = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, s->log_fd, 0);
742 g_assert(log != MAP_FAILED);
744 /* modify first page */
745 write_guest_mem(s, 0x42);
746 log[0] = 1;
747 munmap(log, size);
749 /* speed things up */
750 rsp = qmp("{ 'execute': 'migrate_set_speed',"
751 "'arguments': { 'value': 0 } }");
752 g_assert(qdict_haskey(rsp, "return"));
753 qobject_unref(rsp);
755 qmp_eventwait("STOP");
756 qtest_qmp_eventwait(to, "RESUME");
758 g_assert(wait_for_fds(dest));
759 read_guest_mem_server(to, dest);
761 uninit_virtio_dev(dest);
762 qtest_quit(to);
764 g_source_destroy(source);
765 g_source_unref(source);
767 exit:
768 uninit_virtio_dev(s);
770 test_server_free(dest);
771 qtest_quit(from);
772 test_server_free(s);
773 g_free(uri);
776 static void wait_for_rings_started(TestServer *s, size_t count)
778 gint64 end_time;
780 g_mutex_lock(&s->data_mutex);
781 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
782 while (ctpop64(s->rings) != count) {
783 if (!g_cond_wait_until(&s->data_cond, &s->data_mutex, end_time)) {
784 /* timeout has passed */
785 g_assert_cmpint(ctpop64(s->rings), ==, count);
786 break;
790 g_mutex_unlock(&s->data_mutex);
793 static inline void test_server_connect(TestServer *server)
795 test_server_create_chr(server, ",reconnect=1");
798 static gboolean
799 reconnect_cb(gpointer user_data)
801 TestServer *s = user_data;
803 qemu_chr_fe_disconnect(&s->chr);
805 return FALSE;
808 static gpointer
809 connect_thread(gpointer data)
811 TestServer *s = data;
813 /* wait for qemu to start before first try, to avoid extra warnings */
814 g_usleep(G_USEC_PER_SEC);
815 test_server_connect(s);
817 return NULL;
820 static void test_reconnect_subprocess(void)
822 TestServer *s = test_server_new("reconnect");
823 char *cmd;
825 g_thread_new("connect", connect_thread, s);
826 cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, ",server", "");
827 qtest_start(cmd);
828 g_free(cmd);
830 init_virtio_dev(global_qtest, s, 1u << VIRTIO_NET_F_MAC);
831 if (!wait_for_fds(s)) {
832 goto exit;
835 wait_for_rings_started(s, 2);
837 /* reconnect */
838 s->fds_num = 0;
839 s->rings = 0;
840 g_idle_add(reconnect_cb, s);
841 g_assert(wait_for_fds(s));
842 wait_for_rings_started(s, 2);
844 exit:
845 uninit_virtio_dev(s);
847 qtest_end();
848 test_server_free(s);
849 return;
852 static void test_reconnect(void)
854 gchar *path = g_strdup_printf("/%s/vhost-user/reconnect/subprocess",
855 qtest_get_arch());
856 g_test_trap_subprocess(path, 0, 0);
857 g_test_trap_assert_passed();
858 g_free(path);
861 static void test_connect_fail_subprocess(void)
863 TestServer *s = test_server_new("connect-fail");
864 char *cmd;
866 s->test_fail = true;
867 g_thread_new("connect", connect_thread, s);
868 cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, ",server", "");
869 qtest_start(cmd);
870 g_free(cmd);
872 init_virtio_dev(global_qtest, s, 1u << VIRTIO_NET_F_MAC);
873 if (!wait_for_fds(s)) {
874 goto exit;
876 wait_for_rings_started(s, 2);
878 exit:
879 uninit_virtio_dev(s);
881 qtest_end();
882 test_server_free(s);
885 static void test_connect_fail(void)
887 gchar *path = g_strdup_printf("/%s/vhost-user/connect-fail/subprocess",
888 qtest_get_arch());
889 g_test_trap_subprocess(path, 0, 0);
890 g_test_trap_assert_passed();
891 g_free(path);
894 static void test_flags_mismatch_subprocess(void)
896 TestServer *s = test_server_new("flags-mismatch");
897 char *cmd;
899 s->test_flags = TEST_FLAGS_DISCONNECT;
900 g_thread_new("connect", connect_thread, s);
901 cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, ",server", "");
902 qtest_start(cmd);
903 g_free(cmd);
905 init_virtio_dev(global_qtest, s, 1u << VIRTIO_NET_F_MAC);
906 if (!wait_for_fds(s)) {
907 goto exit;
909 wait_for_rings_started(s, 2);
911 exit:
912 uninit_virtio_dev(s);
914 qtest_end();
915 test_server_free(s);
918 static void test_flags_mismatch(void)
920 gchar *path = g_strdup_printf("/%s/vhost-user/flags-mismatch/subprocess",
921 qtest_get_arch());
922 g_test_trap_subprocess(path, 0, 0);
923 g_test_trap_assert_passed();
924 g_free(path);
928 static void test_multiqueue(void)
930 TestServer *s = test_server_new("mq");
931 char *cmd;
932 uint32_t features_mask = ~(QVIRTIO_F_BAD_FEATURE |
933 (1u << VIRTIO_RING_F_INDIRECT_DESC) |
934 (1u << VIRTIO_RING_F_EVENT_IDX));
935 s->queues = 2;
936 test_server_listen(s);
938 if (qemu_memfd_check(0)) {
939 cmd = g_strdup_printf(
940 QEMU_CMD_MEMFD QEMU_CMD_CHR QEMU_CMD_NETDEV ",queues=%d "
941 "-device virtio-net-pci,netdev=net0,mq=on,vectors=%d",
942 512, 512, s->chr_name,
943 s->socket_path, "", s->chr_name,
944 s->queues, s->queues * 2 + 2);
945 } else {
946 cmd = g_strdup_printf(
947 QEMU_CMD_MEM QEMU_CMD_CHR QEMU_CMD_NETDEV ",queues=%d "
948 "-device virtio-net-pci,netdev=net0,mq=on,vectors=%d",
949 512, 512, root, s->chr_name,
950 s->socket_path, "", s->chr_name,
951 s->queues, s->queues * 2 + 2);
953 qtest_start(cmd);
954 g_free(cmd);
956 init_virtio_dev(global_qtest, s, features_mask);
958 wait_for_rings_started(s, s->queues * 2);
960 uninit_virtio_dev(s);
962 qtest_end();
964 test_server_free(s);
967 int main(int argc, char **argv)
969 const char *hugefs;
970 int ret;
971 char template[] = "/tmp/vhost-test-XXXXXX";
972 GMainLoop *loop;
973 GThread *thread;
975 g_test_init(&argc, &argv, NULL);
977 module_call_init(MODULE_INIT_QOM);
978 qemu_add_opts(&qemu_chardev_opts);
980 tmpfs = mkdtemp(template);
981 if (!tmpfs) {
982 g_test_message("mkdtemp on path (%s): %s\n", template, strerror(errno));
984 g_assert(tmpfs);
986 hugefs = getenv("QTEST_HUGETLBFS_PATH");
987 if (hugefs) {
988 root = init_hugepagefs(hugefs);
989 g_assert(root);
990 } else {
991 root = tmpfs;
994 loop = g_main_loop_new(NULL, FALSE);
995 /* run the main loop thread so the chardev may operate */
996 thread = g_thread_new(NULL, thread_function, loop);
998 if (qemu_memfd_check(0)) {
999 qtest_add_data_func("/vhost-user/read-guest-mem/memfd",
1000 GINT_TO_POINTER(TEST_MEMFD_YES),
1001 test_read_guest_mem);
1003 qtest_add_data_func("/vhost-user/read-guest-mem/memfile",
1004 GINT_TO_POINTER(TEST_MEMFD_NO), test_read_guest_mem);
1005 qtest_add_func("/vhost-user/migrate", test_migrate);
1006 qtest_add_func("/vhost-user/multiqueue", test_multiqueue);
1008 /* keeps failing on build-system since Aug 15 2017 */
1009 if (getenv("QTEST_VHOST_USER_FIXME")) {
1010 qtest_add_func("/vhost-user/reconnect/subprocess",
1011 test_reconnect_subprocess);
1012 qtest_add_func("/vhost-user/reconnect", test_reconnect);
1013 qtest_add_func("/vhost-user/connect-fail/subprocess",
1014 test_connect_fail_subprocess);
1015 qtest_add_func("/vhost-user/connect-fail", test_connect_fail);
1016 qtest_add_func("/vhost-user/flags-mismatch/subprocess",
1017 test_flags_mismatch_subprocess);
1018 qtest_add_func("/vhost-user/flags-mismatch", test_flags_mismatch);
1021 ret = g_test_run();
1023 /* cleanup */
1025 /* finish the helper thread and dispatch pending sources */
1026 g_main_loop_quit(loop);
1027 g_thread_join(thread);
1028 while (g_main_context_pending(NULL)) {
1029 g_main_context_iteration (NULL, TRUE);
1031 g_main_loop_unref(loop);
1033 ret = rmdir(tmpfs);
1034 if (ret != 0) {
1035 g_test_message("unable to rmdir: path (%s): %s\n",
1036 tmpfs, strerror(errno));
1038 g_assert_cmpint(ret, ==, 0);
1040 return ret;