* [PATCH liburing 1/6] test/zc: improve error messages
2022-08-04 14:20 [PATCH liburing 0/6] improve zeoropy testing Pavel Begunkov
@ 2022-08-04 14:20 ` Pavel Begunkov
2022-08-04 14:20 ` [PATCH liburing 2/6] tests/zc: test tcp Pavel Begunkov
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Pavel Begunkov @ 2022-08-04 14:20 UTC (permalink / raw)
To: io-uring; +Cc: Jens Axboe, asml.silence
Signed-off-by: Pavel Begunkov <[email protected]>
---
test/send-zerocopy.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/test/send-zerocopy.c b/test/send-zerocopy.c
index 6fa0535..c04e905 100644
--- a/test/send-zerocopy.c
+++ b/test/send-zerocopy.c
@@ -676,7 +676,7 @@ static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_se
ret = io_uring_submit(ring);
if (ret != nr_reqs) {
- fprintf(stderr, "submit failed %i expected %i\n", ret, nr_reqs);
+ fprintf(stderr, "submit failed, got %i expected %i\n", ret, nr_reqs);
return 1;
}
@@ -704,14 +704,15 @@ static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_se
ret = recv(sock_server, rx_buffer, send_size, 0);
if (ret != send_size) {
- fprintf(stderr, "recv less than expected or recv failed %i\n", ret);
+ fprintf(stderr, "recv less than expected or recv failed, "
+ "got %i, errno %i\n", ret, errno);
return 1;
}
for (i = 0; i < send_size; i++) {
if (buf[i] != rx_buffer[i]) {
- fprintf(stderr, "botched data, first byte %i, %u vs %u\n",
- i, buf[i], rx_buffer[i]);
+ fprintf(stderr, "botched data, first mismated byte %i, "
+ "%u vs %u\n", i, buf[i], rx_buffer[i]);
}
}
return 0;
--
2.37.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH liburing 2/6] tests/zc: test tcp
2022-08-04 14:20 [PATCH liburing 0/6] improve zeoropy testing Pavel Begunkov
2022-08-04 14:20 ` [PATCH liburing 1/6] test/zc: improve error messages Pavel Begunkov
@ 2022-08-04 14:20 ` Pavel Begunkov
2022-08-04 14:20 ` [PATCH liburing 3/6] test/zc: allocate buffers dynamically Pavel Begunkov
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Pavel Begunkov @ 2022-08-04 14:20 UTC (permalink / raw)
To: io-uring; +Cc: Jens Axboe, asml.silence
Add tests for TCP zerocopy send
Signed-off-by: Pavel Begunkov <[email protected]>
---
test/send-zerocopy.c | 53 +++++++++++++++++++++++++++++++++++---------
1 file changed, 42 insertions(+), 11 deletions(-)
diff --git a/test/send-zerocopy.c b/test/send-zerocopy.c
index c04e905..7999f46 100644
--- a/test/send-zerocopy.c
+++ b/test/send-zerocopy.c
@@ -550,10 +550,12 @@ static int test_registration(int sock_tx, int sock_rx)
}
static int prepare_ip(struct sockaddr_storage *addr, int *sock_client, int *sock_server,
- bool ipv6, bool client_connect, bool msg_zc)
+ bool ipv6, bool client_connect, bool msg_zc, bool tcp)
{
int family, addr_size;
int ret, val;
+ int listen_sock = -1;
+ int sock;
memset(addr, 0, sizeof(*addr));
if (ipv6) {
@@ -574,18 +576,29 @@ static int prepare_ip(struct sockaddr_storage *addr, int *sock_client, int *sock
}
/* server sock setup */
- *sock_server = socket(family, SOCK_DGRAM, 0);
- if (*sock_server < 0) {
+ if (tcp) {
+ sock = listen_sock = socket(family, SOCK_STREAM, IPPROTO_TCP);
+ } else {
+ sock = *sock_server = socket(family, SOCK_DGRAM, 0);
+ }
+ if (sock < 0) {
perror("socket");
return 1;
}
val = 1;
- setsockopt(*sock_server, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
- ret = bind(*sock_server, (struct sockaddr *)addr, addr_size);
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
+ val = 1;
+ setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val));
+
+ ret = bind(sock, (struct sockaddr *)addr, addr_size);
if (ret < 0) {
perror("bind");
return 1;
}
+ if (tcp) {
+ ret = listen(sock, 128);
+ assert(ret != -1);
+ }
if (ipv6) {
struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)addr;
@@ -598,7 +611,12 @@ static int prepare_ip(struct sockaddr_storage *addr, int *sock_client, int *sock
}
/* client sock setup */
- *sock_client = socket(family, SOCK_DGRAM, 0);
+ if (tcp) {
+ *sock_client = socket(family, SOCK_STREAM, IPPROTO_TCP);
+ assert(client_connect);
+ } else {
+ *sock_client = socket(family, SOCK_DGRAM, 0);
+ }
if (*sock_client < 0) {
perror("socket");
return 1;
@@ -617,6 +635,14 @@ static int prepare_ip(struct sockaddr_storage *addr, int *sock_client, int *sock
return 1;
}
}
+ if (tcp) {
+ *sock_server = accept(listen_sock, NULL, NULL);
+ if (!*sock_server) {
+ fprintf(stderr, "can't accept\n");
+ return 1;
+ }
+ close(listen_sock);
+ }
return 0;
}
@@ -721,17 +747,20 @@ static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_se
static int test_inet_send(struct io_uring *ring)
{
struct sockaddr_storage addr;
- int sock_client, sock_server;
- int ret, j;
- __u64 i;
+ int sock_client = -1, sock_server = -1;
+ int ret, j, i;
- for (j = 0; j < 8; j++) {
+ for (j = 0; j < 16; j++) {
bool ipv6 = j & 1;
bool client_connect = j & 2;
bool msg_zc_set = j & 4;
+ bool tcp = j & 8;
+
+ if (tcp && !client_connect)
+ continue;
ret = prepare_ip(&addr, &sock_client, &sock_server, ipv6,
- client_connect, msg_zc_set);
+ client_connect, msg_zc_set, tcp);
if (ret) {
fprintf(stderr, "sock prep failed %d\n", ret);
return 1;
@@ -746,6 +775,8 @@ static int test_inet_send(struct io_uring *ring)
bool aligned = i & 32;
int buf_idx = aligned ? 0 : 1;
+ if (tcp && cork)
+ continue;
if (mix_register && (!cork || fixed_buf))
continue;
if (!client_connect && addr_arg == NULL)
--
2.37.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH liburing 3/6] test/zc: allocate buffers dynamically
2022-08-04 14:20 [PATCH liburing 0/6] improve zeoropy testing Pavel Begunkov
2022-08-04 14:20 ` [PATCH liburing 1/6] test/zc: improve error messages Pavel Begunkov
2022-08-04 14:20 ` [PATCH liburing 2/6] tests/zc: test tcp Pavel Begunkov
@ 2022-08-04 14:20 ` Pavel Begunkov
2022-08-04 14:20 ` [PATCH liburing 4/6] test/zc: handle short rx Pavel Begunkov
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Pavel Begunkov @ 2022-08-04 14:20 UTC (permalink / raw)
To: io-uring; +Cc: Jens Axboe, asml.silence
A prep patch, allocate receive and transfer buffers dynamically.
Signed-off-by: Pavel Begunkov <[email protected]>
---
test/send-zerocopy.c | 29 ++++++++++++++++++-----------
1 file changed, 18 insertions(+), 11 deletions(-)
diff --git a/test/send-zerocopy.c b/test/send-zerocopy.c
index 7999f46..a572407 100644
--- a/test/send-zerocopy.c
+++ b/test/send-zerocopy.c
@@ -46,7 +46,6 @@
#define NR_SLOTS 5
#define ZC_TAG 10000
-#define MAX_PAYLOAD 8195
#define BUFFER_OFFSET 41
#ifndef ARRAY_SIZE
@@ -54,14 +53,8 @@
#endif
static int seqs[NR_SLOTS];
-static char tx_buffer[MAX_PAYLOAD] __attribute__((aligned(4096)));
-static char rx_buffer[MAX_PAYLOAD] __attribute__((aligned(4096)));
-static struct iovec buffers_iov[] = {
- { .iov_base = tx_buffer,
- .iov_len = sizeof(tx_buffer), },
- { .iov_base = tx_buffer + BUFFER_OFFSET,
- .iov_len = sizeof(tx_buffer) - BUFFER_OFFSET - 13, },
-};
+static char *tx_buffer, *rx_buffer;
+static struct iovec buffers_iov[2];
static inline bool tag_userdata(__u64 user_data)
{
@@ -662,7 +655,7 @@ static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_se
char *buf = buffers_iov[buf_idx].iov_base;
assert(send_size <= buffers_iov[buf_idx].iov_len);
- memset(rx_buffer, 0, sizeof(rx_buffer));
+ memset(rx_buffer, 0, send_size);
for (i = 0; i < nr_reqs; i++) {
bool cur_fixed_buf = fixed_buf;
@@ -804,10 +797,23 @@ int main(int argc, char *argv[])
{
struct io_uring ring;
int i, ret, sp[2];
+ size_t len = 8096;
if (argc > 1)
return T_EXIT_SKIP;
+ tx_buffer = aligned_alloc(4096, len);
+ rx_buffer = aligned_alloc(4096, len);
+ if (!tx_buffer || !rx_buffer) {
+ fprintf(stderr, "can't allocate buffers\n");
+ return T_EXIT_FAIL;
+ }
+
+ buffers_iov[0].iov_base = tx_buffer;
+ buffers_iov[0].iov_len = len;
+ buffers_iov[1].iov_base = tx_buffer + BUFFER_OFFSET;
+ buffers_iov[1].iov_len = len - BUFFER_OFFSET - 13;
+
ret = io_uring_queue_init(32, &ring, 0);
if (ret) {
fprintf(stderr, "queue init failed: %d\n", ret);
@@ -824,8 +830,9 @@ int main(int argc, char *argv[])
}
srand((unsigned)time(NULL));
- for (i = 0; i < sizeof(tx_buffer); i++)
+ for (i = 0; i < len; i++)
tx_buffer[i] = i;
+ memset(rx_buffer, 0, len);
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sp) != 0) {
perror("Failed to create Unix-domain socket pair\n");
--
2.37.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH liburing 4/6] test/zc: handle short rx
2022-08-04 14:20 [PATCH liburing 0/6] improve zeoropy testing Pavel Begunkov
` (2 preceding siblings ...)
2022-08-04 14:20 ` [PATCH liburing 3/6] test/zc: allocate buffers dynamically Pavel Begunkov
@ 2022-08-04 14:20 ` Pavel Begunkov
2022-08-04 14:20 ` [PATCH liburing 5/6] test/zc: recv asynchronously Pavel Begunkov
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Pavel Begunkov @ 2022-08-04 14:20 UTC (permalink / raw)
To: io-uring; +Cc: Jens Axboe, asml.silence
After a send we receive and check buffers, make sure that we also handle
short receives.
Signed-off-by: Pavel Begunkov <[email protected]>
---
test/send-zerocopy.c | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/test/send-zerocopy.c b/test/send-zerocopy.c
index a572407..d0f5931 100644
--- a/test/send-zerocopy.c
+++ b/test/send-zerocopy.c
@@ -653,6 +653,7 @@ static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_se
size_t chunk_size = send_size / nr_reqs;
size_t chunk_size_last = send_size - chunk_size * (nr_reqs - 1);
char *buf = buffers_iov[buf_idx].iov_base;
+ size_t bytes_received = 0;
assert(send_size <= buffers_iov[buf_idx].iov_len);
memset(rx_buffer, 0, send_size);
@@ -699,6 +700,18 @@ static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_se
return 1;
}
+ while (bytes_received != send_size) {
+ ret = recv(sock_server,
+ rx_buffer + bytes_received,
+ send_size - bytes_received, 0);
+ if (ret <= 0) {
+ fprintf(stderr, "recv failed, got %i, errno %i\n",
+ ret, errno);
+ return 1;
+ }
+ bytes_received += ret;
+ }
+
for (i = 0; i < nr_reqs; i++) {
int expected = chunk_size;
@@ -721,13 +734,6 @@ static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_se
io_uring_cqe_seen(ring, cqe);
}
- ret = recv(sock_server, rx_buffer, send_size, 0);
- if (ret != send_size) {
- fprintf(stderr, "recv less than expected or recv failed, "
- "got %i, errno %i\n", ret, errno);
- return 1;
- }
-
for (i = 0; i < send_size; i++) {
if (buf[i] != rx_buffer[i]) {
fprintf(stderr, "botched data, first mismated byte %i, "
--
2.37.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH liburing 5/6] test/zc: recv asynchronously
2022-08-04 14:20 [PATCH liburing 0/6] improve zeoropy testing Pavel Begunkov
` (3 preceding siblings ...)
2022-08-04 14:20 ` [PATCH liburing 4/6] test/zc: handle short rx Pavel Begunkov
@ 2022-08-04 14:20 ` Pavel Begunkov
2022-08-04 14:20 ` [PATCH liburing 6/6] test/zc: test short zc send Pavel Begunkov
2022-08-04 22:22 ` [PATCH liburing 0/6] improve zeoropy testing Jens Axboe
6 siblings, 0 replies; 8+ messages in thread
From: Pavel Begunkov @ 2022-08-04 14:20 UTC (permalink / raw)
To: io-uring; +Cc: Jens Axboe, asml.silence
Receive in a separate task to avoid locking up in case of short sends.
Signed-off-by: Pavel Begunkov <[email protected]>
---
test/send-zerocopy.c | 56 ++++++++++++++++++++++++++++++++------------
1 file changed, 41 insertions(+), 15 deletions(-)
diff --git a/test/send-zerocopy.c b/test/send-zerocopy.c
index d0f5931..617e7a0 100644
--- a/test/send-zerocopy.c
+++ b/test/send-zerocopy.c
@@ -653,7 +653,8 @@ static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_se
size_t chunk_size = send_size / nr_reqs;
size_t chunk_size_last = send_size - chunk_size * (nr_reqs - 1);
char *buf = buffers_iov[buf_idx].iov_base;
- size_t bytes_received = 0;
+ pid_t p;
+ int wstatus;
assert(send_size <= buffers_iov[buf_idx].iov_len);
memset(rx_buffer, 0, send_size);
@@ -700,16 +701,35 @@ static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_se
return 1;
}
- while (bytes_received != send_size) {
- ret = recv(sock_server,
- rx_buffer + bytes_received,
- send_size - bytes_received, 0);
- if (ret <= 0) {
- fprintf(stderr, "recv failed, got %i, errno %i\n",
- ret, errno);
- return 1;
+ p = fork();
+ if (p == -1) {
+ fprintf(stderr, "fork() failed\n");
+ return 1;
+ }
+
+ if (p == 0) {
+ size_t bytes_received = 0;
+
+ while (bytes_received != send_size) {
+ ret = recv(sock_server,
+ rx_buffer + bytes_received,
+ send_size - bytes_received, 0);
+ if (ret <= 0) {
+ fprintf(stderr, "recv failed, got %i, errno %i\n",
+ ret, errno);
+ exit(1);
+ }
+ bytes_received += ret;
}
- bytes_received += ret;
+
+ for (i = 0; i < send_size; i++) {
+ if (buf[i] != rx_buffer[i]) {
+ fprintf(stderr, "botched data, first mismated byte %i, "
+ "%u vs %u\n", i, buf[i], rx_buffer[i]);
+ exit(1);
+ }
+ }
+ exit(0);
}
for (i = 0; i < nr_reqs; i++) {
@@ -734,11 +754,17 @@ static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_se
io_uring_cqe_seen(ring, cqe);
}
- for (i = 0; i < send_size; i++) {
- if (buf[i] != rx_buffer[i]) {
- fprintf(stderr, "botched data, first mismated byte %i, "
- "%u vs %u\n", i, buf[i], rx_buffer[i]);
- }
+ if (waitpid(p, &wstatus, 0) == (pid_t)-1) {
+ perror("waitpid()");
+ return 1;
+ }
+ if (!WIFEXITED(wstatus)) {
+ fprintf(stderr, "child failed %i\n", WEXITSTATUS(wstatus));
+ return 1;
+ }
+ if (WEXITSTATUS(wstatus)) {
+ fprintf(stderr, "child failed\n");
+ return 1;
}
return 0;
}
--
2.37.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH liburing 6/6] test/zc: test short zc send
2022-08-04 14:20 [PATCH liburing 0/6] improve zeoropy testing Pavel Begunkov
` (4 preceding siblings ...)
2022-08-04 14:20 ` [PATCH liburing 5/6] test/zc: recv asynchronously Pavel Begunkov
@ 2022-08-04 14:20 ` Pavel Begunkov
2022-08-04 22:22 ` [PATCH liburing 0/6] improve zeoropy testing Jens Axboe
6 siblings, 0 replies; 8+ messages in thread
From: Pavel Begunkov @ 2022-08-04 14:20 UTC (permalink / raw)
To: io-uring; +Cc: Jens Axboe, asml.silence
Zerocopy send should hide short writes for stream sockets, test it.
Signed-off-by: Pavel Begunkov <[email protected]>
---
test/send-zerocopy.c | 34 ++++++++++++++++++++++++++++------
1 file changed, 28 insertions(+), 6 deletions(-)
diff --git a/test/send-zerocopy.c b/test/send-zerocopy.c
index 617e7a0..307c114 100644
--- a/test/send-zerocopy.c
+++ b/test/send-zerocopy.c
@@ -54,7 +54,7 @@
static int seqs[NR_SLOTS];
static char *tx_buffer, *rx_buffer;
-static struct iovec buffers_iov[2];
+static struct iovec buffers_iov[3];
static inline bool tag_userdata(__u64 user_data)
{
@@ -662,7 +662,7 @@ static int do_test_inet_send(struct io_uring *ring, int sock_client, int sock_se
for (i = 0; i < nr_reqs; i++) {
bool cur_fixed_buf = fixed_buf;
size_t cur_size = chunk_size;
- int msg_flags = 0;
+ int msg_flags = MSG_WAITALL;
if (mix_register)
cur_fixed_buf = rand() & 1;
@@ -791,15 +791,26 @@ static int test_inet_send(struct io_uring *ring)
return 1;
}
- for (i = 0; i < 64; i++) {
+ for (i = 0; i < 128; i++) {
bool fixed_buf = i & 1;
struct sockaddr_storage *addr_arg = (i & 2) ? &addr : NULL;
size_t size = (i & 4) ? 137 : 4096;
bool cork = i & 8;
bool mix_register = i & 16;
bool aligned = i & 32;
+ bool large_buf = i & 64;
int buf_idx = aligned ? 0 : 1;
+ if (!tcp || !large_buf)
+ continue;
+ if (large_buf) {
+ buf_idx = 2;
+ size = buffers_iov[buf_idx].iov_len;
+ if (!aligned || !tcp)
+ continue;
+ }
+ if (!buffers_iov[buf_idx].iov_base)
+ continue;
if (tcp && cork)
continue;
if (mix_register && (!cork || fixed_buf))
@@ -829,22 +840,33 @@ int main(int argc, char *argv[])
{
struct io_uring ring;
int i, ret, sp[2];
- size_t len = 8096;
+ size_t len;
if (argc > 1)
return T_EXIT_SKIP;
+ len = 1U << 25; /* 32MB, should be enough to trigger a short send */
tx_buffer = aligned_alloc(4096, len);
rx_buffer = aligned_alloc(4096, len);
+ if (tx_buffer && rx_buffer) {
+ buffers_iov[2].iov_base = tx_buffer;
+ buffers_iov[2].iov_len = len;
+ } else {
+ printf("skip large buffer tests, can't alloc\n");
+
+ len = 8192;
+ tx_buffer = aligned_alloc(4096, len);
+ rx_buffer = aligned_alloc(4096, len);
+ }
if (!tx_buffer || !rx_buffer) {
fprintf(stderr, "can't allocate buffers\n");
return T_EXIT_FAIL;
}
buffers_iov[0].iov_base = tx_buffer;
- buffers_iov[0].iov_len = len;
+ buffers_iov[0].iov_len = 8192;
buffers_iov[1].iov_base = tx_buffer + BUFFER_OFFSET;
- buffers_iov[1].iov_len = len - BUFFER_OFFSET - 13;
+ buffers_iov[1].iov_len = 8192 - BUFFER_OFFSET - 13;
ret = io_uring_queue_init(32, &ring, 0);
if (ret) {
--
2.37.0
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH liburing 0/6] improve zeoropy testing
2022-08-04 14:20 [PATCH liburing 0/6] improve zeoropy testing Pavel Begunkov
` (5 preceding siblings ...)
2022-08-04 14:20 ` [PATCH liburing 6/6] test/zc: test short zc send Pavel Begunkov
@ 2022-08-04 22:22 ` Jens Axboe
6 siblings, 0 replies; 8+ messages in thread
From: Jens Axboe @ 2022-08-04 22:22 UTC (permalink / raw)
To: io-uring, asml.silence
On Thu, 4 Aug 2022 15:20:19 +0100, Pavel Begunkov wrote:
> Add test cases for TCP and for short sends.
>
> Pavel Begunkov (6):
> test/zc: improve error messages
> tests/zc: test tcp
> test/zc: allocate buffers dynamically
> test/zc: handle short rx
> test/zc: recv asynchronously
> test/zc: test short zc send
>
> [...]
Applied, thanks!
[1/6] test/zc: improve error messages
(no commit info)
[2/6] tests/zc: test tcp
(no commit info)
[3/6] test/zc: allocate buffers dynamically
(no commit info)
[4/6] test/zc: handle short rx
(no commit info)
[5/6] test/zc: recv asynchronously
(no commit info)
[6/6] test/zc: test short zc send
(no commit info)
Best regards,
--
Jens Axboe
^ permalink raw reply [flat|nested] 8+ messages in thread