All of lore.kernel.org
 help / color / mirror / Atom feed
From: Martin KaFai Lau <martin.lau@linux.dev>
To: bpf@vger.kernel.org
Cc: 'Alexei Starovoitov ' <ast@kernel.org>,
	'Andrii Nakryiko ' <andrii@kernel.org>,
	'Daniel Borkmann ' <daniel@iogearbox.net>,
	netdev@vger.kernel.org, kernel-team@meta.com
Subject: [PATCH bpf 2/2] selftests/bpf: Test udp and tcp iter batching
Date: Tue, 19 Dec 2023 11:32:59 -0800	[thread overview]
Message-ID: <20231219193259.3230692-2-martin.lau@linux.dev> (raw)
In-Reply-To: <20231219193259.3230692-1-martin.lau@linux.dev>

From: Martin KaFai Lau <martin.lau@kernel.org>

The patch adds a test to exercise the bpf_iter_udp batching
logic. It specifically tests the case that there are multiple
so_reuseport udp_sk in a bucket of the udp_table.
The userspace is only reading one udp_sk at a time from
the bpf_iter_udp prog. The true case in
"read_batch(..., bool read_one)". This is the buggy case
that the previous patch fixed.

It also tests the "false" case in "read_batch(..., bool read_one)",
meaning the userspace reads the whole bucket. There is
no bug in this case but adding this test also while
at it.

Considering the way to have multiple tcp_sk in the same
bucket is similar (by using so_reuseport),
this patch also tests the bpf_iter_tcp even though the
bpf_iter_tcp batching logic works correctly.

Both IP v4 and v6 are exercising the same bpf_iter batching
code path, so only v6 is tested.

Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
---
 .../bpf/prog_tests/sock_iter_batch.c          | 101 ++++++++++++++++++
 .../selftests/bpf/progs/sock_iter_batch.c     |  43 ++++++++
 2 files changed, 144 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/prog_tests/sock_iter_batch.c
 create mode 100644 tools/testing/selftests/bpf/progs/sock_iter_batch.c

diff --git a/tools/testing/selftests/bpf/prog_tests/sock_iter_batch.c b/tools/testing/selftests/bpf/prog_tests/sock_iter_batch.c
new file mode 100644
index 000000000000..38aa564862e8
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/sock_iter_batch.c
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2023 Meta
+
+#include <test_progs.h>
+#include "network_helpers.h"
+#include "sock_iter_batch.skel.h"
+
+#define TEST_NS "sock_iter_batch_netns"
+
+static const char expected_char = 'x';
+static const int nr_soreuse = 4;
+
+static void read_batch(struct bpf_program *prog, bool read_one)
+{
+	int iter_fd, i, nread, total_nread = 0;
+	struct bpf_link *link;
+	char b[nr_soreuse];
+
+	link = bpf_program__attach_iter(prog, NULL);
+	if (!ASSERT_OK_PTR(link, "bpf_program__attach_iter"))
+		return;
+
+	iter_fd = bpf_iter_create(bpf_link__fd(link));
+	if (!ASSERT_GE(iter_fd, 0, "bpf_iter_create")) {
+		bpf_link__destroy(link);
+		return;
+	}
+
+	do {
+		nread = read(iter_fd, b, read_one ? 1 : nr_soreuse);
+		if (nread <= 0)
+			break;
+
+		for (i = 0; i < nread; i++)
+			ASSERT_EQ(b[i], expected_char, "b[i]");
+
+		total_nread += nread;
+	} while (total_nread <= nr_soreuse);
+
+	ASSERT_EQ(nread, 0, "nread");
+	ASSERT_EQ(total_nread, nr_soreuse, "total_nread");
+
+	close(iter_fd);
+	bpf_link__destroy(link);
+}
+
+static void do_test(int sock_type)
+{
+	struct sock_iter_batch *skel;
+	int *fds, err;
+
+	fds = start_reuseport_server(AF_INET6, sock_type, "::1", 0, 0,
+				     nr_soreuse);
+	if (!ASSERT_OK_PTR(fds, "start_reuseport_server"))
+		return;
+
+	skel = sock_iter_batch__open();
+	if (!ASSERT_OK_PTR(skel, "sock_iter_batch__open"))
+		goto done;
+
+	skel->rodata->local_port = ntohs(get_socket_local_port(fds[0]));
+	skel->rodata->expected_char = expected_char;
+
+	err = sock_iter_batch__load(skel);
+	if (!ASSERT_OK(err, "sock_iter_batch__load"))
+		goto done;
+
+	if (sock_type == SOCK_STREAM) {
+		read_batch(skel->progs.iter_tcp_soreuse, true);
+		read_batch(skel->progs.iter_tcp_soreuse, false);
+	} else {
+		read_batch(skel->progs.iter_udp_soreuse, true);
+		read_batch(skel->progs.iter_udp_soreuse, false);
+	}
+
+done:
+	sock_iter_batch__destroy(skel);
+	free_fds(fds, nr_soreuse);
+}
+
+void test_sock_iter_batch(void)
+{
+	struct nstoken *nstoken = NULL;
+
+	SYS_NOFAIL("ip netns del " TEST_NS " &> /dev/null");
+	SYS(done, "ip netns add %s", TEST_NS);
+	SYS(done, "ip -net %s link set dev lo up", TEST_NS);
+
+	nstoken = open_netns(TEST_NS);
+	if (!ASSERT_OK_PTR(nstoken, "open_netns"))
+		goto done;
+
+	if (test__start_subtest("tcp"))
+		do_test(SOCK_STREAM);
+	if (test__start_subtest("udp"))
+		do_test(SOCK_DGRAM);
+
+done:
+	close_netns(nstoken);
+	SYS_NOFAIL("ip netns del " TEST_NS " &> /dev/null");
+}
diff --git a/tools/testing/selftests/bpf/progs/sock_iter_batch.c b/tools/testing/selftests/bpf/progs/sock_iter_batch.c
new file mode 100644
index 000000000000..4264df162d83
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/sock_iter_batch.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2023 Meta
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_core_read.h>
+#include "bpf_tracing_net.h"
+#include "bpf_kfuncs.h"
+
+volatile const __u16 local_port;
+volatile const char expected_char;
+
+SEC("iter/tcp")
+int iter_tcp_soreuse(struct bpf_iter__tcp *ctx)
+{
+	struct sock *sk = (struct sock *)ctx->sk_common;
+
+	if (!sk)
+		return 0;
+
+	sk = bpf_rdonly_cast(sk, bpf_core_type_id_kernel(struct sock));
+	if (sk->sk_family == AF_INET6 && sk->sk_num == local_port)
+		bpf_seq_write(ctx->meta->seq, (void *)&expected_char, 1);
+
+	return 0;
+}
+
+SEC("iter/udp")
+int iter_udp_soreuse(struct bpf_iter__udp *ctx)
+{
+	struct sock *sk = (struct sock *)ctx->udp_sk;
+
+	if (!sk)
+		return 0;
+
+	sk = bpf_rdonly_cast(sk, bpf_core_type_id_kernel(struct sock));
+	if (sk->sk_family == AF_INET6 && sk->sk_num == local_port)
+		bpf_seq_write(ctx->meta->seq, (void *)&expected_char, 1);
+
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";
-- 
2.34.1


  reply	other threads:[~2023-12-19 19:33 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-19 19:32 [PATCH bpf 1/2] bpf: Avoid iter->offset making backward progress in bpf_iter_udp Martin KaFai Lau
2023-12-19 19:32 ` Martin KaFai Lau [this message]
2023-12-20 14:24 ` Daniel Borkmann
2023-12-20 19:10   ` Martin KaFai Lau
2023-12-21  4:45     ` Martin KaFai Lau
2023-12-21 13:21       ` Daniel Borkmann
2023-12-21 14:58         ` Martin KaFai Lau
2023-12-21 20:27           ` Daniel Borkmann
2023-12-21 22:19             ` Martin KaFai Lau
2024-01-04 20:21           ` Aditi Ghag
2024-01-04 22:27             ` Martin KaFai Lau
2024-01-04 23:38               ` Aditi Ghag
2024-01-05  0:33                 ` Martin KaFai Lau
2024-01-08 23:24                   ` Aditi Ghag

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=20231219193259.3230692-2-martin.lau@linux.dev \
    --to=martin.lau@linux.dev \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=kernel-team@meta.com \
    --cc=netdev@vger.kernel.org \
    /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.