1 #include "bpf_experimental.h" 2 3 struct val_t { 4 long b, c, d; 5 }; 6 7 struct elem { 8 long sum; 9 struct val_t __percpu_kptr *pc; 10 }; 11 12 struct { 13 __uint(type, BPF_MAP_TYPE_ARRAY); 14 __uint(max_entries, 1); 15 __type(key, int); 16 __type(value, struct elem); 17 } array SEC(".maps"); 18 19 void bpf_rcu_read_lock(void) __ksym; 20 void bpf_rcu_read_unlock(void) __ksym; 21 22 const volatile int nr_cpus; 23 24 /* Initialize the percpu object */ 25 SEC("?fentry/bpf_fentry_test1") 26 int BPF_PROG(test_array_map_1) 27 { 28 struct val_t __percpu_kptr *p; 29 struct elem *e; 30 int index = 0; 31 32 e = bpf_map_lookup_elem(&array, &index); 33 if (!e) 34 return 0; 35 36 p = bpf_percpu_obj_new(struct val_t); 37 if (!p) 38 return 0; 39 40 p = bpf_kptr_xchg(&e->pc, p); 41 if (p) 42 bpf_percpu_obj_drop(p); 43 44 return 0; 45 } 46 47 /* Update percpu data */ 48 SEC("?fentry/bpf_fentry_test2") 49 int BPF_PROG(test_array_map_2) 50 { 51 struct val_t __percpu_kptr *p; 52 struct val_t *v; 53 struct elem *e; 54 int index = 0; 55 56 e = bpf_map_lookup_elem(&array, &index); 57 if (!e) 58 return 0; 59 60 p = e->pc; 61 if (!p) 62 return 0; 63 64 v = bpf_per_cpu_ptr(p, 0); 65 if (!v) 66 return 0; 67 v->c = 1; 68 v->d = 2; 69 70 return 0; 71 } 72 73 int cpu0_field_d, sum_field_c; 74 int my_pid; 75 76 /* Summarize percpu data */ 77 SEC("?fentry/bpf_fentry_test3") 78 int BPF_PROG(test_array_map_3) 79 { 80 struct val_t __percpu_kptr *p; 81 int i, index = 0; 82 struct val_t *v; 83 struct elem *e; 84 85 if ((bpf_get_current_pid_tgid() >> 32) != my_pid) 86 return 0; 87 88 e = bpf_map_lookup_elem(&array, &index); 89 if (!e) 90 return 0; 91 92 p = e->pc; 93 if (!p) 94 return 0; 95 96 bpf_for(i, 0, nr_cpus) { 97 v = bpf_per_cpu_ptr(p, i); 98 if (v) { 99 if (i == 0) 100 cpu0_field_d = v->d; 101 sum_field_c += v->c; 102 } 103 } 104 105 return 0; 106 } 107 108 /* Explicitly free allocated percpu data */ 109 SEC("?fentry/bpf_fentry_test4") 110 int BPF_PROG(test_array_map_4) 111 { 112 struct val_t __percpu_kptr *p; 113 struct elem *e; 114 int index = 0; 115 116 e = bpf_map_lookup_elem(&array, &index); 117 if (!e) 118 return 0; 119 120 /* delete */ 121 p = bpf_kptr_xchg(&e->pc, NULL); 122 if (p) { 123 bpf_percpu_obj_drop(p); 124 } 125 126 return 0; 127 } 128 129 SEC("?fentry.s/bpf_fentry_test1") 130 int BPF_PROG(test_array_map_10) 131 { 132 struct val_t __percpu_kptr *p, *p1; 133 int i, index = 0; 134 struct val_t *v; 135 struct elem *e; 136 137 if ((bpf_get_current_pid_tgid() >> 32) != my_pid) 138 return 0; 139 140 e = bpf_map_lookup_elem(&array, &index); 141 if (!e) 142 return 0; 143 144 bpf_rcu_read_lock(); 145 p = e->pc; 146 if (!p) { 147 p = bpf_percpu_obj_new(struct val_t); 148 if (!p) 149 goto out; 150 151 p1 = bpf_kptr_xchg(&e->pc, p); 152 if (p1) { 153 /* race condition */ 154 bpf_percpu_obj_drop(p1); 155 } 156 } 157 158 v = bpf_this_cpu_ptr(p); 159 v->c = 3; 160 v = bpf_this_cpu_ptr(p); 161 v->c = 0; 162 163 v = bpf_per_cpu_ptr(p, 0); 164 if (!v) 165 goto out; 166 v->c = 1; 167 v->d = 2; 168 169 /* delete */ 170 p1 = bpf_kptr_xchg(&e->pc, NULL); 171 if (!p1) 172 goto out; 173 174 bpf_for(i, 0, nr_cpus) { 175 v = bpf_per_cpu_ptr(p, i); 176 if (v) { 177 if (i == 0) 178 cpu0_field_d = v->d; 179 sum_field_c += v->c; 180 } 181 } 182 183 /* finally release p */ 184 bpf_percpu_obj_drop(p1); 185 out: 186 bpf_rcu_read_unlock(); 187 return 0; 188 } 189 190 char _license[] SEC("license") = "GPL"; 191