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 /* FIXME: 295 * return test_list_push_pop(&glock, &ghead); 296 */ 297 return 0; 298 } 299 300 SEC("tc") 301 int map_list_push_pop_multiple(void *ctx) 302 { 303 struct map_value *v; 304 int ret; 305 306 v = bpf_map_lookup_elem(&array_map, &(int){0}); 307 if (!v) 308 return 1; 309 return test_list_push_pop_multiple(&v->lock, &v->head); 310 } 311 312 SEC("tc") 313 int inner_map_list_push_pop_multiple(void *ctx) 314 { 315 struct map_value *v; 316 void *map; 317 int ret; 318 319 map = bpf_map_lookup_elem(&map_of_maps, &(int){0}); 320 if (!map) 321 return 1; 322 v = bpf_map_lookup_elem(map, &(int){0}); 323 if (!v) 324 return 1; 325 return test_list_push_pop_multiple(&v->lock, &v->head); 326 } 327 328 SEC("tc") 329 int global_list_push_pop_multiple(void *ctx) 330 { 331 int ret; 332 333 /* FIXME: 334 ret = list_push_pop_multiple(&glock, &ghead, false); 335 if (ret) 336 return ret; 337 return list_push_pop_multiple(&glock, &ghead, true); 338 */ 339 return 0; 340 } 341 342 SEC("tc") 343 int map_list_in_list(void *ctx) 344 { 345 struct map_value *v; 346 int ret; 347 348 v = bpf_map_lookup_elem(&array_map, &(int){0}); 349 if (!v) 350 return 1; 351 return test_list_in_list(&v->lock, &v->head); 352 } 353 354 SEC("tc") 355 int inner_map_list_in_list(void *ctx) 356 { 357 struct map_value *v; 358 void *map; 359 int ret; 360 361 map = bpf_map_lookup_elem(&map_of_maps, &(int){0}); 362 if (!map) 363 return 1; 364 v = bpf_map_lookup_elem(map, &(int){0}); 365 if (!v) 366 return 1; 367 return test_list_in_list(&v->lock, &v->head); 368 } 369 370 SEC("tc") 371 int global_list_in_list(void *ctx) 372 { 373 /* FIXME 374 return test_list_in_list(&glock, &ghead); 375 */ 376 return 0; 377 } 378 379 char _license[] SEC("license") = "GPL"; 380