]>
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 ZC |
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 | ||
60 | static 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. */ | |
dc491fea | 102 | qmp_discard_response("{ 'execute' : 'query-status'}"); |
9fd3c5d5 ZC |
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 | ||
136 | static 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. */ | |
dc491fea | 187 | qmp_discard_response("{ 'execute' : 'query-status'}"); |
9fd3c5d5 ZC |
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 | ||
210 | int main(int argc, char **argv) | |
211 | { | |
9fd3c5d5 ZC |
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); | |
9be38598 | 215 | return g_test_run(); |
9fd3c5d5 | 216 | } |