diff mbox

[V3,2/2] tests/test-filter-mirror:add filter-mirror unit test

Message ID 1454571834-18021-3-git-send-email-zhangchen.fnst@cn.fujitsu.com
State New
Headers show

Commit Message

Zhang Chen Feb. 4, 2016, 7:43 a.m. UTC
From: ZhangChen <zhangchen.fnst@cn.fujitsu.com>

Using qtest qmp interface to implement following cases:
1) add/remove filter-mirror
2) add a filter-mirror then delete the netdev
3) add/remove more than one filter-mirrors
4) add more than one filter-mirrors and then delete the netdev
5) add filter-mirror with:
   -object filter-mirror,id=qtest-f0,netdev=qtest-bn0,queue=tx,outdev=mirror0

   then inject packet from the socket connected to qtest-bn0,
   filter-mirror will copy and mirror the packet to mirror0.
   we read packet from mirror0 and then compare to what we inject.
   del filter-mirror.

we start qemu with:
-netdev socket,id=qtest-bn0,listen=127.0.0.1:9005
-device e1000,netdev=qtest-bn0,id=qtest-e0
-chardev socket,id=mirror0,host=127.0.0.1,port=9003,server,nowait
-chardev socket,id=mirror1,host=127.0.0.1,port=9004,server,nowait

Signed-off-by: zhangchen <zhangchen.fnst@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
---
 tests/.gitignore           |   1 +
 tests/Makefile             |   2 +
 tests/test-filter-mirror.c | 285 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 288 insertions(+)
 create mode 100644 tests/test-filter-mirror.c

Comments

Jason Wang Feb. 15, 2016, 5:54 a.m. UTC | #1
On 02/04/2016 03:43 PM, Zhang Chen wrote:
> From: ZhangChen <zhangchen.fnst@cn.fujitsu.com>
>
> Using qtest qmp interface to implement following cases:
> 1) add/remove filter-mirror
> 2) add a filter-mirror then delete the netdev
> 3) add/remove more than one filter-mirrors
> 4) add more than one filter-mirrors and then delete the netdev

The steps here is rather similar to test-netfilter.c. Let's try to
generalize them instead of duplicating codes.

> 5) add filter-mirror with:
>    -object filter-mirror,id=qtest-f0,netdev=qtest-bn0,queue=tx,outdev=mirror0
>
>    then inject packet from the socket connected to qtest-bn0,
>    filter-mirror will copy and mirror the packet to mirror0.
>    we read packet from mirror0 and then compare to what we inject.
>    del filter-mirror.
>
> we start qemu with:
> -netdev socket,id=qtest-bn0,listen=127.0.0.1:9005
> -device e1000,netdev=qtest-bn0,id=qtest-e0
> -chardev socket,id=mirror0,host=127.0.0.1,port=9003,server,nowait
> -chardev socket,id=mirror1,host=127.0.0.1,port=9004,server,nowait

Hardcoded port is not good here since it may cause false positive
(consider the tests may be trigged by lots of automated script both
upstream and downstream). A better solution is using socketpair(2) and
passing pre-created fd(s) to file chardev.

>
> Signed-off-by: zhangchen <zhangchen.fnst@cn.fujitsu.com>
> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
>

[...]
Zhang Chen Feb. 17, 2016, 5:23 a.m. UTC | #2
On 02/15/2016 01:54 PM, Jason Wang wrote:
>
> On 02/04/2016 03:43 PM, Zhang Chen wrote:
>> From: ZhangChen <zhangchen.fnst@cn.fujitsu.com>
>>
>> Using qtest qmp interface to implement following cases:
>> 1) add/remove filter-mirror
>> 2) add a filter-mirror then delete the netdev
>> 3) add/remove more than one filter-mirrors
>> 4) add more than one filter-mirrors and then delete the netdev
> The steps here is rather similar to test-netfilter.c. Let's try to
> generalize them instead of duplicating codes.

We consider that netfilter need a common test case to test common
function for all filter plugin. so we will remove it in this patch and
write anther patch for netfilter common test in futrue. and now
we will focus on filter-redirector, filter-rewriter and filter-compare.

>> 5) add filter-mirror with:
>>     -object filter-mirror,id=qtest-f0,netdev=qtest-bn0,queue=tx,outdev=mirror0
>>
>>     then inject packet from the socket connected to qtest-bn0,
>>     filter-mirror will copy and mirror the packet to mirror0.
>>     we read packet from mirror0 and then compare to what we inject.
>>     del filter-mirror.
>>
>> we start qemu with:
>> -netdev socket,id=qtest-bn0,listen=127.0.0.1:9005
>> -device e1000,netdev=qtest-bn0,id=qtest-e0
>> -chardev socket,id=mirror0,host=127.0.0.1,port=9003,server,nowait
>> -chardev socket,id=mirror1,host=127.0.0.1,port=9004,server,nowait
> Hardcoded port is not good here since it may cause false positive
> (consider the tests may be trigged by lots of automated script both
> upstream and downstream). A better solution is using socketpair(2) and
> passing pre-created fd(s) to file chardev.

I will fix it in next patch

Thanks
zhangchen

>> Signed-off-by: zhangchen <zhangchen.fnst@cn.fujitsu.com>
>> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
>>
> [...]
>
>
> .
>
diff mbox

Patch

diff --git a/tests/.gitignore b/tests/.gitignore
index 787c95c..10df017 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -63,5 +63,6 @@  test-write-threshold
 test-x86-cpuid
 test-xbzrle
 test-netfilter
+test-filter-mirror
 *-test
 qapi-schema/*.test.*
diff --git a/tests/Makefile b/tests/Makefile
index 650e654..e56c514 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -212,6 +212,7 @@  ifeq ($(CONFIG_VHOST_NET_TEST_i386),)
 check-qtest-x86_64-$(CONFIG_VHOST_NET_TEST_x86_64) += tests/vhost-user-test$(EXESUF)
 endif
 check-qtest-i386-y += tests/test-netfilter$(EXESUF)
+check-qtest-i386-y += tests/test-filter-mirror$(EXESUF)
 check-qtest-x86_64-y = $(check-qtest-i386-y)
 gcov-files-i386-y += i386-softmmu/hw/timer/mc146818rtc.c
 gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
@@ -563,6 +564,7 @@  tests/qemu-iotests/socket_scm_helper$(EXESUF): tests/qemu-iotests/socket_scm_hel
 tests/test-qemu-opts$(EXESUF): tests/test-qemu-opts.o $(test-util-obj-y)
 tests/test-write-threshold$(EXESUF): tests/test-write-threshold.o $(test-block-obj-y)
 tests/test-netfilter$(EXESUF): tests/test-netfilter.o $(qtest-obj-y)
+tests/test-filter-mirror$(EXESUF): tests/test-filter-mirror.o $(qtest-obj-y)
 tests/ivshmem-test$(EXESUF): tests/ivshmem-test.o contrib/ivshmem-server/ivshmem-server.o $(libqos-pc-obj-y)
 tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o
 
diff --git a/tests/test-filter-mirror.c b/tests/test-filter-mirror.c
new file mode 100644
index 0000000..f8dd20b
--- /dev/null
+++ b/tests/test-filter-mirror.c
@@ -0,0 +1,285 @@ 
+/*
+ * QTest testcase for filter-mirror
+ *
+ * Copyright (c) 2016 FUJITSU LIMITED
+ * Author: Zhang chen <zhangchen.fnst@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later.  See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+#include "libqtest.h"
+#include "qemu/iov.h"
+#include "qemu/sockets.h"
+#include "qemu/error-report.h"
+#include "qemu/main-loop.h"
+
+/* add a netfilter to a netdev and then remove it */
+
+static void add_one_netfilter(void)
+{
+    QDict *response;
+
+    response = qmp("{'execute': 'object-add',"
+                   " 'arguments': {"
+                   "   'qom-type': 'filter-mirror',"
+                   "   'id': 'qtest-f0',"
+                   "   'props': {"
+                   "     'netdev': 'qtest-bn0',"
+                   "     'queue': 'tx',"
+                   "     'outdev': 'mirror0'"
+                   "}}}");
+
+    g_assert(response);
+    g_assert(!qdict_haskey(response, "error"));
+    QDECREF(response);
+
+    response = qmp("{'execute': 'object-del',"
+                   " 'arguments': {"
+                   "   'id': 'qtest-f0'"
+                   "}}");
+    g_assert(response);
+    g_assert(!qdict_haskey(response, "error"));
+    QDECREF(response);
+}
+
+/* add a netfilter to a netdev and then remove the netdev */
+static void remove_netdev_with_one_netfilter(void)
+{
+    QDict *response;
+
+    response = qmp("{'execute': 'object-add',"
+                   " 'arguments': {"
+                   "   'qom-type': 'filter-mirror',"
+                   "   'id': 'qtest-f0',"
+                   "   'props': {"
+                   "     'netdev': 'qtest-bn0',"
+                   "     'queue': 'tx',"
+                   "     'outdev': 'mirror0'"
+                   "}}}");
+
+    g_assert(response);
+    g_assert(!qdict_haskey(response, "error"));
+    QDECREF(response);
+
+    response = qmp("{'execute': 'netdev_del',"
+                   " 'arguments': {"
+                   "   'id': 'qtest-bn0'"
+                   "}}");
+    g_assert(response);
+    g_assert(!qdict_haskey(response, "error"));
+    QDECREF(response);
+
+    /* add back the netdev */
+    response = qmp("{'execute': 'netdev_add',"
+                   " 'arguments': {"
+                   "   'type': 'socket',"
+                   "   'id': 'qtest-bn0',"
+                   "   'listen': '127.0.0.1:9005'"
+                   "}}");
+    g_assert(response);
+    g_assert(!qdict_haskey(response, "error"));
+    QDECREF(response);
+}
+
+/* add multi(2) netfilters to a netdev and then remove them */
+static void add_multi_netfilter(void)
+{
+    QDict *response;
+
+    response = qmp("{'execute': 'object-add',"
+                   " 'arguments': {"
+                   "   'qom-type': 'filter-mirror',"
+                   "   'id': 'qtest-f0',"
+                   "   'props': {"
+                   "     'netdev': 'qtest-bn0',"
+                   "     'queue': 'tx',"
+                   "     'outdev': 'mirror0'"
+                   "}}}");
+
+    g_assert(response);
+    g_assert(!qdict_haskey(response, "error"));
+    QDECREF(response);
+
+    response = qmp("{'execute': 'object-add',"
+                   " 'arguments': {"
+                   "   'qom-type': 'filter-mirror',"
+                   "   'id': 'qtest-f1',"
+                   "   'props': {"
+                   "     'netdev': 'qtest-bn0',"
+                   "     'queue': 'tx',"
+                   "     'outdev': 'mirror1'"
+                   "}}}");
+
+    g_assert(response);
+    g_assert(!qdict_haskey(response, "error"));
+    QDECREF(response);
+
+    response = qmp("{'execute': 'object-del',"
+                   " 'arguments': {"
+                   "   'id': 'qtest-f0'"
+                   "}}");
+    g_assert(response);
+    g_assert(!qdict_haskey(response, "error"));
+    QDECREF(response);
+
+    response = qmp("{'execute': 'object-del',"
+                   " 'arguments': {"
+                   "   'id': 'qtest-f1'"
+                   "}}");
+    g_assert(response);
+    g_assert(!qdict_haskey(response, "error"));
+    QDECREF(response);
+}
+
+/* add multi(2) netfilters to a netdev and then remove the netdev */
+static void remove_netdev_with_multi_netfilter(void)
+{
+    QDict *response;
+
+    response = qmp("{'execute': 'object-add',"
+                   " 'arguments': {"
+                   "   'qom-type': 'filter-mirror',"
+                   "   'id': 'qtest-f0',"
+                   "   'props': {"
+                   "     'netdev': 'qtest-bn0',"
+                   "     'queue': 'tx',"
+                   "     'outdev': 'mirror0'"
+                   "}}}");
+
+    g_assert(response);
+    g_assert(!qdict_haskey(response, "error"));
+    QDECREF(response);
+
+    response = qmp("{'execute': 'object-add',"
+                   " 'arguments': {"
+                   "   'qom-type': 'filter-mirror',"
+                   "   'id': 'qtest-f1',"
+                   "   'props': {"
+                   "     'netdev': 'qtest-bn0',"
+                   "     'queue': 'tx',"
+                   "     'outdev': 'mirror1'"
+                   "}}}");
+
+    g_assert(response);
+    g_assert(!qdict_haskey(response, "error"));
+    QDECREF(response);
+
+    response = qmp("{'execute': 'netdev_del',"
+                   " 'arguments': {"
+                   "   'id': 'qtest-bn0'"
+                   "}}");
+    g_assert(response);
+    g_assert(!qdict_haskey(response, "error"));
+    QDECREF(response);
+
+    /* add back the netdev */
+    response = qmp("{'execute': 'netdev_add',"
+                   " 'arguments': {"
+                   "   'type': 'socket',"
+                   "   'id': 'qtest-bn0',"
+                   "   'listen': '127.0.0.1:9005'"
+                   "}}");
+    g_assert(response);
+    g_assert(!qdict_haskey(response, "error"));
+    QDECREF(response);
+}
+
+static void test_mirror(void)
+{
+    QDict *response;
+
+    response = qmp("{'execute': 'object-add',"
+                   " 'arguments': {"
+                   "   'qom-type': 'filter-mirror',"
+                   "   'id': 'qtest-f0',"
+                   "   'props': {"
+                   "     'netdev': 'qtest-bn0',"
+                   "     'queue': 'tx',"
+                   "     'outdev': 'mirror0'"
+                   "}}}");
+
+    g_assert(response);
+    g_assert(!qdict_haskey(response, "error"));
+    QDECREF(response);
+
+    int send_sock;
+    uint32_t ret = 0;
+    char send_buf[] = "Hello! filter-mirror~";
+    uint32_t size = sizeof(send_buf);
+    size = htonl(size);
+
+    send_sock = inet_connect("127.0.0.1:9005", NULL);
+    if (send_sock < 0) {
+        error_report("test_mirror connect send_sock 127.0.0.1:9005 failed");
+        return;
+    }
+
+    if (fork() == 0) {
+        int recv_sock;
+        uint32_t len = 0;
+        char *recv_buf;
+
+        recv_sock = inet_connect("127.0.0.1:9003", NULL);
+        if (recv_sock < 0) {
+            error_report("test_mirror connect recv_sock 127.0.0.1:9003 failed");
+            exit(1);
+        }
+        ret = qemu_recv(recv_sock, &len, sizeof(len), 0);
+        g_assert_cmpint(ret, ==, sizeof(len));
+        len = ntohl(len);
+
+        g_assert_cmpint(len, ==, sizeof(send_buf));
+        recv_buf = g_malloc0(len);
+        ret = qemu_recv(recv_sock, recv_buf, len, 0);
+        g_assert_cmpstr(recv_buf, ==, send_buf);
+
+        g_free(recv_buf);
+        close(recv_sock);
+        exit(0);
+    }
+
+    usleep(5000);
+    struct iovec iov[] = {
+        {
+            .iov_base = &size,
+            .iov_len = sizeof(size),
+        }, {
+            .iov_base = send_buf,
+            .iov_len = sizeof(send_buf),
+        },
+    };
+    ret = iov_send(send_sock, iov, 2, 0, sizeof(size) + sizeof(send_buf));
+    g_assert_cmpint(ret, ==, sizeof(send_buf) + sizeof(size));
+    close(send_sock);
+
+    response = qmp("{'execute': 'object-del',"
+                   " 'arguments': {"
+                   "   'id': 'qtest-f0'"
+                   "}}");
+}
+
+int main(int argc, char **argv)
+{
+    int ret;
+
+    g_test_init(&argc, &argv, NULL);
+
+    qtest_add_func("/netfilter/test-mirror", test_mirror);
+    qtest_add_func("/netfilter/addremove_one", add_one_netfilter);
+    qtest_add_func("/netfilter/addremove_multi", add_multi_netfilter);
+    qtest_add_func("/netfilter/remove_netdev_one",
+                   remove_netdev_with_one_netfilter);
+    qtest_add_func("/netfilter/remove_netdev_multi",
+                   remove_netdev_with_multi_netfilter);
+
+    qtest_start("-netdev socket,id=qtest-bn0,listen=127.0.0.1:9005 "
+                 "-device e1000,netdev=qtest-bn0,id=qtest-e0 "
+                 "-chardev socket,id=mirror0,host=127.0.0.1,port=9003,server,nowait "
+                 "-chardev socket,id=mirror1,host=127.0.0.1,port=9004,server,nowait ");
+    ret = g_test_run();
+    qtest_end();
+
+    return ret;
+}