xref: /linux/tools/testing/selftests/bpf/progs/tailcall_bpf2bpf_hierarchy3.c (revision 872cc6abda1507429b97cc7b42a9dae51ee0a668)
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
34 int subprog_tail(struct __sk_buff *skb, void *jmp_table)
35 {
36 	int ret = 0;
37 
38 	bpf_tail_call_static(skb, jmp_table, 0);
39 	barrier_var(ret);
40 	return ret;
41 }
42 
43 __auxiliary
44 SEC("tc")
45 int classifier_0(struct __sk_buff *skb)
46 {
47 	int ret1, ret2;
48 
49 	count++;
50 	ret1 = subprog_tail(skb, &jmp_table0);
51 	ret2 = subprog_tail(skb, &jmp_table1);
52 	__sink(ret1);
53 	__sink(ret2);
54 	return count;
55 }
56 
57 __success
58 __retval(33)
59 SEC("tc")
60 int tailcall_bpf2bpf_hierarchy_3(struct __sk_buff *skb)
61 {
62 	int ret = 0;
63 
64 	clobber_regs_stack();
65 
66 	bpf_tail_call_static(skb, &jmp_table0, 0);
67 
68 	__sink(ret);
69 	return ret;
70 }
71 
72 char __license[] SEC("license") = "GPL";
73