]>
Commit | Line | Data |
---|---|---|
9fd3c5d5 ZC |
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" | |
9fd3c5d5 | 54 | #include "libqtest.h" |
055a1efc | 55 | #include "qapi/qmp/qdict.h" |
9fd3c5d5 ZC |
56 | #include "qemu/iov.h" |
57 | #include "qemu/sockets.h" | |
58 | #include "qemu/error-report.h" | |
59 | #include "qemu/main-loop.h" | |
60 | ||
055a1efc | 61 | /* TODO actually test the results and get rid of this */ |
a2569b00 | 62 | #define qmp_discard_response(qs, ...) qobject_unref(qtest_qmp(qs, __VA_ARGS__)) |
055a1efc | 63 | |
ea5bef49 TH |
64 | static const char *get_devstr(void) |
65 | { | |
66 | if (g_str_equal(qtest_get_arch(), "s390x")) { | |
67 | return "virtio-net-ccw"; | |
68 | } | |
69 | ||
70 | return "rtl8139"; | |
71 | } | |
72 | ||
73 | ||
9fd3c5d5 ZC |
74 | static void test_redirector_tx(void) |
75 | { | |
9fd3c5d5 | 76 | int backend_sock[2], recv_sock; |
9fd3c5d5 ZC |
77 | uint32_t ret = 0, len = 0; |
78 | char send_buf[] = "Hello!!"; | |
79 | char sock_path0[] = "filter-redirector0.XXXXXX"; | |
80 | char sock_path1[] = "filter-redirector1.XXXXXX"; | |
81 | char *recv_buf; | |
82 | uint32_t size = sizeof(send_buf); | |
83 | size = htonl(size); | |
a2569b00 | 84 | QTestState *qts; |
9fd3c5d5 ZC |
85 | |
86 | ret = socketpair(PF_UNIX, SOCK_STREAM, 0, backend_sock); | |
87 | g_assert_cmpint(ret, !=, -1); | |
88 | ||
89 | ret = mkstemp(sock_path0); | |
90 | g_assert_cmpint(ret, !=, -1); | |
91 | ret = mkstemp(sock_path1); | |
92 | g_assert_cmpint(ret, !=, -1); | |
93 | ||
a2569b00 | 94 | qts = qtest_initf( |
78b27bad EB |
95 | "-netdev socket,id=qtest-bn0,fd=%d " |
96 | "-device %s,netdev=qtest-bn0,id=qtest-e0 " | |
97 | "-chardev socket,id=redirector0,path=%s,server,nowait " | |
98 | "-chardev socket,id=redirector1,path=%s,server,nowait " | |
767abe7f | 99 | "-chardev socket,id=redirector2,path=%s " |
78b27bad EB |
100 | "-object filter-redirector,id=qtest-f0,netdev=qtest-bn0," |
101 | "queue=tx,outdev=redirector0 " | |
102 | "-object filter-redirector,id=qtest-f1,netdev=qtest-bn0," | |
103 | "queue=tx,indev=redirector2 " | |
104 | "-object filter-redirector,id=qtest-f2,netdev=qtest-bn0," | |
105 | "queue=tx,outdev=redirector1 ", backend_sock[1], get_devstr(), | |
106 | sock_path0, sock_path1, sock_path0); | |
9fd3c5d5 ZC |
107 | |
108 | recv_sock = unix_connect(sock_path1, NULL); | |
109 | g_assert_cmpint(recv_sock, !=, -1); | |
110 | ||
111 | /* send a qmp command to guarantee that 'connected' is setting to true. */ | |
a2569b00 | 112 | qmp_discard_response(qts, "{ 'execute' : 'query-status'}"); |
9fd3c5d5 ZC |
113 | |
114 | struct iovec iov[] = { | |
115 | { | |
116 | .iov_base = &size, | |
117 | .iov_len = sizeof(size), | |
118 | }, { | |
119 | .iov_base = send_buf, | |
120 | .iov_len = sizeof(send_buf), | |
121 | }, | |
122 | }; | |
123 | ||
124 | ret = iov_send(backend_sock[0], iov, 2, 0, sizeof(size) + sizeof(send_buf)); | |
125 | g_assert_cmpint(ret, ==, sizeof(send_buf) + sizeof(size)); | |
126 | close(backend_sock[0]); | |
127 | ||
128 | ret = qemu_recv(recv_sock, &len, sizeof(len), 0); | |
129 | g_assert_cmpint(ret, ==, sizeof(len)); | |
130 | len = ntohl(len); | |
131 | ||
132 | g_assert_cmpint(len, ==, sizeof(send_buf)); | |
133 | recv_buf = g_malloc(len); | |
134 | ret = qemu_recv(recv_sock, recv_buf, len, 0); | |
135 | g_assert_cmpstr(recv_buf, ==, send_buf); | |
136 | ||
137 | g_free(recv_buf); | |
138 | close(recv_sock); | |
139 | unlink(sock_path0); | |
140 | unlink(sock_path1); | |
a2569b00 | 141 | qtest_quit(qts); |
9fd3c5d5 ZC |
142 | } |
143 | ||
144 | static void test_redirector_rx(void) | |
145 | { | |
9fd3c5d5 | 146 | int backend_sock[2], send_sock; |
9fd3c5d5 ZC |
147 | uint32_t ret = 0, len = 0; |
148 | char send_buf[] = "Hello!!"; | |
149 | char sock_path0[] = "filter-redirector0.XXXXXX"; | |
150 | char sock_path1[] = "filter-redirector1.XXXXXX"; | |
151 | char *recv_buf; | |
152 | uint32_t size = sizeof(send_buf); | |
153 | size = htonl(size); | |
a2569b00 | 154 | QTestState *qts; |
9fd3c5d5 ZC |
155 | |
156 | ret = socketpair(PF_UNIX, SOCK_STREAM, 0, backend_sock); | |
157 | g_assert_cmpint(ret, !=, -1); | |
158 | ||
159 | ret = mkstemp(sock_path0); | |
160 | g_assert_cmpint(ret, !=, -1); | |
161 | ret = mkstemp(sock_path1); | |
162 | g_assert_cmpint(ret, !=, -1); | |
163 | ||
a2569b00 | 164 | qts = qtest_initf( |
78b27bad EB |
165 | "-netdev socket,id=qtest-bn0,fd=%d " |
166 | "-device %s,netdev=qtest-bn0,id=qtest-e0 " | |
167 | "-chardev socket,id=redirector0,path=%s,server,nowait " | |
168 | "-chardev socket,id=redirector1,path=%s,server,nowait " | |
767abe7f | 169 | "-chardev socket,id=redirector2,path=%s " |
78b27bad EB |
170 | "-object filter-redirector,id=qtest-f0,netdev=qtest-bn0," |
171 | "queue=rx,indev=redirector0 " | |
172 | "-object filter-redirector,id=qtest-f1,netdev=qtest-bn0," | |
173 | "queue=rx,outdev=redirector2 " | |
174 | "-object filter-redirector,id=qtest-f2,netdev=qtest-bn0," | |
175 | "queue=rx,indev=redirector1 ", backend_sock[1], get_devstr(), | |
176 | sock_path0, sock_path1, sock_path0); | |
9fd3c5d5 ZC |
177 | |
178 | struct iovec iov[] = { | |
179 | { | |
180 | .iov_base = &size, | |
181 | .iov_len = sizeof(size), | |
182 | }, { | |
183 | .iov_base = send_buf, | |
184 | .iov_len = sizeof(send_buf), | |
185 | }, | |
186 | }; | |
187 | ||
188 | send_sock = unix_connect(sock_path1, NULL); | |
189 | g_assert_cmpint(send_sock, !=, -1); | |
190 | /* send a qmp command to guarantee that 'connected' is setting to true. */ | |
a2569b00 | 191 | qmp_discard_response(qts, "{ 'execute' : 'query-status'}"); |
9fd3c5d5 ZC |
192 | |
193 | ret = iov_send(send_sock, iov, 2, 0, sizeof(size) + sizeof(send_buf)); | |
194 | g_assert_cmpint(ret, ==, sizeof(send_buf) + sizeof(size)); | |
9fd3c5d5 ZC |
195 | |
196 | ret = qemu_recv(backend_sock[0], &len, sizeof(len), 0); | |
197 | g_assert_cmpint(ret, ==, sizeof(len)); | |
198 | len = ntohl(len); | |
199 | ||
200 | g_assert_cmpint(len, ==, sizeof(send_buf)); | |
201 | recv_buf = g_malloc(len); | |
202 | ret = qemu_recv(backend_sock[0], recv_buf, len, 0); | |
203 | g_assert_cmpstr(recv_buf, ==, send_buf); | |
204 | ||
8f6d7010 | 205 | close(send_sock); |
9fd3c5d5 ZC |
206 | g_free(recv_buf); |
207 | unlink(sock_path0); | |
208 | unlink(sock_path1); | |
a2569b00 | 209 | qtest_quit(qts); |
9fd3c5d5 ZC |
210 | } |
211 | ||
212 | int main(int argc, char **argv) | |
213 | { | |
9fd3c5d5 ZC |
214 | g_test_init(&argc, &argv, NULL); |
215 | qtest_add_func("/netfilter/redirector_tx", test_redirector_tx); | |
216 | qtest_add_func("/netfilter/redirector_rx", test_redirector_rx); | |
9be38598 | 217 | return g_test_run(); |
9fd3c5d5 | 218 | } |