xref: /linux/tools/testing/selftests/bpf/progs/bpf_loop.c (revision e91d280c840f133560072f246321f9a4d1f4eb14)
14e5070b6SJoanne Koong // SPDX-License-Identifier: GPL-2.0
24e5070b6SJoanne Koong /* Copyright (c) 2021 Facebook */
34e5070b6SJoanne Koong 
44e5070b6SJoanne Koong #include "vmlinux.h"
54e5070b6SJoanne Koong #include <bpf/bpf_helpers.h>
6*e91d280cSNaveen N. Rao #include "bpf_misc.h"
74e5070b6SJoanne Koong 
84e5070b6SJoanne Koong char _license[] SEC("license") = "GPL";
94e5070b6SJoanne Koong 
104e5070b6SJoanne Koong struct callback_ctx {
114e5070b6SJoanne Koong 	int output;
124e5070b6SJoanne Koong };
134e5070b6SJoanne Koong 
144e5070b6SJoanne Koong /* These should be set by the user program */
154e5070b6SJoanne Koong u32 nested_callback_nr_loops;
164e5070b6SJoanne Koong u32 stop_index = -1;
174e5070b6SJoanne Koong u32 nr_loops;
184e5070b6SJoanne Koong int pid;
194e5070b6SJoanne Koong 
204e5070b6SJoanne Koong /* Making these global variables so that the userspace program
214e5070b6SJoanne Koong  * can verify the output through the skeleton
224e5070b6SJoanne Koong  */
234e5070b6SJoanne Koong int nr_loops_returned;
244e5070b6SJoanne Koong int g_output;
254e5070b6SJoanne Koong int err;
264e5070b6SJoanne Koong 
274e5070b6SJoanne Koong static int callback(__u32 index, void *data)
284e5070b6SJoanne Koong {
294e5070b6SJoanne Koong 	struct callback_ctx *ctx = data;
304e5070b6SJoanne Koong 
314e5070b6SJoanne Koong 	if (index >= stop_index)
324e5070b6SJoanne Koong 		return 1;
334e5070b6SJoanne Koong 
344e5070b6SJoanne Koong 	ctx->output += index;
354e5070b6SJoanne Koong 
364e5070b6SJoanne Koong 	return 0;
374e5070b6SJoanne Koong }
384e5070b6SJoanne Koong 
394e5070b6SJoanne Koong static int empty_callback(__u32 index, void *data)
404e5070b6SJoanne Koong {
414e5070b6SJoanne Koong 	return 0;
424e5070b6SJoanne Koong }
434e5070b6SJoanne Koong 
444e5070b6SJoanne Koong static int nested_callback2(__u32 index, void *data)
454e5070b6SJoanne Koong {
464e5070b6SJoanne Koong 	nr_loops_returned += bpf_loop(nested_callback_nr_loops, callback, data, 0);
474e5070b6SJoanne Koong 
484e5070b6SJoanne Koong 	return 0;
494e5070b6SJoanne Koong }
504e5070b6SJoanne Koong 
514e5070b6SJoanne Koong static int nested_callback1(__u32 index, void *data)
524e5070b6SJoanne Koong {
534e5070b6SJoanne Koong 	bpf_loop(nested_callback_nr_loops, nested_callback2, data, 0);
544e5070b6SJoanne Koong 	return 0;
554e5070b6SJoanne Koong }
564e5070b6SJoanne Koong 
57*e91d280cSNaveen N. Rao SEC("fentry/" SYS_PREFIX "sys_nanosleep")
584e5070b6SJoanne Koong int test_prog(void *ctx)
594e5070b6SJoanne Koong {
604e5070b6SJoanne Koong 	struct callback_ctx data = {};
614e5070b6SJoanne Koong 
624e5070b6SJoanne Koong 	if (bpf_get_current_pid_tgid() >> 32 != pid)
634e5070b6SJoanne Koong 		return 0;
644e5070b6SJoanne Koong 
654e5070b6SJoanne Koong 	nr_loops_returned = bpf_loop(nr_loops, callback, &data, 0);
664e5070b6SJoanne Koong 
674e5070b6SJoanne Koong 	if (nr_loops_returned < 0)
684e5070b6SJoanne Koong 		err = nr_loops_returned;
694e5070b6SJoanne Koong 	else
704e5070b6SJoanne Koong 		g_output = data.output;
714e5070b6SJoanne Koong 
724e5070b6SJoanne Koong 	return 0;
734e5070b6SJoanne Koong }
744e5070b6SJoanne Koong 
75*e91d280cSNaveen N. Rao SEC("fentry/" SYS_PREFIX "sys_nanosleep")
764e5070b6SJoanne Koong int prog_null_ctx(void *ctx)
774e5070b6SJoanne Koong {
784e5070b6SJoanne Koong 	if (bpf_get_current_pid_tgid() >> 32 != pid)
794e5070b6SJoanne Koong 		return 0;
804e5070b6SJoanne Koong 
814e5070b6SJoanne Koong 	nr_loops_returned = bpf_loop(nr_loops, empty_callback, NULL, 0);
824e5070b6SJoanne Koong 
834e5070b6SJoanne Koong 	return 0;
844e5070b6SJoanne Koong }
854e5070b6SJoanne Koong 
86*e91d280cSNaveen N. Rao SEC("fentry/" SYS_PREFIX "sys_nanosleep")
874e5070b6SJoanne Koong int prog_invalid_flags(void *ctx)
884e5070b6SJoanne Koong {
894e5070b6SJoanne Koong 	struct callback_ctx data = {};
904e5070b6SJoanne Koong 
914e5070b6SJoanne Koong 	if (bpf_get_current_pid_tgid() >> 32 != pid)
924e5070b6SJoanne Koong 		return 0;
934e5070b6SJoanne Koong 
944e5070b6SJoanne Koong 	err = bpf_loop(nr_loops, callback, &data, 1);
954e5070b6SJoanne Koong 
964e5070b6SJoanne Koong 	return 0;
974e5070b6SJoanne Koong }
984e5070b6SJoanne Koong 
99*e91d280cSNaveen N. Rao SEC("fentry/" SYS_PREFIX "sys_nanosleep")
1004e5070b6SJoanne Koong int prog_nested_calls(void *ctx)
1014e5070b6SJoanne Koong {
1024e5070b6SJoanne Koong 	struct callback_ctx data = {};
1034e5070b6SJoanne Koong 
1044e5070b6SJoanne Koong 	if (bpf_get_current_pid_tgid() >> 32 != pid)
1054e5070b6SJoanne Koong 		return 0;
1064e5070b6SJoanne Koong 
1074e5070b6SJoanne Koong 	nr_loops_returned = 0;
1084e5070b6SJoanne Koong 	bpf_loop(nr_loops, nested_callback1, &data, 0);
1094e5070b6SJoanne Koong 
1104e5070b6SJoanne Koong 	g_output = data.output;
1114e5070b6SJoanne Koong 
1124e5070b6SJoanne Koong 	return 0;
1134e5070b6SJoanne Koong }
114