1 // SPDX-License-Identifier: GPL-2.0 2 #include <vmlinux.h> 3 #include <bpf/bpf_tracing.h> 4 #include <bpf/bpf_helpers.h> 5 #include <bpf/bpf_core_read.h> 6 #include "bpf_experimental.h" 7 8 #ifndef ARRAY_SIZE 9 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 10 #endif 11 12 #include "linked_list.h" 13 14 static __always_inline 15 int list_push_pop(struct bpf_spin_lock *lock, struct bpf_list_head *head, bool leave_in_map) 16 { 17 struct bpf_list_node *n; 18 struct foo *f; 19 20 f = bpf_obj_new(typeof(*f)); 21 if (!f) 22 return 2; 23 24 bpf_spin_lock(lock); 25 n = bpf_list_pop_front(head); 26 bpf_spin_unlock(lock); 27 if (n) { 28 bpf_obj_drop(container_of(n, struct foo, node)); 29 bpf_obj_drop(f); 30 return 3; 31 } 32 33 bpf_spin_lock(lock); 34 n = bpf_list_pop_back(head); 35 bpf_spin_unlock(lock); 36 if (n) { 37 bpf_obj_drop(container_of(n, struct foo, node)); 38 bpf_obj_drop(f); 39 return 4; 40 } 41 42 43 bpf_spin_lock(lock); 44 f->data = 42; 45 bpf_list_push_front(head, &f->node); 46 bpf_spin_unlock(lock); 47 if (leave_in_map) 48 return 0; 49 bpf_spin_lock(lock); 50 n = bpf_list_pop_back(head); 51 bpf_spin_unlock(lock); 52 if (!n) 53 return 5; 54 f = container_of(n, struct foo, node); 55 if (f->data != 42) { 56 bpf_obj_drop(f); 57 return 6; 58 } 59 60 bpf_spin_lock(lock); 61 f->data = 13; 62 bpf_list_push_front(head, &f->node); 63 bpf_spin_unlock(lock); 64 bpf_spin_lock(lock); 65 n = bpf_list_pop_front(head); 66 bpf_spin_unlock(lock); 67 if (!n) 68 return 7; 69 f = container_of(n, struct foo, node); 70 if (f->data != 13) { 71 bpf_obj_drop(f); 72 return 8; 73 } 74 bpf_obj_drop(f); 75 76 bpf_spin_lock(lock); 77 n = bpf_list_pop_front(head); 78 bpf_spin_unlock(lock); 79 if (n) { 80 bpf_obj_drop(container_of(n, struct foo, node)); 81 return 9; 82 } 83 84 bpf_spin_lock(lock); 85 n = bpf_list_pop_back(head); 86 bpf_spin_unlock(lock); 87 if (n) { 88 bpf_obj_drop(container_of(n, struct foo, node)); 89 return 10; 90 } 91 return 0; 92 } 93 94 95 static __always_inline 96 int list_push_pop_multiple(struct bpf_spin_lock *lock, struct bpf_list_head *head, bool leave_in_map) 97 { 98 struct bpf_list_node *n; 99 struct foo *f[8], *pf; 100 int i; 101 102 for (i = 0; i < ARRAY_SIZE(f); i++) { 103 f[i] = bpf_obj_new(typeof(**f)); 104 if (!f[i]) 105 return 2; 106 f[i]->data = i; 107 bpf_spin_lock(lock); 108 bpf_list_push_front(head, &f[i]->node); 109 bpf_spin_unlock(lock); 110 } 111 112 for (i = 0; i < ARRAY_SIZE(f); i++) { 113 bpf_spin_lock(lock); 114 n = bpf_list_pop_front(head); 115 bpf_spin_unlock(lock); 116 if (!n) 117 return 3; 118 pf = container_of(n, struct foo, node); 119 if (pf->data != (ARRAY_SIZE(f) - i - 1)) { 120 bpf_obj_drop(pf); 121 return 4; 122 } 123 bpf_spin_lock(lock); 124 bpf_list_push_back(head, &pf->node); 125 bpf_spin_unlock(lock); 126 } 127 128 if (leave_in_map) 129 return 0; 130 131 for (i = 0; i < ARRAY_SIZE(f); i++) { 132 bpf_spin_lock(lock); 133 n = bpf_list_pop_back(head); 134 bpf_spin_unlock(lock); 135 if (!n) 136 return 5; 137 pf = container_of(n, struct foo, node); 138 if (pf->data != i) { 139 bpf_obj_drop(pf); 140 return 6; 141 } 142 bpf_obj_drop(pf); 143 } 144 bpf_spin_lock(lock); 145 n = bpf_list_pop_back(head); 146 bpf_spin_unlock(lock); 147 if (n) { 148 bpf_obj_drop(container_of(n, struct foo, node)); 149 return 7; 150 } 151 152 bpf_spin_lock(lock); 153 n = bpf_list_pop_front(head); 154 bpf_spin_unlock(lock); 155 if (n) { 156 bpf_obj_drop(container_of(n, struct foo, node)); 157 return 8; 158 } 159 return 0; 160 } 161 162 static __always_inline 163 int list_in_list(struct bpf_spin_lock *lock, struct bpf_list_head *head, bool leave_in_map) 164 { 165 struct bpf_list_node *n; 166 struct bar *ba[8], *b; 167 struct foo *f; 168 int i; 169 170 f = bpf_obj_new(typeof(*f)); 171 if (!f) 172 return 2; 173 for (i = 0; i < ARRAY_SIZE(ba); i++) { 174 b = bpf_obj_new(typeof(*b)); 175 if (!b) { 176 bpf_obj_drop(f); 177 return 3; 178 } 179 b->data = i; 180 bpf_spin_lock(&f->lock); 181 bpf_list_push_back(&f->head, &b->node); 182 bpf_spin_unlock(&f->lock); 183 } 184 185 bpf_spin_lock(lock); 186 f->data = 42; 187 bpf_list_push_front(head, &f->node); 188 bpf_spin_unlock(lock); 189 190 if (leave_in_map) 191 return 0; 192 193 bpf_spin_lock(lock); 194 n = bpf_list_pop_front(head); 195 bpf_spin_unlock(lock); 196 if (!n) 197 return 4; 198 f = container_of(n, struct foo, node); 199 if (f->data != 42) { 200 bpf_obj_drop(f); 201 return 5; 202 } 203 204 for (i = 0; i < ARRAY_SIZE(ba); i++) { 205 bpf_spin_lock(&f->lock); 206 n = bpf_list_pop_front(&f->head); 207 bpf_spin_unlock(&f->lock); 208 if (!n) { 209 bpf_obj_drop(f); 210 return 6; 211 } 212 b = container_of(n, struct bar, node); 213 if (b->data != i) { 214 bpf_obj_drop(f); 215 bpf_obj_drop(b); 216 return 7; 217 } 218 bpf_obj_drop(b); 219 } 220 bpf_spin_lock(&f->lock); 221 n = bpf_list_pop_front(&f->head); 222 bpf_spin_unlock(&f->lock); 223 if (n) { 224 bpf_obj_drop(f); 225 bpf_obj_drop(container_of(n, struct bar, node)); 226 return 8; 227 } 228 bpf_obj_drop(f); 229 return 0; 230 } 231 232 static __always_inline 233 int test_list_push_pop(struct bpf_spin_lock *lock, struct bpf_list_head *head) 234 { 235 int ret; 236 237 ret = list_push_pop(lock, head, false); 238 if (ret) 239 return ret; 240 return list_push_pop(lock, head, true); 241 } 242 243 static __always_inline 244 int test_list_push_pop_multiple(struct bpf_spin_lock *lock, struct bpf_list_head *head) 245 { 246 int ret; 247 248 ret = list_push_pop_multiple(lock ,head, false); 249 if (ret) 250 return ret; 251 return list_push_pop_multiple(lock, head, true); 252 } 253 254 static __always_inline 255 int test_list_in_list(struct bpf_spin_lock *lock, struct bpf_list_head *head) 256 { 257 int ret; 258 259 ret = list_in_list(lock, head, false); 260 if (ret) 261 return ret; 262 return list_in_list(lock, head, true); 263 } 264 265 SEC("tc") 266 int map_list_push_pop(void *ctx) 267 { 268 struct map_value *v; 269 270 v = bpf_map_lookup_elem(&array_map, &(int){0}); 271 if (!v) 272 return 1; 273 return test_list_push_pop(&v->lock, &v->head); 274 } 275 276 SEC("tc") 277 int inner_map_list_push_pop(void *ctx) 278 { 279 struct map_value *v; 280 void *map; 281 282 map = bpf_map_lookup_elem(&map_of_maps, &(int){0}); 283 if (!map) 284 return 1; 285 v = bpf_map_lookup_elem(map, &(int){0}); 286 if (!v) 287 return 1; 288 return test_list_push_pop(&v->lock, &v->head); 289 } 290 291 SEC("tc") 292 int global_list_push_pop(void *ctx) 293 { 294 return test_list_push_pop(&glock, &ghead); 295 } 296 297 SEC("tc") 298 int map_list_push_pop_multiple(void *ctx) 299 { 300 struct map_value *v; 301 int ret; 302 303 v = bpf_map_lookup_elem(&array_map, &(int){0}); 304 if (!v) 305 return 1; 306 return test_list_push_pop_multiple(&v->lock, &v->head); 307 } 308 309 SEC("tc") 310 int inner_map_list_push_pop_multiple(void *ctx) 311 { 312 struct map_value *v; 313 void *map; 314 int ret; 315 316 map = bpf_map_lookup_elem(&map_of_maps, &(int){0}); 317 if (!map) 318 return 1; 319 v = bpf_map_lookup_elem(map, &(int){0}); 320 if (!v) 321 return 1; 322 return test_list_push_pop_multiple(&v->lock, &v->head); 323 } 324 325 SEC("tc") 326 int global_list_push_pop_multiple(void *ctx) 327 { 328 int ret; 329 330 ret = list_push_pop_multiple(&glock, &ghead, false); 331 if (ret) 332 return ret; 333 return list_push_pop_multiple(&glock, &ghead, true); 334 } 335 336 SEC("tc") 337 int map_list_in_list(void *ctx) 338 { 339 struct map_value *v; 340 int ret; 341 342 v = bpf_map_lookup_elem(&array_map, &(int){0}); 343 if (!v) 344 return 1; 345 return test_list_in_list(&v->lock, &v->head); 346 } 347 348 SEC("tc") 349 int inner_map_list_in_list(void *ctx) 350 { 351 struct map_value *v; 352 void *map; 353 int ret; 354 355 map = bpf_map_lookup_elem(&map_of_maps, &(int){0}); 356 if (!map) 357 return 1; 358 v = bpf_map_lookup_elem(map, &(int){0}); 359 if (!v) 360 return 1; 361 return test_list_in_list(&v->lock, &v->head); 362 } 363 364 SEC("tc") 365 int global_list_in_list(void *ctx) 366 { 367 return test_list_in_list(&glock, &ghead); 368 } 369 370 char _license[] SEC("license") = "GPL"; 371