From: gang.yan@linux.dev
To: "Paolo Abeni" <pabeni@redhat.com>, mptcp@lists.linux.dev
Subject: Re: [Patch mptcp-net 1/3] mptcp: add backlog_list bug reproducer test
Date: Thu, 05 Feb 2026 13:05:04 +0000 [thread overview]
Message-ID: <8e2151925594cdb075fa75486645e2e2c07415d4@linux.dev> (raw)
In-Reply-To: <aa6f6618-d89c-4804-95ef-745b449a71d8@redhat.com>
>February 5, 2026 at 5:20 PM, "Paolo Abeni" <pabeni@redhat.com mailto:pabeni@redhat.com?to=%22Paolo%20Abeni%22%20%3Cpabeni%40redhat.com%3E > wrote:
Hi, Paolo:
Thanks for your detailed review comments.
This patch is for temporary testing purposes only to reproduce the
backlog_list-related issues, and it's not meant for merging. In the upcoming
v2 version, I'll incorporate all your suggestions and add the appropriate
"do-not-merge" tag.
Best regards,
Gang
>
> On 2/5/26 7:41 AM, Gang Yan wrote:
>
> >
> > From: Gang Yan <yangang@kylinos.cn>
> >
> > This patch introduces a test program to reproduce bugs related to the
> > backlog_list in MPTCP. The test is derived from tls.c in the selftests
> > suite, but adapted to work without TLS configuration specifically for
> > MPTCP testing.
> >
> > The program performs chunked sendfile operations with various payload
> > sizes to exercise different code paths and trigger backlog_list-related
> > issues.
> >
> > It can be run in .virtme-exec-run:
> > run_loop run_selftest_one ./multi_chunk.sh
> >
> > '''
> > selftest Test: ./multi_chunk.sh
> > TAP version 13
> > 1..1
> > [stalls for a while]
> > ^C
> >
> > '''
> >
> > Co-developed-by: Geliang Tang <tanggeliang@kylinos.cn>
> > Signed-off-by: Geliang Tang <tanggeliang@kylinos.cn>
> > Signed-off-by: Gang Yan <yangang@kylinos.cn>
> > ---
> > tools/testing/selftests/net/mptcp/Makefile | 1 +
> > .../testing/selftests/net/mptcp/multi_chunk.c | 148 ++++++++++++++++++
> > .../selftests/net/mptcp/multi_chunk.sh | 37 +++++
> > 3 files changed, 186 insertions(+)
> > create mode 100644 tools/testing/selftests/net/mptcp/multi_chunk.c
> > create mode 100755 tools/testing/selftests/net/mptcp/multi_chunk.sh
> >
> > diff --git a/tools/testing/selftests/net/mptcp/Makefile b/tools/testing/selftests/net/mptcp/Makefile
> > index 22ba0da2adb8..087e6ae6f0b8 100644
> > --- a/tools/testing/selftests/net/mptcp/Makefile
> > +++ b/tools/testing/selftests/net/mptcp/Makefile
> > @@ -24,6 +24,7 @@ TEST_GEN_FILES := \
> > mptcp_diag \
> > mptcp_inq \
> > mptcp_sockopt \
> > + multi_chunk \
> > pm_nl_ctl \
> > # end of TEST_GEN_FILES
> >
> > diff --git a/tools/testing/selftests/net/mptcp/multi_chunk.c b/tools/testing/selftests/net/mptcp/multi_chunk.c
> > new file mode 100644
> > index 000000000000..8c97db58a6db
> > --- /dev/null
> > +++ b/tools/testing/selftests/net/mptcp/multi_chunk.c
> > @@ -0,0 +1,148 @@
> > +#define _GNU_SOURCE
> > +#include <stdio.h>
> > +#include <stdlib.h>
> > +#include <string.h>
> > +#include <unistd.h>
> > +#include <fcntl.h>
> > +#include <sys/socket.h>
> > +#include <netinet/in.h>
> > +#include <sys/sendfile.h>
> > +#include <sys/types.h>
> > +#include <sys/stat.h>
> > +#include <errno.h>
> > +#include <arpa/inet.h>
> > +#include <sys/wait.h>
> > +
> > +#ifndef IPPROTO_MPTCP
> > +#define IPPROTO_MPTCP 262
> > +#endif
> >
> Minor nit: I think we can avoid the compiler guards here; older test
> program have them for historical reasons.
>
> >
> > +
> > +#define TLS_PAYLOAD_MAX_LEN 16384
> >
> Possibly this macro should be renamed, i.e. to PAYLOAD_MAX_LEN and
> likely the value increased to 64K
>
> >
> > +#define TEST_PORT 12345
> > +
> > +static void chunked_sendfile(int cfd, int sfd,
> > + size_t chunk_size,
> > + size_t extra_payload_size)
> > +{
> > + char buf[TLS_PAYLOAD_MAX_LEN];
> > + uint16_t test_payload_size;
> > + size_t recved = 0;
> > + size_t sent = 0;
> > + int size = 0;
> > + int ret;
> > + char filename[] = "/tmp/mytemp.XXXXXX";
> > + int fd = mkstemp(filename);
> > + off_t offset = 0;
> > +
> > + unlink(filename);
> > + if (fd <= 0) {
> > + perror("tempfile");
> > + exit(1);
> >
> Here and below you could use the error() libcall instead of the
> perror/exit combo.
>
> >
> > + }
> > + if (chunk_size < 1) {
> > + perror("chunksize");
> > + exit(1);
> > + }
> > +
> > + test_payload_size = chunk_size + extra_payload_size;
> > + if (test_payload_size > TLS_PAYLOAD_MAX_LEN) {
> > + perror("payload_size");
> > + exit(1);
> > + }
> > + memset(buf, 1, test_payload_size);
> > + size = write(fd, buf, test_payload_size);
> > + if (size != test_payload_size) {
> > + perror("file write");
> > + exit(1);
> > + }
> > + fsync(fd);
> > +
> > + while (size > 0) {
> > + ret = sendfile(sfd, fd, &offset, chunk_size);
> > + if (ret <= 0)
> > + exit(1);
> > + size -= ret;
> > + sent += ret;
> > + }
> > + printf("[client] sent %zu bytes\n", sent);
> > +
> > + recved = recv(cfd, buf, test_payload_size, MSG_WAITALL);
> > + printf("[server] receieved %zu bytes\n", recved);
> >
> Possibly the above 2 print should be off by default and enabled via
> command line switch.
>
> >
> > +
> > + if (recved != test_payload_size)
> > + exit(1);
> > +
> > + close(fd);
> > +}
> > +
> > +int main()
> > +{
> > + int sfd = socket(AF_INET, SOCK_STREAM, IPPROTO_MPTCP);
> > + int cfd = socket(AF_INET, SOCK_STREAM, IPPROTO_MPTCP);
> > + struct sockaddr_in addr = {0};
> > + socklen_t addrlen = sizeof(addr);
> > +
> > + printf("==== multi_chunk_sendfile MPTCP test ====\n");
> > +
> > + if (sfd < 0 || cfd < 0) {
> > + perror("socket");
> > + exit(1);
> > + }
> > +
> > + addr.sin_family = AF_INET;
> > + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
> > + addr.sin_port = htons(TEST_PORT);
> > +
> > + if (bind(sfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
> > + perror("bind");
> > + exit(1);
> > + }
> > +
> > + if (listen(sfd, 1) < 0) {
> > + perror("listen");
> > + exit(1);
> > + }
> > +
> > + if (getsockname(sfd, (struct sockaddr *)&addr, &addrlen) < 0) {
> > + perror("getsockname");
> > + exit(1);
> > + }
> > +
> > + if (connect(cfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
> > + perror("connect");
> > + exit(1);
> > + }
> > +
> > + int nfd = accept(sfd, NULL, NULL);
> > + if (nfd < 0) {
> > + perror("accept");
> > + exit(1);
> > + }
> > +
> > + chunked_sendfile(cfd, nfd, 4096, 4096);
> > + chunked_sendfile(cfd, nfd, 4096, 0);
> > + chunked_sendfile(cfd, nfd, 4096, 1);
> > + chunked_sendfile(cfd, nfd, 4096, 2048);
> > + chunked_sendfile(cfd, nfd, 8192, 2048);
> > + chunked_sendfile(cfd, nfd, 4096, 8192);
> > + chunked_sendfile(cfd, nfd, 8192, 4096);
> > + chunked_sendfile(cfd, nfd, 12288, 1024);
> > + chunked_sendfile(cfd, nfd, 12288, 2000);
> > + chunked_sendfile(cfd, nfd, 15360, 100);
> > + chunked_sendfile(cfd, nfd, 15360, 300);
> > + chunked_sendfile(cfd, nfd, 1, 4096);
> > + chunked_sendfile(cfd, nfd, 2048, 4096);
> > + chunked_sendfile(cfd, nfd, 2048, 8192);
> > + chunked_sendfile(cfd, nfd, 4096, 8192);
> > + chunked_sendfile(cfd, nfd, 1024, 12288);
> > + chunked_sendfile(cfd, nfd, 2000, 12288);
> > + chunked_sendfile(cfd, nfd, 100, 15360);
> > + chunked_sendfile(cfd, nfd, 300, 15360);
> > +
> > + close(cfd);
> > + close(nfd);
> > + close(sfd);
> > +
> > + printf("==== test ends ====\n");
> > + return 0;
> > +}
> > diff --git a/tools/testing/selftests/net/mptcp/multi_chunk.sh b/tools/testing/selftests/net/mptcp/multi_chunk.sh
> > new file mode 100755
> > index 000000000000..c0352c89087f
> > --- /dev/null
> > +++ b/tools/testing/selftests/net/mptcp/multi_chunk.sh
> > @@ -0,0 +1,37 @@
> > +#!/bin/bash
> > +# SPDX-License-Identifier: GPL-2.0
> > +
> > +. "$(dirname "${0}")/mptcp_lib.sh"
> > +
> > +cleanup()
> > +{
> > + if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
> > + kill "$pid" 2>/dev/null
> > + wait "$pid" 2>/dev/null
> > + fi
> > +
> > + mptcp_lib_ns_exit "${ns1}"
> > +}
> > +
> > +init()
> > +{
> > + mptcp_lib_ns_init ns1
> > +
> > + local i
> > + for i in $(seq 1 4); do
> > + mptcp_lib_pm_nl_add_endpoint "${ns1}" "127.0.0.1" flags signal port 1000$i
> > + done
> > +
> > + mptcp_lib_pm_nl_set_limits "${ns1}" 8 8
> > +
> > + ip netns exec ${ns1} ip mptcp endpoint show
> > + ip netns exec ${ns1} ip mptcp limits
> > +}
> > +
> > +init
> > +trap cleanup EXIT
> > +
> > +ip netns exec $ns1 ./multi_chunk &
> > +
> > +pid=$!
> > +wait $pid
> >
> I think it would be nice to emit an ok/fail message as other tests
>
> /P
>
next prev parent reply other threads:[~2026-02-05 13:05 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-05 6:41 [Patch mptcp-net 0/3] Fix the transmission stall due to backlog Gang Yan
2026-02-05 6:41 ` [Patch mptcp-net 1/3] mptcp: add backlog_list bug reproducer test Gang Yan
2026-02-05 9:20 ` Paolo Abeni
2026-02-05 13:05 ` gang.yan [this message]
2026-02-05 18:01 ` Matthieu Baerts
2026-02-05 6:41 ` [Patch mptcp-net 2/3] mptcp: fix receive stalls when 'ack_seq' in backlog_list Gang Yan
2026-02-05 9:36 ` Paolo Abeni
[not found] ` <f9a2229cd1d69731db91a003ac1018f446be9572@linux.dev>
2026-02-09 9:02 ` gang.yan
2026-02-05 6:41 ` [Patch mptcp-net 3/3] mptcp: fix stall because of data_ready Gang Yan
2026-02-05 10:07 ` Paolo Abeni
2026-02-05 13:27 ` gang.yan
2026-02-09 8:56 ` gang.yan
2026-02-05 7:58 ` [Patch mptcp-net 0/3] Fix the transmission stall due to backlog MPTCP CI
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=8e2151925594cdb075fa75486645e2e2c07415d4@linux.dev \
--to=gang.yan@linux.dev \
--cc=mptcp@lists.linux.dev \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.