* [PATCH mptcp-net] selftests: mptcp: sockopt: echo until EOF on partial reads
@ 2026-10-17 11:22 ` Quanye Yang
0 siblings, 0 replies; 3+ messages in thread
From: Quanye Yang via B4 Relay @ 2026-10-17 11:22 UTC (permalink / raw)
To: MPTCP Linux
From: Quanye Yang <quanyeyang@proton.me>
process_one_client() used a single read() and write() before waiting
for hangup. A SOCK_STREAM read() can return a short count when the
payload is segmented, so the server echoed only part of the data and
then blocked on FIN.
The client keeps reading until it has the full length and only then
closes the socket. The two sides wait on each other and the test
hangs until SIGALRM.
Loop the server read/write until read() returns 0, and accumulate the
copied byte counts for the existing sockopt checks.
Fixes: ce9979129a0b ("selftests: mptcp: add mptcp getsockopt test cases")
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/639
Signed-off-by: Quanye Yang <quanyeyang@proton.me>
---
tools/testing/selftests/net/mptcp/mptcp_sockopt.c | 34 +++++++++++++----------
1 file changed, 19 insertions(+), 15 deletions(-)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index b6e58d936ebe..5e1ec3336859 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -638,7 +638,7 @@ static void connect_one_server(int fd, int pipefd)
static void process_one_client(int fd, int pipefd)
{
- ssize_t ret, ret2, ret3;
+ ssize_t ret, ret2, n, w;
struct so_state s;
char buf[4096];
@@ -648,23 +648,27 @@ static void process_one_client(int fd, int pipefd)
ret = write(pipefd, "xmit", 4);
assert(ret == 4);
- ret = read(fd, buf, sizeof(buf));
- if (ret < 0)
- die_perror("read");
+ ret = 0;
+ ret2 = 0;
+ while ((n = read(fd, buf, sizeof(buf))) > 0) {
+ if (!ret) {
+ assert(s.mptcpi_rcv_delta <= (uint64_t)n);
- assert(s.mptcpi_rcv_delta <= (uint64_t)ret);
-
- if (s.tcpi_rcv_delta)
- assert(s.tcpi_rcv_delta == (uint64_t)ret);
+ if (s.tcpi_rcv_delta)
+ assert(s.tcpi_rcv_delta <= (uint64_t)n);
+ }
- ret2 = write(fd, buf, ret);
- if (ret2 < 0)
- die_perror("write");
+ w = write(fd, buf, n);
+ if (w < 0)
+ die_perror("write");
+ if (w != n)
+ xerror("short write");
- /* wait for hangup */
- ret3 = read(fd, buf, 1);
- if (ret3 != 0)
- xerror("expected EOF, got %lu", ret3);
+ ret += n;
+ ret2 += w;
+ }
+ if (n < 0)
+ die_perror("read");
do_getsockopts(&s, fd, ret, ret2);
if (s.mptcpi_rcv_delta != (uint64_t)ret + 1)
---
base-commit: a22035be824449c4921ec406f6383089016a628c
change-id: 20261017-fix-mptcp-issue-639-96339a3d921a
Best regards,
--
Quanye Yang <quanyeyang@proton.me>
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH mptcp-net] selftests: mptcp: sockopt: echo until EOF on partial reads
@ 2026-10-17 11:22 ` Quanye Yang
0 siblings, 0 replies; 3+ messages in thread
From: Quanye Yang @ 2026-10-17 11:22 UTC (permalink / raw)
To: MPTCP Linux
process_one_client() used a single read() and write() before waiting
for hangup. A SOCK_STREAM read() can return a short count when the
payload is segmented, so the server echoed only part of the data and
then blocked on FIN.
The client keeps reading until it has the full length and only then
closes the socket. The two sides wait on each other and the test
hangs until SIGALRM.
Loop the server read/write until read() returns 0, and accumulate the
copied byte counts for the existing sockopt checks.
Fixes: ce9979129a0b ("selftests: mptcp: add mptcp getsockopt test cases")
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/639
Signed-off-by: Quanye Yang <quanyeyang@proton.me>
---
tools/testing/selftests/net/mptcp/mptcp_sockopt.c | 34 +++++++++++++----------
1 file changed, 19 insertions(+), 15 deletions(-)
diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
index b6e58d936ebe..5e1ec3336859 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
@@ -638,7 +638,7 @@ static void connect_one_server(int fd, int pipefd)
static void process_one_client(int fd, int pipefd)
{
- ssize_t ret, ret2, ret3;
+ ssize_t ret, ret2, n, w;
struct so_state s;
char buf[4096];
@@ -648,23 +648,27 @@ static void process_one_client(int fd, int pipefd)
ret = write(pipefd, "xmit", 4);
assert(ret == 4);
- ret = read(fd, buf, sizeof(buf));
- if (ret < 0)
- die_perror("read");
+ ret = 0;
+ ret2 = 0;
+ while ((n = read(fd, buf, sizeof(buf))) > 0) {
+ if (!ret) {
+ assert(s.mptcpi_rcv_delta <= (uint64_t)n);
- assert(s.mptcpi_rcv_delta <= (uint64_t)ret);
-
- if (s.tcpi_rcv_delta)
- assert(s.tcpi_rcv_delta == (uint64_t)ret);
+ if (s.tcpi_rcv_delta)
+ assert(s.tcpi_rcv_delta <= (uint64_t)n);
+ }
- ret2 = write(fd, buf, ret);
- if (ret2 < 0)
- die_perror("write");
+ w = write(fd, buf, n);
+ if (w < 0)
+ die_perror("write");
+ if (w != n)
+ xerror("short write");
- /* wait for hangup */
- ret3 = read(fd, buf, 1);
- if (ret3 != 0)
- xerror("expected EOF, got %lu", ret3);
+ ret += n;
+ ret2 += w;
+ }
+ if (n < 0)
+ die_perror("read");
do_getsockopts(&s, fd, ret, ret2);
if (s.mptcpi_rcv_delta != (uint64_t)ret + 1)
---
base-commit: a22035be824449c4921ec406f6383089016a628c
change-id: 20261017-fix-mptcp-issue-639-96339a3d921a
Best regards,
--
Quanye Yang <quanyeyang@proton.me>
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH mptcp-net] selftests: mptcp: sockopt: echo until EOF on partial reads
2026-10-17 11:22 ` Quanye Yang
(?)
@ 2026-10-17 11:29 ` sashiko-bot
-1 siblings, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-10-17 11:29 UTC (permalink / raw)
To: Quanye Yang, MPTCP Linux
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] selftests: mptcp: connect_one_server() passes partial ret to do_getsockopts()
--
commit 522b0ff16267ee948ab4943b8089644ce3f33c32
Author: Quanye Yang <quanyeyang@proton.me>
selftests: mptcp: sockopt: echo until EOF on partial reads
This commit updates process_one_client() in mptcp_sockopt.c to loop over
read() and write() until EOF, preventing a hang when payload segmentation
causes a short read on the server.
> diff --git a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
> index b6e58d936ebe5..5e1ec33368590 100644
> --- a/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
> +++ b/tools/testing/selftests/net/mptcp/mptcp_sockopt.c
> @@ -638,7 +638,7 @@ static void connect_one_server(int fd, int pipefd)
>
> static void process_one_client(int fd, int pipefd)
> {
> - ssize_t ret, ret2, ret3;
> + ssize_t ret, ret2, n, w;
> struct so_state s;
> char buf[4096];
>
> @@ -648,23 +648,27 @@ static void process_one_client(int fd, int pipefd)
> ret = write(pipefd, "xmit", 4);
> assert(ret == 4);
>
> - ret = read(fd, buf, sizeof(buf));
> - if (ret < 0)
> - die_perror("read");
> + ret = 0;
> + ret2 = 0;
> + while ((n = read(fd, buf, sizeof(buf))) > 0) {
> + if (!ret) {
> + assert(s.mptcpi_rcv_delta <= (uint64_t)n);
>
> - assert(s.mptcpi_rcv_delta <= (uint64_t)ret);
> -
> - if (s.tcpi_rcv_delta)
> - assert(s.tcpi_rcv_delta == (uint64_t)ret);
> + if (s.tcpi_rcv_delta)
> + assert(s.tcpi_rcv_delta <= (uint64_t)n);
> + }
>
> - ret2 = write(fd, buf, ret);
> - if (ret2 < 0)
> - die_perror("write");
> + w = write(fd, buf, n);
> + if (w < 0)
> + die_perror("write");
> + if (w != n)
> + xerror("short write");
>
> - /* wait for hangup */
> - ret3 = read(fd, buf, 1);
> - if (ret3 != 0)
> - xerror("expected EOF, got %lu", ret3);
> + ret += n;
> + ret2 += w;
> + }
[Severity: Medium]
When a partial read occurs in process_one_client(), it immediately echoes
the partial chunk n back to the client before reading and echoing the rest
of the payload in subsequent loop iterations.
If the client in connect_one_server() reads the echoed data across more
than one read() call, ret only holds the byte count of the final chunk
while total accumulates the full length:
tools/testing/selftests/net/mptcp/mptcp_sockopt.c:connect_one_server() {
...
total = 0;
do {
ret = read(fd, buf2 + total, sizeof(buf2) - total);
if (ret < 0)
die_perror("read");
if (ret == 0) {
eof = true;
break;
}
total += ret;
} while (total < len);
...
do_getsockopts(&s, fd, ret, ret);
}
Because connect_one_server() passes ret instead of total to
do_getsockopts(), won't connect_one_server() -> do_getsockopts() ->
do_getsockopt_mptcp_info() fail on:
assert(s->mi.mptcpi_write_seq + w == i.mptcpi_write_seq);
and do_getsockopt_tcp_info() fail when checking tcpi_bytes_sent and
tcpi_bytes_received against r and w whenever the echoed response is read in
multiple chunks? Should connect_one_server() pass total to do_getsockopts()
as well?
> + if (n < 0)
> + die_perror("read");
>
> do_getsockopts(&s, fd, ret, ret2);
> if (s.mptcpi_rcv_delta != (uint64_t)ret + 1)
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261017-fix-mptcp-issue-639-v1-1-0554d07ab8f8@proton.me?part=1
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-17 11:29 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-17 11:22 [PATCH mptcp-net] selftests: mptcp: sockopt: echo until EOF on partial reads Quanye Yang via B4 Relay
2026-10-17 11:22 ` Quanye Yang
2026-10-17 11:29 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.