From: Dong Chenchen <dongchenchen2@huawei.com>
To: <daniel@iogearbox.net>, <edumazet@google.com>,
<ncardwell@google.com>, <kuniyu@google.com>,
<john.fastabend@gmail.com>, <jakub@cloudflare.com>,
<jiayuan.chen@linux.dev>
Cc: <davem@davemloft.net>, <kuba@kernel.org>, <pabeni@redhat.com>,
<horms@kernel.org>, <zhangchangzhong@huawei.com>,
<netdev@vger.kernel.org>, <bpf@vger.kernel.org>,
Dong Chenchen <dongchenchen2@huawei.com>
Subject: [PATCH net 2/2] selftests/bpf: cover sockmap drop after partial TCP read
Date: Thu, 2 Jul 2026 22:09:59 +0800 [thread overview]
Message-ID: <20260702140959.1806754-3-dongchenchen2@huawei.com> (raw)
In-Reply-To: <20260702140959.1806754-1-dongchenchen2@huawei.com>
Add a regression test for a TCP socket that is partially read before it
is inserted into a sockmap with an SK_DROP verdict.
The test leaves part of the original skb on the receive queue, adds the
socket to the map, and sends another byte to drive the verdict path.
After removing the socket from the map, it invokes TCP_ZEROCOPY_RECEIVE
on newly arrived native data.
Without the tcp_eat_skb() fix, copied_seq includes the already consumed
prefix, TCP_ZEROCOPY_RECEIVE triggers the sequence warning, and no data
is copied. With the fix, the new byte is copied without a warning.
Signed-off-by: Dong Chenchen <dongchenchen2@huawei.com>
---
.../selftests/bpf/prog_tests/sockmap_basic.c | 73 +++++++++++++++++++
1 file changed, 73 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c b/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
index cb3229711f93..106dd03cde84 100644
--- a/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
+++ b/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
@@ -1275,6 +1275,77 @@ static void test_sockmap_copied_seq(bool strp)
test_sockmap_pass_prog__destroy(skel);
}
+static void test_sockmap_drop_after_partial_read(void)
+{
+ int map, err, sent, recvd, zero = 0, on = 1;
+ struct test_sockmap_drop_prog *skel;
+ int c0 = -1, p0 = -1, c1 = -1, p1 = -1;
+ struct tcp_zerocopy_receive zc = {};
+ socklen_t zc_len = sizeof(zc);
+ char buf[200] = {}, rcv[50], addr[100];
+ struct bpf_program *prog;
+
+ skel = test_sockmap_drop_prog__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "open_and_load"))
+ return;
+
+ if (create_socket_pairs(AF_INET, SOCK_STREAM, &c0, &c1, &p0, &p1))
+ goto end;
+
+ sent = xsend(c0, buf, sizeof(buf), 0);
+ if (!ASSERT_EQ(sent, sizeof(buf), "xsend(native)"))
+ goto end;
+
+ recvd = recv_timeout(p0, rcv, sizeof(rcv), MSG_DONTWAIT, 1);
+ if (!ASSERT_EQ(recvd, sizeof(rcv), "recv_timeout(partial)"))
+ goto end;
+
+ prog = skel->progs.prog_skb_verdict;
+ map = bpf_map__fd(skel->maps.sock_map_rx);
+ err = bpf_prog_attach(bpf_program__fd(prog), map,
+ BPF_SK_SKB_STREAM_VERDICT, 0);
+ if (!ASSERT_OK(err, "bpf_prog_attach"))
+ goto end;
+
+ err = bpf_map_update_elem(map, &zero, &p0, BPF_NOEXIST);
+ if (!ASSERT_OK(err, "bpf_map_update_elem"))
+ goto end;
+
+ sent = xsend(c0, buf, 1, 0);
+ if (!ASSERT_EQ(sent, 1, "xsend(drop)"))
+ goto end;
+
+ err = bpf_map_delete_elem(map, &zero);
+ if (!ASSERT_OK(err, "bpf_map_delete_elem"))
+ goto end;
+
+ sent = xsend(c0, buf, 1, 0);
+ if (!ASSERT_EQ(sent, 1, "xsend(native again)"))
+ goto end;
+
+ err = setsockopt(p0, SOL_SOCKET, SO_ZEROCOPY, &on, sizeof(on));
+ if (!ASSERT_OK(err, "setsockopt(SO_ZEROCOPY)"))
+ goto end;
+
+ zc.copybuf_address = (__u64)(unsigned long)addr;
+ zc.copybuf_len = sizeof(addr);
+ err = getsockopt(p0, IPPROTO_TCP, TCP_ZEROCOPY_RECEIVE, &zc, &zc_len);
+ if (!ASSERT_OK(err, "getsockopt(TCP_ZEROCOPY_RECEIVE)"))
+ goto end;
+
+ ASSERT_EQ(zc.copybuf_len, 1, "TCP_ZEROCOPY_RECEIVE copied");
+end:
+ if (c0 >= 0)
+ close(c0);
+ if (p0 >= 0)
+ close(p0);
+ if (c1 >= 0)
+ close(c1);
+ if (p1 >= 0)
+ close(p1);
+ test_sockmap_drop_prog__destroy(skel);
+}
+
/* Wait until FIONREAD returns the expected value or timeout */
static int wait_for_fionread(int fd, int expected, unsigned int timeout_ms)
{
@@ -1447,6 +1518,8 @@ void test_sockmap_basic(void)
test_sockmap_copied_seq(false);
if (test__start_subtest("sockmap recover with strp"))
test_sockmap_copied_seq(true);
+ if (test__start_subtest("sockmap drop after partial read"))
+ test_sockmap_drop_after_partial_read();
if (test__start_subtest("sockmap tcp multi channels"))
test_sockmap_multi_channels(SOCK_STREAM);
if (test__start_subtest("sockmap udp multi channels"))
--
2.43.0
prev parent reply other threads:[~2026-07-02 14:01 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-02 14:09 [PATCH net 0/2] bpf, sockmap: fix copied_seq after partial TCP read Dong Chenchen
2026-07-02 14:09 ` [PATCH net 1/2] bpf, sockmap: account only unread data in tcp_eat_skb Dong Chenchen
2026-07-02 14:09 ` Dong Chenchen [this message]
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=20260702140959.1806754-3-dongchenchen2@huawei.com \
--to=dongchenchen2@huawei.com \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=jakub@cloudflare.com \
--cc=jiayuan.chen@linux.dev \
--cc=john.fastabend@gmail.com \
--cc=kuba@kernel.org \
--cc=kuniyu@google.com \
--cc=ncardwell@google.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=zhangchangzhong@huawei.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox