Merge branch 'Enhance-virtio-vsock-connection-semantics'

Sebastien Boeuf says:

====================
Enhance virtio-vsock connection semantics

This series improves the semantics behind the way virtio-vsock server
accepts connections coming from the client. Whenever the server
receives a connection request from the client, if it is bound to the
socket but not yet listening, it will answer with a RST packet. The
point is to ensure each request from the client is quickly processed
so that the client can decide about the strategy of retrying or not.

The series includes along with the improvement patch a new test to
ensure the behavior is consistent across all hypervisors drivers.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2020-02-16 19:01:50 -08:00
commit 8c8da5b8ea
2 changed files with 78 additions and 0 deletions

View file

@ -1153,6 +1153,7 @@ void virtio_transport_recv_pkt(struct virtio_transport *t,
virtio_transport_free_pkt(pkt);
break;
default:
(void)virtio_transport_reset_no_sock(t, pkt);
virtio_transport_free_pkt(pkt);
break;
}

View file

@ -55,6 +55,78 @@ static void test_stream_connection_reset(const struct test_opts *opts)
close(fd);
}
static void test_stream_bind_only_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 ret;
int fd;
/* Wait for the server to be ready */
control_expectln("BIND");
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);
}
/* Notify the server that the client has finished */
control_writeln("DONE");
close(fd);
}
static void test_stream_bind_only_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,
},
};
int fd;
fd = socket(AF_VSOCK, SOCK_STREAM, 0);
if (bind(fd, &addr.sa, sizeof(addr.svm)) < 0) {
perror("bind");
exit(EXIT_FAILURE);
}
/* Notify the client that the server is ready */
control_writeln("BIND");
/* Wait for the client to finish */
control_expectln("DONE");
close(fd);
}
static void test_stream_client_close_client(const struct test_opts *opts)
{
int fd;
@ -212,6 +284,11 @@ static struct test_case test_cases[] = {
.name = "SOCK_STREAM connection reset",
.run_client = test_stream_connection_reset,
},
{
.name = "SOCK_STREAM bind only",
.run_client = test_stream_bind_only_client,
.run_server = test_stream_bind_only_server,
},
{
.name = "SOCK_STREAM client close",
.run_client = test_stream_client_close_client,