xref: /linux/tools/testing/selftests/bpf/prog_tests/stack_arg.c (revision 12e896b9794bbd88f56aeac2a5807ae8d4bb5ad8)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */
3 
4 #include <test_progs.h>
5 #include <network_helpers.h>
6 #include "stack_arg.skel.h"
7 #include "stack_arg_kfunc.skel.h"
8 
9 static void run_subtest(struct bpf_program *prog, int expected)
10 {
11 	int err, prog_fd;
12 	LIBBPF_OPTS(bpf_test_run_opts, topts,
13 		.data_in = &pkt_v4,
14 		.data_size_in = sizeof(pkt_v4),
15 		.repeat = 1,
16 	);
17 
18 	prog_fd = bpf_program__fd(prog);
19 	err = bpf_prog_test_run_opts(prog_fd, &topts);
20 	ASSERT_OK(err, "test_run");
21 	ASSERT_EQ(topts.retval, expected, "retval");
22 }
23 
24 static void test_global_many(void)
25 {
26 	struct stack_arg *skel;
27 
28 	skel = stack_arg__open();
29 	if (!ASSERT_OK_PTR(skel, "open"))
30 		return;
31 
32 	if (!skel->rodata->has_stack_arg) {
33 		test__skip();
34 		goto out;
35 	}
36 
37 	if (!ASSERT_OK(stack_arg__load(skel), "load"))
38 		goto out;
39 
40 	run_subtest(skel->progs.test_global_many_args, 36);
41 
42 out:
43 	stack_arg__destroy(skel);
44 }
45 
46 static void test_async_cb_many(void)
47 {
48 	struct stack_arg *skel;
49 
50 	skel = stack_arg__open();
51 	if (!ASSERT_OK_PTR(skel, "open"))
52 		return;
53 
54 	if (!skel->rodata->has_stack_arg) {
55 		test__skip();
56 		goto out;
57 	}
58 
59 	if (!ASSERT_OK(stack_arg__load(skel), "load"))
60 		goto out;
61 
62 	run_subtest(skel->progs.test_async_cb_many_args, 0);
63 
64 	/* Wait for the timer callback to fire and verify the result.
65 	 * 10+20+30+40+50+60+70+80 = 360
66 	 */
67 	usleep(50);
68 	ASSERT_EQ(skel->bss->timer_result, 360, "timer_result");
69 
70 out:
71 	stack_arg__destroy(skel);
72 }
73 
74 static void test_bpf2bpf(void)
75 {
76 	struct stack_arg *skel;
77 
78 	skel = stack_arg__open();
79 	if (!ASSERT_OK_PTR(skel, "open"))
80 		return;
81 
82 	if (!skel->rodata->has_stack_arg) {
83 		test__skip();
84 		goto out;
85 	}
86 
87 	if (!ASSERT_OK(stack_arg__load(skel), "load"))
88 		goto out;
89 
90 	run_subtest(skel->progs.test_bpf2bpf_ptr_stack_arg, 45);
91 	run_subtest(skel->progs.test_bpf2bpf_mix_stack_args, 51);
92 	run_subtest(skel->progs.test_bpf2bpf_nesting_stack_arg, 50);
93 	run_subtest(skel->progs.test_bpf2bpf_dynptr_stack_arg, 69);
94 	run_subtest(skel->progs.test_two_callees, 91);
95 
96 out:
97 	stack_arg__destroy(skel);
98 }
99 
100 static void test_kfunc(void)
101 {
102 	struct stack_arg_kfunc *skel;
103 
104 	skel = stack_arg_kfunc__open();
105 	if (!ASSERT_OK_PTR(skel, "open"))
106 		return;
107 
108 	if (!skel->rodata->has_stack_arg) {
109 		test__skip();
110 		goto out;
111 	}
112 
113 	if (!ASSERT_OK(stack_arg_kfunc__load(skel), "load"))
114 		goto out;
115 
116 	run_subtest(skel->progs.test_stack_arg_scalar, 36);
117 	run_subtest(skel->progs.test_stack_arg_ptr, 45);
118 	run_subtest(skel->progs.test_stack_arg_mix, 51);
119 	run_subtest(skel->progs.test_stack_arg_dynptr, 69);
120 	run_subtest(skel->progs.test_stack_arg_mem, 151);
121 	run_subtest(skel->progs.test_stack_arg_iter, 115);
122 	run_subtest(skel->progs.test_stack_arg_const_str, 15);
123 	run_subtest(skel->progs.test_stack_arg_timer, 15);
124 
125 out:
126 	stack_arg_kfunc__destroy(skel);
127 }
128 
129 void test_stack_arg(void)
130 {
131 	if (test__start_subtest("global_many_args"))
132 		test_global_many();
133 	if (test__start_subtest("async_cb_many_args"))
134 		test_async_cb_many();
135 	if (test__start_subtest("bpf2bpf"))
136 		test_bpf2bpf();
137 	if (test__start_subtest("kfunc"))
138 		test_kfunc();
139 }
140