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