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 bpf_tail_call_static(skb, jmp_table, 0); 37 return 0; 38 } 39 40 __auxiliary 41 SEC("tc") 42 int classifier_0(struct __sk_buff *skb) 43 { 44 count++; 45 subprog_tail(skb, &jmp_table0); 46 subprog_tail(skb, &jmp_table1); 47 return count; 48 } 49 50 __success 51 __retval(33) 52 SEC("tc") 53 int tailcall_bpf2bpf_hierarchy_3(struct __sk_buff *skb) 54 { 55 int ret = 0; 56 57 clobber_regs_stack(); 58 59 bpf_tail_call_static(skb, &jmp_table0, 0); 60 61 __sink(ret); 62 return ret; 63 } 64 65 char __license[] SEC("license") = "GPL"; 66