]> Git Repo - linux.git/blob - tools/testing/vsock/vsock_test.c
scsi: zfcp: Trace when request remove fails after qdio send fails
[linux.git] / tools / testing / vsock / vsock_test.c
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 <[email protected]>
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 }
This page took 0.087406 seconds and 4 git commands to generate.