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