1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * vsock_test - vsock.ko test suite 4 * 5 * Copyright (C) 2017 Red Hat, Inc. 6 * 7 * Author: Stefan Hajnoczi <stefanha@redhat.com> 8 */ 9 10 #include <getopt.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <errno.h> 15 #include <unistd.h> 16 #include <linux/kernel.h> 17 #include <sys/types.h> 18 #include <sys/socket.h> 19 #include <time.h> 20 #include <sys/mman.h> 21 #include <poll.h> 22 23 #include "timeout.h" 24 #include "control.h" 25 #include "util.h" 26 27 static void test_stream_connection_reset(const struct test_opts *opts) 28 { 29 union { 30 struct sockaddr sa; 31 struct sockaddr_vm svm; 32 } addr = { 33 .svm = { 34 .svm_family = AF_VSOCK, 35 .svm_port = 1234, 36 .svm_cid = opts->peer_cid, 37 }, 38 }; 39 int ret; 40 int fd; 41 42 fd = socket(AF_VSOCK, SOCK_STREAM, 0); 43 44 timeout_begin(TIMEOUT); 45 do { 46 ret = connect(fd, &addr.sa, sizeof(addr.svm)); 47 timeout_check("connect"); 48 } while (ret < 0 && errno == EINTR); 49 timeout_end(); 50 51 if (ret != -1) { 52 fprintf(stderr, "expected connect(2) failure, got %d\n", ret); 53 exit(EXIT_FAILURE); 54 } 55 if (errno != ECONNRESET) { 56 fprintf(stderr, "unexpected connect(2) errno %d\n", errno); 57 exit(EXIT_FAILURE); 58 } 59 60 close(fd); 61 } 62 63 static void test_stream_bind_only_client(const struct test_opts *opts) 64 { 65 union { 66 struct sockaddr sa; 67 struct sockaddr_vm svm; 68 } addr = { 69 .svm = { 70 .svm_family = AF_VSOCK, 71 .svm_port = 1234, 72 .svm_cid = opts->peer_cid, 73 }, 74 }; 75 int ret; 76 int fd; 77 78 /* Wait for the server to be ready */ 79 control_expectln("BIND"); 80 81 fd = socket(AF_VSOCK, SOCK_STREAM, 0); 82 83 timeout_begin(TIMEOUT); 84 do { 85 ret = connect(fd, &addr.sa, sizeof(addr.svm)); 86 timeout_check("connect"); 87 } while (ret < 0 && errno == EINTR); 88 timeout_end(); 89 90 if (ret != -1) { 91 fprintf(stderr, "expected connect(2) failure, got %d\n", ret); 92 exit(EXIT_FAILURE); 93 } 94 if (errno != ECONNRESET) { 95 fprintf(stderr, "unexpected connect(2) errno %d\n", errno); 96 exit(EXIT_FAILURE); 97 } 98 99 /* Notify the server that the client has finished */ 100 control_writeln("DONE"); 101 102 close(fd); 103 } 104 105 static void test_stream_bind_only_server(const struct test_opts *opts) 106 { 107 union { 108 struct sockaddr sa; 109 struct sockaddr_vm svm; 110 } addr = { 111 .svm = { 112 .svm_family = AF_VSOCK, 113 .svm_port = 1234, 114 .svm_cid = VMADDR_CID_ANY, 115 }, 116 }; 117 int fd; 118 119 fd = socket(AF_VSOCK, SOCK_STREAM, 0); 120 121 if (bind(fd, &addr.sa, sizeof(addr.svm)) < 0) { 122 perror("bind"); 123 exit(EXIT_FAILURE); 124 } 125 126 /* Notify the client that the server is ready */ 127 control_writeln("BIND"); 128 129 /* Wait for the client to finish */ 130 control_expectln("DONE"); 131 132 close(fd); 133 } 134 135 static void test_stream_client_close_client(const struct test_opts *opts) 136 { 137 int fd; 138 139 fd = vsock_stream_connect(opts->peer_cid, 1234); 140 if (fd < 0) { 141 perror("connect"); 142 exit(EXIT_FAILURE); 143 } 144 145 send_byte(fd, 1, 0); 146 close(fd); 147 } 148 149 static void test_stream_client_close_server(const struct test_opts *opts) 150 { 151 int fd; 152 153 fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); 154 if (fd < 0) { 155 perror("accept"); 156 exit(EXIT_FAILURE); 157 } 158 159 /* Wait for the remote to close the connection, before check 160 * -EPIPE error on send. 161 */ 162 vsock_wait_remote_close(fd); 163 164 send_byte(fd, -EPIPE, 0); 165 recv_byte(fd, 1, 0); 166 recv_byte(fd, 0, 0); 167 close(fd); 168 } 169 170 static void test_stream_server_close_client(const struct test_opts *opts) 171 { 172 int fd; 173 174 fd = vsock_stream_connect(opts->peer_cid, 1234); 175 if (fd < 0) { 176 perror("connect"); 177 exit(EXIT_FAILURE); 178 } 179 180 /* Wait for the remote to close the connection, before check 181 * -EPIPE error on send. 182 */ 183 vsock_wait_remote_close(fd); 184 185 send_byte(fd, -EPIPE, 0); 186 recv_byte(fd, 1, 0); 187 recv_byte(fd, 0, 0); 188 close(fd); 189 } 190 191 static void test_stream_server_close_server(const struct test_opts *opts) 192 { 193 int fd; 194 195 fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); 196 if (fd < 0) { 197 perror("accept"); 198 exit(EXIT_FAILURE); 199 } 200 201 send_byte(fd, 1, 0); 202 close(fd); 203 } 204 205 /* With the standard socket sizes, VMCI is able to support about 100 206 * concurrent stream connections. 207 */ 208 #define MULTICONN_NFDS 100 209 210 static void test_stream_multiconn_client(const struct test_opts *opts) 211 { 212 int fds[MULTICONN_NFDS]; 213 int i; 214 215 for (i = 0; i < MULTICONN_NFDS; i++) { 216 fds[i] = vsock_stream_connect(opts->peer_cid, 1234); 217 if (fds[i] < 0) { 218 perror("connect"); 219 exit(EXIT_FAILURE); 220 } 221 } 222 223 for (i = 0; i < MULTICONN_NFDS; i++) { 224 if (i % 2) 225 recv_byte(fds[i], 1, 0); 226 else 227 send_byte(fds[i], 1, 0); 228 } 229 230 for (i = 0; i < MULTICONN_NFDS; i++) 231 close(fds[i]); 232 } 233 234 static void test_stream_multiconn_server(const struct test_opts *opts) 235 { 236 int fds[MULTICONN_NFDS]; 237 int i; 238 239 for (i = 0; i < MULTICONN_NFDS; i++) { 240 fds[i] = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); 241 if (fds[i] < 0) { 242 perror("accept"); 243 exit(EXIT_FAILURE); 244 } 245 } 246 247 for (i = 0; i < MULTICONN_NFDS; i++) { 248 if (i % 2) 249 send_byte(fds[i], 1, 0); 250 else 251 recv_byte(fds[i], 1, 0); 252 } 253 254 for (i = 0; i < MULTICONN_NFDS; i++) 255 close(fds[i]); 256 } 257 258 static void test_stream_msg_peek_client(const struct test_opts *opts) 259 { 260 int fd; 261 262 fd = vsock_stream_connect(opts->peer_cid, 1234); 263 if (fd < 0) { 264 perror("connect"); 265 exit(EXIT_FAILURE); 266 } 267 268 send_byte(fd, 1, 0); 269 close(fd); 270 } 271 272 static void test_stream_msg_peek_server(const struct test_opts *opts) 273 { 274 int fd; 275 276 fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); 277 if (fd < 0) { 278 perror("accept"); 279 exit(EXIT_FAILURE); 280 } 281 282 recv_byte(fd, 1, MSG_PEEK); 283 recv_byte(fd, 1, 0); 284 close(fd); 285 } 286 287 #define MESSAGES_CNT 7 288 #define MSG_EOR_IDX (MESSAGES_CNT / 2) 289 static void test_seqpacket_msg_bounds_client(const struct test_opts *opts) 290 { 291 int fd; 292 293 fd = vsock_seqpacket_connect(opts->peer_cid, 1234); 294 if (fd < 0) { 295 perror("connect"); 296 exit(EXIT_FAILURE); 297 } 298 299 /* Send several messages, one with MSG_EOR flag */ 300 for (int i = 0; i < MESSAGES_CNT; i++) 301 send_byte(fd, 1, (i == MSG_EOR_IDX) ? MSG_EOR : 0); 302 303 control_writeln("SENDDONE"); 304 close(fd); 305 } 306 307 static void test_seqpacket_msg_bounds_server(const struct test_opts *opts) 308 { 309 int fd; 310 char buf[16]; 311 struct msghdr msg = {0}; 312 struct iovec iov = {0}; 313 314 fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL); 315 if (fd < 0) { 316 perror("accept"); 317 exit(EXIT_FAILURE); 318 } 319 320 control_expectln("SENDDONE"); 321 iov.iov_base = buf; 322 iov.iov_len = sizeof(buf); 323 msg.msg_iov = &iov; 324 msg.msg_iovlen = 1; 325 326 for (int i = 0; i < MESSAGES_CNT; i++) { 327 if (recvmsg(fd, &msg, 0) != 1) { 328 perror("message bound violated"); 329 exit(EXIT_FAILURE); 330 } 331 332 if ((i == MSG_EOR_IDX) ^ !!(msg.msg_flags & MSG_EOR)) { 333 perror("MSG_EOR"); 334 exit(EXIT_FAILURE); 335 } 336 } 337 338 close(fd); 339 } 340 341 #define MESSAGE_TRUNC_SZ 32 342 static void test_seqpacket_msg_trunc_client(const struct test_opts *opts) 343 { 344 int fd; 345 char buf[MESSAGE_TRUNC_SZ]; 346 347 fd = vsock_seqpacket_connect(opts->peer_cid, 1234); 348 if (fd < 0) { 349 perror("connect"); 350 exit(EXIT_FAILURE); 351 } 352 353 if (send(fd, buf, sizeof(buf), 0) != sizeof(buf)) { 354 perror("send failed"); 355 exit(EXIT_FAILURE); 356 } 357 358 control_writeln("SENDDONE"); 359 close(fd); 360 } 361 362 static void test_seqpacket_msg_trunc_server(const struct test_opts *opts) 363 { 364 int fd; 365 char buf[MESSAGE_TRUNC_SZ / 2]; 366 struct msghdr msg = {0}; 367 struct iovec iov = {0}; 368 369 fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL); 370 if (fd < 0) { 371 perror("accept"); 372 exit(EXIT_FAILURE); 373 } 374 375 control_expectln("SENDDONE"); 376 iov.iov_base = buf; 377 iov.iov_len = sizeof(buf); 378 msg.msg_iov = &iov; 379 msg.msg_iovlen = 1; 380 381 ssize_t ret = recvmsg(fd, &msg, MSG_TRUNC); 382 383 if (ret != MESSAGE_TRUNC_SZ) { 384 printf("%zi\n", ret); 385 perror("MSG_TRUNC doesn't work"); 386 exit(EXIT_FAILURE); 387 } 388 389 if (!(msg.msg_flags & MSG_TRUNC)) { 390 fprintf(stderr, "MSG_TRUNC expected\n"); 391 exit(EXIT_FAILURE); 392 } 393 394 close(fd); 395 } 396 397 static time_t current_nsec(void) 398 { 399 struct timespec ts; 400 401 if (clock_gettime(CLOCK_REALTIME, &ts)) { 402 perror("clock_gettime(3) failed"); 403 exit(EXIT_FAILURE); 404 } 405 406 return (ts.tv_sec * 1000000000ULL) + ts.tv_nsec; 407 } 408 409 #define RCVTIMEO_TIMEOUT_SEC 1 410 #define READ_OVERHEAD_NSEC 250000000 /* 0.25 sec */ 411 412 static void test_seqpacket_timeout_client(const struct test_opts *opts) 413 { 414 int fd; 415 struct timeval tv; 416 char dummy; 417 time_t read_enter_ns; 418 time_t read_overhead_ns; 419 420 fd = vsock_seqpacket_connect(opts->peer_cid, 1234); 421 if (fd < 0) { 422 perror("connect"); 423 exit(EXIT_FAILURE); 424 } 425 426 tv.tv_sec = RCVTIMEO_TIMEOUT_SEC; 427 tv.tv_usec = 0; 428 429 if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(tv)) == -1) { 430 perror("setsockopt 'SO_RCVTIMEO'"); 431 exit(EXIT_FAILURE); 432 } 433 434 read_enter_ns = current_nsec(); 435 436 if (read(fd, &dummy, sizeof(dummy)) != -1) { 437 fprintf(stderr, 438 "expected 'dummy' read(2) failure\n"); 439 exit(EXIT_FAILURE); 440 } 441 442 if (errno != EAGAIN) { 443 perror("EAGAIN expected"); 444 exit(EXIT_FAILURE); 445 } 446 447 read_overhead_ns = current_nsec() - read_enter_ns - 448 1000000000ULL * RCVTIMEO_TIMEOUT_SEC; 449 450 if (read_overhead_ns > READ_OVERHEAD_NSEC) { 451 fprintf(stderr, 452 "too much time in read(2), %lu > %i ns\n", 453 read_overhead_ns, READ_OVERHEAD_NSEC); 454 exit(EXIT_FAILURE); 455 } 456 457 control_writeln("WAITDONE"); 458 close(fd); 459 } 460 461 static void test_seqpacket_timeout_server(const struct test_opts *opts) 462 { 463 int fd; 464 465 fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL); 466 if (fd < 0) { 467 perror("accept"); 468 exit(EXIT_FAILURE); 469 } 470 471 control_expectln("WAITDONE"); 472 close(fd); 473 } 474 475 #define BUF_PATTERN_1 'a' 476 #define BUF_PATTERN_2 'b' 477 478 static void test_seqpacket_invalid_rec_buffer_client(const struct test_opts *opts) 479 { 480 int fd; 481 unsigned char *buf1; 482 unsigned char *buf2; 483 int buf_size = getpagesize() * 3; 484 485 fd = vsock_seqpacket_connect(opts->peer_cid, 1234); 486 if (fd < 0) { 487 perror("connect"); 488 exit(EXIT_FAILURE); 489 } 490 491 buf1 = malloc(buf_size); 492 if (!buf1) { 493 perror("'malloc()' for 'buf1'"); 494 exit(EXIT_FAILURE); 495 } 496 497 buf2 = malloc(buf_size); 498 if (!buf2) { 499 perror("'malloc()' for 'buf2'"); 500 exit(EXIT_FAILURE); 501 } 502 503 memset(buf1, BUF_PATTERN_1, buf_size); 504 memset(buf2, BUF_PATTERN_2, buf_size); 505 506 if (send(fd, buf1, buf_size, 0) != buf_size) { 507 perror("send failed"); 508 exit(EXIT_FAILURE); 509 } 510 511 if (send(fd, buf2, buf_size, 0) != buf_size) { 512 perror("send failed"); 513 exit(EXIT_FAILURE); 514 } 515 516 close(fd); 517 } 518 519 static void test_seqpacket_invalid_rec_buffer_server(const struct test_opts *opts) 520 { 521 int fd; 522 unsigned char *broken_buf; 523 unsigned char *valid_buf; 524 int page_size = getpagesize(); 525 int buf_size = page_size * 3; 526 ssize_t res; 527 int prot = PROT_READ | PROT_WRITE; 528 int flags = MAP_PRIVATE | MAP_ANONYMOUS; 529 int i; 530 531 fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL); 532 if (fd < 0) { 533 perror("accept"); 534 exit(EXIT_FAILURE); 535 } 536 537 /* Setup first buffer. */ 538 broken_buf = mmap(NULL, buf_size, prot, flags, -1, 0); 539 if (broken_buf == MAP_FAILED) { 540 perror("mmap for 'broken_buf'"); 541 exit(EXIT_FAILURE); 542 } 543 544 /* Unmap "hole" in buffer. */ 545 if (munmap(broken_buf + page_size, page_size)) { 546 perror("'broken_buf' setup"); 547 exit(EXIT_FAILURE); 548 } 549 550 valid_buf = mmap(NULL, buf_size, prot, flags, -1, 0); 551 if (valid_buf == MAP_FAILED) { 552 perror("mmap for 'valid_buf'"); 553 exit(EXIT_FAILURE); 554 } 555 556 /* Try to fill buffer with unmapped middle. */ 557 res = read(fd, broken_buf, buf_size); 558 if (res != -1) { 559 fprintf(stderr, 560 "expected 'broken_buf' read(2) failure, got %zi\n", 561 res); 562 exit(EXIT_FAILURE); 563 } 564 565 if (errno != ENOMEM) { 566 perror("unexpected errno of 'broken_buf'"); 567 exit(EXIT_FAILURE); 568 } 569 570 /* Try to fill valid buffer. */ 571 res = read(fd, valid_buf, buf_size); 572 if (res < 0) { 573 perror("unexpected 'valid_buf' read(2) failure"); 574 exit(EXIT_FAILURE); 575 } 576 577 if (res != buf_size) { 578 fprintf(stderr, 579 "invalid 'valid_buf' read(2), expected %i, got %zi\n", 580 buf_size, res); 581 exit(EXIT_FAILURE); 582 } 583 584 for (i = 0; i < buf_size; i++) { 585 if (valid_buf[i] != BUF_PATTERN_2) { 586 fprintf(stderr, 587 "invalid pattern for 'valid_buf' at %i, expected %hhX, got %hhX\n", 588 i, BUF_PATTERN_2, valid_buf[i]); 589 exit(EXIT_FAILURE); 590 } 591 } 592 593 /* Unmap buffers. */ 594 munmap(broken_buf, page_size); 595 munmap(broken_buf + page_size * 2, page_size); 596 munmap(valid_buf, buf_size); 597 close(fd); 598 } 599 600 #define RCVLOWAT_BUF_SIZE 128 601 602 static void test_stream_poll_rcvlowat_server(const struct test_opts *opts) 603 { 604 int fd; 605 int i; 606 607 fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); 608 if (fd < 0) { 609 perror("accept"); 610 exit(EXIT_FAILURE); 611 } 612 613 /* Send 1 byte. */ 614 send_byte(fd, 1, 0); 615 616 control_writeln("SRVSENT"); 617 618 /* Wait until client is ready to receive rest of data. */ 619 control_expectln("CLNSENT"); 620 621 for (i = 0; i < RCVLOWAT_BUF_SIZE - 1; i++) 622 send_byte(fd, 1, 0); 623 624 /* Keep socket in active state. */ 625 control_expectln("POLLDONE"); 626 627 close(fd); 628 } 629 630 static void test_stream_poll_rcvlowat_client(const struct test_opts *opts) 631 { 632 unsigned long lowat_val = RCVLOWAT_BUF_SIZE; 633 char buf[RCVLOWAT_BUF_SIZE]; 634 struct pollfd fds; 635 ssize_t read_res; 636 short poll_flags; 637 int fd; 638 639 fd = vsock_stream_connect(opts->peer_cid, 1234); 640 if (fd < 0) { 641 perror("connect"); 642 exit(EXIT_FAILURE); 643 } 644 645 if (setsockopt(fd, SOL_SOCKET, SO_RCVLOWAT, 646 &lowat_val, sizeof(lowat_val))) { 647 perror("setsockopt"); 648 exit(EXIT_FAILURE); 649 } 650 651 control_expectln("SRVSENT"); 652 653 /* At this point, server sent 1 byte. */ 654 fds.fd = fd; 655 poll_flags = POLLIN | POLLRDNORM; 656 fds.events = poll_flags; 657 658 /* Try to wait for 1 sec. */ 659 if (poll(&fds, 1, 1000) < 0) { 660 perror("poll"); 661 exit(EXIT_FAILURE); 662 } 663 664 /* poll() must return nothing. */ 665 if (fds.revents) { 666 fprintf(stderr, "Unexpected poll result %hx\n", 667 fds.revents); 668 exit(EXIT_FAILURE); 669 } 670 671 /* Tell server to send rest of data. */ 672 control_writeln("CLNSENT"); 673 674 /* Poll for data. */ 675 if (poll(&fds, 1, 10000) < 0) { 676 perror("poll"); 677 exit(EXIT_FAILURE); 678 } 679 680 /* Only these two bits are expected. */ 681 if (fds.revents != poll_flags) { 682 fprintf(stderr, "Unexpected poll result %hx\n", 683 fds.revents); 684 exit(EXIT_FAILURE); 685 } 686 687 /* Use MSG_DONTWAIT, if call is going to wait, EAGAIN 688 * will be returned. 689 */ 690 read_res = recv(fd, buf, sizeof(buf), MSG_DONTWAIT); 691 if (read_res != RCVLOWAT_BUF_SIZE) { 692 fprintf(stderr, "Unexpected recv result %zi\n", 693 read_res); 694 exit(EXIT_FAILURE); 695 } 696 697 control_writeln("POLLDONE"); 698 699 close(fd); 700 } 701 702 static struct test_case test_cases[] = { 703 { 704 .name = "SOCK_STREAM connection reset", 705 .run_client = test_stream_connection_reset, 706 }, 707 { 708 .name = "SOCK_STREAM bind only", 709 .run_client = test_stream_bind_only_client, 710 .run_server = test_stream_bind_only_server, 711 }, 712 { 713 .name = "SOCK_STREAM client close", 714 .run_client = test_stream_client_close_client, 715 .run_server = test_stream_client_close_server, 716 }, 717 { 718 .name = "SOCK_STREAM server close", 719 .run_client = test_stream_server_close_client, 720 .run_server = test_stream_server_close_server, 721 }, 722 { 723 .name = "SOCK_STREAM multiple connections", 724 .run_client = test_stream_multiconn_client, 725 .run_server = test_stream_multiconn_server, 726 }, 727 { 728 .name = "SOCK_STREAM MSG_PEEK", 729 .run_client = test_stream_msg_peek_client, 730 .run_server = test_stream_msg_peek_server, 731 }, 732 { 733 .name = "SOCK_SEQPACKET msg bounds", 734 .run_client = test_seqpacket_msg_bounds_client, 735 .run_server = test_seqpacket_msg_bounds_server, 736 }, 737 { 738 .name = "SOCK_SEQPACKET MSG_TRUNC flag", 739 .run_client = test_seqpacket_msg_trunc_client, 740 .run_server = test_seqpacket_msg_trunc_server, 741 }, 742 { 743 .name = "SOCK_SEQPACKET timeout", 744 .run_client = test_seqpacket_timeout_client, 745 .run_server = test_seqpacket_timeout_server, 746 }, 747 { 748 .name = "SOCK_SEQPACKET invalid receive buffer", 749 .run_client = test_seqpacket_invalid_rec_buffer_client, 750 .run_server = test_seqpacket_invalid_rec_buffer_server, 751 }, 752 { 753 .name = "SOCK_STREAM poll() + SO_RCVLOWAT", 754 .run_client = test_stream_poll_rcvlowat_client, 755 .run_server = test_stream_poll_rcvlowat_server, 756 }, 757 {}, 758 }; 759 760 static const char optstring[] = ""; 761 static const struct option longopts[] = { 762 { 763 .name = "control-host", 764 .has_arg = required_argument, 765 .val = 'H', 766 }, 767 { 768 .name = "control-port", 769 .has_arg = required_argument, 770 .val = 'P', 771 }, 772 { 773 .name = "mode", 774 .has_arg = required_argument, 775 .val = 'm', 776 }, 777 { 778 .name = "peer-cid", 779 .has_arg = required_argument, 780 .val = 'p', 781 }, 782 { 783 .name = "list", 784 .has_arg = no_argument, 785 .val = 'l', 786 }, 787 { 788 .name = "skip", 789 .has_arg = required_argument, 790 .val = 's', 791 }, 792 { 793 .name = "help", 794 .has_arg = no_argument, 795 .val = '?', 796 }, 797 {}, 798 }; 799 800 static void usage(void) 801 { 802 fprintf(stderr, "Usage: vsock_test [--help] [--control-host=<host>] --control-port=<port> --mode=client|server --peer-cid=<cid> [--list] [--skip=<test_id>]\n" 803 "\n" 804 " Server: vsock_test --control-port=1234 --mode=server --peer-cid=3\n" 805 " Client: vsock_test --control-host=192.168.0.1 --control-port=1234 --mode=client --peer-cid=2\n" 806 "\n" 807 "Run vsock.ko tests. Must be launched in both guest\n" 808 "and host. One side must use --mode=client and\n" 809 "the other side must use --mode=server.\n" 810 "\n" 811 "A TCP control socket connection is used to coordinate tests\n" 812 "between the client and the server. The server requires a\n" 813 "listen address and the client requires an address to\n" 814 "connect to.\n" 815 "\n" 816 "The CID of the other side must be given with --peer-cid=<cid>.\n" 817 "\n" 818 "Options:\n" 819 " --help This help message\n" 820 " --control-host <host> Server IP address to connect to\n" 821 " --control-port <port> Server port to listen on/connect to\n" 822 " --mode client|server Server or client mode\n" 823 " --peer-cid <cid> CID of the other side\n" 824 " --list List of tests that will be executed\n" 825 " --skip <test_id> Test ID to skip;\n" 826 " use multiple --skip options to skip more tests\n" 827 ); 828 exit(EXIT_FAILURE); 829 } 830 831 int main(int argc, char **argv) 832 { 833 const char *control_host = NULL; 834 const char *control_port = NULL; 835 struct test_opts opts = { 836 .mode = TEST_MODE_UNSET, 837 .peer_cid = VMADDR_CID_ANY, 838 }; 839 840 init_signals(); 841 842 for (;;) { 843 int opt = getopt_long(argc, argv, optstring, longopts, NULL); 844 845 if (opt == -1) 846 break; 847 848 switch (opt) { 849 case 'H': 850 control_host = optarg; 851 break; 852 case 'm': 853 if (strcmp(optarg, "client") == 0) 854 opts.mode = TEST_MODE_CLIENT; 855 else if (strcmp(optarg, "server") == 0) 856 opts.mode = TEST_MODE_SERVER; 857 else { 858 fprintf(stderr, "--mode must be \"client\" or \"server\"\n"); 859 return EXIT_FAILURE; 860 } 861 break; 862 case 'p': 863 opts.peer_cid = parse_cid(optarg); 864 break; 865 case 'P': 866 control_port = optarg; 867 break; 868 case 'l': 869 list_tests(test_cases); 870 break; 871 case 's': 872 skip_test(test_cases, ARRAY_SIZE(test_cases) - 1, 873 optarg); 874 break; 875 case '?': 876 default: 877 usage(); 878 } 879 } 880 881 if (!control_port) 882 usage(); 883 if (opts.mode == TEST_MODE_UNSET) 884 usage(); 885 if (opts.peer_cid == VMADDR_CID_ANY) 886 usage(); 887 888 if (!control_host) { 889 if (opts.mode != TEST_MODE_SERVER) 890 usage(); 891 control_host = "0.0.0.0"; 892 } 893 894 control_init(control_host, control_port, 895 opts.mode == TEST_MODE_SERVER); 896 897 run_tests(test_cases, &opts); 898 899 control_cleanup(); 900 return EXIT_SUCCESS; 901 } 902