Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

VSOCK: add AF_VSOCK test cases

The vsock_test.c program runs a test suite of AF_VSOCK test cases.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Stefan Hajnoczi and committed by
David S. Miller
cdbcc18d 092f32ae

+317 -2
+1
tools/testing/vsock/.gitignore
··· 1 1 *.d 2 + vsock_test 2 3 vsock_diag_test
+3 -2
tools/testing/vsock/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 all: test 3 - test: vsock_diag_test 3 + test: vsock_test vsock_diag_test 4 + vsock_test: vsock_test.o timeout.o control.o util.o 4 5 vsock_diag_test: vsock_diag_test.o timeout.o control.o util.o 5 6 6 7 CFLAGS += -g -O2 -Werror -Wall -I. -I../../include -I../../../usr/include -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -D_GNU_SOURCE 7 8 .PHONY: all test clean 8 9 clean: 9 - ${RM} *.o *.d vsock_diag_test 10 + ${RM} *.o *.d vsock_test vsock_diag_test 10 11 -include *.d
+1
tools/testing/vsock/README
··· 5 5 6 6 The following tests are available: 7 7 8 + * vsock_test - core AF_VSOCK socket functionality 8 9 * vsock_diag_test - vsock_diag.ko module for listing open sockets 9 10 10 11 The following prerequisite steps are not automated and must be performed prior
+312
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 <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 + 17 + #include "timeout.h" 18 + #include "control.h" 19 + #include "util.h" 20 + 21 + static void test_stream_connection_reset(const struct test_opts *opts) 22 + { 23 + union { 24 + struct sockaddr sa; 25 + struct sockaddr_vm svm; 26 + } addr = { 27 + .svm = { 28 + .svm_family = AF_VSOCK, 29 + .svm_port = 1234, 30 + .svm_cid = opts->peer_cid, 31 + }, 32 + }; 33 + int ret; 34 + int fd; 35 + 36 + fd = socket(AF_VSOCK, SOCK_STREAM, 0); 37 + 38 + timeout_begin(TIMEOUT); 39 + do { 40 + ret = connect(fd, &addr.sa, sizeof(addr.svm)); 41 + timeout_check("connect"); 42 + } while (ret < 0 && errno == EINTR); 43 + timeout_end(); 44 + 45 + if (ret != -1) { 46 + fprintf(stderr, "expected connect(2) failure, got %d\n", ret); 47 + exit(EXIT_FAILURE); 48 + } 49 + if (errno != ECONNRESET) { 50 + fprintf(stderr, "unexpected connect(2) errno %d\n", errno); 51 + exit(EXIT_FAILURE); 52 + } 53 + 54 + close(fd); 55 + } 56 + 57 + static void test_stream_client_close_client(const struct test_opts *opts) 58 + { 59 + int fd; 60 + 61 + fd = vsock_stream_connect(opts->peer_cid, 1234); 62 + if (fd < 0) { 63 + perror("connect"); 64 + exit(EXIT_FAILURE); 65 + } 66 + 67 + send_byte(fd, 1, 0); 68 + close(fd); 69 + control_writeln("CLOSED"); 70 + } 71 + 72 + static void test_stream_client_close_server(const struct test_opts *opts) 73 + { 74 + int fd; 75 + 76 + fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); 77 + if (fd < 0) { 78 + perror("accept"); 79 + exit(EXIT_FAILURE); 80 + } 81 + 82 + control_expectln("CLOSED"); 83 + 84 + send_byte(fd, -EPIPE, 0); 85 + recv_byte(fd, 1, 0); 86 + recv_byte(fd, 0, 0); 87 + close(fd); 88 + } 89 + 90 + static void test_stream_server_close_client(const struct test_opts *opts) 91 + { 92 + int fd; 93 + 94 + fd = vsock_stream_connect(opts->peer_cid, 1234); 95 + if (fd < 0) { 96 + perror("connect"); 97 + exit(EXIT_FAILURE); 98 + } 99 + 100 + control_expectln("CLOSED"); 101 + 102 + send_byte(fd, -EPIPE, 0); 103 + recv_byte(fd, 1, 0); 104 + recv_byte(fd, 0, 0); 105 + close(fd); 106 + } 107 + 108 + static void test_stream_server_close_server(const struct test_opts *opts) 109 + { 110 + int fd; 111 + 112 + fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); 113 + if (fd < 0) { 114 + perror("accept"); 115 + exit(EXIT_FAILURE); 116 + } 117 + 118 + send_byte(fd, 1, 0); 119 + close(fd); 120 + control_writeln("CLOSED"); 121 + } 122 + 123 + /* With the standard socket sizes, VMCI is able to support about 100 124 + * concurrent stream connections. 125 + */ 126 + #define MULTICONN_NFDS 100 127 + 128 + static void test_stream_multiconn_client(const struct test_opts *opts) 129 + { 130 + int fds[MULTICONN_NFDS]; 131 + int i; 132 + 133 + for (i = 0; i < MULTICONN_NFDS; i++) { 134 + fds[i] = vsock_stream_connect(opts->peer_cid, 1234); 135 + if (fds[i] < 0) { 136 + perror("connect"); 137 + exit(EXIT_FAILURE); 138 + } 139 + } 140 + 141 + for (i = 0; i < MULTICONN_NFDS; i++) { 142 + if (i % 2) 143 + recv_byte(fds[i], 1, 0); 144 + else 145 + send_byte(fds[i], 1, 0); 146 + } 147 + 148 + for (i = 0; i < MULTICONN_NFDS; i++) 149 + close(fds[i]); 150 + } 151 + 152 + static void test_stream_multiconn_server(const struct test_opts *opts) 153 + { 154 + int fds[MULTICONN_NFDS]; 155 + int i; 156 + 157 + for (i = 0; i < MULTICONN_NFDS; i++) { 158 + fds[i] = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); 159 + if (fds[i] < 0) { 160 + perror("accept"); 161 + exit(EXIT_FAILURE); 162 + } 163 + } 164 + 165 + for (i = 0; i < MULTICONN_NFDS; i++) { 166 + if (i % 2) 167 + send_byte(fds[i], 1, 0); 168 + else 169 + recv_byte(fds[i], 1, 0); 170 + } 171 + 172 + for (i = 0; i < MULTICONN_NFDS; i++) 173 + close(fds[i]); 174 + } 175 + 176 + static struct test_case test_cases[] = { 177 + { 178 + .name = "SOCK_STREAM connection reset", 179 + .run_client = test_stream_connection_reset, 180 + }, 181 + { 182 + .name = "SOCK_STREAM client close", 183 + .run_client = test_stream_client_close_client, 184 + .run_server = test_stream_client_close_server, 185 + }, 186 + { 187 + .name = "SOCK_STREAM server close", 188 + .run_client = test_stream_server_close_client, 189 + .run_server = test_stream_server_close_server, 190 + }, 191 + { 192 + .name = "SOCK_STREAM multiple connections", 193 + .run_client = test_stream_multiconn_client, 194 + .run_server = test_stream_multiconn_server, 195 + }, 196 + {}, 197 + }; 198 + 199 + static const char optstring[] = ""; 200 + static const struct option longopts[] = { 201 + { 202 + .name = "control-host", 203 + .has_arg = required_argument, 204 + .val = 'H', 205 + }, 206 + { 207 + .name = "control-port", 208 + .has_arg = required_argument, 209 + .val = 'P', 210 + }, 211 + { 212 + .name = "mode", 213 + .has_arg = required_argument, 214 + .val = 'm', 215 + }, 216 + { 217 + .name = "peer-cid", 218 + .has_arg = required_argument, 219 + .val = 'p', 220 + }, 221 + { 222 + .name = "help", 223 + .has_arg = no_argument, 224 + .val = '?', 225 + }, 226 + {}, 227 + }; 228 + 229 + static void usage(void) 230 + { 231 + fprintf(stderr, "Usage: vsock_test [--help] [--control-host=<host>] --control-port=<port> --mode=client|server --peer-cid=<cid>\n" 232 + "\n" 233 + " Server: vsock_test --control-port=1234 --mode=server --peer-cid=3\n" 234 + " Client: vsock_test --control-host=192.168.0.1 --control-port=1234 --mode=client --peer-cid=2\n" 235 + "\n" 236 + "Run vsock.ko tests. Must be launched in both guest\n" 237 + "and host. One side must use --mode=client and\n" 238 + "the other side must use --mode=server.\n" 239 + "\n" 240 + "A TCP control socket connection is used to coordinate tests\n" 241 + "between the client and the server. The server requires a\n" 242 + "listen address and the client requires an address to\n" 243 + "connect to.\n" 244 + "\n" 245 + "The CID of the other side must be given with --peer-cid=<cid>.\n"); 246 + exit(EXIT_FAILURE); 247 + } 248 + 249 + int main(int argc, char **argv) 250 + { 251 + const char *control_host = NULL; 252 + const char *control_port = NULL; 253 + struct test_opts opts = { 254 + .mode = TEST_MODE_UNSET, 255 + .peer_cid = VMADDR_CID_ANY, 256 + }; 257 + 258 + init_signals(); 259 + 260 + for (;;) { 261 + int opt = getopt_long(argc, argv, optstring, longopts, NULL); 262 + 263 + if (opt == -1) 264 + break; 265 + 266 + switch (opt) { 267 + case 'H': 268 + control_host = optarg; 269 + break; 270 + case 'm': 271 + if (strcmp(optarg, "client") == 0) 272 + opts.mode = TEST_MODE_CLIENT; 273 + else if (strcmp(optarg, "server") == 0) 274 + opts.mode = TEST_MODE_SERVER; 275 + else { 276 + fprintf(stderr, "--mode must be \"client\" or \"server\"\n"); 277 + return EXIT_FAILURE; 278 + } 279 + break; 280 + case 'p': 281 + opts.peer_cid = parse_cid(optarg); 282 + break; 283 + case 'P': 284 + control_port = optarg; 285 + break; 286 + case '?': 287 + default: 288 + usage(); 289 + } 290 + } 291 + 292 + if (!control_port) 293 + usage(); 294 + if (opts.mode == TEST_MODE_UNSET) 295 + usage(); 296 + if (opts.peer_cid == VMADDR_CID_ANY) 297 + usage(); 298 + 299 + if (!control_host) { 300 + if (opts.mode != TEST_MODE_SERVER) 301 + usage(); 302 + control_host = "0.0.0.0"; 303 + } 304 + 305 + control_init(control_host, control_port, 306 + opts.mode == TEST_MODE_SERVER); 307 + 308 + run_tests(test_cases, &opts); 309 + 310 + control_cleanup(); 311 + return EXIT_SUCCESS; 312 + }