xref: /DragonOS/kernel/crates/rbpf/src/helpers.rs (revision fae6e9ade46a52976ad5d099643d51cc20876448)
1*fae6e9adSlinfeng // SPDX-License-Identifier: (Apache-2.0 OR MIT)
2*fae6e9adSlinfeng // Copyright 2015 Big Switch Networks, Inc
3*fae6e9adSlinfeng //      (Algorithms for uBPF helpers, originally in C)
4*fae6e9adSlinfeng // Copyright 2016 6WIND S.A. <quentin.monnet@6wind.com>
5*fae6e9adSlinfeng //      (Translation to Rust, other helpers)
6*fae6e9adSlinfeng 
7*fae6e9adSlinfeng //! This module implements some built-in helpers that can be called from within an eBPF program.
8*fae6e9adSlinfeng //!
9*fae6e9adSlinfeng //! These helpers may originate from several places:
10*fae6e9adSlinfeng //!
11*fae6e9adSlinfeng //! * Some of them mimic the helpers available in the Linux kernel.
12*fae6e9adSlinfeng //! * Some of them were proposed as example helpers in uBPF and they were adapted here.
13*fae6e9adSlinfeng //! * Other helpers may be specific to rbpf.
14*fae6e9adSlinfeng //!
15*fae6e9adSlinfeng //! The prototype for helpers is always the same: five `u64` as arguments, and a `u64` as a return
16*fae6e9adSlinfeng //! value. Hence some helpers have unused arguments, or return a 0 value in all cases, in order to
17*fae6e9adSlinfeng //! respect this convention.
18*fae6e9adSlinfeng 
19*fae6e9adSlinfeng // Helpers associated to kernel helpers
20*fae6e9adSlinfeng // See also linux/include/uapi/linux/bpf.h in Linux kernel sources.
21*fae6e9adSlinfeng 
22*fae6e9adSlinfeng // bpf_ktime_getns()
23*fae6e9adSlinfeng 
24*fae6e9adSlinfeng /// Index of helper `bpf_ktime_getns()`, equivalent to `bpf_time_getns()`, in Linux kernel, see
25*fae6e9adSlinfeng /// <https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/bpf.h>.
26*fae6e9adSlinfeng pub const BPF_KTIME_GETNS_IDX: u32 = 5;
27*fae6e9adSlinfeng 
28*fae6e9adSlinfeng /// Get monotonic time (since boot time) in nanoseconds. All arguments are unused.
29*fae6e9adSlinfeng ///
30*fae6e9adSlinfeng /// # Examples
31*fae6e9adSlinfeng ///
32*fae6e9adSlinfeng /// ```
33*fae6e9adSlinfeng /// use rbpf::helpers;
34*fae6e9adSlinfeng ///
35*fae6e9adSlinfeng /// let t = helpers::bpf_time_getns(0, 0, 0, 0, 0);
36*fae6e9adSlinfeng /// let d =  t / 10u64.pow(9)  / 60   / 60  / 24;
37*fae6e9adSlinfeng /// let h = (t / 10u64.pow(9)  / 60   / 60) % 24;
38*fae6e9adSlinfeng /// let m = (t / 10u64.pow(9)  / 60 ) % 60;
39*fae6e9adSlinfeng /// let s = (t / 10u64.pow(9)) % 60;
40*fae6e9adSlinfeng /// let ns = t % 10u64.pow(9);
41*fae6e9adSlinfeng /// println!("Uptime: {:#x} == {} days {}:{}:{}, {} ns", t, d, h, m, s, ns);
42*fae6e9adSlinfeng /// ```
43*fae6e9adSlinfeng #[allow(dead_code)]
44*fae6e9adSlinfeng #[allow(unused_variables)]
45*fae6e9adSlinfeng #[allow(deprecated)]
46*fae6e9adSlinfeng #[cfg(feature = "std")]
bpf_time_getns(unused1: u64, unused2: u64, unused3: u64, unused4: u64, unused5: u64) -> u6447*fae6e9adSlinfeng pub fn bpf_time_getns(unused1: u64, unused2: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
48*fae6e9adSlinfeng     time::precise_time_ns()
49*fae6e9adSlinfeng }
50*fae6e9adSlinfeng 
51*fae6e9adSlinfeng // bpf_trace_printk()
52*fae6e9adSlinfeng 
53*fae6e9adSlinfeng /// Index of helper `bpf_trace_printk()`, equivalent to `bpf_trace_printf()`, in Linux kernel, see
54*fae6e9adSlinfeng /// <https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/bpf.h>.
55*fae6e9adSlinfeng pub const BPF_TRACE_PRINTK_IDX: u32 = 6;
56*fae6e9adSlinfeng 
57*fae6e9adSlinfeng /// Prints its **last three** arguments to standard output. The **first two** arguments are
58*fae6e9adSlinfeng /// **unused**. Returns the number of bytes written.
59*fae6e9adSlinfeng ///
60*fae6e9adSlinfeng /// By ignoring the first two arguments, it creates a helper that will have a behavior similar to
61*fae6e9adSlinfeng /// the one of the equivalent helper `bpf_trace_printk()` from Linux kernel.
62*fae6e9adSlinfeng ///
63*fae6e9adSlinfeng /// # Examples
64*fae6e9adSlinfeng ///
65*fae6e9adSlinfeng /// ```
66*fae6e9adSlinfeng /// use rbpf::helpers;
67*fae6e9adSlinfeng ///
68*fae6e9adSlinfeng /// let res = helpers::bpf_trace_printf(0, 0, 1, 15, 32);
69*fae6e9adSlinfeng /// assert_eq!(res as usize, "bpf_trace_printf: 0x1, 0xf, 0x20\n".len());
70*fae6e9adSlinfeng /// ```
71*fae6e9adSlinfeng ///
72*fae6e9adSlinfeng /// This will print `bpf_trace_printf: 0x1, 0xf, 0x20`.
73*fae6e9adSlinfeng ///
74*fae6e9adSlinfeng /// The eBPF code needed to perform the call in this example would be nearly identical to the code
75*fae6e9adSlinfeng /// obtained by compiling the following code from C to eBPF with clang:
76*fae6e9adSlinfeng ///
77*fae6e9adSlinfeng /// ```c
78*fae6e9adSlinfeng /// #include <linux/bpf.h>
79*fae6e9adSlinfeng /// #include "path/to/linux/samples/bpf/bpf_helpers.h"
80*fae6e9adSlinfeng ///
81*fae6e9adSlinfeng /// int main(struct __sk_buff *skb)
82*fae6e9adSlinfeng /// {
83*fae6e9adSlinfeng ///     // Only %d %u %x %ld %lu %lx %lld %llu %llx %p %s conversion specifiers allowed.
84*fae6e9adSlinfeng ///     // See <https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/kernel/trace/bpf_trace.c>.
85*fae6e9adSlinfeng ///     char *fmt = "bpf_trace_printk %llx, %llx, %llx\n";
86*fae6e9adSlinfeng ///     return bpf_trace_printk(fmt, sizeof(fmt), 1, 15, 32);
87*fae6e9adSlinfeng /// }
88*fae6e9adSlinfeng /// ```
89*fae6e9adSlinfeng ///
90*fae6e9adSlinfeng /// This would equally print the three numbers in `/sys/kernel/debug/tracing` file each time the
91*fae6e9adSlinfeng /// program is run.
92*fae6e9adSlinfeng #[allow(dead_code)]
93*fae6e9adSlinfeng #[allow(unused_variables)]
94*fae6e9adSlinfeng #[cfg(feature = "std")]
bpf_trace_printf(unused1: u64, unused2: u64, arg3: u64, arg4: u64, arg5: u64) -> u6495*fae6e9adSlinfeng pub fn bpf_trace_printf(unused1: u64, unused2: u64, arg3: u64, arg4: u64, arg5: u64) -> u64 {
96*fae6e9adSlinfeng     println!("bpf_trace_printf: {arg3:#x}, {arg4:#x}, {arg5:#x}");
97*fae6e9adSlinfeng     let size_arg = |x| {
98*fae6e9adSlinfeng         if x == 0 {
99*fae6e9adSlinfeng             1
100*fae6e9adSlinfeng         } else {
101*fae6e9adSlinfeng             (x as f64).log(16.0).floor() as u64 + 1
102*fae6e9adSlinfeng         }
103*fae6e9adSlinfeng     };
104*fae6e9adSlinfeng     "bpf_trace_printf: 0x, 0x, 0x\n".len() as u64 + size_arg(arg3) + size_arg(arg4) + size_arg(arg5)
105*fae6e9adSlinfeng }
106*fae6e9adSlinfeng 
107*fae6e9adSlinfeng // Helpers coming from uBPF <https://github.com/iovisor/ubpf/blob/master/vm/test.c>
108*fae6e9adSlinfeng 
109*fae6e9adSlinfeng /// The idea is to assemble five bytes into a single `u64`. For compatibility with the helpers API,
110*fae6e9adSlinfeng /// each argument must be a `u64`.
111*fae6e9adSlinfeng ///
112*fae6e9adSlinfeng /// # Examples
113*fae6e9adSlinfeng ///
114*fae6e9adSlinfeng /// ```
115*fae6e9adSlinfeng /// use rbpf::helpers;
116*fae6e9adSlinfeng ///
117*fae6e9adSlinfeng /// let gathered = helpers::gather_bytes(0x11, 0x22, 0x33, 0x44, 0x55);
118*fae6e9adSlinfeng /// assert_eq!(gathered, 0x1122334455);
119*fae6e9adSlinfeng /// ```
gather_bytes(arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) -> u64120*fae6e9adSlinfeng pub fn gather_bytes(arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) -> u64 {
121*fae6e9adSlinfeng     arg1.wrapping_shl(32)
122*fae6e9adSlinfeng         | arg2.wrapping_shl(24)
123*fae6e9adSlinfeng         | arg3.wrapping_shl(16)
124*fae6e9adSlinfeng         | arg4.wrapping_shl(8)
125*fae6e9adSlinfeng         | arg5
126*fae6e9adSlinfeng }
127*fae6e9adSlinfeng 
128*fae6e9adSlinfeng /// Same as `void *memfrob(void *s, size_t n);` in `string.h` in C. See the GNU manual page (in
129*fae6e9adSlinfeng /// section 3) for `memfrob`. The memory is directly modified, and the helper returns 0 in all
130*fae6e9adSlinfeng /// cases. Arguments 3 to 5 are unused.
131*fae6e9adSlinfeng ///
132*fae6e9adSlinfeng /// # Examples
133*fae6e9adSlinfeng ///
134*fae6e9adSlinfeng /// ```
135*fae6e9adSlinfeng /// use rbpf::helpers;
136*fae6e9adSlinfeng ///
137*fae6e9adSlinfeng /// let val: u64 = 0x112233;
138*fae6e9adSlinfeng /// let val_ptr = &val as *const u64;
139*fae6e9adSlinfeng ///
140*fae6e9adSlinfeng /// helpers::memfrob(val_ptr as u64, 8, 0, 0, 0);
141*fae6e9adSlinfeng /// assert_eq!(val, 0x2a2a2a2a2a3b0819);
142*fae6e9adSlinfeng /// helpers::memfrob(val_ptr as u64, 8, 0, 0, 0);
143*fae6e9adSlinfeng /// assert_eq!(val, 0x112233);
144*fae6e9adSlinfeng /// ```
145*fae6e9adSlinfeng #[allow(unused_variables)]
memfrob(ptr: u64, len: u64, unused3: u64, unused4: u64, unused5: u64) -> u64146*fae6e9adSlinfeng pub fn memfrob(ptr: u64, len: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
147*fae6e9adSlinfeng     for i in 0..len {
148*fae6e9adSlinfeng         unsafe {
149*fae6e9adSlinfeng             let mut p = (ptr + i) as *mut u8;
150*fae6e9adSlinfeng             *p ^= 0b101010;
151*fae6e9adSlinfeng         }
152*fae6e9adSlinfeng     }
153*fae6e9adSlinfeng     0
154*fae6e9adSlinfeng }
155*fae6e9adSlinfeng 
156*fae6e9adSlinfeng // TODO: Try again when asm!() is available in stable Rust.
157*fae6e9adSlinfeng // #![feature(asm)]
158*fae6e9adSlinfeng // #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
159*fae6e9adSlinfeng // #[allow(unused_variables)]
160*fae6e9adSlinfeng // pub fn memfrob (ptr: u64, len: u64, arg3: u64, arg4: u64, arg5: u64) -> u64 {
161*fae6e9adSlinfeng //     unsafe {
162*fae6e9adSlinfeng //         asm!(
163*fae6e9adSlinfeng //                 "mov $0xf0, %rax"
164*fae6e9adSlinfeng //             ::: "mov $0xf1, %rcx"
165*fae6e9adSlinfeng //             ::: "mov $0xf2, %rdx"
166*fae6e9adSlinfeng //             ::: "mov $0xf3, %rsi"
167*fae6e9adSlinfeng //             ::: "mov $0xf4, %rdi"
168*fae6e9adSlinfeng //             ::: "mov $0xf5, %r8"
169*fae6e9adSlinfeng //             ::: "mov $0xf6, %r9"
170*fae6e9adSlinfeng //             ::: "mov $0xf7, %r10"
171*fae6e9adSlinfeng //             ::: "mov $0xf8, %r11"
172*fae6e9adSlinfeng //         );
173*fae6e9adSlinfeng //     }
174*fae6e9adSlinfeng //     0
175*fae6e9adSlinfeng // }
176*fae6e9adSlinfeng 
177*fae6e9adSlinfeng /// Compute and return the square root of argument 1, cast as a float. Arguments 2 to 5 are
178*fae6e9adSlinfeng /// unused.
179*fae6e9adSlinfeng ///
180*fae6e9adSlinfeng /// # Examples
181*fae6e9adSlinfeng ///
182*fae6e9adSlinfeng /// ```
183*fae6e9adSlinfeng /// use rbpf::helpers;
184*fae6e9adSlinfeng ///
185*fae6e9adSlinfeng /// let x = helpers::sqrti(9, 0, 0, 0, 0);
186*fae6e9adSlinfeng /// assert_eq!(x, 3);
187*fae6e9adSlinfeng /// ```
188*fae6e9adSlinfeng #[allow(dead_code)]
189*fae6e9adSlinfeng #[allow(unused_variables)]
190*fae6e9adSlinfeng #[cfg(feature = "std")] // sqrt is only available when using `std`
sqrti(arg1: u64, unused2: u64, unused3: u64, unused4: u64, unused5: u64) -> u64191*fae6e9adSlinfeng pub fn sqrti(arg1: u64, unused2: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
192*fae6e9adSlinfeng     (arg1 as f64).sqrt() as u64
193*fae6e9adSlinfeng }
194*fae6e9adSlinfeng 
195*fae6e9adSlinfeng /// C-like `strcmp`, return 0 if the strings are equal, and a non-null value otherwise.
196*fae6e9adSlinfeng ///
197*fae6e9adSlinfeng /// # Examples
198*fae6e9adSlinfeng ///
199*fae6e9adSlinfeng /// ```
200*fae6e9adSlinfeng /// use rbpf::helpers;
201*fae6e9adSlinfeng ///
202*fae6e9adSlinfeng /// let foo = "This is a string.\0".as_ptr() as u64;
203*fae6e9adSlinfeng /// let bar = "This is another sting.\0".as_ptr() as u64;
204*fae6e9adSlinfeng ///
205*fae6e9adSlinfeng /// assert!(helpers::strcmp(foo, foo, 0, 0, 0) == 0);
206*fae6e9adSlinfeng /// assert!(helpers::strcmp(foo, bar, 0, 0, 0) != 0);
207*fae6e9adSlinfeng /// ```
208*fae6e9adSlinfeng #[allow(dead_code)]
209*fae6e9adSlinfeng #[allow(unused_variables)]
strcmp(arg1: u64, arg2: u64, arg3: u64, unused4: u64, unused5: u64) -> u64210*fae6e9adSlinfeng pub fn strcmp(arg1: u64, arg2: u64, arg3: u64, unused4: u64, unused5: u64) -> u64 {
211*fae6e9adSlinfeng     // C-like strcmp, maybe shorter than converting the bytes to string and comparing?
212*fae6e9adSlinfeng     if arg1 == 0 || arg2 == 0 {
213*fae6e9adSlinfeng         return u64::MAX;
214*fae6e9adSlinfeng     }
215*fae6e9adSlinfeng     let mut a = arg1;
216*fae6e9adSlinfeng     let mut b = arg2;
217*fae6e9adSlinfeng     unsafe {
218*fae6e9adSlinfeng         let mut a_val = *(a as *const u8);
219*fae6e9adSlinfeng         let mut b_val = *(b as *const u8);
220*fae6e9adSlinfeng         while a_val == b_val && a_val != 0 && b_val != 0 {
221*fae6e9adSlinfeng             a += 1;
222*fae6e9adSlinfeng             b += 1;
223*fae6e9adSlinfeng             a_val = *(a as *const u8);
224*fae6e9adSlinfeng             b_val = *(b as *const u8);
225*fae6e9adSlinfeng         }
226*fae6e9adSlinfeng         if a_val >= b_val {
227*fae6e9adSlinfeng             (a_val - b_val) as u64
228*fae6e9adSlinfeng         } else {
229*fae6e9adSlinfeng             (b_val - a_val) as u64
230*fae6e9adSlinfeng         }
231*fae6e9adSlinfeng     }
232*fae6e9adSlinfeng }
233*fae6e9adSlinfeng 
234*fae6e9adSlinfeng // Some additional helpers
235*fae6e9adSlinfeng 
236*fae6e9adSlinfeng /// Returns a random u64 value comprised between `min` and `max` values (inclusive). Arguments 3 to
237*fae6e9adSlinfeng /// 5 are unused.
238*fae6e9adSlinfeng ///
239*fae6e9adSlinfeng /// Relies on `rand()` function from libc, so `libc::srand()` should be called once before this
240*fae6e9adSlinfeng /// helper is used.
241*fae6e9adSlinfeng ///
242*fae6e9adSlinfeng /// # Examples
243*fae6e9adSlinfeng ///
244*fae6e9adSlinfeng /// ```
245*fae6e9adSlinfeng /// extern crate libc;
246*fae6e9adSlinfeng /// extern crate rbpf;
247*fae6e9adSlinfeng /// extern crate time;
248*fae6e9adSlinfeng ///
249*fae6e9adSlinfeng /// unsafe {
250*fae6e9adSlinfeng ///     libc::srand(time::precise_time_ns() as u32)
251*fae6e9adSlinfeng /// }
252*fae6e9adSlinfeng ///
253*fae6e9adSlinfeng /// let n = rbpf::helpers::rand(3, 6, 0, 0, 0);
254*fae6e9adSlinfeng /// assert!(3 <= n && n <= 6);
255*fae6e9adSlinfeng /// ```
256*fae6e9adSlinfeng #[allow(dead_code)]
257*fae6e9adSlinfeng #[allow(unused_variables)]
258*fae6e9adSlinfeng #[cfg(feature = "std")]
rand(min: u64, max: u64, unused3: u64, unused4: u64, unused5: u64) -> u64259*fae6e9adSlinfeng pub fn rand(min: u64, max: u64, unused3: u64, unused4: u64, unused5: u64) -> u64 {
260*fae6e9adSlinfeng     let mut n = unsafe { (libc::rand() as u64).wrapping_shl(32) + libc::rand() as u64 };
261*fae6e9adSlinfeng     if min < max {
262*fae6e9adSlinfeng         n = n % (max + 1 - min) + min;
263*fae6e9adSlinfeng     };
264*fae6e9adSlinfeng     n
265*fae6e9adSlinfeng }
266*fae6e9adSlinfeng /// Prints the helper functions name and it's index.
267*fae6e9adSlinfeng #[cfg(feature = "std")]
show_helper()268*fae6e9adSlinfeng pub fn show_helper() {
269*fae6e9adSlinfeng     for (index, name) in BPF_FUNC_MAPPER.iter().enumerate() {
270*fae6e9adSlinfeng         println!("{}:{}", index, name);
271*fae6e9adSlinfeng     }
272*fae6e9adSlinfeng }
273*fae6e9adSlinfeng 
274*fae6e9adSlinfeng /// See https://github.com/torvalds/linux/blob/master/include/uapi/linux/bpf.h
275*fae6e9adSlinfeng pub const BPF_FUNC_MAPPER: &[&str] = &[
276*fae6e9adSlinfeng     "unspec",
277*fae6e9adSlinfeng     "map_lookup_elem",
278*fae6e9adSlinfeng     "map_update_elem",
279*fae6e9adSlinfeng     "map_delete_elem",
280*fae6e9adSlinfeng     "probe_read",
281*fae6e9adSlinfeng     "ktime_get_ns",
282*fae6e9adSlinfeng     "trace_printk",
283*fae6e9adSlinfeng     "get_prandom_u32",
284*fae6e9adSlinfeng     "get_smp_processor_id",
285*fae6e9adSlinfeng     "skb_store_bytes",
286*fae6e9adSlinfeng     "l3_csum_replace",
287*fae6e9adSlinfeng     "l4_csum_replace",
288*fae6e9adSlinfeng     "tail_call",
289*fae6e9adSlinfeng     "clone_redirect",
290*fae6e9adSlinfeng     "get_current_pid_tgid",
291*fae6e9adSlinfeng     "get_current_uid_gid",
292*fae6e9adSlinfeng     "get_current_comm",
293*fae6e9adSlinfeng     "get_cgroup_classid",
294*fae6e9adSlinfeng     "skb_vlan_push",
295*fae6e9adSlinfeng     "skb_vlan_pop",
296*fae6e9adSlinfeng     "skb_get_tunnel_key",
297*fae6e9adSlinfeng     "skb_set_tunnel_key",
298*fae6e9adSlinfeng     "perf_event_read",
299*fae6e9adSlinfeng     "redirect",
300*fae6e9adSlinfeng     "get_route_realm",
301*fae6e9adSlinfeng     "perf_event_output",
302*fae6e9adSlinfeng     "skb_load_bytes",
303*fae6e9adSlinfeng     "get_stackid",
304*fae6e9adSlinfeng     "csum_diff",
305*fae6e9adSlinfeng     "skb_get_tunnel_opt",
306*fae6e9adSlinfeng     "skb_set_tunnel_opt",
307*fae6e9adSlinfeng     "skb_change_proto",
308*fae6e9adSlinfeng     "skb_change_type",
309*fae6e9adSlinfeng     "skb_under_cgroup",
310*fae6e9adSlinfeng     "get_hash_recalc",
311*fae6e9adSlinfeng     "get_current_task",
312*fae6e9adSlinfeng     "probe_write_user",
313*fae6e9adSlinfeng     "current_task_under_cgroup",
314*fae6e9adSlinfeng     "skb_change_tail",
315*fae6e9adSlinfeng     "skb_pull_data",
316*fae6e9adSlinfeng     "csum_update",
317*fae6e9adSlinfeng     "set_hash_invalid",
318*fae6e9adSlinfeng     "get_numa_node_id",
319*fae6e9adSlinfeng     "skb_change_head",
320*fae6e9adSlinfeng     "xdp_adjust_head",
321*fae6e9adSlinfeng     "probe_read_str",
322*fae6e9adSlinfeng     "get_socket_cookie",
323*fae6e9adSlinfeng     "get_socket_uid",
324*fae6e9adSlinfeng     "set_hash",
325*fae6e9adSlinfeng     "setsockopt",
326*fae6e9adSlinfeng     "skb_adjust_room",
327*fae6e9adSlinfeng     "redirect_map",
328*fae6e9adSlinfeng     "sk_redirect_map",
329*fae6e9adSlinfeng     "sock_map_update",
330*fae6e9adSlinfeng     "xdp_adjust_meta",
331*fae6e9adSlinfeng     "perf_event_read_value",
332*fae6e9adSlinfeng     "perf_prog_read_value",
333*fae6e9adSlinfeng     "getsockopt",
334*fae6e9adSlinfeng     "override_return",
335*fae6e9adSlinfeng     "sock_ops_cb_flags_set",
336*fae6e9adSlinfeng     "msg_redirect_map",
337*fae6e9adSlinfeng     "msg_apply_bytes",
338*fae6e9adSlinfeng     "msg_cork_bytes",
339*fae6e9adSlinfeng     "msg_pull_data",
340*fae6e9adSlinfeng     "bind",
341*fae6e9adSlinfeng     "xdp_adjust_tail",
342*fae6e9adSlinfeng     "skb_get_xfrm_state",
343*fae6e9adSlinfeng     "get_stack",
344*fae6e9adSlinfeng     "skb_load_bytes_relative",
345*fae6e9adSlinfeng     "fib_lookup",
346*fae6e9adSlinfeng     "sock_hash_update",
347*fae6e9adSlinfeng     "msg_redirect_hash",
348*fae6e9adSlinfeng     "sk_redirect_hash",
349*fae6e9adSlinfeng     "lwt_push_encap",
350*fae6e9adSlinfeng     "lwt_seg6_store_bytes",
351*fae6e9adSlinfeng     "lwt_seg6_adjust_srh",
352*fae6e9adSlinfeng     "lwt_seg6_action",
353*fae6e9adSlinfeng     "rc_repeat",
354*fae6e9adSlinfeng     "rc_keydown",
355*fae6e9adSlinfeng     "skb_cgroup_id",
356*fae6e9adSlinfeng     "get_current_cgroup_id",
357*fae6e9adSlinfeng     "get_local_storage",
358*fae6e9adSlinfeng     "sk_select_reuseport",
359*fae6e9adSlinfeng     "skb_ancestor_cgroup_id",
360*fae6e9adSlinfeng     "sk_lookup_tcp",
361*fae6e9adSlinfeng     "sk_lookup_udp",
362*fae6e9adSlinfeng     "sk_release",
363*fae6e9adSlinfeng     "map_push_elem",
364*fae6e9adSlinfeng     "map_pop_elem",
365*fae6e9adSlinfeng     "map_peek_elem",
366*fae6e9adSlinfeng     "msg_push_data",
367*fae6e9adSlinfeng     "msg_pop_data",
368*fae6e9adSlinfeng     "rc_pointer_rel",
369*fae6e9adSlinfeng     "spin_lock",
370*fae6e9adSlinfeng     "spin_unlock",
371*fae6e9adSlinfeng     "sk_fullsock",
372*fae6e9adSlinfeng     "tcp_sock",
373*fae6e9adSlinfeng     "skb_ecn_set_ce",
374*fae6e9adSlinfeng     "get_listener_sock",
375*fae6e9adSlinfeng     "skc_lookup_tcp",
376*fae6e9adSlinfeng     "tcp_check_syncookie",
377*fae6e9adSlinfeng     "sysctl_get_name",
378*fae6e9adSlinfeng     "sysctl_get_current_value",
379*fae6e9adSlinfeng     "sysctl_get_new_value",
380*fae6e9adSlinfeng     "sysctl_set_new_value",
381*fae6e9adSlinfeng     "strtol",
382*fae6e9adSlinfeng     "strtoul",
383*fae6e9adSlinfeng     "sk_storage_get",
384*fae6e9adSlinfeng     "sk_storage_delete",
385*fae6e9adSlinfeng     "send_signal",
386*fae6e9adSlinfeng     "tcp_gen_syncookie",
387*fae6e9adSlinfeng     "skb_output",
388*fae6e9adSlinfeng     "probe_read_user",
389*fae6e9adSlinfeng     "probe_read_kernel",
390*fae6e9adSlinfeng     "probe_read_user_str",
391*fae6e9adSlinfeng     "probe_read_kernel_str",
392*fae6e9adSlinfeng     "tcp_send_ack",
393*fae6e9adSlinfeng     "send_signal_thread",
394*fae6e9adSlinfeng     "jiffies64",
395*fae6e9adSlinfeng     "read_branch_records",
396*fae6e9adSlinfeng     "get_ns_current_pid_tgid",
397*fae6e9adSlinfeng     "xdp_output",
398*fae6e9adSlinfeng     "get_netns_cookie",
399*fae6e9adSlinfeng     "get_current_ancestor_cgroup_id",
400*fae6e9adSlinfeng     "sk_assign",
401*fae6e9adSlinfeng     "ktime_get_boot_ns",
402*fae6e9adSlinfeng     "seq_printf",
403*fae6e9adSlinfeng     "seq_write",
404*fae6e9adSlinfeng     "sk_cgroup_id",
405*fae6e9adSlinfeng     "sk_ancestor_cgroup_id",
406*fae6e9adSlinfeng     "ringbuf_output",
407*fae6e9adSlinfeng     "ringbuf_reserve",
408*fae6e9adSlinfeng     "ringbuf_submit",
409*fae6e9adSlinfeng     "ringbuf_discard",
410*fae6e9adSlinfeng     "ringbuf_query",
411*fae6e9adSlinfeng     "csum_level",
412*fae6e9adSlinfeng     "skc_to_tcp6_sock",
413*fae6e9adSlinfeng     "skc_to_tcp_sock",
414*fae6e9adSlinfeng     "skc_to_tcp_timewait_sock",
415*fae6e9adSlinfeng     "skc_to_tcp_request_sock",
416*fae6e9adSlinfeng     "skc_to_udp6_sock",
417*fae6e9adSlinfeng     "get_task_stack",
418*fae6e9adSlinfeng     "load_hdr_opt",
419*fae6e9adSlinfeng     "store_hdr_opt",
420*fae6e9adSlinfeng     "reserve_hdr_opt",
421*fae6e9adSlinfeng     "inode_storage_get",
422*fae6e9adSlinfeng     "inode_storage_delete",
423*fae6e9adSlinfeng     "d_path",
424*fae6e9adSlinfeng     "copy_from_user",
425*fae6e9adSlinfeng     "snprintf_btf",
426*fae6e9adSlinfeng     "seq_printf_btf",
427*fae6e9adSlinfeng     "skb_cgroup_classid",
428*fae6e9adSlinfeng     "redirect_neigh",
429*fae6e9adSlinfeng     "per_cpu_ptr",
430*fae6e9adSlinfeng     "this_cpu_ptr",
431*fae6e9adSlinfeng     "redirect_peer",
432*fae6e9adSlinfeng     "task_storage_get",
433*fae6e9adSlinfeng     "task_storage_delete",
434*fae6e9adSlinfeng     "get_current_task_btf",
435*fae6e9adSlinfeng     "bprm_opts_set",
436*fae6e9adSlinfeng     "ktime_get_coarse_ns",
437*fae6e9adSlinfeng     "ima_inode_hash",
438*fae6e9adSlinfeng     "sock_from_file",
439*fae6e9adSlinfeng     "check_mtu",
440*fae6e9adSlinfeng     "for_each_map_elem",
441*fae6e9adSlinfeng     "snprintf",
442*fae6e9adSlinfeng     "sys_bpf",
443*fae6e9adSlinfeng     "btf_find_by_name_kind",
444*fae6e9adSlinfeng     "sys_close",
445*fae6e9adSlinfeng     "timer_init",
446*fae6e9adSlinfeng     "timer_set_callback",
447*fae6e9adSlinfeng     "timer_start",
448*fae6e9adSlinfeng     "timer_cancel",
449*fae6e9adSlinfeng     "get_func_ip",
450*fae6e9adSlinfeng     "get_attach_cookie",
451*fae6e9adSlinfeng     "task_pt_regs",
452*fae6e9adSlinfeng     "get_branch_snapshot",
453*fae6e9adSlinfeng     "trace_vprintk",
454*fae6e9adSlinfeng     "skc_to_unix_sock",
455*fae6e9adSlinfeng     "kallsyms_lookup_name",
456*fae6e9adSlinfeng     "find_vma",
457*fae6e9adSlinfeng     "loop",
458*fae6e9adSlinfeng     "strncmp",
459*fae6e9adSlinfeng     "get_func_arg",
460*fae6e9adSlinfeng     "get_func_ret",
461*fae6e9adSlinfeng     "get_func_arg_cnt",
462*fae6e9adSlinfeng     "get_retval",
463*fae6e9adSlinfeng     "set_retval",
464*fae6e9adSlinfeng     "xdp_get_buff_len",
465*fae6e9adSlinfeng     "xdp_load_bytes",
466*fae6e9adSlinfeng     "xdp_store_bytes",
467*fae6e9adSlinfeng     "copy_from_user_task",
468*fae6e9adSlinfeng     "skb_set_tstamp",
469*fae6e9adSlinfeng     "ima_file_hash",
470*fae6e9adSlinfeng     "kptr_xchg",
471*fae6e9adSlinfeng     "map_lookup_percpu_elem",
472*fae6e9adSlinfeng     "skc_to_mptcp_sock",
473*fae6e9adSlinfeng     "dynptr_from_mem",
474*fae6e9adSlinfeng     "ringbuf_reserve_dynptr",
475*fae6e9adSlinfeng     "ringbuf_submit_dynptr",
476*fae6e9adSlinfeng     "ringbuf_discard_dynptr",
477*fae6e9adSlinfeng     "dynptr_read",
478*fae6e9adSlinfeng     "dynptr_write",
479*fae6e9adSlinfeng     "dynptr_data",
480*fae6e9adSlinfeng     "tcp_raw_gen_syncookie_ipv4",
481*fae6e9adSlinfeng     "tcp_raw_gen_syncookie_ipv6",
482*fae6e9adSlinfeng     "tcp_raw_check_syncookie_ipv4",
483*fae6e9adSlinfeng     "tcp_raw_check_syncookie_ipv6",
484*fae6e9adSlinfeng     "ktime_get_tai_ns",
485*fae6e9adSlinfeng     "user_ringbuf_drain",
486*fae6e9adSlinfeng     "cgrp_storage_get",
487*fae6e9adSlinfeng     "cgrp_storage_delete",
488*fae6e9adSlinfeng ];
489