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