1cdbcc18dSStefan Hajnoczi // SPDX-License-Identifier: GPL-2.0-only 2cdbcc18dSStefan Hajnoczi /* 3cdbcc18dSStefan Hajnoczi * vsock_test - vsock.ko test suite 4cdbcc18dSStefan Hajnoczi * 5cdbcc18dSStefan Hajnoczi * Copyright (C) 2017 Red Hat, Inc. 6cdbcc18dSStefan Hajnoczi * 7cdbcc18dSStefan Hajnoczi * Author: Stefan Hajnoczi <stefanha@redhat.com> 8cdbcc18dSStefan Hajnoczi */ 9cdbcc18dSStefan Hajnoczi 10cdbcc18dSStefan Hajnoczi #include <getopt.h> 11cdbcc18dSStefan Hajnoczi #include <stdio.h> 12cdbcc18dSStefan Hajnoczi #include <stdlib.h> 13cdbcc18dSStefan Hajnoczi #include <string.h> 14cdbcc18dSStefan Hajnoczi #include <errno.h> 15cdbcc18dSStefan Hajnoczi #include <unistd.h> 165a2b2425SStefano Garzarella #include <linux/kernel.h> 1741b792d7SArseny Krasnov #include <sys/types.h> 1841b792d7SArseny Krasnov #include <sys/socket.h> 19efb3719fSKrasnov Arseniy Vladimirovich #include <time.h> 20*e89600ebSKrasnov Arseniy Vladimirovich #include <sys/mman.h> 21cdbcc18dSStefan Hajnoczi 22cdbcc18dSStefan Hajnoczi #include "timeout.h" 23cdbcc18dSStefan Hajnoczi #include "control.h" 24cdbcc18dSStefan Hajnoczi #include "util.h" 25cdbcc18dSStefan Hajnoczi 26cdbcc18dSStefan Hajnoczi static void test_stream_connection_reset(const struct test_opts *opts) 27cdbcc18dSStefan Hajnoczi { 28cdbcc18dSStefan Hajnoczi union { 29cdbcc18dSStefan Hajnoczi struct sockaddr sa; 30cdbcc18dSStefan Hajnoczi struct sockaddr_vm svm; 31cdbcc18dSStefan Hajnoczi } addr = { 32cdbcc18dSStefan Hajnoczi .svm = { 33cdbcc18dSStefan Hajnoczi .svm_family = AF_VSOCK, 34cdbcc18dSStefan Hajnoczi .svm_port = 1234, 35cdbcc18dSStefan Hajnoczi .svm_cid = opts->peer_cid, 36cdbcc18dSStefan Hajnoczi }, 37cdbcc18dSStefan Hajnoczi }; 38cdbcc18dSStefan Hajnoczi int ret; 39cdbcc18dSStefan Hajnoczi int fd; 40cdbcc18dSStefan Hajnoczi 41cdbcc18dSStefan Hajnoczi fd = socket(AF_VSOCK, SOCK_STREAM, 0); 42cdbcc18dSStefan Hajnoczi 43cdbcc18dSStefan Hajnoczi timeout_begin(TIMEOUT); 44cdbcc18dSStefan Hajnoczi do { 45cdbcc18dSStefan Hajnoczi ret = connect(fd, &addr.sa, sizeof(addr.svm)); 46cdbcc18dSStefan Hajnoczi timeout_check("connect"); 47cdbcc18dSStefan Hajnoczi } while (ret < 0 && errno == EINTR); 48cdbcc18dSStefan Hajnoczi timeout_end(); 49cdbcc18dSStefan Hajnoczi 50cdbcc18dSStefan Hajnoczi if (ret != -1) { 51cdbcc18dSStefan Hajnoczi fprintf(stderr, "expected connect(2) failure, got %d\n", ret); 52cdbcc18dSStefan Hajnoczi exit(EXIT_FAILURE); 53cdbcc18dSStefan Hajnoczi } 54cdbcc18dSStefan Hajnoczi if (errno != ECONNRESET) { 55cdbcc18dSStefan Hajnoczi fprintf(stderr, "unexpected connect(2) errno %d\n", errno); 56cdbcc18dSStefan Hajnoczi exit(EXIT_FAILURE); 57cdbcc18dSStefan Hajnoczi } 58cdbcc18dSStefan Hajnoczi 59cdbcc18dSStefan Hajnoczi close(fd); 60cdbcc18dSStefan Hajnoczi } 61cdbcc18dSStefan Hajnoczi 629de9f7d1SSebastien Boeuf static void test_stream_bind_only_client(const struct test_opts *opts) 639de9f7d1SSebastien Boeuf { 649de9f7d1SSebastien Boeuf union { 659de9f7d1SSebastien Boeuf struct sockaddr sa; 669de9f7d1SSebastien Boeuf struct sockaddr_vm svm; 679de9f7d1SSebastien Boeuf } addr = { 689de9f7d1SSebastien Boeuf .svm = { 699de9f7d1SSebastien Boeuf .svm_family = AF_VSOCK, 709de9f7d1SSebastien Boeuf .svm_port = 1234, 719de9f7d1SSebastien Boeuf .svm_cid = opts->peer_cid, 729de9f7d1SSebastien Boeuf }, 739de9f7d1SSebastien Boeuf }; 749de9f7d1SSebastien Boeuf int ret; 759de9f7d1SSebastien Boeuf int fd; 769de9f7d1SSebastien Boeuf 779de9f7d1SSebastien Boeuf /* Wait for the server to be ready */ 789de9f7d1SSebastien Boeuf control_expectln("BIND"); 799de9f7d1SSebastien Boeuf 809de9f7d1SSebastien Boeuf fd = socket(AF_VSOCK, SOCK_STREAM, 0); 819de9f7d1SSebastien Boeuf 829de9f7d1SSebastien Boeuf timeout_begin(TIMEOUT); 839de9f7d1SSebastien Boeuf do { 849de9f7d1SSebastien Boeuf ret = connect(fd, &addr.sa, sizeof(addr.svm)); 859de9f7d1SSebastien Boeuf timeout_check("connect"); 869de9f7d1SSebastien Boeuf } while (ret < 0 && errno == EINTR); 879de9f7d1SSebastien Boeuf timeout_end(); 889de9f7d1SSebastien Boeuf 899de9f7d1SSebastien Boeuf if (ret != -1) { 909de9f7d1SSebastien Boeuf fprintf(stderr, "expected connect(2) failure, got %d\n", ret); 919de9f7d1SSebastien Boeuf exit(EXIT_FAILURE); 929de9f7d1SSebastien Boeuf } 939de9f7d1SSebastien Boeuf if (errno != ECONNRESET) { 949de9f7d1SSebastien Boeuf fprintf(stderr, "unexpected connect(2) errno %d\n", errno); 959de9f7d1SSebastien Boeuf exit(EXIT_FAILURE); 969de9f7d1SSebastien Boeuf } 979de9f7d1SSebastien Boeuf 989de9f7d1SSebastien Boeuf /* Notify the server that the client has finished */ 999de9f7d1SSebastien Boeuf control_writeln("DONE"); 1009de9f7d1SSebastien Boeuf 1019de9f7d1SSebastien Boeuf close(fd); 1029de9f7d1SSebastien Boeuf } 1039de9f7d1SSebastien Boeuf 1049de9f7d1SSebastien Boeuf static void test_stream_bind_only_server(const struct test_opts *opts) 1059de9f7d1SSebastien Boeuf { 1069de9f7d1SSebastien Boeuf union { 1079de9f7d1SSebastien Boeuf struct sockaddr sa; 1089de9f7d1SSebastien Boeuf struct sockaddr_vm svm; 1099de9f7d1SSebastien Boeuf } addr = { 1109de9f7d1SSebastien Boeuf .svm = { 1119de9f7d1SSebastien Boeuf .svm_family = AF_VSOCK, 1129de9f7d1SSebastien Boeuf .svm_port = 1234, 1139de9f7d1SSebastien Boeuf .svm_cid = VMADDR_CID_ANY, 1149de9f7d1SSebastien Boeuf }, 1159de9f7d1SSebastien Boeuf }; 1169de9f7d1SSebastien Boeuf int fd; 1179de9f7d1SSebastien Boeuf 1189de9f7d1SSebastien Boeuf fd = socket(AF_VSOCK, SOCK_STREAM, 0); 1199de9f7d1SSebastien Boeuf 1209de9f7d1SSebastien Boeuf if (bind(fd, &addr.sa, sizeof(addr.svm)) < 0) { 1219de9f7d1SSebastien Boeuf perror("bind"); 1229de9f7d1SSebastien Boeuf exit(EXIT_FAILURE); 1239de9f7d1SSebastien Boeuf } 1249de9f7d1SSebastien Boeuf 1259de9f7d1SSebastien Boeuf /* Notify the client that the server is ready */ 1269de9f7d1SSebastien Boeuf control_writeln("BIND"); 1279de9f7d1SSebastien Boeuf 1289de9f7d1SSebastien Boeuf /* Wait for the client to finish */ 1299de9f7d1SSebastien Boeuf control_expectln("DONE"); 1309de9f7d1SSebastien Boeuf 1319de9f7d1SSebastien Boeuf close(fd); 1329de9f7d1SSebastien Boeuf } 1339de9f7d1SSebastien Boeuf 134cdbcc18dSStefan Hajnoczi static void test_stream_client_close_client(const struct test_opts *opts) 135cdbcc18dSStefan Hajnoczi { 136cdbcc18dSStefan Hajnoczi int fd; 137cdbcc18dSStefan Hajnoczi 138cdbcc18dSStefan Hajnoczi fd = vsock_stream_connect(opts->peer_cid, 1234); 139cdbcc18dSStefan Hajnoczi if (fd < 0) { 140cdbcc18dSStefan Hajnoczi perror("connect"); 141cdbcc18dSStefan Hajnoczi exit(EXIT_FAILURE); 142cdbcc18dSStefan Hajnoczi } 143cdbcc18dSStefan Hajnoczi 144cdbcc18dSStefan Hajnoczi send_byte(fd, 1, 0); 145cdbcc18dSStefan Hajnoczi close(fd); 146cdbcc18dSStefan Hajnoczi } 147cdbcc18dSStefan Hajnoczi 148cdbcc18dSStefan Hajnoczi static void test_stream_client_close_server(const struct test_opts *opts) 149cdbcc18dSStefan Hajnoczi { 150cdbcc18dSStefan Hajnoczi int fd; 151cdbcc18dSStefan Hajnoczi 152cdbcc18dSStefan Hajnoczi fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); 153cdbcc18dSStefan Hajnoczi if (fd < 0) { 154cdbcc18dSStefan Hajnoczi perror("accept"); 155cdbcc18dSStefan Hajnoczi exit(EXIT_FAILURE); 156cdbcc18dSStefan Hajnoczi } 157cdbcc18dSStefan Hajnoczi 158770ce007SStefano Garzarella /* Wait for the remote to close the connection, before check 159770ce007SStefano Garzarella * -EPIPE error on send. 160770ce007SStefano Garzarella */ 161770ce007SStefano Garzarella vsock_wait_remote_close(fd); 162cdbcc18dSStefan Hajnoczi 163cdbcc18dSStefan Hajnoczi send_byte(fd, -EPIPE, 0); 164cdbcc18dSStefan Hajnoczi recv_byte(fd, 1, 0); 165cdbcc18dSStefan Hajnoczi recv_byte(fd, 0, 0); 166cdbcc18dSStefan Hajnoczi close(fd); 167cdbcc18dSStefan Hajnoczi } 168cdbcc18dSStefan Hajnoczi 169cdbcc18dSStefan Hajnoczi static void test_stream_server_close_client(const struct test_opts *opts) 170cdbcc18dSStefan Hajnoczi { 171cdbcc18dSStefan Hajnoczi int fd; 172cdbcc18dSStefan Hajnoczi 173cdbcc18dSStefan Hajnoczi fd = vsock_stream_connect(opts->peer_cid, 1234); 174cdbcc18dSStefan Hajnoczi if (fd < 0) { 175cdbcc18dSStefan Hajnoczi perror("connect"); 176cdbcc18dSStefan Hajnoczi exit(EXIT_FAILURE); 177cdbcc18dSStefan Hajnoczi } 178cdbcc18dSStefan Hajnoczi 179770ce007SStefano Garzarella /* Wait for the remote to close the connection, before check 180770ce007SStefano Garzarella * -EPIPE error on send. 181770ce007SStefano Garzarella */ 182770ce007SStefano Garzarella vsock_wait_remote_close(fd); 183cdbcc18dSStefan Hajnoczi 184cdbcc18dSStefan Hajnoczi send_byte(fd, -EPIPE, 0); 185cdbcc18dSStefan Hajnoczi recv_byte(fd, 1, 0); 186cdbcc18dSStefan Hajnoczi recv_byte(fd, 0, 0); 187cdbcc18dSStefan Hajnoczi close(fd); 188cdbcc18dSStefan Hajnoczi } 189cdbcc18dSStefan Hajnoczi 190cdbcc18dSStefan Hajnoczi static void test_stream_server_close_server(const struct test_opts *opts) 191cdbcc18dSStefan Hajnoczi { 192cdbcc18dSStefan Hajnoczi int fd; 193cdbcc18dSStefan Hajnoczi 194cdbcc18dSStefan Hajnoczi fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); 195cdbcc18dSStefan Hajnoczi if (fd < 0) { 196cdbcc18dSStefan Hajnoczi perror("accept"); 197cdbcc18dSStefan Hajnoczi exit(EXIT_FAILURE); 198cdbcc18dSStefan Hajnoczi } 199cdbcc18dSStefan Hajnoczi 200cdbcc18dSStefan Hajnoczi send_byte(fd, 1, 0); 201cdbcc18dSStefan Hajnoczi close(fd); 202cdbcc18dSStefan Hajnoczi } 203cdbcc18dSStefan Hajnoczi 204cdbcc18dSStefan Hajnoczi /* With the standard socket sizes, VMCI is able to support about 100 205cdbcc18dSStefan Hajnoczi * concurrent stream connections. 206cdbcc18dSStefan Hajnoczi */ 207cdbcc18dSStefan Hajnoczi #define MULTICONN_NFDS 100 208cdbcc18dSStefan Hajnoczi 209cdbcc18dSStefan Hajnoczi static void test_stream_multiconn_client(const struct test_opts *opts) 210cdbcc18dSStefan Hajnoczi { 211cdbcc18dSStefan Hajnoczi int fds[MULTICONN_NFDS]; 212cdbcc18dSStefan Hajnoczi int i; 213cdbcc18dSStefan Hajnoczi 214cdbcc18dSStefan Hajnoczi for (i = 0; i < MULTICONN_NFDS; i++) { 215cdbcc18dSStefan Hajnoczi fds[i] = vsock_stream_connect(opts->peer_cid, 1234); 216cdbcc18dSStefan Hajnoczi if (fds[i] < 0) { 217cdbcc18dSStefan Hajnoczi perror("connect"); 218cdbcc18dSStefan Hajnoczi exit(EXIT_FAILURE); 219cdbcc18dSStefan Hajnoczi } 220cdbcc18dSStefan Hajnoczi } 221cdbcc18dSStefan Hajnoczi 222cdbcc18dSStefan Hajnoczi for (i = 0; i < MULTICONN_NFDS; i++) { 223cdbcc18dSStefan Hajnoczi if (i % 2) 224cdbcc18dSStefan Hajnoczi recv_byte(fds[i], 1, 0); 225cdbcc18dSStefan Hajnoczi else 226cdbcc18dSStefan Hajnoczi send_byte(fds[i], 1, 0); 227cdbcc18dSStefan Hajnoczi } 228cdbcc18dSStefan Hajnoczi 229cdbcc18dSStefan Hajnoczi for (i = 0; i < MULTICONN_NFDS; i++) 230cdbcc18dSStefan Hajnoczi close(fds[i]); 231cdbcc18dSStefan Hajnoczi } 232cdbcc18dSStefan Hajnoczi 233cdbcc18dSStefan Hajnoczi static void test_stream_multiconn_server(const struct test_opts *opts) 234cdbcc18dSStefan Hajnoczi { 235cdbcc18dSStefan Hajnoczi int fds[MULTICONN_NFDS]; 236cdbcc18dSStefan Hajnoczi int i; 237cdbcc18dSStefan Hajnoczi 238cdbcc18dSStefan Hajnoczi for (i = 0; i < MULTICONN_NFDS; i++) { 239cdbcc18dSStefan Hajnoczi fds[i] = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); 240cdbcc18dSStefan Hajnoczi if (fds[i] < 0) { 241cdbcc18dSStefan Hajnoczi perror("accept"); 242cdbcc18dSStefan Hajnoczi exit(EXIT_FAILURE); 243cdbcc18dSStefan Hajnoczi } 244cdbcc18dSStefan Hajnoczi } 245cdbcc18dSStefan Hajnoczi 246cdbcc18dSStefan Hajnoczi for (i = 0; i < MULTICONN_NFDS; i++) { 247cdbcc18dSStefan Hajnoczi if (i % 2) 248cdbcc18dSStefan Hajnoczi send_byte(fds[i], 1, 0); 249cdbcc18dSStefan Hajnoczi else 250cdbcc18dSStefan Hajnoczi recv_byte(fds[i], 1, 0); 251cdbcc18dSStefan Hajnoczi } 252cdbcc18dSStefan Hajnoczi 253cdbcc18dSStefan Hajnoczi for (i = 0; i < MULTICONN_NFDS; i++) 254cdbcc18dSStefan Hajnoczi close(fds[i]); 255cdbcc18dSStefan Hajnoczi } 256cdbcc18dSStefan Hajnoczi 257d6269a93SStefano Garzarella static void test_stream_msg_peek_client(const struct test_opts *opts) 258d6269a93SStefano Garzarella { 259d6269a93SStefano Garzarella int fd; 260d6269a93SStefano Garzarella 261d6269a93SStefano Garzarella fd = vsock_stream_connect(opts->peer_cid, 1234); 262d6269a93SStefano Garzarella if (fd < 0) { 263d6269a93SStefano Garzarella perror("connect"); 264d6269a93SStefano Garzarella exit(EXIT_FAILURE); 265d6269a93SStefano Garzarella } 266d6269a93SStefano Garzarella 267d6269a93SStefano Garzarella send_byte(fd, 1, 0); 268d6269a93SStefano Garzarella close(fd); 269d6269a93SStefano Garzarella } 270d6269a93SStefano Garzarella 271d6269a93SStefano Garzarella static void test_stream_msg_peek_server(const struct test_opts *opts) 272d6269a93SStefano Garzarella { 273d6269a93SStefano Garzarella int fd; 274d6269a93SStefano Garzarella 275d6269a93SStefano Garzarella fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); 276d6269a93SStefano Garzarella if (fd < 0) { 277d6269a93SStefano Garzarella perror("accept"); 278d6269a93SStefano Garzarella exit(EXIT_FAILURE); 279d6269a93SStefano Garzarella } 280d6269a93SStefano Garzarella 281d6269a93SStefano Garzarella recv_byte(fd, 1, MSG_PEEK); 282d6269a93SStefano Garzarella recv_byte(fd, 1, 0); 283d6269a93SStefano Garzarella close(fd); 284d6269a93SStefano Garzarella } 285d6269a93SStefano Garzarella 28641b792d7SArseny Krasnov #define MESSAGES_CNT 7 2870e115c45SArseny Krasnov #define MSG_EOR_IDX (MESSAGES_CNT / 2) 28841b792d7SArseny Krasnov static void test_seqpacket_msg_bounds_client(const struct test_opts *opts) 28941b792d7SArseny Krasnov { 29041b792d7SArseny Krasnov int fd; 29141b792d7SArseny Krasnov 29241b792d7SArseny Krasnov fd = vsock_seqpacket_connect(opts->peer_cid, 1234); 29341b792d7SArseny Krasnov if (fd < 0) { 29441b792d7SArseny Krasnov perror("connect"); 29541b792d7SArseny Krasnov exit(EXIT_FAILURE); 29641b792d7SArseny Krasnov } 29741b792d7SArseny Krasnov 29841b792d7SArseny Krasnov /* Send several messages, one with MSG_EOR flag */ 29941b792d7SArseny Krasnov for (int i = 0; i < MESSAGES_CNT; i++) 3000e115c45SArseny Krasnov send_byte(fd, 1, (i == MSG_EOR_IDX) ? MSG_EOR : 0); 30141b792d7SArseny Krasnov 30241b792d7SArseny Krasnov control_writeln("SENDDONE"); 30341b792d7SArseny Krasnov close(fd); 30441b792d7SArseny Krasnov } 30541b792d7SArseny Krasnov 30641b792d7SArseny Krasnov static void test_seqpacket_msg_bounds_server(const struct test_opts *opts) 30741b792d7SArseny Krasnov { 30841b792d7SArseny Krasnov int fd; 30941b792d7SArseny Krasnov char buf[16]; 31041b792d7SArseny Krasnov struct msghdr msg = {0}; 31141b792d7SArseny Krasnov struct iovec iov = {0}; 31241b792d7SArseny Krasnov 31341b792d7SArseny Krasnov fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL); 31441b792d7SArseny Krasnov if (fd < 0) { 31541b792d7SArseny Krasnov perror("accept"); 31641b792d7SArseny Krasnov exit(EXIT_FAILURE); 31741b792d7SArseny Krasnov } 31841b792d7SArseny Krasnov 31941b792d7SArseny Krasnov control_expectln("SENDDONE"); 32041b792d7SArseny Krasnov iov.iov_base = buf; 32141b792d7SArseny Krasnov iov.iov_len = sizeof(buf); 32241b792d7SArseny Krasnov msg.msg_iov = &iov; 32341b792d7SArseny Krasnov msg.msg_iovlen = 1; 32441b792d7SArseny Krasnov 32541b792d7SArseny Krasnov for (int i = 0; i < MESSAGES_CNT; i++) { 32641b792d7SArseny Krasnov if (recvmsg(fd, &msg, 0) != 1) { 32741b792d7SArseny Krasnov perror("message bound violated"); 32841b792d7SArseny Krasnov exit(EXIT_FAILURE); 32941b792d7SArseny Krasnov } 3300e115c45SArseny Krasnov 3310e115c45SArseny Krasnov if ((i == MSG_EOR_IDX) ^ !!(msg.msg_flags & MSG_EOR)) { 3320e115c45SArseny Krasnov perror("MSG_EOR"); 3330e115c45SArseny Krasnov exit(EXIT_FAILURE); 3340e115c45SArseny Krasnov } 33541b792d7SArseny Krasnov } 33641b792d7SArseny Krasnov 33741b792d7SArseny Krasnov close(fd); 33841b792d7SArseny Krasnov } 33941b792d7SArseny Krasnov 34041b792d7SArseny Krasnov #define MESSAGE_TRUNC_SZ 32 34141b792d7SArseny Krasnov static void test_seqpacket_msg_trunc_client(const struct test_opts *opts) 34241b792d7SArseny Krasnov { 34341b792d7SArseny Krasnov int fd; 34441b792d7SArseny Krasnov char buf[MESSAGE_TRUNC_SZ]; 34541b792d7SArseny Krasnov 34641b792d7SArseny Krasnov fd = vsock_seqpacket_connect(opts->peer_cid, 1234); 34741b792d7SArseny Krasnov if (fd < 0) { 34841b792d7SArseny Krasnov perror("connect"); 34941b792d7SArseny Krasnov exit(EXIT_FAILURE); 35041b792d7SArseny Krasnov } 35141b792d7SArseny Krasnov 35241b792d7SArseny Krasnov if (send(fd, buf, sizeof(buf), 0) != sizeof(buf)) { 35341b792d7SArseny Krasnov perror("send failed"); 35441b792d7SArseny Krasnov exit(EXIT_FAILURE); 35541b792d7SArseny Krasnov } 35641b792d7SArseny Krasnov 35741b792d7SArseny Krasnov control_writeln("SENDDONE"); 35841b792d7SArseny Krasnov close(fd); 35941b792d7SArseny Krasnov } 36041b792d7SArseny Krasnov 36141b792d7SArseny Krasnov static void test_seqpacket_msg_trunc_server(const struct test_opts *opts) 36241b792d7SArseny Krasnov { 36341b792d7SArseny Krasnov int fd; 36441b792d7SArseny Krasnov char buf[MESSAGE_TRUNC_SZ / 2]; 36541b792d7SArseny Krasnov struct msghdr msg = {0}; 36641b792d7SArseny Krasnov struct iovec iov = {0}; 36741b792d7SArseny Krasnov 36841b792d7SArseny Krasnov fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL); 36941b792d7SArseny Krasnov if (fd < 0) { 37041b792d7SArseny Krasnov perror("accept"); 37141b792d7SArseny Krasnov exit(EXIT_FAILURE); 37241b792d7SArseny Krasnov } 37341b792d7SArseny Krasnov 37441b792d7SArseny Krasnov control_expectln("SENDDONE"); 37541b792d7SArseny Krasnov iov.iov_base = buf; 37641b792d7SArseny Krasnov iov.iov_len = sizeof(buf); 37741b792d7SArseny Krasnov msg.msg_iov = &iov; 37841b792d7SArseny Krasnov msg.msg_iovlen = 1; 37941b792d7SArseny Krasnov 38041b792d7SArseny Krasnov ssize_t ret = recvmsg(fd, &msg, MSG_TRUNC); 38141b792d7SArseny Krasnov 38241b792d7SArseny Krasnov if (ret != MESSAGE_TRUNC_SZ) { 38341b792d7SArseny Krasnov printf("%zi\n", ret); 38441b792d7SArseny Krasnov perror("MSG_TRUNC doesn't work"); 38541b792d7SArseny Krasnov exit(EXIT_FAILURE); 38641b792d7SArseny Krasnov } 38741b792d7SArseny Krasnov 38841b792d7SArseny Krasnov if (!(msg.msg_flags & MSG_TRUNC)) { 38941b792d7SArseny Krasnov fprintf(stderr, "MSG_TRUNC expected\n"); 39041b792d7SArseny Krasnov exit(EXIT_FAILURE); 39141b792d7SArseny Krasnov } 39241b792d7SArseny Krasnov 39341b792d7SArseny Krasnov close(fd); 39441b792d7SArseny Krasnov } 39541b792d7SArseny Krasnov 396efb3719fSKrasnov Arseniy Vladimirovich static time_t current_nsec(void) 397efb3719fSKrasnov Arseniy Vladimirovich { 398efb3719fSKrasnov Arseniy Vladimirovich struct timespec ts; 399efb3719fSKrasnov Arseniy Vladimirovich 400efb3719fSKrasnov Arseniy Vladimirovich if (clock_gettime(CLOCK_REALTIME, &ts)) { 401efb3719fSKrasnov Arseniy Vladimirovich perror("clock_gettime(3) failed"); 402efb3719fSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 403efb3719fSKrasnov Arseniy Vladimirovich } 404efb3719fSKrasnov Arseniy Vladimirovich 405efb3719fSKrasnov Arseniy Vladimirovich return (ts.tv_sec * 1000000000ULL) + ts.tv_nsec; 406efb3719fSKrasnov Arseniy Vladimirovich } 407efb3719fSKrasnov Arseniy Vladimirovich 408efb3719fSKrasnov Arseniy Vladimirovich #define RCVTIMEO_TIMEOUT_SEC 1 409efb3719fSKrasnov Arseniy Vladimirovich #define READ_OVERHEAD_NSEC 250000000 /* 0.25 sec */ 410efb3719fSKrasnov Arseniy Vladimirovich 411efb3719fSKrasnov Arseniy Vladimirovich static void test_seqpacket_timeout_client(const struct test_opts *opts) 412efb3719fSKrasnov Arseniy Vladimirovich { 413efb3719fSKrasnov Arseniy Vladimirovich int fd; 414efb3719fSKrasnov Arseniy Vladimirovich struct timeval tv; 415efb3719fSKrasnov Arseniy Vladimirovich char dummy; 416efb3719fSKrasnov Arseniy Vladimirovich time_t read_enter_ns; 417efb3719fSKrasnov Arseniy Vladimirovich time_t read_overhead_ns; 418efb3719fSKrasnov Arseniy Vladimirovich 419efb3719fSKrasnov Arseniy Vladimirovich fd = vsock_seqpacket_connect(opts->peer_cid, 1234); 420efb3719fSKrasnov Arseniy Vladimirovich if (fd < 0) { 421efb3719fSKrasnov Arseniy Vladimirovich perror("connect"); 422efb3719fSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 423efb3719fSKrasnov Arseniy Vladimirovich } 424efb3719fSKrasnov Arseniy Vladimirovich 425efb3719fSKrasnov Arseniy Vladimirovich tv.tv_sec = RCVTIMEO_TIMEOUT_SEC; 426efb3719fSKrasnov Arseniy Vladimirovich tv.tv_usec = 0; 427efb3719fSKrasnov Arseniy Vladimirovich 428efb3719fSKrasnov Arseniy Vladimirovich if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(tv)) == -1) { 429efb3719fSKrasnov Arseniy Vladimirovich perror("setsockopt 'SO_RCVTIMEO'"); 430efb3719fSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 431efb3719fSKrasnov Arseniy Vladimirovich } 432efb3719fSKrasnov Arseniy Vladimirovich 433efb3719fSKrasnov Arseniy Vladimirovich read_enter_ns = current_nsec(); 434efb3719fSKrasnov Arseniy Vladimirovich 435efb3719fSKrasnov Arseniy Vladimirovich if (read(fd, &dummy, sizeof(dummy)) != -1) { 436efb3719fSKrasnov Arseniy Vladimirovich fprintf(stderr, 437efb3719fSKrasnov Arseniy Vladimirovich "expected 'dummy' read(2) failure\n"); 438efb3719fSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 439efb3719fSKrasnov Arseniy Vladimirovich } 440efb3719fSKrasnov Arseniy Vladimirovich 441efb3719fSKrasnov Arseniy Vladimirovich if (errno != EAGAIN) { 442efb3719fSKrasnov Arseniy Vladimirovich perror("EAGAIN expected"); 443efb3719fSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 444efb3719fSKrasnov Arseniy Vladimirovich } 445efb3719fSKrasnov Arseniy Vladimirovich 446efb3719fSKrasnov Arseniy Vladimirovich read_overhead_ns = current_nsec() - read_enter_ns - 447efb3719fSKrasnov Arseniy Vladimirovich 1000000000ULL * RCVTIMEO_TIMEOUT_SEC; 448efb3719fSKrasnov Arseniy Vladimirovich 449efb3719fSKrasnov Arseniy Vladimirovich if (read_overhead_ns > READ_OVERHEAD_NSEC) { 450efb3719fSKrasnov Arseniy Vladimirovich fprintf(stderr, 451efb3719fSKrasnov Arseniy Vladimirovich "too much time in read(2), %lu > %i ns\n", 452efb3719fSKrasnov Arseniy Vladimirovich read_overhead_ns, READ_OVERHEAD_NSEC); 453efb3719fSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 454efb3719fSKrasnov Arseniy Vladimirovich } 455efb3719fSKrasnov Arseniy Vladimirovich 456efb3719fSKrasnov Arseniy Vladimirovich control_writeln("WAITDONE"); 457efb3719fSKrasnov Arseniy Vladimirovich close(fd); 458efb3719fSKrasnov Arseniy Vladimirovich } 459efb3719fSKrasnov Arseniy Vladimirovich 460efb3719fSKrasnov Arseniy Vladimirovich static void test_seqpacket_timeout_server(const struct test_opts *opts) 461efb3719fSKrasnov Arseniy Vladimirovich { 462efb3719fSKrasnov Arseniy Vladimirovich int fd; 463efb3719fSKrasnov Arseniy Vladimirovich 464efb3719fSKrasnov Arseniy Vladimirovich fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL); 465efb3719fSKrasnov Arseniy Vladimirovich if (fd < 0) { 466efb3719fSKrasnov Arseniy Vladimirovich perror("accept"); 467efb3719fSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 468efb3719fSKrasnov Arseniy Vladimirovich } 469efb3719fSKrasnov Arseniy Vladimirovich 470efb3719fSKrasnov Arseniy Vladimirovich control_expectln("WAITDONE"); 471efb3719fSKrasnov Arseniy Vladimirovich close(fd); 472efb3719fSKrasnov Arseniy Vladimirovich } 473efb3719fSKrasnov Arseniy Vladimirovich 474*e89600ebSKrasnov Arseniy Vladimirovich #define BUF_PATTERN_1 'a' 475*e89600ebSKrasnov Arseniy Vladimirovich #define BUF_PATTERN_2 'b' 476*e89600ebSKrasnov Arseniy Vladimirovich 477*e89600ebSKrasnov Arseniy Vladimirovich static void test_seqpacket_invalid_rec_buffer_client(const struct test_opts *opts) 478*e89600ebSKrasnov Arseniy Vladimirovich { 479*e89600ebSKrasnov Arseniy Vladimirovich int fd; 480*e89600ebSKrasnov Arseniy Vladimirovich unsigned char *buf1; 481*e89600ebSKrasnov Arseniy Vladimirovich unsigned char *buf2; 482*e89600ebSKrasnov Arseniy Vladimirovich int buf_size = getpagesize() * 3; 483*e89600ebSKrasnov Arseniy Vladimirovich 484*e89600ebSKrasnov Arseniy Vladimirovich fd = vsock_seqpacket_connect(opts->peer_cid, 1234); 485*e89600ebSKrasnov Arseniy Vladimirovich if (fd < 0) { 486*e89600ebSKrasnov Arseniy Vladimirovich perror("connect"); 487*e89600ebSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 488*e89600ebSKrasnov Arseniy Vladimirovich } 489*e89600ebSKrasnov Arseniy Vladimirovich 490*e89600ebSKrasnov Arseniy Vladimirovich buf1 = malloc(buf_size); 491*e89600ebSKrasnov Arseniy Vladimirovich if (!buf1) { 492*e89600ebSKrasnov Arseniy Vladimirovich perror("'malloc()' for 'buf1'"); 493*e89600ebSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 494*e89600ebSKrasnov Arseniy Vladimirovich } 495*e89600ebSKrasnov Arseniy Vladimirovich 496*e89600ebSKrasnov Arseniy Vladimirovich buf2 = malloc(buf_size); 497*e89600ebSKrasnov Arseniy Vladimirovich if (!buf2) { 498*e89600ebSKrasnov Arseniy Vladimirovich perror("'malloc()' for 'buf2'"); 499*e89600ebSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 500*e89600ebSKrasnov Arseniy Vladimirovich } 501*e89600ebSKrasnov Arseniy Vladimirovich 502*e89600ebSKrasnov Arseniy Vladimirovich memset(buf1, BUF_PATTERN_1, buf_size); 503*e89600ebSKrasnov Arseniy Vladimirovich memset(buf2, BUF_PATTERN_2, buf_size); 504*e89600ebSKrasnov Arseniy Vladimirovich 505*e89600ebSKrasnov Arseniy Vladimirovich if (send(fd, buf1, buf_size, 0) != buf_size) { 506*e89600ebSKrasnov Arseniy Vladimirovich perror("send failed"); 507*e89600ebSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 508*e89600ebSKrasnov Arseniy Vladimirovich } 509*e89600ebSKrasnov Arseniy Vladimirovich 510*e89600ebSKrasnov Arseniy Vladimirovich if (send(fd, buf2, buf_size, 0) != buf_size) { 511*e89600ebSKrasnov Arseniy Vladimirovich perror("send failed"); 512*e89600ebSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 513*e89600ebSKrasnov Arseniy Vladimirovich } 514*e89600ebSKrasnov Arseniy Vladimirovich 515*e89600ebSKrasnov Arseniy Vladimirovich close(fd); 516*e89600ebSKrasnov Arseniy Vladimirovich } 517*e89600ebSKrasnov Arseniy Vladimirovich 518*e89600ebSKrasnov Arseniy Vladimirovich static void test_seqpacket_invalid_rec_buffer_server(const struct test_opts *opts) 519*e89600ebSKrasnov Arseniy Vladimirovich { 520*e89600ebSKrasnov Arseniy Vladimirovich int fd; 521*e89600ebSKrasnov Arseniy Vladimirovich unsigned char *broken_buf; 522*e89600ebSKrasnov Arseniy Vladimirovich unsigned char *valid_buf; 523*e89600ebSKrasnov Arseniy Vladimirovich int page_size = getpagesize(); 524*e89600ebSKrasnov Arseniy Vladimirovich int buf_size = page_size * 3; 525*e89600ebSKrasnov Arseniy Vladimirovich ssize_t res; 526*e89600ebSKrasnov Arseniy Vladimirovich int prot = PROT_READ | PROT_WRITE; 527*e89600ebSKrasnov Arseniy Vladimirovich int flags = MAP_PRIVATE | MAP_ANONYMOUS; 528*e89600ebSKrasnov Arseniy Vladimirovich int i; 529*e89600ebSKrasnov Arseniy Vladimirovich 530*e89600ebSKrasnov Arseniy Vladimirovich fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL); 531*e89600ebSKrasnov Arseniy Vladimirovich if (fd < 0) { 532*e89600ebSKrasnov Arseniy Vladimirovich perror("accept"); 533*e89600ebSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 534*e89600ebSKrasnov Arseniy Vladimirovich } 535*e89600ebSKrasnov Arseniy Vladimirovich 536*e89600ebSKrasnov Arseniy Vladimirovich /* Setup first buffer. */ 537*e89600ebSKrasnov Arseniy Vladimirovich broken_buf = mmap(NULL, buf_size, prot, flags, -1, 0); 538*e89600ebSKrasnov Arseniy Vladimirovich if (broken_buf == MAP_FAILED) { 539*e89600ebSKrasnov Arseniy Vladimirovich perror("mmap for 'broken_buf'"); 540*e89600ebSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 541*e89600ebSKrasnov Arseniy Vladimirovich } 542*e89600ebSKrasnov Arseniy Vladimirovich 543*e89600ebSKrasnov Arseniy Vladimirovich /* Unmap "hole" in buffer. */ 544*e89600ebSKrasnov Arseniy Vladimirovich if (munmap(broken_buf + page_size, page_size)) { 545*e89600ebSKrasnov Arseniy Vladimirovich perror("'broken_buf' setup"); 546*e89600ebSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 547*e89600ebSKrasnov Arseniy Vladimirovich } 548*e89600ebSKrasnov Arseniy Vladimirovich 549*e89600ebSKrasnov Arseniy Vladimirovich valid_buf = mmap(NULL, buf_size, prot, flags, -1, 0); 550*e89600ebSKrasnov Arseniy Vladimirovich if (valid_buf == MAP_FAILED) { 551*e89600ebSKrasnov Arseniy Vladimirovich perror("mmap for 'valid_buf'"); 552*e89600ebSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 553*e89600ebSKrasnov Arseniy Vladimirovich } 554*e89600ebSKrasnov Arseniy Vladimirovich 555*e89600ebSKrasnov Arseniy Vladimirovich /* Try to fill buffer with unmapped middle. */ 556*e89600ebSKrasnov Arseniy Vladimirovich res = read(fd, broken_buf, buf_size); 557*e89600ebSKrasnov Arseniy Vladimirovich if (res != -1) { 558*e89600ebSKrasnov Arseniy Vladimirovich fprintf(stderr, 559*e89600ebSKrasnov Arseniy Vladimirovich "expected 'broken_buf' read(2) failure, got %zi\n", 560*e89600ebSKrasnov Arseniy Vladimirovich res); 561*e89600ebSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 562*e89600ebSKrasnov Arseniy Vladimirovich } 563*e89600ebSKrasnov Arseniy Vladimirovich 564*e89600ebSKrasnov Arseniy Vladimirovich if (errno != ENOMEM) { 565*e89600ebSKrasnov Arseniy Vladimirovich perror("unexpected errno of 'broken_buf'"); 566*e89600ebSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 567*e89600ebSKrasnov Arseniy Vladimirovich } 568*e89600ebSKrasnov Arseniy Vladimirovich 569*e89600ebSKrasnov Arseniy Vladimirovich /* Try to fill valid buffer. */ 570*e89600ebSKrasnov Arseniy Vladimirovich res = read(fd, valid_buf, buf_size); 571*e89600ebSKrasnov Arseniy Vladimirovich if (res < 0) { 572*e89600ebSKrasnov Arseniy Vladimirovich perror("unexpected 'valid_buf' read(2) failure"); 573*e89600ebSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 574*e89600ebSKrasnov Arseniy Vladimirovich } 575*e89600ebSKrasnov Arseniy Vladimirovich 576*e89600ebSKrasnov Arseniy Vladimirovich if (res != buf_size) { 577*e89600ebSKrasnov Arseniy Vladimirovich fprintf(stderr, 578*e89600ebSKrasnov Arseniy Vladimirovich "invalid 'valid_buf' read(2), expected %i, got %zi\n", 579*e89600ebSKrasnov Arseniy Vladimirovich buf_size, res); 580*e89600ebSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 581*e89600ebSKrasnov Arseniy Vladimirovich } 582*e89600ebSKrasnov Arseniy Vladimirovich 583*e89600ebSKrasnov Arseniy Vladimirovich for (i = 0; i < buf_size; i++) { 584*e89600ebSKrasnov Arseniy Vladimirovich if (valid_buf[i] != BUF_PATTERN_2) { 585*e89600ebSKrasnov Arseniy Vladimirovich fprintf(stderr, 586*e89600ebSKrasnov Arseniy Vladimirovich "invalid pattern for 'valid_buf' at %i, expected %hhX, got %hhX\n", 587*e89600ebSKrasnov Arseniy Vladimirovich i, BUF_PATTERN_2, valid_buf[i]); 588*e89600ebSKrasnov Arseniy Vladimirovich exit(EXIT_FAILURE); 589*e89600ebSKrasnov Arseniy Vladimirovich } 590*e89600ebSKrasnov Arseniy Vladimirovich } 591*e89600ebSKrasnov Arseniy Vladimirovich 592*e89600ebSKrasnov Arseniy Vladimirovich /* Unmap buffers. */ 593*e89600ebSKrasnov Arseniy Vladimirovich munmap(broken_buf, page_size); 594*e89600ebSKrasnov Arseniy Vladimirovich munmap(broken_buf + page_size * 2, page_size); 595*e89600ebSKrasnov Arseniy Vladimirovich munmap(valid_buf, buf_size); 596*e89600ebSKrasnov Arseniy Vladimirovich close(fd); 597*e89600ebSKrasnov Arseniy Vladimirovich } 598*e89600ebSKrasnov Arseniy Vladimirovich 599cdbcc18dSStefan Hajnoczi static struct test_case test_cases[] = { 600cdbcc18dSStefan Hajnoczi { 601cdbcc18dSStefan Hajnoczi .name = "SOCK_STREAM connection reset", 602cdbcc18dSStefan Hajnoczi .run_client = test_stream_connection_reset, 603cdbcc18dSStefan Hajnoczi }, 604cdbcc18dSStefan Hajnoczi { 6059de9f7d1SSebastien Boeuf .name = "SOCK_STREAM bind only", 6069de9f7d1SSebastien Boeuf .run_client = test_stream_bind_only_client, 6079de9f7d1SSebastien Boeuf .run_server = test_stream_bind_only_server, 6089de9f7d1SSebastien Boeuf }, 6099de9f7d1SSebastien Boeuf { 610cdbcc18dSStefan Hajnoczi .name = "SOCK_STREAM client close", 611cdbcc18dSStefan Hajnoczi .run_client = test_stream_client_close_client, 612cdbcc18dSStefan Hajnoczi .run_server = test_stream_client_close_server, 613cdbcc18dSStefan Hajnoczi }, 614cdbcc18dSStefan Hajnoczi { 615cdbcc18dSStefan Hajnoczi .name = "SOCK_STREAM server close", 616cdbcc18dSStefan Hajnoczi .run_client = test_stream_server_close_client, 617cdbcc18dSStefan Hajnoczi .run_server = test_stream_server_close_server, 618cdbcc18dSStefan Hajnoczi }, 619cdbcc18dSStefan Hajnoczi { 620cdbcc18dSStefan Hajnoczi .name = "SOCK_STREAM multiple connections", 621cdbcc18dSStefan Hajnoczi .run_client = test_stream_multiconn_client, 622cdbcc18dSStefan Hajnoczi .run_server = test_stream_multiconn_server, 623cdbcc18dSStefan Hajnoczi }, 624d6269a93SStefano Garzarella { 625d6269a93SStefano Garzarella .name = "SOCK_STREAM MSG_PEEK", 626d6269a93SStefano Garzarella .run_client = test_stream_msg_peek_client, 627d6269a93SStefano Garzarella .run_server = test_stream_msg_peek_server, 628d6269a93SStefano Garzarella }, 62941b792d7SArseny Krasnov { 63041b792d7SArseny Krasnov .name = "SOCK_SEQPACKET msg bounds", 63141b792d7SArseny Krasnov .run_client = test_seqpacket_msg_bounds_client, 63241b792d7SArseny Krasnov .run_server = test_seqpacket_msg_bounds_server, 63341b792d7SArseny Krasnov }, 63441b792d7SArseny Krasnov { 63541b792d7SArseny Krasnov .name = "SOCK_SEQPACKET MSG_TRUNC flag", 63641b792d7SArseny Krasnov .run_client = test_seqpacket_msg_trunc_client, 63741b792d7SArseny Krasnov .run_server = test_seqpacket_msg_trunc_server, 63841b792d7SArseny Krasnov }, 639efb3719fSKrasnov Arseniy Vladimirovich { 640efb3719fSKrasnov Arseniy Vladimirovich .name = "SOCK_SEQPACKET timeout", 641efb3719fSKrasnov Arseniy Vladimirovich .run_client = test_seqpacket_timeout_client, 642efb3719fSKrasnov Arseniy Vladimirovich .run_server = test_seqpacket_timeout_server, 643efb3719fSKrasnov Arseniy Vladimirovich }, 644*e89600ebSKrasnov Arseniy Vladimirovich { 645*e89600ebSKrasnov Arseniy Vladimirovich .name = "SOCK_SEQPACKET invalid receive buffer", 646*e89600ebSKrasnov Arseniy Vladimirovich .run_client = test_seqpacket_invalid_rec_buffer_client, 647*e89600ebSKrasnov Arseniy Vladimirovich .run_server = test_seqpacket_invalid_rec_buffer_server, 648*e89600ebSKrasnov Arseniy Vladimirovich }, 649cdbcc18dSStefan Hajnoczi {}, 650cdbcc18dSStefan Hajnoczi }; 651cdbcc18dSStefan Hajnoczi 652cdbcc18dSStefan Hajnoczi static const char optstring[] = ""; 653cdbcc18dSStefan Hajnoczi static const struct option longopts[] = { 654cdbcc18dSStefan Hajnoczi { 655cdbcc18dSStefan Hajnoczi .name = "control-host", 656cdbcc18dSStefan Hajnoczi .has_arg = required_argument, 657cdbcc18dSStefan Hajnoczi .val = 'H', 658cdbcc18dSStefan Hajnoczi }, 659cdbcc18dSStefan Hajnoczi { 660cdbcc18dSStefan Hajnoczi .name = "control-port", 661cdbcc18dSStefan Hajnoczi .has_arg = required_argument, 662cdbcc18dSStefan Hajnoczi .val = 'P', 663cdbcc18dSStefan Hajnoczi }, 664cdbcc18dSStefan Hajnoczi { 665cdbcc18dSStefan Hajnoczi .name = "mode", 666cdbcc18dSStefan Hajnoczi .has_arg = required_argument, 667cdbcc18dSStefan Hajnoczi .val = 'm', 668cdbcc18dSStefan Hajnoczi }, 669cdbcc18dSStefan Hajnoczi { 670cdbcc18dSStefan Hajnoczi .name = "peer-cid", 671cdbcc18dSStefan Hajnoczi .has_arg = required_argument, 672cdbcc18dSStefan Hajnoczi .val = 'p', 673cdbcc18dSStefan Hajnoczi }, 674cdbcc18dSStefan Hajnoczi { 6755a2b2425SStefano Garzarella .name = "list", 6765a2b2425SStefano Garzarella .has_arg = no_argument, 6775a2b2425SStefano Garzarella .val = 'l', 6785a2b2425SStefano Garzarella }, 6795a2b2425SStefano Garzarella { 6805a2b2425SStefano Garzarella .name = "skip", 6815a2b2425SStefano Garzarella .has_arg = required_argument, 6825a2b2425SStefano Garzarella .val = 's', 6835a2b2425SStefano Garzarella }, 6845a2b2425SStefano Garzarella { 685cdbcc18dSStefan Hajnoczi .name = "help", 686cdbcc18dSStefan Hajnoczi .has_arg = no_argument, 687cdbcc18dSStefan Hajnoczi .val = '?', 688cdbcc18dSStefan Hajnoczi }, 689cdbcc18dSStefan Hajnoczi {}, 690cdbcc18dSStefan Hajnoczi }; 691cdbcc18dSStefan Hajnoczi 692cdbcc18dSStefan Hajnoczi static void usage(void) 693cdbcc18dSStefan Hajnoczi { 6945a2b2425SStefano Garzarella fprintf(stderr, "Usage: vsock_test [--help] [--control-host=<host>] --control-port=<port> --mode=client|server --peer-cid=<cid> [--list] [--skip=<test_id>]\n" 695cdbcc18dSStefan Hajnoczi "\n" 696cdbcc18dSStefan Hajnoczi " Server: vsock_test --control-port=1234 --mode=server --peer-cid=3\n" 697cdbcc18dSStefan Hajnoczi " Client: vsock_test --control-host=192.168.0.1 --control-port=1234 --mode=client --peer-cid=2\n" 698cdbcc18dSStefan Hajnoczi "\n" 699cdbcc18dSStefan Hajnoczi "Run vsock.ko tests. Must be launched in both guest\n" 700cdbcc18dSStefan Hajnoczi "and host. One side must use --mode=client and\n" 701cdbcc18dSStefan Hajnoczi "the other side must use --mode=server.\n" 702cdbcc18dSStefan Hajnoczi "\n" 703cdbcc18dSStefan Hajnoczi "A TCP control socket connection is used to coordinate tests\n" 704cdbcc18dSStefan Hajnoczi "between the client and the server. The server requires a\n" 705cdbcc18dSStefan Hajnoczi "listen address and the client requires an address to\n" 706cdbcc18dSStefan Hajnoczi "connect to.\n" 707cdbcc18dSStefan Hajnoczi "\n" 7088d00b93fSStefano Garzarella "The CID of the other side must be given with --peer-cid=<cid>.\n" 7098d00b93fSStefano Garzarella "\n" 7108d00b93fSStefano Garzarella "Options:\n" 7118d00b93fSStefano Garzarella " --help This help message\n" 7128d00b93fSStefano Garzarella " --control-host <host> Server IP address to connect to\n" 7138d00b93fSStefano Garzarella " --control-port <port> Server port to listen on/connect to\n" 7148d00b93fSStefano Garzarella " --mode client|server Server or client mode\n" 7158d00b93fSStefano Garzarella " --peer-cid <cid> CID of the other side\n" 7168d00b93fSStefano Garzarella " --list List of tests that will be executed\n" 7178d00b93fSStefano Garzarella " --skip <test_id> Test ID to skip;\n" 7188d00b93fSStefano Garzarella " use multiple --skip options to skip more tests\n" 7198d00b93fSStefano Garzarella ); 720cdbcc18dSStefan Hajnoczi exit(EXIT_FAILURE); 721cdbcc18dSStefan Hajnoczi } 722cdbcc18dSStefan Hajnoczi 723cdbcc18dSStefan Hajnoczi int main(int argc, char **argv) 724cdbcc18dSStefan Hajnoczi { 725cdbcc18dSStefan Hajnoczi const char *control_host = NULL; 726cdbcc18dSStefan Hajnoczi const char *control_port = NULL; 727cdbcc18dSStefan Hajnoczi struct test_opts opts = { 728cdbcc18dSStefan Hajnoczi .mode = TEST_MODE_UNSET, 729cdbcc18dSStefan Hajnoczi .peer_cid = VMADDR_CID_ANY, 730cdbcc18dSStefan Hajnoczi }; 731cdbcc18dSStefan Hajnoczi 732cdbcc18dSStefan Hajnoczi init_signals(); 733cdbcc18dSStefan Hajnoczi 734cdbcc18dSStefan Hajnoczi for (;;) { 735cdbcc18dSStefan Hajnoczi int opt = getopt_long(argc, argv, optstring, longopts, NULL); 736cdbcc18dSStefan Hajnoczi 737cdbcc18dSStefan Hajnoczi if (opt == -1) 738cdbcc18dSStefan Hajnoczi break; 739cdbcc18dSStefan Hajnoczi 740cdbcc18dSStefan Hajnoczi switch (opt) { 741cdbcc18dSStefan Hajnoczi case 'H': 742cdbcc18dSStefan Hajnoczi control_host = optarg; 743cdbcc18dSStefan Hajnoczi break; 744cdbcc18dSStefan Hajnoczi case 'm': 745cdbcc18dSStefan Hajnoczi if (strcmp(optarg, "client") == 0) 746cdbcc18dSStefan Hajnoczi opts.mode = TEST_MODE_CLIENT; 747cdbcc18dSStefan Hajnoczi else if (strcmp(optarg, "server") == 0) 748cdbcc18dSStefan Hajnoczi opts.mode = TEST_MODE_SERVER; 749cdbcc18dSStefan Hajnoczi else { 750cdbcc18dSStefan Hajnoczi fprintf(stderr, "--mode must be \"client\" or \"server\"\n"); 751cdbcc18dSStefan Hajnoczi return EXIT_FAILURE; 752cdbcc18dSStefan Hajnoczi } 753cdbcc18dSStefan Hajnoczi break; 754cdbcc18dSStefan Hajnoczi case 'p': 755cdbcc18dSStefan Hajnoczi opts.peer_cid = parse_cid(optarg); 756cdbcc18dSStefan Hajnoczi break; 757cdbcc18dSStefan Hajnoczi case 'P': 758cdbcc18dSStefan Hajnoczi control_port = optarg; 759cdbcc18dSStefan Hajnoczi break; 7605a2b2425SStefano Garzarella case 'l': 7615a2b2425SStefano Garzarella list_tests(test_cases); 7625a2b2425SStefano Garzarella break; 7635a2b2425SStefano Garzarella case 's': 7645a2b2425SStefano Garzarella skip_test(test_cases, ARRAY_SIZE(test_cases) - 1, 7655a2b2425SStefano Garzarella optarg); 7665a2b2425SStefano Garzarella break; 767cdbcc18dSStefan Hajnoczi case '?': 768cdbcc18dSStefan Hajnoczi default: 769cdbcc18dSStefan Hajnoczi usage(); 770cdbcc18dSStefan Hajnoczi } 771cdbcc18dSStefan Hajnoczi } 772cdbcc18dSStefan Hajnoczi 773cdbcc18dSStefan Hajnoczi if (!control_port) 774cdbcc18dSStefan Hajnoczi usage(); 775cdbcc18dSStefan Hajnoczi if (opts.mode == TEST_MODE_UNSET) 776cdbcc18dSStefan Hajnoczi usage(); 777cdbcc18dSStefan Hajnoczi if (opts.peer_cid == VMADDR_CID_ANY) 778cdbcc18dSStefan Hajnoczi usage(); 779cdbcc18dSStefan Hajnoczi 780cdbcc18dSStefan Hajnoczi if (!control_host) { 781cdbcc18dSStefan Hajnoczi if (opts.mode != TEST_MODE_SERVER) 782cdbcc18dSStefan Hajnoczi usage(); 783cdbcc18dSStefan Hajnoczi control_host = "0.0.0.0"; 784cdbcc18dSStefan Hajnoczi } 785cdbcc18dSStefan Hajnoczi 786cdbcc18dSStefan Hajnoczi control_init(control_host, control_port, 787cdbcc18dSStefan Hajnoczi opts.mode == TEST_MODE_SERVER); 788cdbcc18dSStefan Hajnoczi 789cdbcc18dSStefan Hajnoczi run_tests(test_cases, &opts); 790cdbcc18dSStefan Hajnoczi 791cdbcc18dSStefan Hajnoczi control_cleanup(); 792cdbcc18dSStefan Hajnoczi return EXIT_SUCCESS; 793cdbcc18dSStefan Hajnoczi } 794