1 /*
2  * QTest testcase for the vhost-user
3  *
4  * Copyright (c) 2014 Virtual Open Systems Sarl.
5  *
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.
8  *
9  */
10 
11 #include "qemu/osdep.h"
12 
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"
26 
27 #include "libqos/malloc-pc.h"
28 #include "hw/virtio/virtio-net.h"
29 
30 #include <linux/vhost.h>
31 #include <linux/virtio_ids.h>
32 #include <linux/virtio_net.h>
33 #include <sys/vfs.h>
34 
35 
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"
43 
44 #define HUGETLBFS_MAGIC       0x958458f6
45 
46 /*********** FROM hw/virtio/vhost-user.c *************************************/
47 
48 #define VHOST_MEMORY_MAX_NREGIONS    8
49 #define VHOST_MAX_VIRTQUEUES    0x100
50 
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 
55 #define VHOST_LOG_PAGE 0x1000
56 
57 typedef enum VhostUserRequest {
58     VHOST_USER_NONE = 0,
59     VHOST_USER_GET_FEATURES = 1,
60     VHOST_USER_SET_FEATURES = 2,
61     VHOST_USER_SET_OWNER = 3,
62     VHOST_USER_RESET_OWNER = 4,
63     VHOST_USER_SET_MEM_TABLE = 5,
64     VHOST_USER_SET_LOG_BASE = 6,
65     VHOST_USER_SET_LOG_FD = 7,
66     VHOST_USER_SET_VRING_NUM = 8,
67     VHOST_USER_SET_VRING_ADDR = 9,
68     VHOST_USER_SET_VRING_BASE = 10,
69     VHOST_USER_GET_VRING_BASE = 11,
70     VHOST_USER_SET_VRING_KICK = 12,
71     VHOST_USER_SET_VRING_CALL = 13,
72     VHOST_USER_SET_VRING_ERR = 14,
73     VHOST_USER_GET_PROTOCOL_FEATURES = 15,
74     VHOST_USER_SET_PROTOCOL_FEATURES = 16,
75     VHOST_USER_GET_QUEUE_NUM = 17,
76     VHOST_USER_SET_VRING_ENABLE = 18,
77     VHOST_USER_MAX
78 } VhostUserRequest;
79 
80 typedef struct VhostUserMemoryRegion {
81     uint64_t guest_phys_addr;
82     uint64_t memory_size;
83     uint64_t userspace_addr;
84     uint64_t mmap_offset;
85 } VhostUserMemoryRegion;
86 
87 typedef struct VhostUserMemory {
88     uint32_t nregions;
89     uint32_t padding;
90     VhostUserMemoryRegion regions[VHOST_MEMORY_MAX_NREGIONS];
91 } VhostUserMemory;
92 
93 typedef struct VhostUserLog {
94     uint64_t mmap_size;
95     uint64_t mmap_offset;
96 } VhostUserLog;
97 
98 typedef struct VhostUserMsg {
99     VhostUserRequest request;
100 
101 #define VHOST_USER_VERSION_MASK     (0x3)
102 #define VHOST_USER_REPLY_MASK       (0x1<<2)
103     uint32_t flags;
104     uint32_t size; /* the following payload size */
105     union {
106 #define VHOST_USER_VRING_IDX_MASK   (0xff)
107 #define VHOST_USER_VRING_NOFD_MASK  (0x1<<8)
108         uint64_t u64;
109         struct vhost_vring_state state;
110         struct vhost_vring_addr addr;
111         VhostUserMemory memory;
112         VhostUserLog log;
113     } payload;
114 } QEMU_PACKED VhostUserMsg;
115 
116 static VhostUserMsg m __attribute__ ((unused));
117 #define VHOST_USER_HDR_SIZE (sizeof(m.request) \
118                             + sizeof(m.flags) \
119                             + sizeof(m.size))
120 
121 #define VHOST_USER_PAYLOAD_SIZE (sizeof(m) - VHOST_USER_HDR_SIZE)
122 
123 /* The version of the protocol we support */
124 #define VHOST_USER_VERSION    (0x1)
125 /*****************************************************************************/
126 
127 enum {
128     TEST_FLAGS_OK,
129     TEST_FLAGS_DISCONNECT,
130     TEST_FLAGS_BAD,
131     TEST_FLAGS_END,
132 };
133 
134 typedef struct TestServer {
135     QPCIBus *bus;
136     QVirtioPCIDevice *dev;
137     QVirtQueue *vq[VHOST_MAX_VIRTQUEUES];
138     gchar *socket_path;
139     gchar *mig_path;
140     gchar *chr_name;
141     CharBackend chr;
142     int fds_num;
143     int fds[VHOST_MEMORY_MAX_NREGIONS];
144     VhostUserMemory memory;
145     GMutex data_mutex;
146     GCond data_cond;
147     int log_fd;
148     uint64_t rings;
149     bool test_fail;
150     int test_flags;
151     int queues;
152     QGuestAllocator *alloc;
153 } TestServer;
154 
155 static TestServer *test_server_new(const gchar *name);
156 static void test_server_free(TestServer *server);
157 static void test_server_listen(TestServer *server);
158 
159 static const char *tmpfs;
160 static const char *root;
161 
162 enum test_memfd {
163     TEST_MEMFD_AUTO,
164     TEST_MEMFD_YES,
165     TEST_MEMFD_NO,
166 };
167 
get_qemu_cmd(TestServer * s,int mem,enum test_memfd memfd,const char * mem_path,const char * chr_opts,const char * extra)168 static char *get_qemu_cmd(TestServer *s,
169                           int mem, enum test_memfd memfd, const char *mem_path,
170                           const char *chr_opts, const char *extra)
171 {
172     if (memfd == TEST_MEMFD_AUTO && qemu_memfd_check(0)) {
173         memfd = TEST_MEMFD_YES;
174     }
175 
176     if (memfd == TEST_MEMFD_YES) {
177         return g_strdup_printf(QEMU_CMD_MEMFD QEMU_CMD_CHR
178                                QEMU_CMD_NETDEV QEMU_CMD_NET "%s", mem, mem,
179                                s->chr_name, s->socket_path,
180                                chr_opts, s->chr_name, extra);
181     } else {
182         return g_strdup_printf(QEMU_CMD_MEM QEMU_CMD_CHR
183                                QEMU_CMD_NETDEV QEMU_CMD_NET "%s", mem, mem,
184                                mem_path, s->chr_name, s->socket_path,
185                                chr_opts, s->chr_name, extra);
186     }
187 }
188 
init_virtio_dev(TestServer * s,uint32_t features_mask)189 static void init_virtio_dev(TestServer *s, uint32_t features_mask)
190 {
191     uint32_t features;
192     int i;
193 
194     s->bus = qpci_init_pc(global_qtest, NULL);
195     g_assert_nonnull(s->bus);
196 
197     s->dev = qvirtio_pci_device_find(s->bus, VIRTIO_ID_NET);
198     g_assert_nonnull(s->dev);
199 
200     qvirtio_pci_device_enable(s->dev);
201     qvirtio_reset(&s->dev->vdev);
202     qvirtio_set_acknowledge(&s->dev->vdev);
203     qvirtio_set_driver(&s->dev->vdev);
204 
205     s->alloc = pc_alloc_init(global_qtest);
206 
207     for (i = 0; i < s->queues * 2; i++) {
208         s->vq[i] = qvirtqueue_setup(&s->dev->vdev, s->alloc, i);
209     }
210 
211     features = qvirtio_get_features(&s->dev->vdev);
212     features = features & features_mask;
213     qvirtio_set_features(&s->dev->vdev, features);
214 
215     qvirtio_set_driver_ok(&s->dev->vdev);
216 }
217 
uninit_virtio_dev(TestServer * s)218 static void uninit_virtio_dev(TestServer *s)
219 {
220     int i;
221 
222     for (i = 0; i < s->queues * 2; i++) {
223         qvirtqueue_cleanup(s->dev->vdev.bus, s->vq[i], s->alloc);
224     }
225     pc_alloc_uninit(s->alloc);
226 
227     qvirtio_pci_device_free(s->dev);
228 }
229 
wait_for_fds(TestServer * s)230 static void wait_for_fds(TestServer *s)
231 {
232     gint64 end_time;
233 
234     g_mutex_lock(&s->data_mutex);
235 
236     end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
237     while (!s->fds_num) {
238         if (!g_cond_wait_until(&s->data_cond, &s->data_mutex, end_time)) {
239             /* timeout has passed */
240             g_assert(s->fds_num);
241             break;
242         }
243     }
244 
245     /* check for sanity */
246     g_assert_cmpint(s->fds_num, >, 0);
247     g_assert_cmpint(s->fds_num, ==, s->memory.nregions);
248 
249     g_mutex_unlock(&s->data_mutex);
250 }
251 
read_guest_mem_server(TestServer * s)252 static void read_guest_mem_server(TestServer *s)
253 {
254     uint32_t *guest_mem;
255     int i, j;
256     size_t size;
257 
258     wait_for_fds(s);
259 
260     g_mutex_lock(&s->data_mutex);
261 
262     /* iterate all regions */
263     for (i = 0; i < s->fds_num; i++) {
264 
265         /* We'll check only the region statring at 0x0*/
266         if (s->memory.regions[i].guest_phys_addr != 0x0) {
267             continue;
268         }
269 
270         g_assert_cmpint(s->memory.regions[i].memory_size, >, 1024);
271 
272         size = s->memory.regions[i].memory_size +
273             s->memory.regions[i].mmap_offset;
274 
275         guest_mem = mmap(0, size, PROT_READ | PROT_WRITE,
276                          MAP_SHARED, s->fds[i], 0);
277 
278         g_assert(guest_mem != MAP_FAILED);
279         guest_mem += (s->memory.regions[i].mmap_offset / sizeof(*guest_mem));
280 
281         for (j = 0; j < 256; j++) {
282             uint32_t a = readl(s->memory.regions[i].guest_phys_addr + j*4);
283             uint32_t b = guest_mem[j];
284 
285             g_assert_cmpint(a, ==, b);
286         }
287 
288         munmap(guest_mem, s->memory.regions[i].memory_size);
289     }
290 
291     g_mutex_unlock(&s->data_mutex);
292 }
293 
thread_function(void * data)294 static void *thread_function(void *data)
295 {
296     GMainLoop *loop = data;
297     g_main_loop_run(loop);
298     return NULL;
299 }
300 
chr_can_read(void * opaque)301 static int chr_can_read(void *opaque)
302 {
303     return VHOST_USER_HDR_SIZE;
304 }
305 
chr_read(void * opaque,const uint8_t * buf,int size)306 static void chr_read(void *opaque, const uint8_t *buf, int size)
307 {
308     TestServer *s = opaque;
309     CharBackend *chr = &s->chr;
310     VhostUserMsg msg;
311     uint8_t *p = (uint8_t *) &msg;
312     int fd;
313 
314     if (s->test_fail) {
315         qemu_chr_fe_disconnect(chr);
316         /* now switch to non-failure */
317         s->test_fail = false;
318     }
319 
320     if (size != VHOST_USER_HDR_SIZE) {
321         g_test_message("Wrong message size received %d\n", size);
322         return;
323     }
324 
325     g_mutex_lock(&s->data_mutex);
326     memcpy(p, buf, VHOST_USER_HDR_SIZE);
327 
328     if (msg.size) {
329         p += VHOST_USER_HDR_SIZE;
330         size = qemu_chr_fe_read_all(chr, p, msg.size);
331         if (size != msg.size) {
332             g_test_message("Wrong message size received %d != %d\n",
333                            size, msg.size);
334             return;
335         }
336     }
337 
338     switch (msg.request) {
339     case VHOST_USER_GET_FEATURES:
340         /* send back features to qemu */
341         msg.flags |= VHOST_USER_REPLY_MASK;
342         msg.size = sizeof(m.payload.u64);
343         msg.payload.u64 = 0x1ULL << VHOST_F_LOG_ALL |
344             0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES;
345         if (s->queues > 1) {
346             msg.payload.u64 |= 0x1ULL << VIRTIO_NET_F_MQ;
347         }
348         if (s->test_flags >= TEST_FLAGS_BAD) {
349             msg.payload.u64 = 0;
350             s->test_flags = TEST_FLAGS_END;
351         }
352         p = (uint8_t *) &msg;
353         qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
354         break;
355 
356     case VHOST_USER_SET_FEATURES:
357 	g_assert_cmpint(msg.payload.u64 & (0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES),
358 			!=, 0ULL);
359         if (s->test_flags == TEST_FLAGS_DISCONNECT) {
360             qemu_chr_fe_disconnect(chr);
361             s->test_flags = TEST_FLAGS_BAD;
362         }
363         break;
364 
365     case VHOST_USER_GET_PROTOCOL_FEATURES:
366         /* send back features to qemu */
367         msg.flags |= VHOST_USER_REPLY_MASK;
368         msg.size = sizeof(m.payload.u64);
369         msg.payload.u64 = 1 << VHOST_USER_PROTOCOL_F_LOG_SHMFD;
370         if (s->queues > 1) {
371             msg.payload.u64 |= 1 << VHOST_USER_PROTOCOL_F_MQ;
372         }
373         p = (uint8_t *) &msg;
374         qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
375         break;
376 
377     case VHOST_USER_GET_VRING_BASE:
378         /* send back vring base to qemu */
379         msg.flags |= VHOST_USER_REPLY_MASK;
380         msg.size = sizeof(m.payload.state);
381         msg.payload.state.num = 0;
382         p = (uint8_t *) &msg;
383         qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
384 
385         assert(msg.payload.state.index < s->queues * 2);
386         s->rings &= ~(0x1ULL << msg.payload.state.index);
387         break;
388 
389     case VHOST_USER_SET_MEM_TABLE:
390         /* received the mem table */
391         memcpy(&s->memory, &msg.payload.memory, sizeof(msg.payload.memory));
392         s->fds_num = qemu_chr_fe_get_msgfds(chr, s->fds,
393                                             G_N_ELEMENTS(s->fds));
394 
395         /* signal the test that it can continue */
396         g_cond_signal(&s->data_cond);
397         break;
398 
399     case VHOST_USER_SET_VRING_KICK:
400     case VHOST_USER_SET_VRING_CALL:
401         /* consume the fd */
402         qemu_chr_fe_get_msgfds(chr, &fd, 1);
403         /*
404          * This is a non-blocking eventfd.
405          * The receive function forces it to be blocking,
406          * so revert it back to non-blocking.
407          */
408         qemu_set_nonblock(fd);
409         break;
410 
411     case VHOST_USER_SET_LOG_BASE:
412         if (s->log_fd != -1) {
413             close(s->log_fd);
414             s->log_fd = -1;
415         }
416         qemu_chr_fe_get_msgfds(chr, &s->log_fd, 1);
417         msg.flags |= VHOST_USER_REPLY_MASK;
418         msg.size = 0;
419         p = (uint8_t *) &msg;
420         qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE);
421 
422         g_cond_signal(&s->data_cond);
423         break;
424 
425     case VHOST_USER_SET_VRING_BASE:
426         assert(msg.payload.state.index < s->queues * 2);
427         s->rings |= 0x1ULL << msg.payload.state.index;
428         break;
429 
430     case VHOST_USER_GET_QUEUE_NUM:
431         msg.flags |= VHOST_USER_REPLY_MASK;
432         msg.size = sizeof(m.payload.u64);
433         msg.payload.u64 = s->queues;
434         p = (uint8_t *) &msg;
435         qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size);
436         break;
437 
438     default:
439         break;
440     }
441 
442     g_mutex_unlock(&s->data_mutex);
443 }
444 
init_hugepagefs(const char * path)445 static const char *init_hugepagefs(const char *path)
446 {
447     struct statfs fs;
448     int ret;
449 
450     if (access(path, R_OK | W_OK | X_OK)) {
451         g_test_message("access on path (%s): %s\n", path, strerror(errno));
452         return NULL;
453     }
454 
455     do {
456         ret = statfs(path, &fs);
457     } while (ret != 0 && errno == EINTR);
458 
459     if (ret != 0) {
460         g_test_message("statfs on path (%s): %s\n", path, strerror(errno));
461         return NULL;
462     }
463 
464     if (fs.f_type != HUGETLBFS_MAGIC) {
465         g_test_message("Warning: path not on HugeTLBFS: %s\n", path);
466         return NULL;
467     }
468 
469     return path;
470 }
471 
test_server_new(const gchar * name)472 static TestServer *test_server_new(const gchar *name)
473 {
474     TestServer *server = g_new0(TestServer, 1);
475 
476     server->socket_path = g_strdup_printf("%s/%s.sock", tmpfs, name);
477     server->mig_path = g_strdup_printf("%s/%s.mig", tmpfs, name);
478     server->chr_name = g_strdup_printf("chr-%s", name);
479 
480     g_mutex_init(&server->data_mutex);
481     g_cond_init(&server->data_cond);
482 
483     server->log_fd = -1;
484     server->queues = 1;
485 
486     return server;
487 }
488 
chr_event(void * opaque,int event)489 static void chr_event(void *opaque, int event)
490 {
491     TestServer *s = opaque;
492 
493     if (s->test_flags == TEST_FLAGS_END &&
494         event == CHR_EVENT_CLOSED) {
495         s->test_flags = TEST_FLAGS_OK;
496     }
497 }
498 
test_server_create_chr(TestServer * server,const gchar * opt)499 static void test_server_create_chr(TestServer *server, const gchar *opt)
500 {
501     gchar *chr_path;
502     Chardev *chr;
503 
504     chr_path = g_strdup_printf("unix:%s%s", server->socket_path, opt);
505     chr = qemu_chr_new(server->chr_name, chr_path);
506     g_free(chr_path);
507 
508     g_assert_nonnull(chr);
509     qemu_chr_fe_init(&server->chr, chr, &error_abort);
510     qemu_chr_fe_set_handlers(&server->chr, chr_can_read, chr_read,
511                              chr_event, NULL, server, NULL, true);
512 }
513 
test_server_listen(TestServer * server)514 static void test_server_listen(TestServer *server)
515 {
516     test_server_create_chr(server, ",server,nowait");
517 }
518 
_test_server_free(TestServer * server)519 static gboolean _test_server_free(TestServer *server)
520 {
521     int i;
522 
523     qemu_chr_fe_deinit(&server->chr, true);
524 
525     for (i = 0; i < server->fds_num; i++) {
526         close(server->fds[i]);
527     }
528 
529     if (server->log_fd != -1) {
530         close(server->log_fd);
531     }
532 
533     unlink(server->socket_path);
534     g_free(server->socket_path);
535 
536     unlink(server->mig_path);
537     g_free(server->mig_path);
538 
539     g_free(server->chr_name);
540     g_assert(server->bus);
541     qpci_free_pc(server->bus);
542 
543     g_free(server);
544 
545     return FALSE;
546 }
547 
test_server_free(TestServer * server)548 static void test_server_free(TestServer *server)
549 {
550     g_idle_add((GSourceFunc)_test_server_free, server);
551 }
552 
wait_for_log_fd(TestServer * s)553 static void wait_for_log_fd(TestServer *s)
554 {
555     gint64 end_time;
556 
557     g_mutex_lock(&s->data_mutex);
558     end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
559     while (s->log_fd == -1) {
560         if (!g_cond_wait_until(&s->data_cond, &s->data_mutex, end_time)) {
561             /* timeout has passed */
562             g_assert(s->log_fd != -1);
563             break;
564         }
565     }
566 
567     g_mutex_unlock(&s->data_mutex);
568 }
569 
write_guest_mem(TestServer * s,uint32_t seed)570 static void write_guest_mem(TestServer *s, uint32_t seed)
571 {
572     uint32_t *guest_mem;
573     int i, j;
574     size_t size;
575 
576     wait_for_fds(s);
577 
578     /* iterate all regions */
579     for (i = 0; i < s->fds_num; i++) {
580 
581         /* We'll write only the region statring at 0x0 */
582         if (s->memory.regions[i].guest_phys_addr != 0x0) {
583             continue;
584         }
585 
586         g_assert_cmpint(s->memory.regions[i].memory_size, >, 1024);
587 
588         size = s->memory.regions[i].memory_size +
589             s->memory.regions[i].mmap_offset;
590 
591         guest_mem = mmap(0, size, PROT_READ | PROT_WRITE,
592                          MAP_SHARED, s->fds[i], 0);
593 
594         g_assert(guest_mem != MAP_FAILED);
595         guest_mem += (s->memory.regions[i].mmap_offset / sizeof(*guest_mem));
596 
597         for (j = 0; j < 256; j++) {
598             guest_mem[j] = seed + j;
599         }
600 
601         munmap(guest_mem, s->memory.regions[i].memory_size);
602         break;
603     }
604 }
605 
get_log_size(TestServer * s)606 static guint64 get_log_size(TestServer *s)
607 {
608     guint64 log_size = 0;
609     int i;
610 
611     for (i = 0; i < s->memory.nregions; ++i) {
612         VhostUserMemoryRegion *reg = &s->memory.regions[i];
613         guint64 last = range_get_last(reg->guest_phys_addr,
614                                        reg->memory_size);
615         log_size = MAX(log_size, last / (8 * VHOST_LOG_PAGE) + 1);
616     }
617 
618     return log_size;
619 }
620 
621 typedef struct TestMigrateSource {
622     GSource source;
623     TestServer *src;
624     TestServer *dest;
625 } TestMigrateSource;
626 
627 static gboolean
test_migrate_source_check(GSource * source)628 test_migrate_source_check(GSource *source)
629 {
630     TestMigrateSource *t = (TestMigrateSource *)source;
631     gboolean overlap = t->src->rings && t->dest->rings;
632 
633     g_assert(!overlap);
634 
635     return FALSE;
636 }
637 
638 GSourceFuncs test_migrate_source_funcs = {
639     .check = test_migrate_source_check,
640 };
641 
test_read_guest_mem(const void * arg)642 static void test_read_guest_mem(const void *arg)
643 {
644     enum test_memfd memfd = GPOINTER_TO_INT(arg);
645     TestServer *server = NULL;
646     char *qemu_cmd = NULL;
647     QTestState *s = NULL;
648 
649     server = test_server_new(memfd == TEST_MEMFD_YES ?
650                              "read-guest-memfd" : "read-guest-mem");
651     test_server_listen(server);
652 
653     qemu_cmd = get_qemu_cmd(server, 512, memfd, root, "", "");
654 
655     s = qtest_start(qemu_cmd);
656     g_free(qemu_cmd);
657 
658     init_virtio_dev(server, 1u << VIRTIO_NET_F_MAC);
659 
660     read_guest_mem_server(server);
661 
662     uninit_virtio_dev(server);
663 
664     qtest_quit(s);
665     test_server_free(server);
666 }
667 
test_migrate(void)668 static void test_migrate(void)
669 {
670     TestServer *s = test_server_new("src");
671     TestServer *dest = test_server_new("dest");
672     char *uri = g_strdup_printf("%s%s", "unix:", dest->mig_path);
673     QTestState *global = global_qtest, *from, *to;
674     GSource *source;
675     gchar *cmd, *tmp;
676     QDict *rsp;
677     guint8 *log;
678     guint64 size;
679 
680     test_server_listen(s);
681     test_server_listen(dest);
682 
683     cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, "", "");
684     from = qtest_start(cmd);
685     g_free(cmd);
686 
687     init_virtio_dev(s, 1u << VIRTIO_NET_F_MAC);
688     init_virtio_dev(dest, 1u << VIRTIO_NET_F_MAC);
689     wait_for_fds(s);
690     size = get_log_size(s);
691     g_assert_cmpint(size, ==, (2 * 1024 * 1024) / (VHOST_LOG_PAGE * 8));
692 
693     tmp = g_strdup_printf(" -incoming %s", uri);
694     cmd = get_qemu_cmd(dest, 2, TEST_MEMFD_AUTO, root, "", tmp);
695     g_free(tmp);
696     to = qtest_init(cmd);
697     g_free(cmd);
698 
699     source = g_source_new(&test_migrate_source_funcs,
700                           sizeof(TestMigrateSource));
701     ((TestMigrateSource *)source)->src = s;
702     ((TestMigrateSource *)source)->dest = dest;
703     g_source_attach(source, NULL);
704 
705     /* slow down migration to have time to fiddle with log */
706     /* TODO: qtest could learn to break on some places */
707     rsp = qmp("{ 'execute': 'migrate_set_speed',"
708               "'arguments': { 'value': 10 } }");
709     g_assert(qdict_haskey(rsp, "return"));
710     qobject_unref(rsp);
711 
712     rsp = qmp("{ 'execute': 'migrate', 'arguments': { 'uri': %s } }", uri);
713     g_assert(qdict_haskey(rsp, "return"));
714     qobject_unref(rsp);
715 
716     wait_for_log_fd(s);
717 
718     log = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, s->log_fd, 0);
719     g_assert(log != MAP_FAILED);
720 
721     /* modify first page */
722     write_guest_mem(s, 0x42);
723     log[0] = 1;
724     munmap(log, size);
725 
726     /* speed things up */
727     rsp = qmp("{ 'execute': 'migrate_set_speed',"
728               "'arguments': { 'value': 0 } }");
729     g_assert(qdict_haskey(rsp, "return"));
730     qobject_unref(rsp);
731 
732     qmp_eventwait("STOP");
733 
734     global_qtest = to;
735     qmp_eventwait("RESUME");
736 
737     read_guest_mem_server(dest);
738 
739     uninit_virtio_dev(s);
740     uninit_virtio_dev(dest);
741 
742     g_source_destroy(source);
743     g_source_unref(source);
744 
745     qtest_quit(to);
746     test_server_free(dest);
747     qtest_quit(from);
748     test_server_free(s);
749     g_free(uri);
750 
751     global_qtest = global;
752 }
753 
wait_for_rings_started(TestServer * s,size_t count)754 static void wait_for_rings_started(TestServer *s, size_t count)
755 {
756     gint64 end_time;
757 
758     g_mutex_lock(&s->data_mutex);
759     end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
760     while (ctpop64(s->rings) != count) {
761         if (!g_cond_wait_until(&s->data_cond, &s->data_mutex, end_time)) {
762             /* timeout has passed */
763             g_assert_cmpint(ctpop64(s->rings), ==, count);
764             break;
765         }
766     }
767 
768     g_mutex_unlock(&s->data_mutex);
769 }
770 
test_server_connect(TestServer * server)771 static inline void test_server_connect(TestServer *server)
772 {
773     test_server_create_chr(server, ",reconnect=1");
774 }
775 
776 static gboolean
reconnect_cb(gpointer user_data)777 reconnect_cb(gpointer user_data)
778 {
779     TestServer *s = user_data;
780 
781     qemu_chr_fe_disconnect(&s->chr);
782 
783     return FALSE;
784 }
785 
786 static gpointer
connect_thread(gpointer data)787 connect_thread(gpointer data)
788 {
789     TestServer *s = data;
790 
791     /* wait for qemu to start before first try, to avoid extra warnings */
792     g_usleep(G_USEC_PER_SEC);
793     test_server_connect(s);
794 
795     return NULL;
796 }
797 
test_reconnect_subprocess(void)798 static void test_reconnect_subprocess(void)
799 {
800     TestServer *s = test_server_new("reconnect");
801     char *cmd;
802 
803     g_thread_new("connect", connect_thread, s);
804     cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, ",server", "");
805     qtest_start(cmd);
806     g_free(cmd);
807 
808     init_virtio_dev(s, 1u << VIRTIO_NET_F_MAC);
809     wait_for_fds(s);
810     wait_for_rings_started(s, 2);
811 
812     /* reconnect */
813     s->fds_num = 0;
814     s->rings = 0;
815     g_idle_add(reconnect_cb, s);
816     wait_for_fds(s);
817     wait_for_rings_started(s, 2);
818 
819     uninit_virtio_dev(s);
820 
821     qtest_end();
822     test_server_free(s);
823     return;
824 }
825 
test_reconnect(void)826 static void test_reconnect(void)
827 {
828     gchar *path = g_strdup_printf("/%s/vhost-user/reconnect/subprocess",
829                                   qtest_get_arch());
830     g_test_trap_subprocess(path, 0, 0);
831     g_test_trap_assert_passed();
832     g_free(path);
833 }
834 
test_connect_fail_subprocess(void)835 static void test_connect_fail_subprocess(void)
836 {
837     TestServer *s = test_server_new("connect-fail");
838     char *cmd;
839 
840     s->test_fail = true;
841     g_thread_new("connect", connect_thread, s);
842     cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, ",server", "");
843     qtest_start(cmd);
844     g_free(cmd);
845 
846     init_virtio_dev(s, 1u << VIRTIO_NET_F_MAC);
847     wait_for_fds(s);
848     wait_for_rings_started(s, 2);
849 
850     uninit_virtio_dev(s);
851 
852     qtest_end();
853     test_server_free(s);
854 }
855 
test_connect_fail(void)856 static void test_connect_fail(void)
857 {
858     gchar *path = g_strdup_printf("/%s/vhost-user/connect-fail/subprocess",
859                                   qtest_get_arch());
860     g_test_trap_subprocess(path, 0, 0);
861     g_test_trap_assert_passed();
862     g_free(path);
863 }
864 
test_flags_mismatch_subprocess(void)865 static void test_flags_mismatch_subprocess(void)
866 {
867     TestServer *s = test_server_new("flags-mismatch");
868     char *cmd;
869 
870     s->test_flags = TEST_FLAGS_DISCONNECT;
871     g_thread_new("connect", connect_thread, s);
872     cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, ",server", "");
873     qtest_start(cmd);
874     g_free(cmd);
875 
876     init_virtio_dev(s, 1u << VIRTIO_NET_F_MAC);
877     wait_for_fds(s);
878     wait_for_rings_started(s, 2);
879 
880     uninit_virtio_dev(s);
881 
882     qtest_end();
883     test_server_free(s);
884 }
885 
test_flags_mismatch(void)886 static void test_flags_mismatch(void)
887 {
888     gchar *path = g_strdup_printf("/%s/vhost-user/flags-mismatch/subprocess",
889                                   qtest_get_arch());
890     g_test_trap_subprocess(path, 0, 0);
891     g_test_trap_assert_passed();
892     g_free(path);
893 }
894 
895 
test_multiqueue(void)896 static void test_multiqueue(void)
897 {
898     TestServer *s = test_server_new("mq");
899     char *cmd;
900     uint32_t features_mask = ~(QVIRTIO_F_BAD_FEATURE |
901                             (1u << VIRTIO_RING_F_INDIRECT_DESC) |
902                             (1u << VIRTIO_RING_F_EVENT_IDX));
903     s->queues = 2;
904     test_server_listen(s);
905 
906     if (qemu_memfd_check(0)) {
907         cmd = g_strdup_printf(
908             QEMU_CMD_MEMFD QEMU_CMD_CHR QEMU_CMD_NETDEV ",queues=%d "
909             "-device virtio-net-pci,netdev=net0,mq=on,vectors=%d",
910             512, 512, s->chr_name,
911             s->socket_path, "", s->chr_name,
912             s->queues, s->queues * 2 + 2);
913     } else {
914         cmd = g_strdup_printf(
915             QEMU_CMD_MEM QEMU_CMD_CHR QEMU_CMD_NETDEV ",queues=%d "
916             "-device virtio-net-pci,netdev=net0,mq=on,vectors=%d",
917             512, 512, root, s->chr_name,
918             s->socket_path, "", s->chr_name,
919             s->queues, s->queues * 2 + 2);
920     }
921     qtest_start(cmd);
922     g_free(cmd);
923 
924     init_virtio_dev(s, features_mask);
925 
926     wait_for_rings_started(s, s->queues * 2);
927 
928     uninit_virtio_dev(s);
929 
930     qtest_end();
931 
932     test_server_free(s);
933 }
934 
main(int argc,char ** argv)935 int main(int argc, char **argv)
936 {
937     const char *hugefs;
938     int ret;
939     char template[] = "/tmp/vhost-test-XXXXXX";
940     GMainLoop *loop;
941     GThread *thread;
942 
943     g_test_init(&argc, &argv, NULL);
944 
945     module_call_init(MODULE_INIT_QOM);
946     qemu_add_opts(&qemu_chardev_opts);
947 
948     tmpfs = mkdtemp(template);
949     if (!tmpfs) {
950         g_test_message("mkdtemp on path (%s): %s\n", template, strerror(errno));
951     }
952     g_assert(tmpfs);
953 
954     hugefs = getenv("QTEST_HUGETLBFS_PATH");
955     if (hugefs) {
956         root = init_hugepagefs(hugefs);
957         g_assert(root);
958     } else {
959         root = tmpfs;
960     }
961 
962     loop = g_main_loop_new(NULL, FALSE);
963     /* run the main loop thread so the chardev may operate */
964     thread = g_thread_new(NULL, thread_function, loop);
965 
966     if (qemu_memfd_check(0)) {
967         qtest_add_data_func("/vhost-user/read-guest-mem/memfd",
968                             GINT_TO_POINTER(TEST_MEMFD_YES),
969                             test_read_guest_mem);
970     }
971     qtest_add_data_func("/vhost-user/read-guest-mem/memfile",
972                         GINT_TO_POINTER(TEST_MEMFD_NO), test_read_guest_mem);
973     qtest_add_func("/vhost-user/migrate", test_migrate);
974     qtest_add_func("/vhost-user/multiqueue", test_multiqueue);
975 
976     /* keeps failing on build-system since Aug 15 2017 */
977     if (getenv("QTEST_VHOST_USER_FIXME")) {
978         qtest_add_func("/vhost-user/reconnect/subprocess",
979                        test_reconnect_subprocess);
980         qtest_add_func("/vhost-user/reconnect", test_reconnect);
981         qtest_add_func("/vhost-user/connect-fail/subprocess",
982                        test_connect_fail_subprocess);
983         qtest_add_func("/vhost-user/connect-fail", test_connect_fail);
984         qtest_add_func("/vhost-user/flags-mismatch/subprocess",
985                        test_flags_mismatch_subprocess);
986         qtest_add_func("/vhost-user/flags-mismatch", test_flags_mismatch);
987     }
988 
989     ret = g_test_run();
990 
991     /* cleanup */
992 
993     /* finish the helper thread and dispatch pending sources */
994     g_main_loop_quit(loop);
995     g_thread_join(thread);
996     while (g_main_context_pending(NULL)) {
997         g_main_context_iteration (NULL, TRUE);
998     }
999     g_main_loop_unref(loop);
1000 
1001     ret = rmdir(tmpfs);
1002     if (ret != 0) {
1003         g_test_message("unable to rmdir: path (%s): %s\n",
1004                        tmpfs, strerror(errno));
1005     }
1006     g_assert_cmpint(ret, ==, 0);
1007 
1008     return ret;
1009 }
1010