From patchwork Wed Dec 13 14:49:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 848003 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yxfjn1Lmkz9s7m for ; Thu, 14 Dec 2017 01:49:49 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753280AbdLMOtS (ORCPT ); Wed, 13 Dec 2017 09:49:18 -0500 Received: from mx1.redhat.com ([209.132.183.28]:54937 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752811AbdLMOtQ (ORCPT ); Wed, 13 Dec 2017 09:49:16 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2CDC1C00AE1F; Wed, 13 Dec 2017 14:49:16 +0000 (UTC) Received: from localhost (ovpn-116-41.ams2.redhat.com [10.36.116.41]) by smtp.corp.redhat.com (Postfix) with ESMTP id 159A67BFF5; Wed, 13 Dec 2017 14:49:14 +0000 (UTC) From: Stefan Hajnoczi To: netdev@vger.kernel.org Cc: Jorgen Hansen , Dexuan Cui , Stefan Hajnoczi Subject: [PATCH 1/5] VSOCK: extract utility functions from vsock_diag_test.c Date: Wed, 13 Dec 2017 14:49:07 +0000 Message-Id: <20171213144911.6428-2-stefanha@redhat.com> In-Reply-To: <20171213144911.6428-1-stefanha@redhat.com> References: <20171213144911.6428-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Wed, 13 Dec 2017 14:49:16 +0000 (UTC) Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Move useful functions into a separate file in preparation for more vsock test programs. Signed-off-by: Stefan Hajnoczi --- tools/testing/vsock/Makefile | 2 +- tools/testing/vsock/util.h | 35 +++++++++++++ tools/testing/vsock/util.c | 70 ++++++++++++++++++++++++++ tools/testing/vsock/vsock_diag_test.c | 92 +++++++++-------------------------- 4 files changed, 128 insertions(+), 71 deletions(-) create mode 100644 tools/testing/vsock/util.h create mode 100644 tools/testing/vsock/util.c diff --git a/tools/testing/vsock/Makefile b/tools/testing/vsock/Makefile index 66ba0924194d..cf0650007fa8 100644 --- a/tools/testing/vsock/Makefile +++ b/tools/testing/vsock/Makefile @@ -1,6 +1,6 @@ all: test test: vsock_diag_test -vsock_diag_test: vsock_diag_test.o timeout.o control.o +vsock_diag_test: vsock_diag_test.o timeout.o control.o util.o CFLAGS += -g -O2 -Werror -Wall -I. -I../../include/uapi -I../../include -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -D_GNU_SOURCE .PHONY: all test clean diff --git a/tools/testing/vsock/util.h b/tools/testing/vsock/util.h new file mode 100644 index 000000000000..a51e17578ccf --- /dev/null +++ b/tools/testing/vsock/util.h @@ -0,0 +1,35 @@ +#ifndef UTIL_H +#define UTIL_H + +/* Tests can either run as the client or the server */ +enum test_mode { + TEST_MODE_UNSET, + TEST_MODE_CLIENT, + TEST_MODE_SERVER +}; + +/* Test runner options */ +struct test_opts { + enum test_mode mode; + unsigned int peer_cid; +}; + +/* A test case definition. Test functions must print failures to stderr and + * terminate with exit(EXIT_FAILURE). + */ +struct test_case { + const char *name; /* human-readable name */ + + /* Called when test mode is TEST_MODE_CLIENT */ + void (*run_client)(const struct test_opts *opts); + + /* Called when test mode is TEST_MODE_SERVER */ + void (*run_server)(const struct test_opts *opts); +}; + +void init_signals(void); +unsigned int parse_cid(const char *str); +void run_tests(const struct test_case *test_cases, + const struct test_opts *opts); + +#endif /* UTIL_H */ diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c new file mode 100644 index 000000000000..2567abd90153 --- /dev/null +++ b/tools/testing/vsock/util.c @@ -0,0 +1,70 @@ +/* + * vsock test utilities + * + * Copyright (C) 2017 Red Hat, Inc. + * + * Author: Stefan Hajnoczi + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * of the License. + */ + +#include +#include +#include +#include + +#include "timeout.h" +#include "util.h" + +/* Install signal handlers */ +void init_signals(void) +{ + struct sigaction act = { + .sa_handler = sigalrm, + }; + + sigaction(SIGALRM, &act, NULL); + signal(SIGPIPE, SIG_IGN); +} + +/* Parse a CID in string representation */ +unsigned int parse_cid(const char *str) +{ + char *endptr = NULL; + unsigned long int n; + + errno = 0; + n = strtoul(str, &endptr, 10); + if (errno || *endptr != '\0') { + fprintf(stderr, "malformed CID \"%s\"\n", str); + exit(EXIT_FAILURE); + } + return n; +} + +/* Run test cases. The program terminates if a failure occurs. */ +void run_tests(const struct test_case *test_cases, + const struct test_opts *opts) +{ + int i; + + for (i = 0; test_cases[i].name; i++) { + void (*run)(const struct test_opts *opts); + + printf("%s...", test_cases[i].name); + fflush(stdout); + + if (opts->mode == TEST_MODE_CLIENT) + run = test_cases[i].run_client; + else + run = test_cases[i].run_server; + + if (run) + run(opts); + + printf("ok\n"); + } +} diff --git a/tools/testing/vsock/vsock_diag_test.c b/tools/testing/vsock/vsock_diag_test.c index e896a4af52f4..f1ace5d96e00 100644 --- a/tools/testing/vsock/vsock_diag_test.c +++ b/tools/testing/vsock/vsock_diag_test.c @@ -13,12 +13,10 @@ #include #include -#include #include #include #include #include -#include #include #include #include @@ -33,12 +31,7 @@ #include "timeout.h" #include "control.h" - -enum test_mode { - TEST_MODE_UNSET, - TEST_MODE_CLIENT, - TEST_MODE_SERVER -}; +#include "util.h" /* Per-socket status */ struct vsock_stat { @@ -339,7 +332,7 @@ static void free_sock_stat(struct list_head *sockets) free(st); } -static void test_no_sockets(unsigned int peer_cid) +static void test_no_sockets(const struct test_opts *opts) { LIST_HEAD(sockets); @@ -350,7 +343,7 @@ static void test_no_sockets(unsigned int peer_cid) free_sock_stat(&sockets); } -static void test_listen_socket_server(unsigned int peer_cid) +static void test_listen_socket_server(const struct test_opts *opts) { union { struct sockaddr sa; @@ -388,7 +381,7 @@ static void test_listen_socket_server(unsigned int peer_cid) free_sock_stat(&sockets); } -static void test_connect_client(unsigned int peer_cid) +static void test_connect_client(const struct test_opts *opts) { union { struct sockaddr sa; @@ -397,7 +390,7 @@ static void test_connect_client(unsigned int peer_cid) .svm = { .svm_family = AF_VSOCK, .svm_port = 1234, - .svm_cid = peer_cid, + .svm_cid = opts->peer_cid, }, }; int fd; @@ -434,7 +427,7 @@ static void test_connect_client(unsigned int peer_cid) free_sock_stat(&sockets); } -static void test_connect_server(unsigned int peer_cid) +static void test_connect_server(const struct test_opts *opts) { union { struct sockaddr sa; @@ -486,9 +479,9 @@ static void test_connect_server(unsigned int peer_cid) clientaddr.sa.sa_family); exit(EXIT_FAILURE); } - if (clientaddr.svm.svm_cid != peer_cid) { + if (clientaddr.svm.svm_cid != opts->peer_cid) { fprintf(stderr, "expected peer CID %u from accept(2), got %u\n", - peer_cid, clientaddr.svm.svm_cid); + opts->peer_cid, clientaddr.svm.svm_cid); exit(EXIT_FAILURE); } @@ -507,11 +500,7 @@ static void test_connect_server(unsigned int peer_cid) free_sock_stat(&sockets); } -static struct { - const char *name; - void (*run_client)(unsigned int peer_cid); - void (*run_server)(unsigned int peer_cid); -} test_cases[] = { +static struct test_case test_cases[] = { { .name = "No sockets", .run_server = test_no_sockets, @@ -528,30 +517,6 @@ static struct { {}, }; -static void init_signals(void) -{ - struct sigaction act = { - .sa_handler = sigalrm, - }; - - sigaction(SIGALRM, &act, NULL); - signal(SIGPIPE, SIG_IGN); -} - -static unsigned int parse_cid(const char *str) -{ - char *endptr = NULL; - unsigned long int n; - - errno = 0; - n = strtoul(str, &endptr, 10); - if (errno || *endptr != '\0') { - fprintf(stderr, "malformed CID \"%s\"\n", str); - exit(EXIT_FAILURE); - } - return n; -} - static const char optstring[] = ""; static const struct option longopts[] = { { @@ -606,9 +571,10 @@ int main(int argc, char **argv) { const char *control_host = NULL; const char *control_port = NULL; - int mode = TEST_MODE_UNSET; - unsigned int peer_cid = VMADDR_CID_ANY; - int i; + struct test_opts opts = { + .mode = TEST_MODE_UNSET, + .peer_cid = VMADDR_CID_ANY, + }; init_signals(); @@ -624,16 +590,16 @@ int main(int argc, char **argv) break; case 'm': if (strcmp(optarg, "client") == 0) - mode = TEST_MODE_CLIENT; + opts.mode = TEST_MODE_CLIENT; else if (strcmp(optarg, "server") == 0) - mode = TEST_MODE_SERVER; + opts.mode = TEST_MODE_SERVER; else { fprintf(stderr, "--mode must be \"client\" or \"server\"\n"); return EXIT_FAILURE; } break; case 'p': - peer_cid = parse_cid(optarg); + opts.peer_cid = parse_cid(optarg); break; case 'P': control_port = optarg; @@ -646,35 +612,21 @@ int main(int argc, char **argv) if (!control_port) usage(); - if (mode == TEST_MODE_UNSET) + if (opts.mode == TEST_MODE_UNSET) usage(); - if (peer_cid == VMADDR_CID_ANY) + if (opts.peer_cid == VMADDR_CID_ANY) usage(); if (!control_host) { - if (mode != TEST_MODE_SERVER) + if (opts.mode != TEST_MODE_SERVER) usage(); control_host = "0.0.0.0"; } - control_init(control_host, control_port, mode == TEST_MODE_SERVER); + control_init(control_host, control_port, + opts.mode == TEST_MODE_SERVER); - for (i = 0; test_cases[i].name; i++) { - void (*run)(unsigned int peer_cid); - - printf("%s...", test_cases[i].name); - fflush(stdout); - - if (mode == TEST_MODE_CLIENT) - run = test_cases[i].run_client; - else - run = test_cases[i].run_server; - - if (run) - run(peer_cid); - - printf("ok\n"); - } + run_tests(test_cases, &opts); control_cleanup(); return EXIT_SUCCESS; From patchwork Wed Dec 13 14:49:08 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 847999 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yxfjJ4v8Xz9s7m for ; Thu, 14 Dec 2017 01:49:24 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753370AbdLMOtV (ORCPT ); Wed, 13 Dec 2017 09:49:21 -0500 Received: from mx1.redhat.com ([209.132.183.28]:41074 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753115AbdLMOtT (ORCPT ); Wed, 13 Dec 2017 09:49:19 -0500 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9149F8210D; Wed, 13 Dec 2017 14:49:18 +0000 (UTC) Received: from localhost (ovpn-116-41.ams2.redhat.com [10.36.116.41]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8283E18B56; Wed, 13 Dec 2017 14:49:17 +0000 (UTC) From: Stefan Hajnoczi To: netdev@vger.kernel.org Cc: Jorgen Hansen , Dexuan Cui , Stefan Hajnoczi Subject: [PATCH 2/5] VSOCK: extract connect/accept functions from vsock_diag_test.c Date: Wed, 13 Dec 2017 14:49:08 +0000 Message-Id: <20171213144911.6428-3-stefanha@redhat.com> In-Reply-To: <20171213144911.6428-1-stefanha@redhat.com> References: <20171213144911.6428-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Wed, 13 Dec 2017 14:49:18 +0000 (UTC) Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Many test cases will need to connect to the server or accept incoming connections. This patch extracts these operations into utility functions that can be reused. Signed-off-by: Stefan Hajnoczi --- tools/testing/vsock/util.h | 6 ++ tools/testing/vsock/util.c | 108 ++++++++++++++++++++++++++++++++++ tools/testing/vsock/vsock_diag_test.c | 81 ++----------------------- 3 files changed, 119 insertions(+), 76 deletions(-) diff --git a/tools/testing/vsock/util.h b/tools/testing/vsock/util.h index a51e17578ccf..3e6971f15caa 100644 --- a/tools/testing/vsock/util.h +++ b/tools/testing/vsock/util.h @@ -1,6 +1,9 @@ #ifndef UTIL_H #define UTIL_H +#include +#include "../../../include/uapi/linux/vm_sockets.h" + /* Tests can either run as the client or the server */ enum test_mode { TEST_MODE_UNSET, @@ -29,6 +32,9 @@ struct test_case { void init_signals(void); unsigned int parse_cid(const char *str); +int vsock_stream_connect(unsigned int cid, unsigned int port); +int vsock_stream_accept(unsigned int cid, unsigned int port, + struct sockaddr_vm *clientaddrp); void run_tests(const struct test_case *test_cases, const struct test_opts *opts); diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c index 2567abd90153..75a78f295b37 100644 --- a/tools/testing/vsock/util.c +++ b/tools/testing/vsock/util.c @@ -15,8 +15,10 @@ #include #include #include +#include #include "timeout.h" +#include "control.h" #include "util.h" /* Install signal handlers */ @@ -45,6 +47,112 @@ unsigned int parse_cid(const char *str) return n; } +/* Connect to and return the file descriptor. */ +int vsock_stream_connect(unsigned int cid, unsigned int port) +{ + union { + struct sockaddr sa; + struct sockaddr_vm svm; + } addr = { + .svm = { + .svm_family = AF_VSOCK, + .svm_port = port, + .svm_cid = cid, + }, + }; + int ret; + int fd; + + control_expectln("LISTENING"); + + fd = socket(AF_VSOCK, SOCK_STREAM, 0); + + timeout_begin(TIMEOUT); + do { + ret = connect(fd, &addr.sa, sizeof(addr.svm)); + timeout_check("connect"); + } while (ret < 0 && errno == EINTR); + timeout_end(); + + if (ret < 0) { + int old_errno = errno; + + close(fd); + fd = -1; + errno = old_errno; + } + return fd; +} + +/* Listen on and return the first incoming connection. The remote + * address is stored to clientaddrp. clientaddrp may be NULL. + */ +int vsock_stream_accept(unsigned int cid, unsigned int port, + struct sockaddr_vm *clientaddrp) +{ + union { + struct sockaddr sa; + struct sockaddr_vm svm; + } addr = { + .svm = { + .svm_family = AF_VSOCK, + .svm_port = port, + .svm_cid = cid, + }, + }; + union { + struct sockaddr sa; + struct sockaddr_vm svm; + } clientaddr; + socklen_t clientaddr_len = sizeof(clientaddr.svm); + int fd; + int client_fd; + int old_errno; + + fd = socket(AF_VSOCK, SOCK_STREAM, 0); + + if (bind(fd, &addr.sa, sizeof(addr.svm)) < 0) { + perror("bind"); + exit(EXIT_FAILURE); + } + + if (listen(fd, 1) < 0) { + perror("listen"); + exit(EXIT_FAILURE); + } + + control_writeln("LISTENING"); + + timeout_begin(TIMEOUT); + do { + client_fd = accept(fd, &clientaddr.sa, &clientaddr_len); + timeout_check("accept"); + } while (client_fd < 0 && errno == EINTR); + timeout_end(); + + old_errno = errno; + close(fd); + errno = old_errno; + + if (client_fd < 0) + return client_fd; + + if (clientaddr_len != sizeof(clientaddr.svm)) { + fprintf(stderr, "unexpected addrlen from accept(2), %zu\n", + (size_t)clientaddr_len); + exit(EXIT_FAILURE); + } + if (clientaddr.sa.sa_family != AF_VSOCK) { + fprintf(stderr, "expected AF_VSOCK from accept(2), got %d\n", + clientaddr.sa.sa_family); + exit(EXIT_FAILURE); + } + + if (clientaddrp) + *clientaddrp = clientaddr.svm; + return client_fd; +} + /* Run test cases. The program terminates if a failure occurs. */ void run_tests(const struct test_case *test_cases, const struct test_opts *opts) diff --git a/tools/testing/vsock/vsock_diag_test.c b/tools/testing/vsock/vsock_diag_test.c index f1ace5d96e00..654bbe2fc211 100644 --- a/tools/testing/vsock/vsock_diag_test.c +++ b/tools/testing/vsock/vsock_diag_test.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -26,7 +25,6 @@ #include #include -#include "../../../include/uapi/linux/vm_sockets.h" #include "../../../include/uapi/linux/vm_sockets_diag.h" #include "timeout.h" @@ -383,33 +381,12 @@ static void test_listen_socket_server(const struct test_opts *opts) static void test_connect_client(const struct test_opts *opts) { - union { - struct sockaddr sa; - struct sockaddr_vm svm; - } addr = { - .svm = { - .svm_family = AF_VSOCK, - .svm_port = 1234, - .svm_cid = opts->peer_cid, - }, - }; int fd; - int ret; LIST_HEAD(sockets); struct vsock_stat *st; - control_expectln("LISTENING"); - - fd = socket(AF_VSOCK, SOCK_STREAM, 0); - - timeout_begin(TIMEOUT); - do { - ret = connect(fd, &addr.sa, sizeof(addr.svm)); - timeout_check("connect"); - } while (ret < 0 && errno == EINTR); - timeout_end(); - - if (ret < 0) { + fd = vsock_stream_connect(opts->peer_cid, 1234); + if (fd < 0) { perror("connect"); exit(EXIT_FAILURE); } @@ -429,66 +406,19 @@ static void test_connect_client(const struct test_opts *opts) static void test_connect_server(const struct test_opts *opts) { - union { - struct sockaddr sa; - struct sockaddr_vm svm; - } addr = { - .svm = { - .svm_family = AF_VSOCK, - .svm_port = 1234, - .svm_cid = VMADDR_CID_ANY, - }, - }; - union { - struct sockaddr sa; - struct sockaddr_vm svm; - } clientaddr; - socklen_t clientaddr_len = sizeof(clientaddr.svm); - LIST_HEAD(sockets); struct vsock_stat *st; - int fd; + LIST_HEAD(sockets); int client_fd; - fd = socket(AF_VSOCK, SOCK_STREAM, 0); - - if (bind(fd, &addr.sa, sizeof(addr.svm)) < 0) { - perror("bind"); - exit(EXIT_FAILURE); - } - - if (listen(fd, 1) < 0) { - perror("listen"); - exit(EXIT_FAILURE); - } - - control_writeln("LISTENING"); - - timeout_begin(TIMEOUT); - do { - client_fd = accept(fd, &clientaddr.sa, &clientaddr_len); - timeout_check("accept"); - } while (client_fd < 0 && errno == EINTR); - timeout_end(); - + client_fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); if (client_fd < 0) { perror("accept"); exit(EXIT_FAILURE); } - if (clientaddr.sa.sa_family != AF_VSOCK) { - fprintf(stderr, "expected AF_VSOCK from accept(2), got %d\n", - clientaddr.sa.sa_family); - exit(EXIT_FAILURE); - } - if (clientaddr.svm.svm_cid != opts->peer_cid) { - fprintf(stderr, "expected peer CID %u from accept(2), got %u\n", - opts->peer_cid, clientaddr.svm.svm_cid); - exit(EXIT_FAILURE); - } read_vsock_stat(&sockets); - check_num_sockets(&sockets, 2); - find_vsock_stat(&sockets, fd); + check_num_sockets(&sockets, 1); st = find_vsock_stat(&sockets, client_fd); check_socket_state(st, TCP_ESTABLISHED); @@ -496,7 +426,6 @@ static void test_connect_server(const struct test_opts *opts) control_expectln("DONE"); close(client_fd); - close(fd); free_sock_stat(&sockets); } From patchwork Wed Dec 13 14:49:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 848001 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yxfjQ0zYnz9s7g for ; Thu, 14 Dec 2017 01:49:30 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753376AbdLMOt1 (ORCPT ); Wed, 13 Dec 2017 09:49:27 -0500 Received: from mx1.redhat.com ([209.132.183.28]:25421 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753358AbdLMOtU (ORCPT ); Wed, 13 Dec 2017 09:49:20 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CDEC864049; Wed, 13 Dec 2017 14:49:20 +0000 (UTC) Received: from localhost (ovpn-116-41.ams2.redhat.com [10.36.116.41]) by smtp.corp.redhat.com (Postfix) with ESMTP id F295B182C7; Wed, 13 Dec 2017 14:49:19 +0000 (UTC) From: Stefan Hajnoczi To: netdev@vger.kernel.org Cc: Jorgen Hansen , Dexuan Cui , Stefan Hajnoczi Subject: [PATCH 3/5] VSOCK: add full barrier between test cases Date: Wed, 13 Dec 2017 14:49:09 +0000 Message-Id: <20171213144911.6428-4-stefanha@redhat.com> In-Reply-To: <20171213144911.6428-1-stefanha@redhat.com> References: <20171213144911.6428-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Wed, 13 Dec 2017 14:49:20 +0000 (UTC) Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org See code comment for details. Signed-off-by: Stefan Hajnoczi --- tools/testing/vsock/util.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c index 75a78f295b37..2be923fe9922 100644 --- a/tools/testing/vsock/util.c +++ b/tools/testing/vsock/util.c @@ -165,10 +165,24 @@ void run_tests(const struct test_case *test_cases, printf("%s...", test_cases[i].name); fflush(stdout); - if (opts->mode == TEST_MODE_CLIENT) + if (opts->mode == TEST_MODE_CLIENT) { + /* Full barrier before executing the next test. This + * ensures that client and server are executing the + * same test case. In particular, it means whoever is + * faster will not see the peer still executing the + * last test. This is important because port numbers + * can be used by multiple test cases. + */ + control_expectln("NEXT"); + control_writeln("NEXT"); + run = test_cases[i].run_client; - else + } else { + control_writeln("NEXT"); + control_expectln("NEXT"); + run = test_cases[i].run_server; + } if (run) run(opts); From patchwork Wed Dec 13 14:49:10 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 848000 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yxfjM6jSKz9s7m for ; Thu, 14 Dec 2017 01:49:27 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753372AbdLMOt0 (ORCPT ); Wed, 13 Dec 2017 09:49:26 -0500 Received: from mx1.redhat.com ([209.132.183.28]:42446 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753115AbdLMOtX (ORCPT ); Wed, 13 Dec 2017 09:49:23 -0500 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 183632DACC6; Wed, 13 Dec 2017 14:49:23 +0000 (UTC) Received: from localhost (ovpn-116-41.ams2.redhat.com [10.36.116.41]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3CD3A7DE5E; Wed, 13 Dec 2017 14:49:22 +0000 (UTC) From: Stefan Hajnoczi To: netdev@vger.kernel.org Cc: Jorgen Hansen , Dexuan Cui , Stefan Hajnoczi Subject: [PATCH 4/5] VSOCK: add send_byte()/recv_byte() test utilities Date: Wed, 13 Dec 2017 14:49:10 +0000 Message-Id: <20171213144911.6428-5-stefanha@redhat.com> In-Reply-To: <20171213144911.6428-1-stefanha@redhat.com> References: <20171213144911.6428-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Wed, 13 Dec 2017 14:49:23 +0000 (UTC) Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Test cases will want to transfer data. This patch adds utility functions to do this. Signed-off-by: Stefan Hajnoczi --- tools/testing/vsock/util.h | 2 + tools/testing/vsock/util.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/tools/testing/vsock/util.h b/tools/testing/vsock/util.h index 3e6971f15caa..cf43d42591bc 100644 --- a/tools/testing/vsock/util.h +++ b/tools/testing/vsock/util.h @@ -35,6 +35,8 @@ unsigned int parse_cid(const char *str); int vsock_stream_connect(unsigned int cid, unsigned int port); int vsock_stream_accept(unsigned int cid, unsigned int port, struct sockaddr_vm *clientaddrp); +void send_byte(int fd, int expected_ret); +void recv_byte(int fd, int expected_ret); void run_tests(const struct test_case *test_cases, const struct test_opts *opts); diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c index 2be923fe9922..e28085a2a429 100644 --- a/tools/testing/vsock/util.c +++ b/tools/testing/vsock/util.c @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -153,6 +154,104 @@ int vsock_stream_accept(unsigned int cid, unsigned int port, return client_fd; } +/* Transmit one byte and check the return value. + * + * expected_ret: + * <0 Negative errno (for testing errors) + * 0 End-of-file + * 1 Success + */ +void send_byte(int fd, int expected_ret) +{ + const uint8_t byte = 'A'; + ssize_t nwritten; + + timeout_begin(TIMEOUT); + do { + nwritten = write(fd, &byte, sizeof(byte)); + timeout_check("write"); + } while (nwritten < 0 && errno == EINTR); + timeout_end(); + + if (expected_ret < 0) { + if (nwritten != -1) { + fprintf(stderr, "bogus write(2) return value %zd\n", + nwritten); + exit(EXIT_FAILURE); + } + if (errno != -expected_ret) { + perror("write"); + exit(EXIT_FAILURE); + } + return; + } + + if (nwritten < 0) { + perror("write"); + exit(EXIT_FAILURE); + } + if (nwritten == 0) { + if (expected_ret == 0) + return; + + fprintf(stderr, "unexpected EOF while sending byte\n"); + exit(EXIT_FAILURE); + } + if (nwritten != sizeof(byte)) { + fprintf(stderr, "bogus write(2) return value %zd\n", nwritten); + exit(EXIT_FAILURE); + } +} + +/* Receive one byte and check the return value. + * + * expected_ret: + * <0 Negative errno (for testing errors) + * 0 End-of-file + * 1 Success + */ +void recv_byte(int fd, int expected_ret) +{ + uint8_t byte; + ssize_t nread; + + timeout_begin(TIMEOUT); + do { + nread = read(fd, &byte, sizeof(byte)); + timeout_check("read"); + } while (nread < 0 && errno == EINTR); + timeout_end(); + + if (expected_ret < 0) { + if (nread != -1) { + fprintf(stderr, "bogus read(2) return value %zd\n", + nread); + exit(EXIT_FAILURE); + } + if (errno != -expected_ret) { + perror("read"); + exit(EXIT_FAILURE); + } + return; + } + + if (nread < 0) { + perror("read"); + exit(EXIT_FAILURE); + } + if (nread == 0) { + if (expected_ret == 0) + return; + + fprintf(stderr, "unexpected EOF while receiving byte\n"); + exit(EXIT_FAILURE); + } + if (nread != sizeof(byte)) { + fprintf(stderr, "bogus read(2) return value %zd\n", nread); + exit(EXIT_FAILURE); + } +} + /* Run test cases. The program terminates if a failure occurs. */ void run_tests(const struct test_case *test_cases, const struct test_opts *opts) From patchwork Wed Dec 13 14:49:11 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Hajnoczi X-Patchwork-Id: 848002 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yxfjb505Pz9s7g for ; Thu, 14 Dec 2017 01:49:39 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753197AbdLMOth (ORCPT ); Wed, 13 Dec 2017 09:49:37 -0500 Received: from mx1.redhat.com ([209.132.183.28]:45296 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753144AbdLMOtZ (ORCPT ); Wed, 13 Dec 2017 09:49:25 -0500 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8C1A874A2F; Wed, 13 Dec 2017 14:49:25 +0000 (UTC) Received: from localhost (ovpn-116-41.ams2.redhat.com [10.36.116.41]) by smtp.corp.redhat.com (Postfix) with ESMTP id 798EB5C1AB; Wed, 13 Dec 2017 14:49:24 +0000 (UTC) From: Stefan Hajnoczi To: netdev@vger.kernel.org Cc: Jorgen Hansen , Dexuan Cui , Stefan Hajnoczi Subject: [PATCH 5/5] VSOCK: add AF_VSOCK test cases Date: Wed, 13 Dec 2017 14:49:11 +0000 Message-Id: <20171213144911.6428-6-stefanha@redhat.com> In-Reply-To: <20171213144911.6428-1-stefanha@redhat.com> References: <20171213144911.6428-1-stefanha@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Wed, 13 Dec 2017 14:49:25 +0000 (UTC) Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The vsock_test.c program runs a test suite of AF_VSOCK test cases. Signed-off-by: Stefan Hajnoczi --- tools/testing/vsock/Makefile | 5 +- tools/testing/vsock/vsock_test.c | 321 +++++++++++++++++++++++++++++++++++++++ tools/testing/vsock/.gitignore | 1 + tools/testing/vsock/README | 1 + 4 files changed, 326 insertions(+), 2 deletions(-) create mode 100644 tools/testing/vsock/vsock_test.c diff --git a/tools/testing/vsock/Makefile b/tools/testing/vsock/Makefile index cf0650007fa8..9efb9010df2e 100644 --- a/tools/testing/vsock/Makefile +++ b/tools/testing/vsock/Makefile @@ -1,9 +1,10 @@ all: test -test: vsock_diag_test +test: vsock_test vsock_diag_test +vsock_test: vsock_test.o timeout.o control.o util.o vsock_diag_test: vsock_diag_test.o timeout.o control.o util.o CFLAGS += -g -O2 -Werror -Wall -I. -I../../include/uapi -I../../include -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -D_GNU_SOURCE .PHONY: all test clean clean: - ${RM} *.o *.d vsock_diag_test + ${RM} *.o *.d vsock_test vsock_diag_test -include *.d diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c new file mode 100644 index 000000000000..c1fc376eea00 --- /dev/null +++ b/tools/testing/vsock/vsock_test.c @@ -0,0 +1,321 @@ +/* + * vsock_test - vsock.ko test suite + * + * Copyright (C) 2017 Red Hat, Inc. + * + * Author: Stefan Hajnoczi + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 + * of the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "timeout.h" +#include "control.h" +#include "util.h" + +static void test_stream_connection_reset(const struct test_opts *opts) +{ + union { + struct sockaddr sa; + struct sockaddr_vm svm; + } addr = { + .svm = { + .svm_family = AF_VSOCK, + .svm_port = 1234, + .svm_cid = opts->peer_cid, + }, + }; + int ret; + int fd; + + fd = socket(AF_VSOCK, SOCK_STREAM, 0); + + timeout_begin(TIMEOUT); + do { + ret = connect(fd, &addr.sa, sizeof(addr.svm)); + timeout_check("connect"); + } while (ret < 0 && errno == EINTR); + timeout_end(); + + if (ret != -1) { + fprintf(stderr, "expected connect(2) failure, got %d\n", ret); + exit(EXIT_FAILURE); + } + if (errno != ECONNRESET) { + fprintf(stderr, "unexpected connect(2) errno %d\n", errno); + exit(EXIT_FAILURE); + } + + close(fd); +} + +static void test_stream_client_close_client(const struct test_opts *opts) +{ + int fd; + + fd = vsock_stream_connect(opts->peer_cid, 1234); + if (fd < 0) { + perror("connect"); + exit(EXIT_FAILURE); + } + + send_byte(fd, 1); + close(fd); + control_writeln("CLOSED"); +} + +static void test_stream_client_close_server(const struct test_opts *opts) +{ + int fd; + + fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); + if (fd < 0) { + perror("accept"); + exit(EXIT_FAILURE); + } + + control_expectln("CLOSED"); + + send_byte(fd, -EPIPE); + recv_byte(fd, 1); + recv_byte(fd, 0); + close(fd); +} + +static void test_stream_server_close_client(const struct test_opts *opts) +{ + int fd; + + fd = vsock_stream_connect(opts->peer_cid, 1234); + if (fd < 0) { + perror("connect"); + exit(EXIT_FAILURE); + } + + control_expectln("CLOSED"); + + send_byte(fd, -EPIPE); + recv_byte(fd, 1); + recv_byte(fd, 0); + close(fd); +} + +static void test_stream_server_close_server(const struct test_opts *opts) +{ + int fd; + + fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); + if (fd < 0) { + perror("accept"); + exit(EXIT_FAILURE); + } + + send_byte(fd, 1); + close(fd); + control_writeln("CLOSED"); +} + +#define MULTICONN_NFDS 1000 + +static void test_stream_multiconn_client(const struct test_opts *opts) +{ + int fds[MULTICONN_NFDS]; + int i; + + for (i = 0; i < MULTICONN_NFDS; i++) { + fds[i] = vsock_stream_connect(opts->peer_cid, 1234); + if (fds[i] < 0) { + perror("connect"); + exit(EXIT_FAILURE); + } + } + + for (i = 0; i < MULTICONN_NFDS; i++) { + if (i % 1) + recv_byte(fds[i], 1); + else + send_byte(fds[i], 1); + } + + for (i = 0; i < MULTICONN_NFDS; i++) + close(fds[i]); +} + +static void test_stream_multiconn_server(const struct test_opts *opts) +{ + int fds[MULTICONN_NFDS]; + int i; + + for (i = 0; i < MULTICONN_NFDS; i++) { + fds[i] = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL); + if (fds[i] < 0) { + perror("accept"); + exit(EXIT_FAILURE); + } + } + + for (i = 0; i < MULTICONN_NFDS; i++) { + if (i % 1) + send_byte(fds[i], 1); + else + recv_byte(fds[i], 1); + } + + for (i = 0; i < MULTICONN_NFDS; i++) + close(fds[i]); +} + +static struct test_case test_cases[] = { + { + .name = "SOCK_STREAM connection reset", + .run_client = test_stream_connection_reset, + }, + { + .name = "SOCK_STREAM client close", + .run_client = test_stream_client_close_client, + .run_server = test_stream_client_close_server, + }, + { + .name = "SOCK_STREAM server close", + .run_client = test_stream_server_close_client, + .run_server = test_stream_server_close_server, + }, + { + .name = "SOCK_STREAM multiple connections", + .run_client = test_stream_multiconn_client, + .run_server = test_stream_multiconn_server, + }, + {}, +}; + +static const char optstring[] = ""; +static const struct option longopts[] = { + { + .name = "control-host", + .has_arg = required_argument, + .val = 'H', + }, + { + .name = "control-port", + .has_arg = required_argument, + .val = 'P', + }, + { + .name = "mode", + .has_arg = required_argument, + .val = 'm', + }, + { + .name = "peer-cid", + .has_arg = required_argument, + .val = 'p', + }, + { + .name = "help", + .has_arg = no_argument, + .val = '?', + }, + {}, +}; + +static void usage(void) +{ + fprintf(stderr, "Usage: vsock_test [--help] [--control-host=] --control-port= --mode=client|server --peer-cid=\n" + "\n" + " Server: vsock_test --control-port=1234 --mode=server --peer-cid=3\n" + " Client: vsock_test --control-host=192.168.0.1 --control-port=1234 --mode=client --peer-cid=2\n" + "\n" + "Run vsock.ko tests. Must be launched in both guest\n" + "and host. One side must use --mode=client and\n" + "the other side must use --mode=server.\n" + "\n" + "A TCP control socket connection is used to coordinate tests\n" + "between the client and the server. The server requires a\n" + "listen address and the client requires an address to\n" + "connect to.\n" + "\n" + "The CID of the other side must be given with --peer-cid=.\n"); + exit(EXIT_FAILURE); +} + +int main(int argc, char **argv) +{ + const char *control_host = NULL; + const char *control_port = NULL; + struct test_opts opts = { + .mode = TEST_MODE_UNSET, + .peer_cid = VMADDR_CID_ANY, + }; + + init_signals(); + + for (;;) { + int opt = getopt_long(argc, argv, optstring, longopts, NULL); + + if (opt == -1) + break; + + switch (opt) { + case 'H': + control_host = optarg; + break; + case 'm': + if (strcmp(optarg, "client") == 0) + opts.mode = TEST_MODE_CLIENT; + else if (strcmp(optarg, "server") == 0) + opts.mode = TEST_MODE_SERVER; + else { + fprintf(stderr, "--mode must be \"client\" or \"server\"\n"); + return EXIT_FAILURE; + } + break; + case 'p': + opts.peer_cid = parse_cid(optarg); + break; + case 'P': + control_port = optarg; + break; + case '?': + default: + usage(); + } + } + + if (!control_port) + usage(); + if (opts.mode == TEST_MODE_UNSET) + usage(); + if (opts.peer_cid == VMADDR_CID_ANY) + usage(); + + if (!control_host) { + if (opts.mode != TEST_MODE_SERVER) + usage(); + control_host = "0.0.0.0"; + } + + control_init(control_host, control_port, + opts.mode == TEST_MODE_SERVER); + + run_tests(test_cases, &opts); + + control_cleanup(); + return EXIT_SUCCESS; +} diff --git a/tools/testing/vsock/.gitignore b/tools/testing/vsock/.gitignore index dc5f11faf530..7f7a2ccc30c4 100644 --- a/tools/testing/vsock/.gitignore +++ b/tools/testing/vsock/.gitignore @@ -1,2 +1,3 @@ *.d +vsock_test vsock_diag_test diff --git a/tools/testing/vsock/README b/tools/testing/vsock/README index 2cc6d7302db6..3014d9e4959a 100644 --- a/tools/testing/vsock/README +++ b/tools/testing/vsock/README @@ -5,6 +5,7 @@ Hyper-V. The following tests are available: + * vsock_test - core AF_VSOCK socket functionality * vsock_diag_test - vsock_diag.ko module for listing open sockets The following prerequisite steps are not automated and must be performed prior