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> 17cdbcc18dSStefan Hajnoczi 18cdbcc18dSStefan Hajnoczi #include "timeout.h" 19cdbcc18dSStefan Hajnoczi #include "control.h" 20cdbcc18dSStefan Hajnoczi #include "util.h" 21cdbcc18dSStefan Hajnoczi 22cdbcc18dSStefan Hajnoczi static void test_stream_connection_reset(const struct test_opts *opts) 23cdbcc18dSStefan Hajnoczi { 24cdbcc18dSStefan Hajnoczi union { 25cdbcc18dSStefan Hajnoczi struct sockaddr sa; 26cdbcc18dSStefan Hajnoczi struct sockaddr_vm svm; 27cdbcc18dSStefan Hajnoczi } addr = { 28cdbcc18dSStefan Hajnoczi .svm = { 29cdbcc18dSStefan Hajnoczi .svm_family = AF_VSOCK, 30cdbcc18dSStefan Hajnoczi .svm_port = 1234, 31cdbcc18dSStefan Hajnoczi .svm_cid = opts->peer_cid, 32cdbcc18dSStefan Hajnoczi }, 33cdbcc18dSStefan Hajnoczi }; 34cdbcc18dSStefan Hajnoczi int ret; 35cdbcc18dSStefan Hajnoczi int fd; 36cdbcc18dSStefan Hajnoczi 37cdbcc18dSStefan Hajnoczi fd = socket(AF_VSOCK, SOCK_STREAM, 0); 38cdbcc18dSStefan Hajnoczi 39cdbcc18dSStefan Hajnoczi timeout_begin(TIMEOUT); 40cdbcc18dSStefan Hajnoczi do { 41cdbcc18dSStefan Hajnoczi ret = connect(fd, &addr.sa, sizeof(addr.svm)); 42cdbcc18dSStefan Hajnoczi timeout_check("connect"); 43cdbcc18dSStefan Hajnoczi } while (ret < 0 && errno == EINTR); 44cdbcc18dSStefan Hajnoczi timeout_end(); 45cdbcc18dSStefan Hajnoczi 46cdbcc18dSStefan Hajnoczi if (ret != -1) { 47cdbcc18dSStefan Hajnoczi fprintf(stderr, "expected connect(2) failure, got %d\n", ret); 48cdbcc18dSStefan Hajnoczi exit(EXIT_FAILURE); 49cdbcc18dSStefan Hajnoczi } 50cdbcc18dSStefan Hajnoczi if (errno != ECONNRESET) { 51cdbcc18dSStefan Hajnoczi fprintf(stderr, "unexpected connect(2) errno %d\n", errno); 52cdbcc18dSStefan Hajnoczi exit(EXIT_FAILURE); 53cdbcc18dSStefan Hajnoczi } 54cdbcc18dSStefan Hajnoczi 55cdbcc18dSStefan Hajnoczi close(fd); 56cdbcc18dSStefan Hajnoczi } 57cdbcc18dSStefan Hajnoczi 58cdbcc18dSStefan Hajnoczi static void test_stream_client_close_client(const struct test_opts *opts) 59cdbcc18dSStefan Hajnoczi { 60cdbcc18dSStefan Hajnoczi int fd; 61cdbcc18dSStefan Hajnoczi 62cdbcc18dSStefan Hajnoczi fd = vsock_stream_connect(opts->peer_cid, 1234); 63cdbcc18dSStefan Hajnoczi if (fd < 0) { 64cdbcc18dSStefan Hajnoczi perror("connect"); 65cdbcc18dSStefan Hajnoczi exit(EXIT_FAILURE); 66cdbcc18dSStefan Hajnoczi } 67cdbcc18dSStefan Hajnoczi 68cdbcc18dSStefan Hajnoczi send_byte(fd, 1, 0); 69cdbcc18dSStefan Hajnoczi close(fd); 70cdbcc18dSStefan Hajnoczi } 71cdbcc18dSStefan Hajnoczi 72cdbcc18dSStefan Hajnoczi static void test_stream_client_close_server(const struct test_opts *opts) 73cdbcc18dSStefan Hajnoczi { 74cdbcc18dSStefan Hajnoczi int fd; 75cdbcc18dSStefan Hajnoczi 76cdbcc18dSStefan Hajnoczi fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); 77cdbcc18dSStefan Hajnoczi if (fd < 0) { 78cdbcc18dSStefan Hajnoczi perror("accept"); 79cdbcc18dSStefan Hajnoczi exit(EXIT_FAILURE); 80cdbcc18dSStefan Hajnoczi } 81cdbcc18dSStefan Hajnoczi 82770ce007SStefano Garzarella /* Wait for the remote to close the connection, before check 83770ce007SStefano Garzarella * -EPIPE error on send. 84770ce007SStefano Garzarella */ 85770ce007SStefano Garzarella vsock_wait_remote_close(fd); 86cdbcc18dSStefan Hajnoczi 87cdbcc18dSStefan Hajnoczi send_byte(fd, -EPIPE, 0); 88cdbcc18dSStefan Hajnoczi recv_byte(fd, 1, 0); 89cdbcc18dSStefan Hajnoczi recv_byte(fd, 0, 0); 90cdbcc18dSStefan Hajnoczi close(fd); 91cdbcc18dSStefan Hajnoczi } 92cdbcc18dSStefan Hajnoczi 93cdbcc18dSStefan Hajnoczi static void test_stream_server_close_client(const struct test_opts *opts) 94cdbcc18dSStefan Hajnoczi { 95cdbcc18dSStefan Hajnoczi int fd; 96cdbcc18dSStefan Hajnoczi 97cdbcc18dSStefan Hajnoczi fd = vsock_stream_connect(opts->peer_cid, 1234); 98cdbcc18dSStefan Hajnoczi if (fd < 0) { 99cdbcc18dSStefan Hajnoczi perror("connect"); 100cdbcc18dSStefan Hajnoczi exit(EXIT_FAILURE); 101cdbcc18dSStefan Hajnoczi } 102cdbcc18dSStefan Hajnoczi 103770ce007SStefano Garzarella /* Wait for the remote to close the connection, before check 104770ce007SStefano Garzarella * -EPIPE error on send. 105770ce007SStefano Garzarella */ 106770ce007SStefano Garzarella vsock_wait_remote_close(fd); 107cdbcc18dSStefan Hajnoczi 108cdbcc18dSStefan Hajnoczi send_byte(fd, -EPIPE, 0); 109cdbcc18dSStefan Hajnoczi recv_byte(fd, 1, 0); 110cdbcc18dSStefan Hajnoczi recv_byte(fd, 0, 0); 111cdbcc18dSStefan Hajnoczi close(fd); 112cdbcc18dSStefan Hajnoczi } 113cdbcc18dSStefan Hajnoczi 114cdbcc18dSStefan Hajnoczi static void test_stream_server_close_server(const struct test_opts *opts) 115cdbcc18dSStefan Hajnoczi { 116cdbcc18dSStefan Hajnoczi int fd; 117cdbcc18dSStefan Hajnoczi 118cdbcc18dSStefan Hajnoczi fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); 119cdbcc18dSStefan Hajnoczi if (fd < 0) { 120cdbcc18dSStefan Hajnoczi perror("accept"); 121cdbcc18dSStefan Hajnoczi exit(EXIT_FAILURE); 122cdbcc18dSStefan Hajnoczi } 123cdbcc18dSStefan Hajnoczi 124cdbcc18dSStefan Hajnoczi send_byte(fd, 1, 0); 125cdbcc18dSStefan Hajnoczi close(fd); 126cdbcc18dSStefan Hajnoczi } 127cdbcc18dSStefan Hajnoczi 128cdbcc18dSStefan Hajnoczi /* With the standard socket sizes, VMCI is able to support about 100 129cdbcc18dSStefan Hajnoczi * concurrent stream connections. 130cdbcc18dSStefan Hajnoczi */ 131cdbcc18dSStefan Hajnoczi #define MULTICONN_NFDS 100 132cdbcc18dSStefan Hajnoczi 133cdbcc18dSStefan Hajnoczi static void test_stream_multiconn_client(const struct test_opts *opts) 134cdbcc18dSStefan Hajnoczi { 135cdbcc18dSStefan Hajnoczi int fds[MULTICONN_NFDS]; 136cdbcc18dSStefan Hajnoczi int i; 137cdbcc18dSStefan Hajnoczi 138cdbcc18dSStefan Hajnoczi for (i = 0; i < MULTICONN_NFDS; i++) { 139cdbcc18dSStefan Hajnoczi fds[i] = vsock_stream_connect(opts->peer_cid, 1234); 140cdbcc18dSStefan Hajnoczi if (fds[i] < 0) { 141cdbcc18dSStefan Hajnoczi perror("connect"); 142cdbcc18dSStefan Hajnoczi exit(EXIT_FAILURE); 143cdbcc18dSStefan Hajnoczi } 144cdbcc18dSStefan Hajnoczi } 145cdbcc18dSStefan Hajnoczi 146cdbcc18dSStefan Hajnoczi for (i = 0; i < MULTICONN_NFDS; i++) { 147cdbcc18dSStefan Hajnoczi if (i % 2) 148cdbcc18dSStefan Hajnoczi recv_byte(fds[i], 1, 0); 149cdbcc18dSStefan Hajnoczi else 150cdbcc18dSStefan Hajnoczi send_byte(fds[i], 1, 0); 151cdbcc18dSStefan Hajnoczi } 152cdbcc18dSStefan Hajnoczi 153cdbcc18dSStefan Hajnoczi for (i = 0; i < MULTICONN_NFDS; i++) 154cdbcc18dSStefan Hajnoczi close(fds[i]); 155cdbcc18dSStefan Hajnoczi } 156cdbcc18dSStefan Hajnoczi 157cdbcc18dSStefan Hajnoczi static void test_stream_multiconn_server(const struct test_opts *opts) 158cdbcc18dSStefan Hajnoczi { 159cdbcc18dSStefan Hajnoczi int fds[MULTICONN_NFDS]; 160cdbcc18dSStefan Hajnoczi int i; 161cdbcc18dSStefan Hajnoczi 162cdbcc18dSStefan Hajnoczi for (i = 0; i < MULTICONN_NFDS; i++) { 163cdbcc18dSStefan Hajnoczi fds[i] = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); 164cdbcc18dSStefan Hajnoczi if (fds[i] < 0) { 165cdbcc18dSStefan Hajnoczi perror("accept"); 166cdbcc18dSStefan Hajnoczi exit(EXIT_FAILURE); 167cdbcc18dSStefan Hajnoczi } 168cdbcc18dSStefan Hajnoczi } 169cdbcc18dSStefan Hajnoczi 170cdbcc18dSStefan Hajnoczi for (i = 0; i < MULTICONN_NFDS; i++) { 171cdbcc18dSStefan Hajnoczi if (i % 2) 172cdbcc18dSStefan Hajnoczi send_byte(fds[i], 1, 0); 173cdbcc18dSStefan Hajnoczi else 174cdbcc18dSStefan Hajnoczi recv_byte(fds[i], 1, 0); 175cdbcc18dSStefan Hajnoczi } 176cdbcc18dSStefan Hajnoczi 177cdbcc18dSStefan Hajnoczi for (i = 0; i < MULTICONN_NFDS; i++) 178cdbcc18dSStefan Hajnoczi close(fds[i]); 179cdbcc18dSStefan Hajnoczi } 180cdbcc18dSStefan Hajnoczi 181d6269a93SStefano Garzarella static void test_stream_msg_peek_client(const struct test_opts *opts) 182d6269a93SStefano Garzarella { 183d6269a93SStefano Garzarella int fd; 184d6269a93SStefano Garzarella 185d6269a93SStefano Garzarella fd = vsock_stream_connect(opts->peer_cid, 1234); 186d6269a93SStefano Garzarella if (fd < 0) { 187d6269a93SStefano Garzarella perror("connect"); 188d6269a93SStefano Garzarella exit(EXIT_FAILURE); 189d6269a93SStefano Garzarella } 190d6269a93SStefano Garzarella 191d6269a93SStefano Garzarella send_byte(fd, 1, 0); 192d6269a93SStefano Garzarella close(fd); 193d6269a93SStefano Garzarella } 194d6269a93SStefano Garzarella 195d6269a93SStefano Garzarella static void test_stream_msg_peek_server(const struct test_opts *opts) 196d6269a93SStefano Garzarella { 197d6269a93SStefano Garzarella int fd; 198d6269a93SStefano Garzarella 199d6269a93SStefano Garzarella fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); 200d6269a93SStefano Garzarella if (fd < 0) { 201d6269a93SStefano Garzarella perror("accept"); 202d6269a93SStefano Garzarella exit(EXIT_FAILURE); 203d6269a93SStefano Garzarella } 204d6269a93SStefano Garzarella 205d6269a93SStefano Garzarella recv_byte(fd, 1, MSG_PEEK); 206d6269a93SStefano Garzarella recv_byte(fd, 1, 0); 207d6269a93SStefano Garzarella close(fd); 208d6269a93SStefano Garzarella } 209d6269a93SStefano Garzarella 210cdbcc18dSStefan Hajnoczi static struct test_case test_cases[] = { 211cdbcc18dSStefan Hajnoczi { 212cdbcc18dSStefan Hajnoczi .name = "SOCK_STREAM connection reset", 213cdbcc18dSStefan Hajnoczi .run_client = test_stream_connection_reset, 214cdbcc18dSStefan Hajnoczi }, 215cdbcc18dSStefan Hajnoczi { 216cdbcc18dSStefan Hajnoczi .name = "SOCK_STREAM client close", 217cdbcc18dSStefan Hajnoczi .run_client = test_stream_client_close_client, 218cdbcc18dSStefan Hajnoczi .run_server = test_stream_client_close_server, 219cdbcc18dSStefan Hajnoczi }, 220cdbcc18dSStefan Hajnoczi { 221cdbcc18dSStefan Hajnoczi .name = "SOCK_STREAM server close", 222cdbcc18dSStefan Hajnoczi .run_client = test_stream_server_close_client, 223cdbcc18dSStefan Hajnoczi .run_server = test_stream_server_close_server, 224cdbcc18dSStefan Hajnoczi }, 225cdbcc18dSStefan Hajnoczi { 226cdbcc18dSStefan Hajnoczi .name = "SOCK_STREAM multiple connections", 227cdbcc18dSStefan Hajnoczi .run_client = test_stream_multiconn_client, 228cdbcc18dSStefan Hajnoczi .run_server = test_stream_multiconn_server, 229cdbcc18dSStefan Hajnoczi }, 230d6269a93SStefano Garzarella { 231d6269a93SStefano Garzarella .name = "SOCK_STREAM MSG_PEEK", 232d6269a93SStefano Garzarella .run_client = test_stream_msg_peek_client, 233d6269a93SStefano Garzarella .run_server = test_stream_msg_peek_server, 234d6269a93SStefano Garzarella }, 235cdbcc18dSStefan Hajnoczi {}, 236cdbcc18dSStefan Hajnoczi }; 237cdbcc18dSStefan Hajnoczi 238cdbcc18dSStefan Hajnoczi static const char optstring[] = ""; 239cdbcc18dSStefan Hajnoczi static const struct option longopts[] = { 240cdbcc18dSStefan Hajnoczi { 241cdbcc18dSStefan Hajnoczi .name = "control-host", 242cdbcc18dSStefan Hajnoczi .has_arg = required_argument, 243cdbcc18dSStefan Hajnoczi .val = 'H', 244cdbcc18dSStefan Hajnoczi }, 245cdbcc18dSStefan Hajnoczi { 246cdbcc18dSStefan Hajnoczi .name = "control-port", 247cdbcc18dSStefan Hajnoczi .has_arg = required_argument, 248cdbcc18dSStefan Hajnoczi .val = 'P', 249cdbcc18dSStefan Hajnoczi }, 250cdbcc18dSStefan Hajnoczi { 251cdbcc18dSStefan Hajnoczi .name = "mode", 252cdbcc18dSStefan Hajnoczi .has_arg = required_argument, 253cdbcc18dSStefan Hajnoczi .val = 'm', 254cdbcc18dSStefan Hajnoczi }, 255cdbcc18dSStefan Hajnoczi { 256cdbcc18dSStefan Hajnoczi .name = "peer-cid", 257cdbcc18dSStefan Hajnoczi .has_arg = required_argument, 258cdbcc18dSStefan Hajnoczi .val = 'p', 259cdbcc18dSStefan Hajnoczi }, 260cdbcc18dSStefan Hajnoczi { 2615a2b2425SStefano Garzarella .name = "list", 2625a2b2425SStefano Garzarella .has_arg = no_argument, 2635a2b2425SStefano Garzarella .val = 'l', 2645a2b2425SStefano Garzarella }, 2655a2b2425SStefano Garzarella { 2665a2b2425SStefano Garzarella .name = "skip", 2675a2b2425SStefano Garzarella .has_arg = required_argument, 2685a2b2425SStefano Garzarella .val = 's', 2695a2b2425SStefano Garzarella }, 2705a2b2425SStefano Garzarella { 271cdbcc18dSStefan Hajnoczi .name = "help", 272cdbcc18dSStefan Hajnoczi .has_arg = no_argument, 273cdbcc18dSStefan Hajnoczi .val = '?', 274cdbcc18dSStefan Hajnoczi }, 275cdbcc18dSStefan Hajnoczi {}, 276cdbcc18dSStefan Hajnoczi }; 277cdbcc18dSStefan Hajnoczi 278cdbcc18dSStefan Hajnoczi static void usage(void) 279cdbcc18dSStefan Hajnoczi { 2805a2b2425SStefano Garzarella fprintf(stderr, "Usage: vsock_test [--help] [--control-host=<host>] --control-port=<port> --mode=client|server --peer-cid=<cid> [--list] [--skip=<test_id>]\n" 281cdbcc18dSStefan Hajnoczi "\n" 282cdbcc18dSStefan Hajnoczi " Server: vsock_test --control-port=1234 --mode=server --peer-cid=3\n" 283cdbcc18dSStefan Hajnoczi " Client: vsock_test --control-host=192.168.0.1 --control-port=1234 --mode=client --peer-cid=2\n" 284cdbcc18dSStefan Hajnoczi "\n" 285cdbcc18dSStefan Hajnoczi "Run vsock.ko tests. Must be launched in both guest\n" 286cdbcc18dSStefan Hajnoczi "and host. One side must use --mode=client and\n" 287cdbcc18dSStefan Hajnoczi "the other side must use --mode=server.\n" 288cdbcc18dSStefan Hajnoczi "\n" 289cdbcc18dSStefan Hajnoczi "A TCP control socket connection is used to coordinate tests\n" 290cdbcc18dSStefan Hajnoczi "between the client and the server. The server requires a\n" 291cdbcc18dSStefan Hajnoczi "listen address and the client requires an address to\n" 292cdbcc18dSStefan Hajnoczi "connect to.\n" 293cdbcc18dSStefan Hajnoczi "\n" 2948d00b93fSStefano Garzarella "The CID of the other side must be given with --peer-cid=<cid>.\n" 2958d00b93fSStefano Garzarella "\n" 2968d00b93fSStefano Garzarella "Options:\n" 2978d00b93fSStefano Garzarella " --help This help message\n" 2988d00b93fSStefano Garzarella " --control-host <host> Server IP address to connect to\n" 2998d00b93fSStefano Garzarella " --control-port <port> Server port to listen on/connect to\n" 3008d00b93fSStefano Garzarella " --mode client|server Server or client mode\n" 3018d00b93fSStefano Garzarella " --peer-cid <cid> CID of the other side\n" 3028d00b93fSStefano Garzarella " --list List of tests that will be executed\n" 3038d00b93fSStefano Garzarella " --skip <test_id> Test ID to skip;\n" 3048d00b93fSStefano Garzarella " use multiple --skip options to skip more tests\n" 3058d00b93fSStefano Garzarella ); 306cdbcc18dSStefan Hajnoczi exit(EXIT_FAILURE); 307cdbcc18dSStefan Hajnoczi } 308cdbcc18dSStefan Hajnoczi 309cdbcc18dSStefan Hajnoczi int main(int argc, char **argv) 310cdbcc18dSStefan Hajnoczi { 311cdbcc18dSStefan Hajnoczi const char *control_host = NULL; 312cdbcc18dSStefan Hajnoczi const char *control_port = NULL; 313cdbcc18dSStefan Hajnoczi struct test_opts opts = { 314cdbcc18dSStefan Hajnoczi .mode = TEST_MODE_UNSET, 315cdbcc18dSStefan Hajnoczi .peer_cid = VMADDR_CID_ANY, 316cdbcc18dSStefan Hajnoczi }; 317cdbcc18dSStefan Hajnoczi 318cdbcc18dSStefan Hajnoczi init_signals(); 319cdbcc18dSStefan Hajnoczi 320cdbcc18dSStefan Hajnoczi for (;;) { 321cdbcc18dSStefan Hajnoczi int opt = getopt_long(argc, argv, optstring, longopts, NULL); 322cdbcc18dSStefan Hajnoczi 323cdbcc18dSStefan Hajnoczi if (opt == -1) 324cdbcc18dSStefan Hajnoczi break; 325cdbcc18dSStefan Hajnoczi 326cdbcc18dSStefan Hajnoczi switch (opt) { 327cdbcc18dSStefan Hajnoczi case 'H': 328cdbcc18dSStefan Hajnoczi control_host = optarg; 329cdbcc18dSStefan Hajnoczi break; 330cdbcc18dSStefan Hajnoczi case 'm': 331cdbcc18dSStefan Hajnoczi if (strcmp(optarg, "client") == 0) 332cdbcc18dSStefan Hajnoczi opts.mode = TEST_MODE_CLIENT; 333cdbcc18dSStefan Hajnoczi else if (strcmp(optarg, "server") == 0) 334cdbcc18dSStefan Hajnoczi opts.mode = TEST_MODE_SERVER; 335cdbcc18dSStefan Hajnoczi else { 336cdbcc18dSStefan Hajnoczi fprintf(stderr, "--mode must be \"client\" or \"server\"\n"); 337cdbcc18dSStefan Hajnoczi return EXIT_FAILURE; 338cdbcc18dSStefan Hajnoczi } 339cdbcc18dSStefan Hajnoczi break; 340cdbcc18dSStefan Hajnoczi case 'p': 341cdbcc18dSStefan Hajnoczi opts.peer_cid = parse_cid(optarg); 342cdbcc18dSStefan Hajnoczi break; 343cdbcc18dSStefan Hajnoczi case 'P': 344cdbcc18dSStefan Hajnoczi control_port = optarg; 345cdbcc18dSStefan Hajnoczi break; 3465a2b2425SStefano Garzarella case 'l': 3475a2b2425SStefano Garzarella list_tests(test_cases); 3485a2b2425SStefano Garzarella break; 3495a2b2425SStefano Garzarella case 's': 3505a2b2425SStefano Garzarella skip_test(test_cases, ARRAY_SIZE(test_cases) - 1, 3515a2b2425SStefano Garzarella optarg); 3525a2b2425SStefano Garzarella break; 353cdbcc18dSStefan Hajnoczi case '?': 354cdbcc18dSStefan Hajnoczi default: 355cdbcc18dSStefan Hajnoczi usage(); 356cdbcc18dSStefan Hajnoczi } 357cdbcc18dSStefan Hajnoczi } 358cdbcc18dSStefan Hajnoczi 359cdbcc18dSStefan Hajnoczi if (!control_port) 360cdbcc18dSStefan Hajnoczi usage(); 361cdbcc18dSStefan Hajnoczi if (opts.mode == TEST_MODE_UNSET) 362cdbcc18dSStefan Hajnoczi usage(); 363cdbcc18dSStefan Hajnoczi if (opts.peer_cid == VMADDR_CID_ANY) 364cdbcc18dSStefan Hajnoczi usage(); 365cdbcc18dSStefan Hajnoczi 366cdbcc18dSStefan Hajnoczi if (!control_host) { 367cdbcc18dSStefan Hajnoczi if (opts.mode != TEST_MODE_SERVER) 368cdbcc18dSStefan Hajnoczi usage(); 369cdbcc18dSStefan Hajnoczi control_host = "0.0.0.0"; 370cdbcc18dSStefan Hajnoczi } 371cdbcc18dSStefan Hajnoczi 372cdbcc18dSStefan Hajnoczi control_init(control_host, control_port, 373cdbcc18dSStefan Hajnoczi opts.mode == TEST_MODE_SERVER); 374cdbcc18dSStefan Hajnoczi 375cdbcc18dSStefan Hajnoczi run_tests(test_cases, &opts); 376cdbcc18dSStefan Hajnoczi 377cdbcc18dSStefan Hajnoczi control_cleanup(); 378cdbcc18dSStefan Hajnoczi return EXIT_SUCCESS; 379cdbcc18dSStefan Hajnoczi } 380