diff mbox series

[v2,2/2] selftests/bpf: Refactor xdp_adjust_tail selftest with dynamic sizing

Message ID 1aeebae060d2345331735636db5d8b2298ee5559.1741188826.git.skb99@linux.ibm.com (mailing list archive)
State New
Delegated to: BPF
Headers show
Series Fix xdp_adjust_frags_tail_grow selftest on powerpc | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR success PR summary
netdev/series_format warning Target tree name not specified in the subject
netdev/tree_selection success Guessed tree name to be net-next, async
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/build_tools success Errors and warnings before: 26 (+0) this patch: 26 (+0)
netdev/cc_maintainers warning 5 maintainers not CCed: haoluo@google.com mykolal@fb.com jolsa@kernel.org shuah@kernel.org sdf@fomichev.me
netdev/build_clang success Errors and warnings before: 0 this patch: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 331 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
bpf/vmtest-bpf-next-VM_Test-21 success Logs for set-matrix
bpf/vmtest-bpf-next-VM_Test-20 success Logs for s390x-gcc / veristat-meta
bpf/vmtest-bpf-next-VM_Test-3 success Logs for Validate matrix.py
bpf/vmtest-bpf-next-VM_Test-2 success Logs for Unittests
bpf/vmtest-bpf-next-VM_Test-5 success Logs for aarch64-gcc / build / build for aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-11 success Logs for aarch64-gcc / veristat-kernel
bpf/vmtest-bpf-next-VM_Test-12 success Logs for aarch64-gcc / veristat-meta
bpf/vmtest-bpf-next-VM_Test-0 success Logs for Lint
bpf/vmtest-bpf-next-VM_Test-15 success Logs for s390x-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-1 success Logs for ShellCheck
bpf/vmtest-bpf-next-VM_Test-6 success Logs for aarch64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-14 success Logs for s390x-gcc / build / build for s390x with gcc
bpf/vmtest-bpf-next-VM_Test-19 success Logs for s390x-gcc / veristat-kernel
bpf/vmtest-bpf-next-VM_Test-34 success Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-40 success Logs for x86_64-llvm-17 / veristat-kernel
bpf/vmtest-bpf-next-VM_Test-35 success Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17-O2
bpf/vmtest-bpf-next-VM_Test-50 success Logs for x86_64-llvm-18 / veristat-kernel
bpf/vmtest-bpf-next-VM_Test-23 success Logs for x86_64-gcc / build / build for x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-51 success Logs for x86_64-llvm-18 / veristat-meta
bpf/vmtest-bpf-next-VM_Test-44 success Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18-O2
bpf/vmtest-bpf-next-VM_Test-41 success Logs for x86_64-llvm-17 / veristat-meta
bpf/vmtest-bpf-next-VM_Test-4 success Logs for aarch64-gcc / GCC BPF
bpf/vmtest-bpf-next-VM_Test-13 success Logs for s390x-gcc / GCC BPF
bpf/vmtest-bpf-next-VM_Test-43 success Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-24 success Logs for x86_64-gcc / build-release
bpf/vmtest-bpf-next-VM_Test-42 success Logs for x86_64-llvm-18 / GCC BPF / GCC BPF
bpf/vmtest-bpf-next-VM_Test-33 success Logs for x86_64-llvm-17 / GCC BPF / GCC BPF
bpf/vmtest-bpf-next-VM_Test-22 success Logs for x86_64-gcc / GCC BPF / GCC BPF
bpf/vmtest-bpf-next-VM_Test-10 success Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-30 success Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-32 success Logs for x86_64-gcc / veristat-meta / x86_64-gcc veristat_meta
bpf/vmtest-bpf-next-VM_Test-29 success Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-38 success Logs for x86_64-llvm-17 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-28 success Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-8 success Logs for aarch64-gcc / test (test_progs, false, 360) / test_progs on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-9 success Logs for aarch64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-31 success Logs for x86_64-gcc / veristat-kernel / x86_64-gcc veristat_kernel
bpf/vmtest-bpf-next-VM_Test-37 success Logs for x86_64-llvm-17 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-25 success Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-26 success Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-48 success Logs for x86_64-llvm-18 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-45 success Logs for x86_64-llvm-18 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-46 success Logs for x86_64-llvm-18 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-7 success Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
bpf/vmtest-bpf-next-VM_Test-49 success Logs for x86_64-llvm-18 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-47 success Logs for x86_64-llvm-18 / test (test_progs_cpuv4, false, 360) / test_progs_cpuv4 on x86_64 with llvm-18
bpf/vmtest-bpf-next-VM_Test-39 success Logs for x86_64-llvm-17 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-27 success Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
bpf/vmtest-bpf-next-VM_Test-36 success Logs for x86_64-llvm-17 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-17
bpf/vmtest-bpf-next-VM_Test-18 success Logs for s390x-gcc / test (test_verifier, false, 360) / test_verifier on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-17 success Logs for s390x-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on s390x with gcc
bpf/vmtest-bpf-next-VM_Test-16 success Logs for s390x-gcc / test (test_progs, false, 360) / test_progs on s390x with gcc

Commit Message

Saket Kumar Bhaskar March 5, 2025, 5:13 p.m. UTC
The xdp_adjust_tail/xdp_adjust_frags_tail_grow selftest fails on
powerpc architecture platforms with a default page size greater than
4096 because the page size, tailroom and buffer size are hardcoded.

To resolve this issue, these parameters are now collected dynamically
in the test driver code and communicated to the BPF program using a
map:

1. Page size and cache line size are obtained using sysconf.
2. The size of struct skb_shared_info is determined using BTF.

Signed-off-by: Saket Kumar Bhaskar <skb99@linux.ibm.com>
---
 .../bpf/prog_tests/xdp_adjust_tail.c          | 160 +++++++++++++-----
 .../bpf/progs/test_xdp_adjust_tail_grow.c     |  41 +++--
 2 files changed, 149 insertions(+), 52 deletions(-)
diff mbox series

Patch

diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c b/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c
index b2b2d85dbb1b..2d1fafa9738e 100644
--- a/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c
+++ b/tools/testing/selftests/bpf/prog_tests/xdp_adjust_tail.c
@@ -1,5 +1,6 @@ 
 // SPDX-License-Identifier: GPL-2.0
 #include <test_progs.h>
+#include <bpf/btf.h>
 #include <network_helpers.h>
 
 static void test_xdp_adjust_tail_shrink(void)
@@ -41,21 +42,47 @@  static void test_xdp_adjust_tail_grow(void)
 {
 	const char *file = "./test_xdp_adjust_tail_grow.bpf.o";
 	struct bpf_object *obj;
-	char buf[4096]; /* avoid segfault: large buf to hold grow results */
+	struct btf *btf;
+	__u8 *buf;
 	__u32 expect_sz;
-	int err, prog_fd;
-	LIBBPF_OPTS(bpf_test_run_opts, topts,
-		.data_in = &pkt_v4,
-		.data_size_in = sizeof(pkt_v4),
-		.data_out = buf,
-		.data_size_out = sizeof(buf),
-		.repeat = 1,
-	);
+	int err, prog_fd, id, shinfo_size, map_fd;
+	int key = 0;
+	int page_size = sysconf(_SC_PAGESIZE);
+	int cache_linesize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
+
+	LIBBPF_OPTS(bpf_test_run_opts, topts);
 
 	err = bpf_prog_test_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
 	if (!ASSERT_OK(err, "test_xdp_adjust_tail_grow"))
 		return;
 
+	btf = btf__load_vmlinux_btf();
+	if (libbpf_get_error(btf))
+		return;
+
+	id = btf__find_by_name(btf, "skb_shared_info");
+	if (id < 0)
+		goto out;
+
+	shinfo_size = btf__resolve_size(btf, id);
+
+	map_fd = bpf_find_map(__func__, obj, "size");
+	if (map_fd < 0)
+		goto out;
+
+	bpf_map_update_elem(map_fd, &key, &shinfo_size, BPF_ANY);
+	key++;
+	bpf_map_update_elem(map_fd, &key, &page_size, BPF_ANY);
+	key++;
+	bpf_map_update_elem(map_fd, &key, &cache_linesize, BPF_ANY);
+
+	buf = malloc(page_size);
+
+	topts.data_in = &pkt_v4;
+	topts.data_size_in = sizeof(pkt_v4);
+	topts.data_out = buf;
+	topts.data_size_out = page_size;
+	topts.repeat = 1;
 	err = bpf_prog_test_run_opts(prog_fd, &topts);
 	ASSERT_OK(err, "ipv4");
 	ASSERT_EQ(topts.retval, XDP_DROP, "ipv4 retval");
@@ -63,45 +90,65 @@  static void test_xdp_adjust_tail_grow(void)
 	expect_sz = sizeof(pkt_v6) + 40; /* Test grow with 40 bytes */
 	topts.data_in = &pkt_v6;
 	topts.data_size_in = sizeof(pkt_v6);
-	topts.data_size_out = sizeof(buf);
+	topts.data_size_out = page_size;
 	err = bpf_prog_test_run_opts(prog_fd, &topts);
 	ASSERT_OK(err, "ipv6");
 	ASSERT_EQ(topts.retval, XDP_TX, "ipv6 retval");
 	ASSERT_EQ(topts.data_size_out, expect_sz, "ipv6 size");
 
+out:
 	bpf_object__close(obj);
+	btf__free(btf);
 }
 
 static void test_xdp_adjust_tail_grow2(void)
 {
 	const char *file = "./test_xdp_adjust_tail_grow.bpf.o";
-	char buf[4096]; /* avoid segfault: large buf to hold grow results */
+	__u8 *buf;
 	struct bpf_object *obj;
+	struct btf *btf;
 	int err, cnt, i;
-	int max_grow, prog_fd;
-	/* SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) */
-#if defined(__s390x__)
-	int tailroom = 512;
-#elif defined(__powerpc__)
-	int tailroom = 384;
-#else
-	int tailroom = 320;
-#endif
-
-	LIBBPF_OPTS(bpf_test_run_opts, tattr,
-		.repeat		= 1,
-		.data_in	= &buf,
-		.data_out	= &buf,
-		.data_size_in	= 0, /* Per test */
-		.data_size_out	= 0, /* Per test */
-	);
+	int max_grow, prog_fd, id, shinfo_size, map_fd, tailroom;
+	int key = 0;
+	int page_size = sysconf(_SC_PAGESIZE);
+	int cache_linesize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
+
+	LIBBPF_OPTS(bpf_test_run_opts, tattr);
 
 	err = bpf_prog_test_load(file, BPF_PROG_TYPE_XDP, &obj, &prog_fd);
 	if (!ASSERT_OK(err, "test_xdp_adjust_tail_grow"))
 		return;
 
+	btf = btf__load_vmlinux_btf();
+	if (libbpf_get_error(btf))
+		return;
+
+	id = btf__find_by_name(btf, "skb_shared_info");
+	if (id < 0)
+		goto out;
+
+	shinfo_size = btf__resolve_size(btf, id);
+
+	/* SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) */
+	tailroom = __ALIGN_KERNEL(shinfo_size, cache_linesize);
+
+	map_fd = bpf_find_map(__func__, obj, "size");
+	if (map_fd < 0)
+		goto out;
+
+	bpf_map_update_elem(map_fd, &key, &shinfo_size, BPF_ANY);
+	key++;
+	bpf_map_update_elem(map_fd, &key, &page_size, BPF_ANY);
+	key++;
+	bpf_map_update_elem(map_fd, &key, &cache_linesize, BPF_ANY);
+
+	buf = malloc(page_size);
+
 	/* Test case-64 */
-	memset(buf, 1, sizeof(buf));
+	memset(buf, 1, page_size);
+	tattr.repeat = 1;
+	tattr.data_in = buf;
+	tattr.data_out = buf;
 	tattr.data_size_in  =  64; /* Determine test case via pkt size */
 	tattr.data_size_out = 128; /* Limit copy_size */
 	/* Kernel side alloc packet memory area that is zero init */
@@ -120,25 +167,30 @@  static void test_xdp_adjust_tail_grow2(void)
 	ASSERT_EQ(buf[191], 1, "case-64-data buf[191]");
 
 	/* Test case-128 */
-	memset(buf, 2, sizeof(buf));
+	memset(buf, 2, page_size);
+	tattr.repeat = 1;
+	tattr.data_in = buf;
+	tattr.data_out = buf;
 	tattr.data_size_in  = 128; /* Determine test case via pkt size */
-	tattr.data_size_out = sizeof(buf);   /* Copy everything */
+	tattr.data_size_out = page_size;   /* Copy everything */
 	err = bpf_prog_test_run_opts(prog_fd, &tattr);
 
-	max_grow = 4096 - XDP_PACKET_HEADROOM -	tailroom; /* 3520 */
+	max_grow = page_size - XDP_PACKET_HEADROOM - tailroom; /* 3520 */
 	ASSERT_OK(err, "case-128");
 	ASSERT_EQ(tattr.retval, XDP_TX, "case-128 retval");
 	ASSERT_EQ(tattr.data_size_out, max_grow, "case-128 data_size_out"); /* Expect max grow */
 
 	/* Extra checks for data content: Count grow size, will contain zeros */
-	for (i = 0, cnt = 0; i < sizeof(buf); i++) {
+	for (i = 0, cnt = 0; i < page_size; i++) {
 		if (buf[i] == 0)
 			cnt++;
 	}
 	ASSERT_EQ(cnt, max_grow - tattr.data_size_in, "case-128-data cnt"); /* Grow increase */
 	ASSERT_EQ(tattr.data_size_out, max_grow, "case-128-data data_size_out"); /* Total grow */
 
+out:
 	bpf_object__close(obj);
+	btf__free(btf);
 }
 
 static void test_xdp_adjust_frags_tail_shrink(void)
@@ -149,6 +201,7 @@  static void test_xdp_adjust_frags_tail_shrink(void)
 	struct bpf_object *obj;
 	int err, prog_fd;
 	__u8 *buf;
+
 	LIBBPF_OPTS(bpf_test_run_opts, topts);
 
 	/* For the individual test cases, the first byte in the packet
@@ -214,26 +267,50 @@  static void test_xdp_adjust_frags_tail_grow(void)
 	__u32 exp_size;
 	struct bpf_program *prog;
 	struct bpf_object *obj;
-	int err, i, prog_fd;
+	struct btf *btf;
+	int err, i, prog_fd, id, shinfo_size, map_fd;
+	int key = 0;
+	int page_size = sysconf(_SC_PAGESIZE);
+	int cache_linesize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
 	__u8 *buf;
+
 	LIBBPF_OPTS(bpf_test_run_opts, topts);
 
 	obj = bpf_object__open(file);
 	if (libbpf_get_error(obj))
 		return;
 
+	btf = btf__load_vmlinux_btf();
+	if (libbpf_get_error(btf))
+		return;
+
 	prog = bpf_object__next_program(obj, NULL);
 	if (bpf_object__load(obj))
 		goto out;
 
 	prog_fd = bpf_program__fd(prog);
 
-	buf = malloc(16384);
-	if (!ASSERT_OK_PTR(buf, "alloc buf 16Kb"))
+	id = btf__find_by_name(btf, "skb_shared_info");
+	if (id < 0)
+		goto out;
+
+	shinfo_size = btf__resolve_size(btf, id);
+	map_fd = bpf_find_map(__func__, obj, "size");
+	if (map_fd < 0)
+		goto out;
+
+	bpf_map_update_elem(map_fd, &key, &shinfo_size, BPF_ANY);
+	key++;
+	bpf_map_update_elem(map_fd, &key, &page_size, BPF_ANY);
+	key++;
+	bpf_map_update_elem(map_fd, &key, &cache_linesize, BPF_ANY);
+
+	buf = malloc(4 * page_size);
+	if (!ASSERT_OK_PTR(buf, "alloc buf (4 x page size)Kb"))
 		goto out;
 
 	/* Test case add 10 bytes to last frag */
-	memset(buf, 1, 16384);
+	memset(buf, 1, 4 * page_size);
 	exp_size = 9000 + 10;
 
 	topts.data_in = buf;
@@ -256,12 +333,12 @@  static void test_xdp_adjust_frags_tail_grow(void)
 		ASSERT_EQ(buf[i], 1, "9Kb+10b-untouched");
 
 	/* Test a too large grow */
-	memset(buf, 1, 16384);
-	exp_size = 9001;
+	memset(buf, 1, 4 * page_size);
+	exp_size = 2 * page_size + 1;
 
 	topts.data_in = topts.data_out = buf;
-	topts.data_size_in = 9001;
-	topts.data_size_out = 16384;
+	topts.data_size_in = 2 * page_size + 1;
+	topts.data_size_out = 4 * page_size;
 	err = bpf_prog_test_run_opts(prog_fd, &topts);
 
 	ASSERT_OK(err, "9Kb+10b");
@@ -271,6 +348,7 @@  static void test_xdp_adjust_frags_tail_grow(void)
 	free(buf);
 out:
 	bpf_object__close(obj);
+	btf__free(btf);
 }
 
 void test_xdp_adjust_tail(void)
diff --git a/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_grow.c b/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_grow.c
index dc74d8cf9e3f..f19e5322711b 100644
--- a/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_grow.c
+++ b/tools/testing/selftests/bpf/progs/test_xdp_adjust_tail_grow.c
@@ -1,36 +1,55 @@ 
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/bpf.h>
+#include <linux/const.h>
 #include <bpf/bpf_helpers.h>
 
+struct {
+	__uint(type, BPF_MAP_TYPE_ARRAY);
+	__uint(max_entries, 3);
+	__type(key, int);
+	__type(value, int);
+} size SEC(".maps");
+
 SEC("xdp")
 int _xdp_adjust_tail_grow(struct xdp_md *xdp)
 {
 	int data_len = bpf_xdp_get_buff_len(xdp);
 	int offset = 0;
+	int *page_size, *shinfo_size, *cache_linesize;
+	int tailroom, key = 0;
+
+	shinfo_size = bpf_map_lookup_elem(&size, &key);
+	if (!shinfo_size)
+		return XDP_ABORTED;
+	key++;
+
+	page_size = bpf_map_lookup_elem(&size, &key);
+	if (!page_size)
+		return XDP_ABORTED;
+	key++;
+
+	cache_linesize = bpf_map_lookup_elem(&size, &key);
+	if (!cache_linesize)
+		return XDP_ABORTED;
+
 	/* SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) */
-#if defined(__TARGET_ARCH_s390)
-	int tailroom = 512;
-#elif defined(__TARGET_ARCH_powerpc)
-	int tailroom = 384;
-#else
-	int tailroom = 320;
-#endif
+	tailroom = __ALIGN_KERNEL(*shinfo_size, *cache_linesize);
 
 	/* Data length determine test case */
 
 	if (data_len == 54) { /* sizeof(pkt_v4) */
-		offset = 4096; /* test too large offset */
+		offset = *page_size; /* test too large offset */
 	} else if (data_len == 74) { /* sizeof(pkt_v6) */
 		offset = 40;
 	} else if (data_len == 64) {
 		offset = 128;
 	} else if (data_len == 128) {
 		/* Max tail grow 3520 */
-		offset = 4096 - 256 - tailroom - data_len;
+		offset = *page_size - 256 - tailroom - data_len;
 	} else if (data_len == 9000) {
 		offset = 10;
-	} else if (data_len == 9001) {
-		offset = 4096;
+	} else if (data_len == 2 * (*page_size) + 1) {
+		offset = *page_size;
 	} else {
 		return XDP_ABORTED; /* No matching test */
 	}