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