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