xref: /linux/tools/testing/selftests/bpf/progs/bpf_loop.c (revision 4e5070b64b375a9c1f570893cfceeba108382bef)
1*4e5070b6SJoanne Koong // SPDX-License-Identifier: GPL-2.0
2*4e5070b6SJoanne Koong /* Copyright (c) 2021 Facebook */
3*4e5070b6SJoanne Koong 
4*4e5070b6SJoanne Koong #include "vmlinux.h"
5*4e5070b6SJoanne Koong #include <bpf/bpf_helpers.h>
6*4e5070b6SJoanne Koong 
7*4e5070b6SJoanne Koong char _license[] SEC("license") = "GPL";
8*4e5070b6SJoanne Koong 
9*4e5070b6SJoanne Koong struct callback_ctx {
10*4e5070b6SJoanne Koong 	int output;
11*4e5070b6SJoanne Koong };
12*4e5070b6SJoanne Koong 
13*4e5070b6SJoanne Koong /* These should be set by the user program */
14*4e5070b6SJoanne Koong u32 nested_callback_nr_loops;
15*4e5070b6SJoanne Koong u32 stop_index = -1;
16*4e5070b6SJoanne Koong u32 nr_loops;
17*4e5070b6SJoanne Koong int pid;
18*4e5070b6SJoanne Koong 
19*4e5070b6SJoanne Koong /* Making these global variables so that the userspace program
20*4e5070b6SJoanne Koong  * can verify the output through the skeleton
21*4e5070b6SJoanne Koong  */
22*4e5070b6SJoanne Koong int nr_loops_returned;
23*4e5070b6SJoanne Koong int g_output;
24*4e5070b6SJoanne Koong int err;
25*4e5070b6SJoanne Koong 
26*4e5070b6SJoanne Koong static int callback(__u32 index, void *data)
27*4e5070b6SJoanne Koong {
28*4e5070b6SJoanne Koong 	struct callback_ctx *ctx = data;
29*4e5070b6SJoanne Koong 
30*4e5070b6SJoanne Koong 	if (index >= stop_index)
31*4e5070b6SJoanne Koong 		return 1;
32*4e5070b6SJoanne Koong 
33*4e5070b6SJoanne Koong 	ctx->output += index;
34*4e5070b6SJoanne Koong 
35*4e5070b6SJoanne Koong 	return 0;
36*4e5070b6SJoanne Koong }
37*4e5070b6SJoanne Koong 
38*4e5070b6SJoanne Koong static int empty_callback(__u32 index, void *data)
39*4e5070b6SJoanne Koong {
40*4e5070b6SJoanne Koong 	return 0;
41*4e5070b6SJoanne Koong }
42*4e5070b6SJoanne Koong 
43*4e5070b6SJoanne Koong static int nested_callback2(__u32 index, void *data)
44*4e5070b6SJoanne Koong {
45*4e5070b6SJoanne Koong 	nr_loops_returned += bpf_loop(nested_callback_nr_loops, callback, data, 0);
46*4e5070b6SJoanne Koong 
47*4e5070b6SJoanne Koong 	return 0;
48*4e5070b6SJoanne Koong }
49*4e5070b6SJoanne Koong 
50*4e5070b6SJoanne Koong static int nested_callback1(__u32 index, void *data)
51*4e5070b6SJoanne Koong {
52*4e5070b6SJoanne Koong 	bpf_loop(nested_callback_nr_loops, nested_callback2, data, 0);
53*4e5070b6SJoanne Koong 	return 0;
54*4e5070b6SJoanne Koong }
55*4e5070b6SJoanne Koong 
56*4e5070b6SJoanne Koong SEC("fentry/__x64_sys_nanosleep")
57*4e5070b6SJoanne Koong int test_prog(void *ctx)
58*4e5070b6SJoanne Koong {
59*4e5070b6SJoanne Koong 	struct callback_ctx data = {};
60*4e5070b6SJoanne Koong 
61*4e5070b6SJoanne Koong 	if (bpf_get_current_pid_tgid() >> 32 != pid)
62*4e5070b6SJoanne Koong 		return 0;
63*4e5070b6SJoanne Koong 
64*4e5070b6SJoanne Koong 	nr_loops_returned = bpf_loop(nr_loops, callback, &data, 0);
65*4e5070b6SJoanne Koong 
66*4e5070b6SJoanne Koong 	if (nr_loops_returned < 0)
67*4e5070b6SJoanne Koong 		err = nr_loops_returned;
68*4e5070b6SJoanne Koong 	else
69*4e5070b6SJoanne Koong 		g_output = data.output;
70*4e5070b6SJoanne Koong 
71*4e5070b6SJoanne Koong 	return 0;
72*4e5070b6SJoanne Koong }
73*4e5070b6SJoanne Koong 
74*4e5070b6SJoanne Koong SEC("fentry/__x64_sys_nanosleep")
75*4e5070b6SJoanne Koong int prog_null_ctx(void *ctx)
76*4e5070b6SJoanne Koong {
77*4e5070b6SJoanne Koong 	if (bpf_get_current_pid_tgid() >> 32 != pid)
78*4e5070b6SJoanne Koong 		return 0;
79*4e5070b6SJoanne Koong 
80*4e5070b6SJoanne Koong 	nr_loops_returned = bpf_loop(nr_loops, empty_callback, NULL, 0);
81*4e5070b6SJoanne Koong 
82*4e5070b6SJoanne Koong 	return 0;
83*4e5070b6SJoanne Koong }
84*4e5070b6SJoanne Koong 
85*4e5070b6SJoanne Koong SEC("fentry/__x64_sys_nanosleep")
86*4e5070b6SJoanne Koong int prog_invalid_flags(void *ctx)
87*4e5070b6SJoanne Koong {
88*4e5070b6SJoanne Koong 	struct callback_ctx data = {};
89*4e5070b6SJoanne Koong 
90*4e5070b6SJoanne Koong 	if (bpf_get_current_pid_tgid() >> 32 != pid)
91*4e5070b6SJoanne Koong 		return 0;
92*4e5070b6SJoanne Koong 
93*4e5070b6SJoanne Koong 	err = bpf_loop(nr_loops, callback, &data, 1);
94*4e5070b6SJoanne Koong 
95*4e5070b6SJoanne Koong 	return 0;
96*4e5070b6SJoanne Koong }
97*4e5070b6SJoanne Koong 
98*4e5070b6SJoanne Koong SEC("fentry/__x64_sys_nanosleep")
99*4e5070b6SJoanne Koong int prog_nested_calls(void *ctx)
100*4e5070b6SJoanne Koong {
101*4e5070b6SJoanne Koong 	struct callback_ctx data = {};
102*4e5070b6SJoanne Koong 
103*4e5070b6SJoanne Koong 	if (bpf_get_current_pid_tgid() >> 32 != pid)
104*4e5070b6SJoanne Koong 		return 0;
105*4e5070b6SJoanne Koong 
106*4e5070b6SJoanne Koong 	nr_loops_returned = 0;
107*4e5070b6SJoanne Koong 	bpf_loop(nr_loops, nested_callback1, &data, 0);
108*4e5070b6SJoanne Koong 
109*4e5070b6SJoanne Koong 	g_output = data.output;
110*4e5070b6SJoanne Koong 
111*4e5070b6SJoanne Koong 	return 0;
112*4e5070b6SJoanne Koong }
113