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>
17 #include <sys/types.h>
18 #include <sys/socket.h>
24 static void test_stream_connection_reset(const struct test_opts *opts)
28 struct sockaddr_vm svm;
31 .svm_family = AF_VSOCK,
33 .svm_cid = opts->peer_cid,
39 fd = socket(AF_VSOCK, SOCK_STREAM, 0);
41 timeout_begin(TIMEOUT);
43 ret = connect(fd, &addr.sa, sizeof(addr.svm));
44 timeout_check("connect");
45 } while (ret < 0 && errno == EINTR);
49 fprintf(stderr, "expected connect(2) failure, got %d\n", ret);
52 if (errno != ECONNRESET) {
53 fprintf(stderr, "unexpected connect(2) errno %d\n", errno);
60 static void test_stream_bind_only_client(const struct test_opts *opts)
64 struct sockaddr_vm svm;
67 .svm_family = AF_VSOCK,
69 .svm_cid = opts->peer_cid,
75 /* Wait for the server to be ready */
76 control_expectln("BIND");
78 fd = socket(AF_VSOCK, SOCK_STREAM, 0);
80 timeout_begin(TIMEOUT);
82 ret = connect(fd, &addr.sa, sizeof(addr.svm));
83 timeout_check("connect");
84 } while (ret < 0 && errno == EINTR);
88 fprintf(stderr, "expected connect(2) failure, got %d\n", ret);
91 if (errno != ECONNRESET) {
92 fprintf(stderr, "unexpected connect(2) errno %d\n", errno);
96 /* Notify the server that the client has finished */
97 control_writeln("DONE");
102 static void test_stream_bind_only_server(const struct test_opts *opts)
106 struct sockaddr_vm svm;
109 .svm_family = AF_VSOCK,
111 .svm_cid = VMADDR_CID_ANY,
116 fd = socket(AF_VSOCK, SOCK_STREAM, 0);
118 if (bind(fd, &addr.sa, sizeof(addr.svm)) < 0) {
123 /* Notify the client that the server is ready */
124 control_writeln("BIND");
126 /* Wait for the client to finish */
127 control_expectln("DONE");
132 static void test_stream_client_close_client(const struct test_opts *opts)
136 fd = vsock_stream_connect(opts->peer_cid, 1234);
146 static void test_stream_client_close_server(const struct test_opts *opts)
150 fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL);
156 /* Wait for the remote to close the connection, before check
157 * -EPIPE error on send.
159 vsock_wait_remote_close(fd);
161 send_byte(fd, -EPIPE, 0);
167 static void test_stream_server_close_client(const struct test_opts *opts)
171 fd = vsock_stream_connect(opts->peer_cid, 1234);
177 /* Wait for the remote to close the connection, before check
178 * -EPIPE error on send.
180 vsock_wait_remote_close(fd);
182 send_byte(fd, -EPIPE, 0);
188 static void test_stream_server_close_server(const struct test_opts *opts)
192 fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL);
202 /* With the standard socket sizes, VMCI is able to support about 100
203 * concurrent stream connections.
205 #define MULTICONN_NFDS 100
207 static void test_stream_multiconn_client(const struct test_opts *opts)
209 int fds[MULTICONN_NFDS];
212 for (i = 0; i < MULTICONN_NFDS; i++) {
213 fds[i] = vsock_stream_connect(opts->peer_cid, 1234);
220 for (i = 0; i < MULTICONN_NFDS; i++) {
222 recv_byte(fds[i], 1, 0);
224 send_byte(fds[i], 1, 0);
227 for (i = 0; i < MULTICONN_NFDS; i++)
231 static void test_stream_multiconn_server(const struct test_opts *opts)
233 int fds[MULTICONN_NFDS];
236 for (i = 0; i < MULTICONN_NFDS; i++) {
237 fds[i] = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL);
244 for (i = 0; i < MULTICONN_NFDS; i++) {
246 send_byte(fds[i], 1, 0);
248 recv_byte(fds[i], 1, 0);
251 for (i = 0; i < MULTICONN_NFDS; i++)
255 static void test_stream_msg_peek_client(const struct test_opts *opts)
259 fd = vsock_stream_connect(opts->peer_cid, 1234);
269 static void test_stream_msg_peek_server(const struct test_opts *opts)
273 fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL);
279 recv_byte(fd, 1, MSG_PEEK);
284 #define MESSAGES_CNT 7
285 #define MSG_EOR_IDX (MESSAGES_CNT / 2)
286 static void test_seqpacket_msg_bounds_client(const struct test_opts *opts)
290 fd = vsock_seqpacket_connect(opts->peer_cid, 1234);
296 /* Send several messages, one with MSG_EOR flag */
297 for (int i = 0; i < MESSAGES_CNT; i++)
298 send_byte(fd, 1, (i == MSG_EOR_IDX) ? MSG_EOR : 0);
300 control_writeln("SENDDONE");
304 static void test_seqpacket_msg_bounds_server(const struct test_opts *opts)
308 struct msghdr msg = {0};
309 struct iovec iov = {0};
311 fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL);
317 control_expectln("SENDDONE");
319 iov.iov_len = sizeof(buf);
323 for (int i = 0; i < MESSAGES_CNT; i++) {
324 if (recvmsg(fd, &msg, 0) != 1) {
325 perror("message bound violated");
329 if ((i == MSG_EOR_IDX) ^ !!(msg.msg_flags & MSG_EOR)) {
338 #define MESSAGE_TRUNC_SZ 32
339 static void test_seqpacket_msg_trunc_client(const struct test_opts *opts)
342 char buf[MESSAGE_TRUNC_SZ];
344 fd = vsock_seqpacket_connect(opts->peer_cid, 1234);
350 if (send(fd, buf, sizeof(buf), 0) != sizeof(buf)) {
351 perror("send failed");
355 control_writeln("SENDDONE");
359 static void test_seqpacket_msg_trunc_server(const struct test_opts *opts)
362 char buf[MESSAGE_TRUNC_SZ / 2];
363 struct msghdr msg = {0};
364 struct iovec iov = {0};
366 fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL);
372 control_expectln("SENDDONE");
374 iov.iov_len = sizeof(buf);
378 ssize_t ret = recvmsg(fd, &msg, MSG_TRUNC);
380 if (ret != MESSAGE_TRUNC_SZ) {
381 printf("%zi\n", ret);
382 perror("MSG_TRUNC doesn't work");
386 if (!(msg.msg_flags & MSG_TRUNC)) {
387 fprintf(stderr, "MSG_TRUNC expected\n");
394 static struct test_case test_cases[] = {
396 .name = "SOCK_STREAM connection reset",
397 .run_client = test_stream_connection_reset,
400 .name = "SOCK_STREAM bind only",
401 .run_client = test_stream_bind_only_client,
402 .run_server = test_stream_bind_only_server,
405 .name = "SOCK_STREAM client close",
406 .run_client = test_stream_client_close_client,
407 .run_server = test_stream_client_close_server,
410 .name = "SOCK_STREAM server close",
411 .run_client = test_stream_server_close_client,
412 .run_server = test_stream_server_close_server,
415 .name = "SOCK_STREAM multiple connections",
416 .run_client = test_stream_multiconn_client,
417 .run_server = test_stream_multiconn_server,
420 .name = "SOCK_STREAM MSG_PEEK",
421 .run_client = test_stream_msg_peek_client,
422 .run_server = test_stream_msg_peek_server,
425 .name = "SOCK_SEQPACKET msg bounds",
426 .run_client = test_seqpacket_msg_bounds_client,
427 .run_server = test_seqpacket_msg_bounds_server,
430 .name = "SOCK_SEQPACKET MSG_TRUNC flag",
431 .run_client = test_seqpacket_msg_trunc_client,
432 .run_server = test_seqpacket_msg_trunc_server,
437 static const char optstring[] = "";
438 static const struct option longopts[] = {
440 .name = "control-host",
441 .has_arg = required_argument,
445 .name = "control-port",
446 .has_arg = required_argument,
451 .has_arg = required_argument,
456 .has_arg = required_argument,
461 .has_arg = no_argument,
466 .has_arg = required_argument,
471 .has_arg = no_argument,
477 static void usage(void)
479 fprintf(stderr, "Usage: vsock_test [--help] [--control-host=<host>] --control-port=<port> --mode=client|server --peer-cid=<cid> [--list] [--skip=<test_id>]\n"
481 " Server: vsock_test --control-port=1234 --mode=server --peer-cid=3\n"
482 " Client: vsock_test --control-host=192.168.0.1 --control-port=1234 --mode=client --peer-cid=2\n"
484 "Run vsock.ko tests. Must be launched in both guest\n"
485 "and host. One side must use --mode=client and\n"
486 "the other side must use --mode=server.\n"
488 "A TCP control socket connection is used to coordinate tests\n"
489 "between the client and the server. The server requires a\n"
490 "listen address and the client requires an address to\n"
493 "The CID of the other side must be given with --peer-cid=<cid>.\n"
496 " --help This help message\n"
497 " --control-host <host> Server IP address to connect to\n"
498 " --control-port <port> Server port to listen on/connect to\n"
499 " --mode client|server Server or client mode\n"
500 " --peer-cid <cid> CID of the other side\n"
501 " --list List of tests that will be executed\n"
502 " --skip <test_id> Test ID to skip;\n"
503 " use multiple --skip options to skip more tests\n"
508 int main(int argc, char **argv)
510 const char *control_host = NULL;
511 const char *control_port = NULL;
512 struct test_opts opts = {
513 .mode = TEST_MODE_UNSET,
514 .peer_cid = VMADDR_CID_ANY,
520 int opt = getopt_long(argc, argv, optstring, longopts, NULL);
527 control_host = optarg;
530 if (strcmp(optarg, "client") == 0)
531 opts.mode = TEST_MODE_CLIENT;
532 else if (strcmp(optarg, "server") == 0)
533 opts.mode = TEST_MODE_SERVER;
535 fprintf(stderr, "--mode must be \"client\" or \"server\"\n");
540 opts.peer_cid = parse_cid(optarg);
543 control_port = optarg;
546 list_tests(test_cases);
549 skip_test(test_cases, ARRAY_SIZE(test_cases) - 1,
560 if (opts.mode == TEST_MODE_UNSET)
562 if (opts.peer_cid == VMADDR_CID_ANY)
566 if (opts.mode != TEST_MODE_SERVER)
568 control_host = "0.0.0.0";
571 control_init(control_host, control_port,
572 opts.mode == TEST_MODE_SERVER);
574 run_tests(test_cases, &opts);