]>
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 | { | |
9fd3c5d5 ZC |
62 | int backend_sock[2], recv_sock; |
63 | char *cmdline; | |
64 | uint32_t ret = 0, len = 0; | |
65 | char send_buf[] = "Hello!!"; | |
66 | char sock_path0[] = "filter-redirector0.XXXXXX"; | |
67 | char sock_path1[] = "filter-redirector1.XXXXXX"; | |
68 | char *recv_buf; | |
69 | uint32_t size = sizeof(send_buf); | |
70 | size = htonl(size); | |
71 | ||
72 | ret = socketpair(PF_UNIX, SOCK_STREAM, 0, backend_sock); | |
73 | g_assert_cmpint(ret, !=, -1); | |
74 | ||
75 | ret = mkstemp(sock_path0); | |
76 | g_assert_cmpint(ret, !=, -1); | |
77 | ret = mkstemp(sock_path1); | |
78 | g_assert_cmpint(ret, !=, -1); | |
79 | ||
80 | cmdline = g_strdup_printf("-netdev socket,id=qtest-bn0,fd=%d " | |
81 | "-device rtl8139,netdev=qtest-bn0,id=qtest-e0 " | |
82 | "-chardev socket,id=redirector0,path=%s,server,nowait " | |
83 | "-chardev socket,id=redirector1,path=%s,server,nowait " | |
84 | "-chardev socket,id=redirector2,path=%s,nowait " | |
85 | "-object filter-redirector,id=qtest-f0,netdev=qtest-bn0," | |
86 | "queue=tx,outdev=redirector0 " | |
87 | "-object filter-redirector,id=qtest-f1,netdev=qtest-bn0," | |
88 | "queue=tx,indev=redirector2 " | |
89 | "-object filter-redirector,id=qtest-f2,netdev=qtest-bn0," | |
90 | "queue=tx,outdev=redirector1 " | |
91 | , backend_sock[1], sock_path0, sock_path1, sock_path0); | |
92 | qtest_start(cmdline); | |
93 | g_free(cmdline); | |
94 | ||
95 | recv_sock = unix_connect(sock_path1, NULL); | |
96 | g_assert_cmpint(recv_sock, !=, -1); | |
97 | ||
98 | /* send a qmp command to guarantee that 'connected' is setting to true. */ | |
dc491fea | 99 | qmp_discard_response("{ 'execute' : 'query-status'}"); |
9fd3c5d5 ZC |
100 | |
101 | struct iovec iov[] = { | |
102 | { | |
103 | .iov_base = &size, | |
104 | .iov_len = sizeof(size), | |
105 | }, { | |
106 | .iov_base = send_buf, | |
107 | .iov_len = sizeof(send_buf), | |
108 | }, | |
109 | }; | |
110 | ||
111 | ret = iov_send(backend_sock[0], iov, 2, 0, sizeof(size) + sizeof(send_buf)); | |
112 | g_assert_cmpint(ret, ==, sizeof(send_buf) + sizeof(size)); | |
113 | close(backend_sock[0]); | |
114 | ||
115 | ret = qemu_recv(recv_sock, &len, sizeof(len), 0); | |
116 | g_assert_cmpint(ret, ==, sizeof(len)); | |
117 | len = ntohl(len); | |
118 | ||
119 | g_assert_cmpint(len, ==, sizeof(send_buf)); | |
120 | recv_buf = g_malloc(len); | |
121 | ret = qemu_recv(recv_sock, recv_buf, len, 0); | |
122 | g_assert_cmpstr(recv_buf, ==, send_buf); | |
123 | ||
124 | g_free(recv_buf); | |
125 | close(recv_sock); | |
126 | unlink(sock_path0); | |
127 | unlink(sock_path1); | |
128 | qtest_end(); | |
9fd3c5d5 ZC |
129 | } |
130 | ||
131 | static void test_redirector_rx(void) | |
132 | { | |
9fd3c5d5 ZC |
133 | int backend_sock[2], send_sock; |
134 | char *cmdline; | |
135 | uint32_t ret = 0, len = 0; | |
136 | char send_buf[] = "Hello!!"; | |
137 | char sock_path0[] = "filter-redirector0.XXXXXX"; | |
138 | char sock_path1[] = "filter-redirector1.XXXXXX"; | |
139 | char *recv_buf; | |
140 | uint32_t size = sizeof(send_buf); | |
141 | size = htonl(size); | |
142 | ||
143 | ret = socketpair(PF_UNIX, SOCK_STREAM, 0, backend_sock); | |
144 | g_assert_cmpint(ret, !=, -1); | |
145 | ||
146 | ret = mkstemp(sock_path0); | |
147 | g_assert_cmpint(ret, !=, -1); | |
148 | ret = mkstemp(sock_path1); | |
149 | g_assert_cmpint(ret, !=, -1); | |
150 | ||
151 | cmdline = g_strdup_printf("-netdev socket,id=qtest-bn0,fd=%d " | |
152 | "-device rtl8139,netdev=qtest-bn0,id=qtest-e0 " | |
153 | "-chardev socket,id=redirector0,path=%s,server,nowait " | |
154 | "-chardev socket,id=redirector1,path=%s,server,nowait " | |
155 | "-chardev socket,id=redirector2,path=%s,nowait " | |
156 | "-object filter-redirector,id=qtest-f0,netdev=qtest-bn0," | |
157 | "queue=rx,indev=redirector0 " | |
158 | "-object filter-redirector,id=qtest-f1,netdev=qtest-bn0," | |
159 | "queue=rx,outdev=redirector2 " | |
160 | "-object filter-redirector,id=qtest-f2,netdev=qtest-bn0," | |
161 | "queue=rx,indev=redirector1 " | |
162 | , backend_sock[1], sock_path0, sock_path1, sock_path0); | |
163 | qtest_start(cmdline); | |
164 | g_free(cmdline); | |
165 | ||
166 | struct iovec iov[] = { | |
167 | { | |
168 | .iov_base = &size, | |
169 | .iov_len = sizeof(size), | |
170 | }, { | |
171 | .iov_base = send_buf, | |
172 | .iov_len = sizeof(send_buf), | |
173 | }, | |
174 | }; | |
175 | ||
176 | send_sock = unix_connect(sock_path1, NULL); | |
177 | g_assert_cmpint(send_sock, !=, -1); | |
178 | /* send a qmp command to guarantee that 'connected' is setting to true. */ | |
dc491fea | 179 | qmp_discard_response("{ 'execute' : 'query-status'}"); |
9fd3c5d5 ZC |
180 | |
181 | ret = iov_send(send_sock, iov, 2, 0, sizeof(size) + sizeof(send_buf)); | |
182 | g_assert_cmpint(ret, ==, sizeof(send_buf) + sizeof(size)); | |
183 | close(send_sock); | |
184 | ||
185 | ret = qemu_recv(backend_sock[0], &len, sizeof(len), 0); | |
186 | g_assert_cmpint(ret, ==, sizeof(len)); | |
187 | len = ntohl(len); | |
188 | ||
189 | g_assert_cmpint(len, ==, sizeof(send_buf)); | |
190 | recv_buf = g_malloc(len); | |
191 | ret = qemu_recv(backend_sock[0], recv_buf, len, 0); | |
192 | g_assert_cmpstr(recv_buf, ==, send_buf); | |
193 | ||
194 | g_free(recv_buf); | |
195 | unlink(sock_path0); | |
196 | unlink(sock_path1); | |
197 | qtest_end(); | |
9fd3c5d5 ZC |
198 | } |
199 | ||
200 | int main(int argc, char **argv) | |
201 | { | |
9fd3c5d5 ZC |
202 | g_test_init(&argc, &argv, NULL); |
203 | qtest_add_func("/netfilter/redirector_tx", test_redirector_tx); | |
204 | qtest_add_func("/netfilter/redirector_rx", test_redirector_rx); | |
9be38598 | 205 | return g_test_run(); |
9fd3c5d5 | 206 | } |