From: Junseo Lim <zirajs7@gmail.com>
To: John Fastabend <john.fastabend@gmail.com>,
Jakub Sitnicki <jakub@cloudflare.com>,
Jiayuan Chen <jiayuan.chen@linux.dev>
Cc: "David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Simon Horman <horms@kernel.org>,
Andrii Nakryiko <andrii@kernel.org>,
Eduard Zingerman <eddyz87@gmail.com>,
linux-kernel@vger.kernel.org, bpf@vger.kernel.org,
netdev@vger.kernel.org, Sechang Lim <rhkrqnwk98@gmail.com>,
Daniel Borkmann <daniel@iogearbox.net>,
Emil Tsalapatis <emil@etsalapatis.com>
Subject: [PATCH bpf v3 2/2] selftests/bpf: Cover strparser self-pass forward allocation
Date: Tue, 18 Aug 2026 00:50:09 +0900 [thread overview]
Message-ID: <20260817155009.232670-3-zirajs7@gmail.com> (raw)
In-Reply-To: <20260817155009.232670-1-zirajs7@gmail.com>
Add a sockmap_strp regression test for strparser SK_PASS delivery to the
same socket. A one-byte stream parser splits a single write into many
messages, repeatedly exercising receive ownership transitions while the
skbs remain queued.
Verify through INET_DIAG_MEMINFO that sk_forward_alloc does not become
negative after the self-pass path is exercised.
Signed-off-by: Junseo Lim <zirajs7@gmail.com>
---
.../selftests/bpf/prog_tests/sockmap_strp.c | 171 ++++++++++++++++++
.../selftests/bpf/progs/test_sockmap_strp.c | 6 +
2 files changed, 177 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_strp.c b/tools/testing/selftests/bpf/prog_tests/sockmap_strp.c
index 1d7231728eaf..c7ad21d0bbf4 100644
--- a/tools/testing/selftests/bpf/prog_tests/sockmap_strp.c
+++ b/tools/testing/selftests/bpf/prog_tests/sockmap_strp.c
@@ -1,5 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
#include <error.h>
+#include <linux/inet_diag.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/sock_diag.h>
#include <netinet/tcp.h>
#include <test_progs.h>
#include "sockmap_helpers.h"
@@ -460,6 +464,171 @@ static void test_sockmap_strp_parser_reject(void)
test_sockmap_strp__destroy(strp);
}
+/* Read sk_forward_alloc through inet_diag meminfo. */
+static int sockmap_strp_get_fwd_alloc(int sock, int *fwd_alloc)
+{
+ struct sockaddr_storage local = {}, peer = {};
+ struct sockaddr_in *local_in, *peer_in;
+ socklen_t addr_len = sizeof(local);
+ char buf[1024];
+ struct {
+ struct nlmsghdr nlh;
+ struct inet_diag_req_v2 req;
+ } req = {
+ .nlh = {
+ .nlmsg_len = sizeof(req),
+ .nlmsg_type = SOCK_DIAG_BY_FAMILY,
+ .nlmsg_flags = NLM_F_REQUEST,
+ .nlmsg_seq = 1,
+ },
+ .req = {
+ .sdiag_family = AF_INET,
+ .sdiag_protocol = IPPROTO_TCP,
+ .idiag_ext = 1 << (INET_DIAG_MEMINFO - 1),
+ .idiag_states = ~0U,
+ .id.idiag_cookie = {
+ INET_DIAG_NOCOOKIE,
+ INET_DIAG_NOCOOKIE,
+ },
+ },
+ };
+ int diag_fd, ret, err = -ENOENT;
+
+ if (getsockname(sock, (struct sockaddr *)&local, &addr_len))
+ return -errno;
+ addr_len = sizeof(peer);
+ if (getpeername(sock, (struct sockaddr *)&peer, &addr_len))
+ return -errno;
+
+ local_in = (struct sockaddr_in *)&local;
+ peer_in = (struct sockaddr_in *)&peer;
+ req.req.id.idiag_sport = local_in->sin_port;
+ req.req.id.idiag_dport = peer_in->sin_port;
+ req.req.id.idiag_src[0] = local_in->sin_addr.s_addr;
+ req.req.id.idiag_dst[0] = peer_in->sin_addr.s_addr;
+
+ diag_fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC,
+ NETLINK_SOCK_DIAG);
+ if (diag_fd < 0)
+ return -errno;
+
+ ret = send(diag_fd, &req, sizeof(req), 0);
+ if (ret < 0) {
+ err = -errno;
+ goto out;
+ }
+ if (ret != sizeof(req)) {
+ err = -EIO;
+ goto out;
+ }
+
+ ret = recv(diag_fd, buf, sizeof(buf), 0);
+ if (ret < 0) {
+ err = -errno;
+ goto out;
+ }
+
+ for (struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
+ NLMSG_OK(nlh, ret); nlh = NLMSG_NEXT(nlh, ret)) {
+ struct inet_diag_msg *msg = NLMSG_DATA(nlh);
+ struct rtattr *attr;
+ int len;
+
+ if (nlh->nlmsg_type == NLMSG_ERROR) {
+ err = -EINVAL;
+ goto out;
+ }
+ if (nlh->nlmsg_type == NLMSG_DONE)
+ break;
+
+ len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*msg));
+ for (attr = (struct rtattr *)(msg + 1); RTA_OK(attr, len);
+ attr = RTA_NEXT(attr, len)) {
+ struct inet_diag_meminfo *minfo;
+
+ if (attr->rta_type != INET_DIAG_MEMINFO)
+ continue;
+ minfo = RTA_DATA(attr);
+ *fwd_alloc = (__s32)minfo->idiag_fmem;
+ err = 0;
+ goto out;
+ }
+ }
+
+out:
+ close(diag_fd);
+ return err;
+}
+
+/* Test strparser SK_PASS delivery to the same socket. */
+static void test_sockmap_strp_self_pass_fwd_alloc(void)
+{
+ struct test_sockmap_strp *strp = NULL;
+ char snd[4 * 1024];
+ int c = -1, p = -1;
+ int fwd_alloc;
+ int sndbuf = sizeof(snd);
+ int zero = 0;
+ char rcv;
+ int sent, recvd;
+ int map;
+ int err;
+
+ memset(snd, 0xa5, sizeof(snd));
+
+ strp = test_sockmap_strp__open_and_load();
+ if (!ASSERT_OK_PTR(strp, "test_sockmap_strp__open_and_load"))
+ return;
+
+ map = bpf_map__fd(strp->maps.sock_map);
+ err = xbpf_prog_attach(bpf_program__fd(strp->progs.prog_skb_parser_one),
+ map, BPF_SK_SKB_STREAM_PARSER, 0);
+ if (err)
+ goto out_destroy;
+
+ err = xbpf_prog_attach(bpf_program__fd(strp->progs.prog_skb_verdict_pass),
+ map, BPF_SK_SKB_STREAM_VERDICT, 0);
+ if (err)
+ goto out_destroy;
+
+ err = create_pair(AF_INET, SOCK_STREAM, &c, &p);
+ if (!ASSERT_OK(err, "create_pair"))
+ goto out_destroy;
+
+ err = xsetsockopt(c, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
+ if (err)
+ goto out_destroy;
+
+ err = xsetsockopt(p, SOL_SOCKET, SO_RCVBUF, &sndbuf, sizeof(sndbuf));
+ if (err)
+ goto out_destroy;
+
+ err = xbpf_map_update_elem(map, &zero, &p, BPF_NOEXIST);
+ if (err)
+ goto out_destroy;
+
+ sent = send(c, snd, sizeof(snd), MSG_DONTWAIT);
+ if (!ASSERT_EQ(sent, sizeof(snd), "send"))
+ goto out_destroy;
+
+ recvd = recv_timeout(p, &rcv, sizeof(rcv), MSG_DONTWAIT,
+ IO_TIMEOUT_SEC);
+ if (!ASSERT_EQ(recvd, sizeof(rcv), "recv_timeout") ||
+ !ASSERT_EQ(rcv, snd[0], "data mismatch"))
+ goto out_destroy;
+
+ err = sockmap_strp_get_fwd_alloc(p, &fwd_alloc);
+ if (!ASSERT_OK(err, "sockmap_strp_get_fwd_alloc") ||
+ !ASSERT_GE(fwd_alloc, 0, "sk_forward_alloc"))
+ goto out_destroy;
+out_destroy:
+ test_sockmap_strp__destroy(strp);
+ if (c >= 0)
+ close(c);
+ if (p >= 0)
+ close(p);
+}
+
void test_sockmap_strp(void)
{
if (test__start_subtest("sockmap strp tcp pass"))
@@ -482,4 +651,6 @@ void test_sockmap_strp(void)
test_sockmap_strp_dispatch_pkt(AF_INET, SOCK_STREAM);
if (test__start_subtest("sockmap strp parser reject pkt mod"))
test_sockmap_strp_parser_reject();
+ if (test__start_subtest("sockmap strp self pass fwd alloc"))
+ test_sockmap_strp_self_pass_fwd_alloc();
}
diff --git a/tools/testing/selftests/bpf/progs/test_sockmap_strp.c b/tools/testing/selftests/bpf/progs/test_sockmap_strp.c
index fe88fa6d40bc..682e53d40751 100644
--- a/tools/testing/selftests/bpf/progs/test_sockmap_strp.c
+++ b/tools/testing/selftests/bpf/progs/test_sockmap_strp.c
@@ -50,6 +50,12 @@ int prog_skb_parser_partial(struct __sk_buff *skb)
return 10;
}
+SEC("sk_skb/stream_parser")
+int prog_skb_parser_one(struct __sk_buff *skb)
+{
+ return 1;
+}
+
SEC("sk_skb/stream_parser")
int prog_skb_parser_resize(struct __sk_buff *skb)
{
--
2.55.0
next prev parent reply other threads:[~2026-08-17 15:50 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-17 15:50 [PATCH bpf v3 0/2] bpf, sockmap: fix forward allocation accounting in strparser self-pass path Junseo Lim
2026-08-17 15:50 ` [PATCH bpf v3 1/2] bpf, sockmap: settle sk_forward_alloc for strparser SK_PASS Junseo Lim
2026-08-17 16:11 ` sashiko-bot
2026-08-17 17:13 ` bot+bpf-ci
2026-08-17 15:50 ` Junseo Lim [this message]
2026-08-17 16:52 ` [PATCH bpf v3 2/2] selftests/bpf: Cover strparser self-pass forward allocation bot+bpf-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=20260817155009.232670-3-zirajs7@gmail.com \
--to=zirajs7@gmail.com \
--cc=andrii@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=eddyz87@gmail.com \
--cc=edumazet@google.com \
--cc=emil@etsalapatis.com \
--cc=horms@kernel.org \
--cc=jakub@cloudflare.com \
--cc=jiayuan.chen@linux.dev \
--cc=john.fastabend@gmail.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=rhkrqnwk98@gmail.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.