1 // SPDX-License-Identifier: GPL-2.0-only
3 * vsock_test - vsock.ko test suite
5 * Copyright (C) 2017 Red Hat, Inc.
7 * Author: Stefan Hajnoczi <stefanha@redhat.com>
16 #include <linux/kernel.h>
22 static void test_stream_connection_reset(const struct test_opts
*opts
)
26 struct sockaddr_vm svm
;
29 .svm_family
= AF_VSOCK
,
31 .svm_cid
= opts
->peer_cid
,
37 fd
= socket(AF_VSOCK
, SOCK_STREAM
, 0);
39 timeout_begin(TIMEOUT
);
41 ret
= connect(fd
, &addr
.sa
, sizeof(addr
.svm
));
42 timeout_check("connect");
43 } while (ret
< 0 && errno
== EINTR
);
47 fprintf(stderr
, "expected connect(2) failure, got %d\n", ret
);
50 if (errno
!= ECONNRESET
) {
51 fprintf(stderr
, "unexpected connect(2) errno %d\n", errno
);
58 static void test_stream_client_close_client(const struct test_opts
*opts
)
62 fd
= vsock_stream_connect(opts
->peer_cid
, 1234);
72 static void test_stream_client_close_server(const struct test_opts
*opts
)
76 fd
= vsock_stream_accept(VMADDR_CID_ANY
, 1234, NULL
);
82 /* Wait for the remote to close the connection, before check
83 * -EPIPE error on send.
85 vsock_wait_remote_close(fd
);
87 send_byte(fd
, -EPIPE
, 0);
93 static void test_stream_server_close_client(const struct test_opts
*opts
)
97 fd
= vsock_stream_connect(opts
->peer_cid
, 1234);
103 /* Wait for the remote to close the connection, before check
104 * -EPIPE error on send.
106 vsock_wait_remote_close(fd
);
108 send_byte(fd
, -EPIPE
, 0);
114 static void test_stream_server_close_server(const struct test_opts
*opts
)
118 fd
= vsock_stream_accept(VMADDR_CID_ANY
, 1234, NULL
);
128 /* With the standard socket sizes, VMCI is able to support about 100
129 * concurrent stream connections.
131 #define MULTICONN_NFDS 100
133 static void test_stream_multiconn_client(const struct test_opts
*opts
)
135 int fds
[MULTICONN_NFDS
];
138 for (i
= 0; i
< MULTICONN_NFDS
; i
++) {
139 fds
[i
] = vsock_stream_connect(opts
->peer_cid
, 1234);
146 for (i
= 0; i
< MULTICONN_NFDS
; i
++) {
148 recv_byte(fds
[i
], 1, 0);
150 send_byte(fds
[i
], 1, 0);
153 for (i
= 0; i
< MULTICONN_NFDS
; i
++)
157 static void test_stream_multiconn_server(const struct test_opts
*opts
)
159 int fds
[MULTICONN_NFDS
];
162 for (i
= 0; i
< MULTICONN_NFDS
; i
++) {
163 fds
[i
] = vsock_stream_accept(VMADDR_CID_ANY
, 1234, NULL
);
170 for (i
= 0; i
< MULTICONN_NFDS
; i
++) {
172 send_byte(fds
[i
], 1, 0);
174 recv_byte(fds
[i
], 1, 0);
177 for (i
= 0; i
< MULTICONN_NFDS
; i
++)
181 static void test_stream_msg_peek_client(const struct test_opts
*opts
)
185 fd
= vsock_stream_connect(opts
->peer_cid
, 1234);
195 static void test_stream_msg_peek_server(const struct test_opts
*opts
)
199 fd
= vsock_stream_accept(VMADDR_CID_ANY
, 1234, NULL
);
205 recv_byte(fd
, 1, MSG_PEEK
);
210 static struct test_case test_cases
[] = {
212 .name
= "SOCK_STREAM connection reset",
213 .run_client
= test_stream_connection_reset
,
216 .name
= "SOCK_STREAM client close",
217 .run_client
= test_stream_client_close_client
,
218 .run_server
= test_stream_client_close_server
,
221 .name
= "SOCK_STREAM server close",
222 .run_client
= test_stream_server_close_client
,
223 .run_server
= test_stream_server_close_server
,
226 .name
= "SOCK_STREAM multiple connections",
227 .run_client
= test_stream_multiconn_client
,
228 .run_server
= test_stream_multiconn_server
,
231 .name
= "SOCK_STREAM MSG_PEEK",
232 .run_client
= test_stream_msg_peek_client
,
233 .run_server
= test_stream_msg_peek_server
,
238 static const char optstring
[] = "";
239 static const struct option longopts
[] = {
241 .name
= "control-host",
242 .has_arg
= required_argument
,
246 .name
= "control-port",
247 .has_arg
= required_argument
,
252 .has_arg
= required_argument
,
257 .has_arg
= required_argument
,
262 .has_arg
= no_argument
,
267 .has_arg
= required_argument
,
272 .has_arg
= no_argument
,
278 static void usage(void)
280 fprintf(stderr
, "Usage: vsock_test [--help] [--control-host=<host>] --control-port=<port> --mode=client|server --peer-cid=<cid> [--list] [--skip=<test_id>]\n"
282 " Server: vsock_test --control-port=1234 --mode=server --peer-cid=3\n"
283 " Client: vsock_test --control-host=192.168.0.1 --control-port=1234 --mode=client --peer-cid=2\n"
285 "Run vsock.ko tests. Must be launched in both guest\n"
286 "and host. One side must use --mode=client and\n"
287 "the other side must use --mode=server.\n"
289 "A TCP control socket connection is used to coordinate tests\n"
290 "between the client and the server. The server requires a\n"
291 "listen address and the client requires an address to\n"
294 "The CID of the other side must be given with --peer-cid=<cid>.\n"
297 " --help This help message\n"
298 " --control-host <host> Server IP address to connect to\n"
299 " --control-port <port> Server port to listen on/connect to\n"
300 " --mode client|server Server or client mode\n"
301 " --peer-cid <cid> CID of the other side\n"
302 " --list List of tests that will be executed\n"
303 " --skip <test_id> Test ID to skip;\n"
304 " use multiple --skip options to skip more tests\n"
309 int main(int argc
, char **argv
)
311 const char *control_host
= NULL
;
312 const char *control_port
= NULL
;
313 struct test_opts opts
= {
314 .mode
= TEST_MODE_UNSET
,
315 .peer_cid
= VMADDR_CID_ANY
,
321 int opt
= getopt_long(argc
, argv
, optstring
, longopts
, NULL
);
328 control_host
= optarg
;
331 if (strcmp(optarg
, "client") == 0)
332 opts
.mode
= TEST_MODE_CLIENT
;
333 else if (strcmp(optarg
, "server") == 0)
334 opts
.mode
= TEST_MODE_SERVER
;
336 fprintf(stderr
, "--mode must be \"client\" or \"server\"\n");
341 opts
.peer_cid
= parse_cid(optarg
);
344 control_port
= optarg
;
347 list_tests(test_cases
);
350 skip_test(test_cases
, ARRAY_SIZE(test_cases
) - 1,
361 if (opts
.mode
== TEST_MODE_UNSET
)
363 if (opts
.peer_cid
== VMADDR_CID_ANY
)
367 if (opts
.mode
!= TEST_MODE_SERVER
)
369 control_host
= "0.0.0.0";
372 control_init(control_host
, control_port
,
373 opts
.mode
== TEST_MODE_SERVER
);
375 run_tests(test_cases
, &opts
);