1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/bpf.h>
3 #include <bpf/bpf_helpers.h>
4 #include "bpf_misc.h"
5 #include "bpf_test_utils.h"
6
7 int classifier_0(struct __sk_buff *skb);
8
9 struct {
10 __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
11 __uint(max_entries, 1);
12 __uint(key_size, sizeof(__u32));
13 __array(values, void (void));
14 } jmp_table0 SEC(".maps") = {
15 .values = {
16 [0] = (void *) &classifier_0,
17 },
18 };
19
20 struct {
21 __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
22 __uint(max_entries, 1);
23 __uint(key_size, sizeof(__u32));
24 __array(values, void (void));
25 } jmp_table1 SEC(".maps") = {
26 .values = {
27 [0] = (void *) &classifier_0,
28 },
29 };
30
31 int count = 0;
32
33 static __noinline
subprog_tail(struct __sk_buff * skb,void * jmp_table)34 int subprog_tail(struct __sk_buff *skb, void *jmp_table)
35 {
36 bpf_tail_call_static(skb, jmp_table, 0);
37 return 0;
38 }
39
40 __auxiliary
41 SEC("tc")
classifier_0(struct __sk_buff * skb)42 int classifier_0(struct __sk_buff *skb)
43 {
44 count++;
45 subprog_tail(skb, &jmp_table0);
46 subprog_tail(skb, &jmp_table1);
47 return count;
48 }
49
50 __success
51 __retval(33)
52 SEC("tc")
tailcall_bpf2bpf_hierarchy_3(struct __sk_buff * skb)53 int tailcall_bpf2bpf_hierarchy_3(struct __sk_buff *skb)
54 {
55 int ret = 0;
56
57 clobber_regs_stack();
58
59 bpf_tail_call_static(skb, &jmp_table0, 0);
60
61 __sink(ret);
62 return ret;
63 }
64
65 char __license[] SEC("license") = "GPL";
66