Commit 9bb8a29d authored by Stefan Hajnoczi's avatar Stefan Hajnoczi Committed by David S. Miller

VSOCK: extract connect/accept functions from vsock_diag_test.c

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: default avatarStefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: default avatarStefano Garzarella <sgarzare@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent df7e0e0d
......@@ -11,8 +11,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include "timeout.h"
#include "control.h"
#include "util.h"
/* Install signal handlers */
......@@ -41,6 +43,112 @@ unsigned int parse_cid(const char *str)
return n;
}
/* Connect to <cid, port> 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 <cid, port> 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)
......
......@@ -2,6 +2,9 @@
#ifndef UTIL_H
#define UTIL_H
#include <sys/socket.h>
#include <linux/vm_sockets.h>
/* Tests can either run as the client or the server */
enum test_mode {
TEST_MODE_UNSET,
......@@ -30,6 +33,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);
......
......@@ -13,13 +13,11 @@
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/list.h>
#include <linux/net.h>
#include <linux/netlink.h>
#include <linux/vm_sockets.h>
#include <linux/sock_diag.h>
#include <linux/vm_sockets_diag.h>
#include <netinet/tcp.h>
......@@ -378,33 +376,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);
}
......@@ -424,66 +401,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);
......@@ -491,7 +421,6 @@ static void test_connect_server(const struct test_opts *opts)
control_expectln("DONE");
close(client_fd);
close(fd);
free_sock_stat(&sockets);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment