qemu/tests/test-filter-redirector.c
<<
>>
Prefs
   1/*
   2 * QTest testcase for filter-redirector
   3 *
   4 * Copyright (c) 2016 FUJITSU LIMITED
   5 * Author: Zhang Chen <zhangchen.fnst@cn.fujitsu.com>
   6 *
   7 * This work is licensed under the terms of the GNU GPL, version 2 or
   8 * later.  See the COPYING file in the top-level directory.
   9 *
  10 * Case 1, tx traffic flow:
  11 *
  12 * qemu side              | test side
  13 *                        |
  14 * +---------+            |  +-------+
  15 * | backend <---------------+ sock0 |
  16 * +----+----+            |  +-------+
  17 *      |                 |
  18 * +----v----+  +-------+ |
  19 * |  rd0    +->+chardev| |
  20 * +---------+  +---+---+ |
  21 *                  |     |
  22 * +---------+      |     |
  23 * |  rd1    <------+     |
  24 * +----+----+            |
  25 *      |                 |
  26 * +----v----+            |  +-------+
  27 * |  rd2    +--------------->sock1  |
  28 * +---------+            |  +-------+
  29 *                        +
  30 *
  31 * --------------------------------------
  32 * Case 2, rx traffic flow
  33 * qemu side              | test side
  34 *                        |
  35 * +---------+            |  +-------+
  36 * | backend +---------------> sock1 |
  37 * +----^----+            |  +-------+
  38 *      |                 |
  39 * +----+----+  +-------+ |
  40 * |  rd0    +<-+chardev| |
  41 * +---------+  +---+---+ |
  42 *                  ^     |
  43 * +---------+      |     |
  44 * |  rd1    +------+     |
  45 * +----^----+            |
  46 *      |                 |
  47 * +----+----+            |  +-------+
  48 * |  rd2    <---------------+sock0  |
  49 * +---------+            |  +-------+
  50 *                        +
  51 */
  52
  53#include "qemu/osdep.h"
  54#include "libqtest.h"
  55#include "qemu/iov.h"
  56#include "qemu/sockets.h"
  57#include "qemu/error-report.h"
  58#include "qemu/main-loop.h"
  59
  60static void test_redirector_tx(void)
  61{
  62#ifndef _WIN32
  63/* socketpair(PF_UNIX) which does not exist on windows */
  64
  65    int backend_sock[2], recv_sock;
  66    char *cmdline;
  67    uint32_t ret = 0, len = 0;
  68    char send_buf[] = "Hello!!";
  69    char sock_path0[] = "filter-redirector0.XXXXXX";
  70    char sock_path1[] = "filter-redirector1.XXXXXX";
  71    char *recv_buf;
  72    uint32_t size = sizeof(send_buf);
  73    size = htonl(size);
  74
  75    ret = socketpair(PF_UNIX, SOCK_STREAM, 0, backend_sock);
  76    g_assert_cmpint(ret, !=, -1);
  77
  78    ret = mkstemp(sock_path0);
  79    g_assert_cmpint(ret, !=, -1);
  80    ret = mkstemp(sock_path1);
  81    g_assert_cmpint(ret, !=, -1);
  82
  83    cmdline = g_strdup_printf("-netdev socket,id=qtest-bn0,fd=%d "
  84                "-device rtl8139,netdev=qtest-bn0,id=qtest-e0 "
  85                "-chardev socket,id=redirector0,path=%s,server,nowait "
  86                "-chardev socket,id=redirector1,path=%s,server,nowait "
  87                "-chardev socket,id=redirector2,path=%s,nowait "
  88                "-object filter-redirector,id=qtest-f0,netdev=qtest-bn0,"
  89                "queue=tx,outdev=redirector0 "
  90                "-object filter-redirector,id=qtest-f1,netdev=qtest-bn0,"
  91                "queue=tx,indev=redirector2 "
  92                "-object filter-redirector,id=qtest-f2,netdev=qtest-bn0,"
  93                "queue=tx,outdev=redirector1 "
  94                , backend_sock[1], sock_path0, sock_path1, sock_path0);
  95    qtest_start(cmdline);
  96    g_free(cmdline);
  97
  98    recv_sock = unix_connect(sock_path1, NULL);
  99    g_assert_cmpint(recv_sock, !=, -1);
 100
 101    /* send a qmp command to guarantee that 'connected' is setting to true. */
 102    qmp("{ 'execute' : 'query-status'}");
 103
 104    struct iovec iov[] = {
 105        {
 106            .iov_base = &size,
 107            .iov_len = sizeof(size),
 108        }, {
 109            .iov_base = send_buf,
 110            .iov_len = sizeof(send_buf),
 111        },
 112    };
 113
 114    ret = iov_send(backend_sock[0], iov, 2, 0, sizeof(size) + sizeof(send_buf));
 115    g_assert_cmpint(ret, ==, sizeof(send_buf) + sizeof(size));
 116    close(backend_sock[0]);
 117
 118    ret = qemu_recv(recv_sock, &len, sizeof(len), 0);
 119    g_assert_cmpint(ret, ==, sizeof(len));
 120    len = ntohl(len);
 121
 122    g_assert_cmpint(len, ==, sizeof(send_buf));
 123    recv_buf = g_malloc(len);
 124    ret = qemu_recv(recv_sock, recv_buf, len, 0);
 125    g_assert_cmpstr(recv_buf, ==, send_buf);
 126
 127    g_free(recv_buf);
 128    close(recv_sock);
 129    unlink(sock_path0);
 130    unlink(sock_path1);
 131    qtest_end();
 132
 133#endif
 134}
 135
 136static void test_redirector_rx(void)
 137{
 138#ifndef _WIN32
 139/* socketpair(PF_UNIX) which does not exist on windows */
 140
 141    int backend_sock[2], send_sock;
 142    char *cmdline;
 143    uint32_t ret = 0, len = 0;
 144    char send_buf[] = "Hello!!";
 145    char sock_path0[] = "filter-redirector0.XXXXXX";
 146    char sock_path1[] = "filter-redirector1.XXXXXX";
 147    char *recv_buf;
 148    uint32_t size = sizeof(send_buf);
 149    size = htonl(size);
 150
 151    ret = socketpair(PF_UNIX, SOCK_STREAM, 0, backend_sock);
 152    g_assert_cmpint(ret, !=, -1);
 153
 154    ret = mkstemp(sock_path0);
 155    g_assert_cmpint(ret, !=, -1);
 156    ret = mkstemp(sock_path1);
 157    g_assert_cmpint(ret, !=, -1);
 158
 159    cmdline = g_strdup_printf("-netdev socket,id=qtest-bn0,fd=%d "
 160                "-device rtl8139,netdev=qtest-bn0,id=qtest-e0 "
 161                "-chardev socket,id=redirector0,path=%s,server,nowait "
 162                "-chardev socket,id=redirector1,path=%s,server,nowait "
 163                "-chardev socket,id=redirector2,path=%s,nowait "
 164                "-object filter-redirector,id=qtest-f0,netdev=qtest-bn0,"
 165                "queue=rx,indev=redirector0 "
 166                "-object filter-redirector,id=qtest-f1,netdev=qtest-bn0,"
 167                "queue=rx,outdev=redirector2 "
 168                "-object filter-redirector,id=qtest-f2,netdev=qtest-bn0,"
 169                "queue=rx,indev=redirector1 "
 170                , backend_sock[1], sock_path0, sock_path1, sock_path0);
 171    qtest_start(cmdline);
 172    g_free(cmdline);
 173
 174    struct iovec iov[] = {
 175        {
 176            .iov_base = &size,
 177            .iov_len = sizeof(size),
 178        }, {
 179            .iov_base = send_buf,
 180            .iov_len = sizeof(send_buf),
 181        },
 182    };
 183
 184    send_sock = unix_connect(sock_path1, NULL);
 185    g_assert_cmpint(send_sock, !=, -1);
 186    /* send a qmp command to guarantee that 'connected' is setting to true. */
 187    qmp("{ 'execute' : 'query-status'}");
 188
 189    ret = iov_send(send_sock, iov, 2, 0, sizeof(size) + sizeof(send_buf));
 190    g_assert_cmpint(ret, ==, sizeof(send_buf) + sizeof(size));
 191    close(send_sock);
 192
 193    ret = qemu_recv(backend_sock[0], &len, sizeof(len), 0);
 194    g_assert_cmpint(ret, ==, sizeof(len));
 195    len = ntohl(len);
 196
 197    g_assert_cmpint(len, ==, sizeof(send_buf));
 198    recv_buf = g_malloc(len);
 199    ret = qemu_recv(backend_sock[0], recv_buf, len, 0);
 200    g_assert_cmpstr(recv_buf, ==, send_buf);
 201
 202    g_free(recv_buf);
 203    unlink(sock_path0);
 204    unlink(sock_path1);
 205    qtest_end();
 206
 207#endif
 208}
 209
 210int main(int argc, char **argv)
 211{
 212    g_test_init(&argc, &argv, NULL);
 213    qtest_add_func("/netfilter/redirector_tx", test_redirector_tx);
 214    qtest_add_func("/netfilter/redirector_rx", test_redirector_rx);
 215    return g_test_run();
 216}
 217