xref: /linux/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_hierarchy2.c (revision ae28ed4578e6d5a481e39c5a9827f27048661fdd)
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 int classifier_1(struct __sk_buff *skb);
9 
10 struct {
11 	__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
12 	__uint(max_entries, 2);
13 	__uint(key_size, sizeof(__u32));
14 	__array(values, void (void));
15 } jmp_table SEC(".maps") = {
16 	.values = {
17 		[0] = (void *) &classifier_0,
18 		[1] = (void *) &classifier_1,
19 	},
20 };
21 
22 int count0 = 0;
23 int count1 = 0;
24 
25 static __noinline
26 int subprog_tail0(struct __sk_buff *skb)
27 {
28 	bpf_tail_call_static(skb, &jmp_table, 0);
29 	return 0;
30 }
31 
32 __auxiliary
33 SEC("tc")
34 int classifier_0(struct __sk_buff *skb)
35 {
36 	count0++;
37 	subprog_tail0(skb);
38 	return 0;
39 }
40 
41 static __noinline
42 int subprog_tail1(struct __sk_buff *skb)
43 {
44 	bpf_tail_call_static(skb, &jmp_table, 1);
45 	return 0;
46 }
47 
48 __auxiliary
49 SEC("tc")
50 int classifier_1(struct __sk_buff *skb)
51 {
52 	count1++;
53 	subprog_tail1(skb);
54 	return 0;
55 }
56 
57 __success
58 __retval(33)
59 SEC("tc")
60 int tailcall_bpf2bpf_hierarchy_2(struct __sk_buff *skb)
61 {
62 	int ret = 0;
63 
64 	clobber_regs_stack();
65 
66 	subprog_tail0(skb);
67 	subprog_tail1(skb);
68 
69 	__sink(ret);
70 	return (count1 << 16) | count0;
71 }
72 
73 char __license[] SEC("license") = "GPL";
74