1 #include "../../include/bpf_api.h" 2 3 /* This example demonstrates how classifier run-time behaviour 4 * can be altered with tail calls. We start out with an empty 5 * jmp_tc array, then add section aaa to the array slot 0, and 6 * later on atomically replace it with section bbb. Note that 7 * as shown in other examples, the tc loader can prepopulate 8 * tail called sections, here we start out with an empty one 9 * on purpose to show it can also be done this way. 10 * 11 * tc filter add dev foo parent ffff: bpf obj graft.o 12 * tc exec bpf dbg 13 * [...] 14 * Socket Thread-20229 [001] ..s. 138993.003923: : fallthrough 15 * <idle>-0 [001] ..s. 138993.202265: : fallthrough 16 * Socket Thread-20229 [001] ..s. 138994.004149: : fallthrough 17 * [...] 18 * 19 * tc exec bpf graft m:globals/jmp_tc key 0 obj graft.o sec aaa 20 * tc exec bpf dbg 21 * [...] 22 * Socket Thread-19818 [002] ..s. 139012.053587: : aaa 23 * <idle>-0 [002] ..s. 139012.172359: : aaa 24 * Socket Thread-19818 [001] ..s. 139012.173556: : aaa 25 * [...] 26 * 27 * tc exec bpf graft m:globals/jmp_tc key 0 obj graft.o sec bbb 28 * tc exec bpf dbg 29 * [...] 30 * Socket Thread-19818 [002] ..s. 139022.102967: : bbb 31 * <idle>-0 [002] ..s. 139022.155640: : bbb 32 * Socket Thread-19818 [001] ..s. 139022.156730: : bbb 33 * [...] 34 */ 35 36 BPF_PROG_ARRAY(jmp_tc, 0, PIN_GLOBAL_NS, 1); 37 38 __section("aaa") 39 int cls_aaa(struct __sk_buff *skb) 40 { 41 char fmt[] = "aaa\n"; 42 43 trace_printk(fmt, sizeof(fmt)); 44 return TC_H_MAKE(1, 42); 45 } 46 47 __section("bbb") 48 int cls_bbb(struct __sk_buff *skb) 49 { 50 char fmt[] = "bbb\n"; 51 52 trace_printk(fmt, sizeof(fmt)); 53 return TC_H_MAKE(1, 43); 54 } 55 56 __section_cls_entry 57 int cls_entry(struct __sk_buff *skb) 58 { 59 char fmt[] = "fallthrough\n"; 60 61 tail_call(skb, &jmp_tc, 0); 62 trace_printk(fmt, sizeof(fmt)); 63 64 return BPF_H_DEFAULT; 65 } 66 67 BPF_LICENSE("GPL"); 68