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