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_bind_only_client(const struct test_opts
*opts
)
62 struct sockaddr_vm svm
;
65 .svm_family
= AF_VSOCK
,
67 .svm_cid
= opts
->peer_cid
,
73 /* Wait for the server to be ready */
74 control_expectln("BIND");
76 fd
= socket(AF_VSOCK
, SOCK_STREAM
, 0);
78 timeout_begin(TIMEOUT
);
80 ret
= connect(fd
, &addr
.sa
, sizeof(addr
.svm
));
81 timeout_check("connect");
82 } while (ret
< 0 && errno
== EINTR
);
86 fprintf(stderr
, "expected connect(2) failure, got %d\n", ret
);
89 if (errno
!= ECONNRESET
) {
90 fprintf(stderr
, "unexpected connect(2) errno %d\n", errno
);
94 /* Notify the server that the client has finished */
95 control_writeln("DONE");
100 static void test_stream_bind_only_server(const struct test_opts
*opts
)
104 struct sockaddr_vm svm
;
107 .svm_family
= AF_VSOCK
,
109 .svm_cid
= VMADDR_CID_ANY
,
114 fd
= socket(AF_VSOCK
, SOCK_STREAM
, 0);
116 if (bind(fd
, &addr
.sa
, sizeof(addr
.svm
)) < 0) {
121 /* Notify the client that the server is ready */
122 control_writeln("BIND");
124 /* Wait for the client to finish */
125 control_expectln("DONE");
130 static void test_stream_client_close_client(const struct test_opts
*opts
)
134 fd
= vsock_stream_connect(opts
->peer_cid
, 1234);
144 static void test_stream_client_close_server(const struct test_opts
*opts
)
148 fd
= vsock_stream_accept(VMADDR_CID_ANY
, 1234, NULL
);
154 /* Wait for the remote to close the connection, before check
155 * -EPIPE error on send.
157 vsock_wait_remote_close(fd
);
159 send_byte(fd
, -EPIPE
, 0);
165 static void test_stream_server_close_client(const struct test_opts
*opts
)
169 fd
= vsock_stream_connect(opts
->peer_cid
, 1234);
175 /* Wait for the remote to close the connection, before check
176 * -EPIPE error on send.
178 vsock_wait_remote_close(fd
);
180 send_byte(fd
, -EPIPE
, 0);
186 static void test_stream_server_close_server(const struct test_opts
*opts
)
190 fd
= vsock_stream_accept(VMADDR_CID_ANY
, 1234, NULL
);
200 /* With the standard socket sizes, VMCI is able to support about 100
201 * concurrent stream connections.
203 #define MULTICONN_NFDS 100
205 static void test_stream_multiconn_client(const struct test_opts
*opts
)
207 int fds
[MULTICONN_NFDS
];
210 for (i
= 0; i
< MULTICONN_NFDS
; i
++) {
211 fds
[i
] = vsock_stream_connect(opts
->peer_cid
, 1234);
218 for (i
= 0; i
< MULTICONN_NFDS
; i
++) {
220 recv_byte(fds
[i
], 1, 0);
222 send_byte(fds
[i
], 1, 0);
225 for (i
= 0; i
< MULTICONN_NFDS
; i
++)
229 static void test_stream_multiconn_server(const struct test_opts
*opts
)
231 int fds
[MULTICONN_NFDS
];
234 for (i
= 0; i
< MULTICONN_NFDS
; i
++) {
235 fds
[i
] = vsock_stream_accept(VMADDR_CID_ANY
, 1234, NULL
);
242 for (i
= 0; i
< MULTICONN_NFDS
; i
++) {
244 send_byte(fds
[i
], 1, 0);
246 recv_byte(fds
[i
], 1, 0);
249 for (i
= 0; i
< MULTICONN_NFDS
; i
++)
253 static void test_stream_msg_peek_client(const struct test_opts
*opts
)
257 fd
= vsock_stream_connect(opts
->peer_cid
, 1234);
267 static void test_stream_msg_peek_server(const struct test_opts
*opts
)
271 fd
= vsock_stream_accept(VMADDR_CID_ANY
, 1234, NULL
);
277 recv_byte(fd
, 1, MSG_PEEK
);
282 static struct test_case test_cases
[] = {
284 .name
= "SOCK_STREAM connection reset",
285 .run_client
= test_stream_connection_reset
,
288 .name
= "SOCK_STREAM bind only",
289 .run_client
= test_stream_bind_only_client
,
290 .run_server
= test_stream_bind_only_server
,
293 .name
= "SOCK_STREAM client close",
294 .run_client
= test_stream_client_close_client
,
295 .run_server
= test_stream_client_close_server
,
298 .name
= "SOCK_STREAM server close",
299 .run_client
= test_stream_server_close_client
,
300 .run_server
= test_stream_server_close_server
,
303 .name
= "SOCK_STREAM multiple connections",
304 .run_client
= test_stream_multiconn_client
,
305 .run_server
= test_stream_multiconn_server
,
308 .name
= "SOCK_STREAM MSG_PEEK",
309 .run_client
= test_stream_msg_peek_client
,
310 .run_server
= test_stream_msg_peek_server
,
315 static const char optstring
[] = "";
316 static const struct option longopts
[] = {
318 .name
= "control-host",
319 .has_arg
= required_argument
,
323 .name
= "control-port",
324 .has_arg
= required_argument
,
329 .has_arg
= required_argument
,
334 .has_arg
= required_argument
,
339 .has_arg
= no_argument
,
344 .has_arg
= required_argument
,
349 .has_arg
= no_argument
,
355 static void usage(void)
357 fprintf(stderr
, "Usage: vsock_test [--help] [--control-host=<host>] --control-port=<port> --mode=client|server --peer-cid=<cid> [--list] [--skip=<test_id>]\n"
359 " Server: vsock_test --control-port=1234 --mode=server --peer-cid=3\n"
360 " Client: vsock_test --control-host=192.168.0.1 --control-port=1234 --mode=client --peer-cid=2\n"
362 "Run vsock.ko tests. Must be launched in both guest\n"
363 "and host. One side must use --mode=client and\n"
364 "the other side must use --mode=server.\n"
366 "A TCP control socket connection is used to coordinate tests\n"
367 "between the client and the server. The server requires a\n"
368 "listen address and the client requires an address to\n"
371 "The CID of the other side must be given with --peer-cid=<cid>.\n"
374 " --help This help message\n"
375 " --control-host <host> Server IP address to connect to\n"
376 " --control-port <port> Server port to listen on/connect to\n"
377 " --mode client|server Server or client mode\n"
378 " --peer-cid <cid> CID of the other side\n"
379 " --list List of tests that will be executed\n"
380 " --skip <test_id> Test ID to skip;\n"
381 " use multiple --skip options to skip more tests\n"
386 int main(int argc
, char **argv
)
388 const char *control_host
= NULL
;
389 const char *control_port
= NULL
;
390 struct test_opts opts
= {
391 .mode
= TEST_MODE_UNSET
,
392 .peer_cid
= VMADDR_CID_ANY
,
398 int opt
= getopt_long(argc
, argv
, optstring
, longopts
, NULL
);
405 control_host
= optarg
;
408 if (strcmp(optarg
, "client") == 0)
409 opts
.mode
= TEST_MODE_CLIENT
;
410 else if (strcmp(optarg
, "server") == 0)
411 opts
.mode
= TEST_MODE_SERVER
;
413 fprintf(stderr
, "--mode must be \"client\" or \"server\"\n");
418 opts
.peer_cid
= parse_cid(optarg
);
421 control_port
= optarg
;
424 list_tests(test_cases
);
427 skip_test(test_cases
, ARRAY_SIZE(test_cases
) - 1,
438 if (opts
.mode
== TEST_MODE_UNSET
)
440 if (opts
.peer_cid
== VMADDR_CID_ANY
)
444 if (opts
.mode
!= TEST_MODE_SERVER
)
446 control_host
= "0.0.0.0";
449 control_init(control_host
, control_port
,
450 opts
.mode
== TEST_MODE_SERVER
);
452 run_tests(test_cases
, &opts
);