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