1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Testsuite for eBPF maps 4 * 5 * Copyright (c) 2014 PLUMgrid, http://plumgrid.com 6 * Copyright (c) 2016 Facebook 7 */ 8 9 #include <stdio.h> 10 #include <unistd.h> 11 #include <errno.h> 12 #include <string.h> 13 #include <assert.h> 14 #include <stdlib.h> 15 #include <time.h> 16 17 #include <sys/wait.h> 18 #include <sys/socket.h> 19 #include <netinet/in.h> 20 #include <linux/bpf.h> 21 22 #include <bpf/bpf.h> 23 #include <bpf/libbpf.h> 24 25 #include "bpf_util.h" 26 #include "test_maps.h" 27 #include "testing_helpers.h" 28 29 int skips; 30 31 static struct bpf_map_create_opts map_opts = { .sz = sizeof(map_opts) }; 32 33 static void test_hashmap(unsigned int task, void *data) 34 { 35 long long key, next_key, first_key, value; 36 int fd; 37 38 fd = bpf_map_create(BPF_MAP_TYPE_HASH, NULL, sizeof(key), sizeof(value), 2, &map_opts); 39 if (fd < 0) { 40 printf("Failed to create hashmap '%s'!\n", strerror(errno)); 41 exit(1); 42 } 43 44 key = 1; 45 value = 1234; 46 /* Insert key=1 element. */ 47 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); 48 49 value = 0; 50 /* BPF_NOEXIST means add new element if it doesn't exist. */ 51 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) < 0 && 52 /* key=1 already exists. */ 53 errno == EEXIST); 54 55 /* -1 is an invalid flag. */ 56 assert(bpf_map_update_elem(fd, &key, &value, -1) < 0 && 57 errno == EINVAL); 58 59 /* Check that key=1 can be found. */ 60 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234); 61 62 key = 2; 63 value = 1234; 64 /* Insert key=2 element. */ 65 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); 66 67 /* Check that key=2 matches the value and delete it */ 68 assert(bpf_map_lookup_and_delete_elem(fd, &key, &value) == 0 && value == 1234); 69 70 /* Check that key=2 is not found. */ 71 assert(bpf_map_lookup_elem(fd, &key, &value) < 0 && errno == ENOENT); 72 73 /* BPF_EXIST means update existing element. */ 74 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) < 0 && 75 /* key=2 is not there. */ 76 errno == ENOENT); 77 78 /* Insert key=2 element. */ 79 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0); 80 81 /* key=1 and key=2 were inserted, check that key=0 cannot be 82 * inserted due to max_entries limit. 83 */ 84 key = 0; 85 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) < 0 && 86 errno == E2BIG); 87 88 /* Update existing element, though the map is full. */ 89 key = 1; 90 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0); 91 key = 2; 92 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); 93 key = 3; 94 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) < 0 && 95 errno == E2BIG); 96 97 /* Check that key = 0 doesn't exist. */ 98 key = 0; 99 assert(bpf_map_delete_elem(fd, &key) < 0 && errno == ENOENT); 100 101 /* Iterate over two elements. */ 102 assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 && 103 (first_key == 1 || first_key == 2)); 104 assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 && 105 (next_key == first_key)); 106 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 && 107 (next_key == 1 || next_key == 2) && 108 (next_key != first_key)); 109 assert(bpf_map_get_next_key(fd, &next_key, &next_key) < 0 && 110 errno == ENOENT); 111 112 /* Delete both elements. */ 113 key = 1; 114 assert(bpf_map_delete_elem(fd, &key) == 0); 115 key = 2; 116 assert(bpf_map_delete_elem(fd, &key) == 0); 117 assert(bpf_map_delete_elem(fd, &key) < 0 && errno == ENOENT); 118 119 key = 0; 120 /* Check that map is empty. */ 121 assert(bpf_map_get_next_key(fd, NULL, &next_key) < 0 && 122 errno == ENOENT); 123 assert(bpf_map_get_next_key(fd, &key, &next_key) < 0 && 124 errno == ENOENT); 125 126 close(fd); 127 } 128 129 static void test_hashmap_sizes(unsigned int task, void *data) 130 { 131 int fd, i, j; 132 133 for (i = 1; i <= 512; i <<= 1) 134 for (j = 1; j <= 1 << 18; j <<= 1) { 135 fd = bpf_map_create(BPF_MAP_TYPE_HASH, NULL, i, j, 2, &map_opts); 136 if (fd < 0) { 137 if (errno == ENOMEM) 138 return; 139 printf("Failed to create hashmap key=%d value=%d '%s'\n", 140 i, j, strerror(errno)); 141 exit(1); 142 } 143 close(fd); 144 usleep(10); /* give kernel time to destroy */ 145 } 146 } 147 148 static void test_hashmap_percpu(unsigned int task, void *data) 149 { 150 unsigned int nr_cpus = bpf_num_possible_cpus(); 151 BPF_DECLARE_PERCPU(long, value); 152 long long key, next_key, first_key; 153 int expected_key_mask = 0; 154 int fd, i; 155 156 fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_HASH, NULL, sizeof(key), 157 sizeof(bpf_percpu(value, 0)), 2, &map_opts); 158 if (fd < 0) { 159 printf("Failed to create hashmap '%s'!\n", strerror(errno)); 160 exit(1); 161 } 162 163 for (i = 0; i < nr_cpus; i++) 164 bpf_percpu(value, i) = i + 100; 165 166 key = 1; 167 /* Insert key=1 element. */ 168 assert(!(expected_key_mask & key)); 169 assert(bpf_map_update_elem(fd, &key, value, BPF_ANY) == 0); 170 171 /* Lookup and delete elem key=1 and check value. */ 172 assert(bpf_map_lookup_and_delete_elem(fd, &key, value) == 0 && 173 bpf_percpu(value,0) == 100); 174 175 for (i = 0; i < nr_cpus; i++) 176 bpf_percpu(value,i) = i + 100; 177 178 /* Insert key=1 element which should not exist. */ 179 assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == 0); 180 expected_key_mask |= key; 181 182 /* BPF_NOEXIST means add new element if it doesn't exist. */ 183 assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) < 0 && 184 /* key=1 already exists. */ 185 errno == EEXIST); 186 187 /* -1 is an invalid flag. */ 188 assert(bpf_map_update_elem(fd, &key, value, -1) < 0 && 189 errno == EINVAL); 190 191 /* Check that key=1 can be found. Value could be 0 if the lookup 192 * was run from a different CPU. 193 */ 194 bpf_percpu(value, 0) = 1; 195 assert(bpf_map_lookup_elem(fd, &key, value) == 0 && 196 bpf_percpu(value, 0) == 100); 197 198 key = 2; 199 /* Check that key=2 is not found. */ 200 assert(bpf_map_lookup_elem(fd, &key, value) < 0 && errno == ENOENT); 201 202 /* BPF_EXIST means update existing element. */ 203 assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) < 0 && 204 /* key=2 is not there. */ 205 errno == ENOENT); 206 207 /* Insert key=2 element. */ 208 assert(!(expected_key_mask & key)); 209 assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == 0); 210 expected_key_mask |= key; 211 212 /* key=1 and key=2 were inserted, check that key=0 cannot be 213 * inserted due to max_entries limit. 214 */ 215 key = 0; 216 assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) < 0 && 217 errno == E2BIG); 218 219 /* Check that key = 0 doesn't exist. */ 220 assert(bpf_map_delete_elem(fd, &key) < 0 && errno == ENOENT); 221 222 /* Iterate over two elements. */ 223 assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 && 224 ((expected_key_mask & first_key) == first_key)); 225 while (!bpf_map_get_next_key(fd, &key, &next_key)) { 226 if (first_key) { 227 assert(next_key == first_key); 228 first_key = 0; 229 } 230 assert((expected_key_mask & next_key) == next_key); 231 expected_key_mask &= ~next_key; 232 233 assert(bpf_map_lookup_elem(fd, &next_key, value) == 0); 234 235 for (i = 0; i < nr_cpus; i++) 236 assert(bpf_percpu(value, i) == i + 100); 237 238 key = next_key; 239 } 240 assert(errno == ENOENT); 241 242 /* Update with BPF_EXIST. */ 243 key = 1; 244 assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == 0); 245 246 /* Delete both elements. */ 247 key = 1; 248 assert(bpf_map_delete_elem(fd, &key) == 0); 249 key = 2; 250 assert(bpf_map_delete_elem(fd, &key) == 0); 251 assert(bpf_map_delete_elem(fd, &key) < 0 && errno == ENOENT); 252 253 key = 0; 254 /* Check that map is empty. */ 255 assert(bpf_map_get_next_key(fd, NULL, &next_key) < 0 && 256 errno == ENOENT); 257 assert(bpf_map_get_next_key(fd, &key, &next_key) < 0 && 258 errno == ENOENT); 259 260 close(fd); 261 } 262 263 #define VALUE_SIZE 3 264 static int helper_fill_hashmap(int max_entries) 265 { 266 int i, fd, ret; 267 long long key, value[VALUE_SIZE] = {}; 268 269 fd = bpf_map_create(BPF_MAP_TYPE_HASH, NULL, sizeof(key), sizeof(value), 270 max_entries, &map_opts); 271 CHECK(fd < 0, 272 "failed to create hashmap", 273 "err: %s, flags: 0x%x\n", strerror(errno), map_opts.map_flags); 274 275 for (i = 0; i < max_entries; i++) { 276 key = i; value[0] = key; 277 ret = bpf_map_update_elem(fd, &key, value, BPF_NOEXIST); 278 CHECK(ret != 0, 279 "can't update hashmap", 280 "err: %s\n", strerror(ret)); 281 } 282 283 return fd; 284 } 285 286 static void test_hashmap_walk(unsigned int task, void *data) 287 { 288 int fd, i, max_entries = 10000; 289 long long key, value[VALUE_SIZE], next_key; 290 bool next_key_valid = true; 291 292 fd = helper_fill_hashmap(max_entries); 293 294 for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key, 295 &next_key) == 0; i++) { 296 key = next_key; 297 assert(bpf_map_lookup_elem(fd, &key, value) == 0); 298 } 299 300 assert(i == max_entries); 301 302 assert(bpf_map_get_next_key(fd, NULL, &key) == 0); 303 for (i = 0; next_key_valid; i++) { 304 next_key_valid = bpf_map_get_next_key(fd, &key, &next_key) == 0; 305 assert(bpf_map_lookup_elem(fd, &key, value) == 0); 306 value[0]++; 307 assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == 0); 308 key = next_key; 309 } 310 311 assert(i == max_entries); 312 313 for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key, 314 &next_key) == 0; i++) { 315 key = next_key; 316 assert(bpf_map_lookup_elem(fd, &key, value) == 0); 317 assert(value[0] - 1 == key); 318 } 319 320 assert(i == max_entries); 321 close(fd); 322 } 323 324 static void test_hashmap_zero_seed(void) 325 { 326 int i, first, second, old_flags; 327 long long key, next_first, next_second; 328 329 old_flags = map_opts.map_flags; 330 map_opts.map_flags |= BPF_F_ZERO_SEED; 331 332 first = helper_fill_hashmap(3); 333 second = helper_fill_hashmap(3); 334 335 for (i = 0; ; i++) { 336 void *key_ptr = !i ? NULL : &key; 337 338 if (bpf_map_get_next_key(first, key_ptr, &next_first) != 0) 339 break; 340 341 CHECK(bpf_map_get_next_key(second, key_ptr, &next_second) != 0, 342 "next_key for second map must succeed", 343 "key_ptr: %p", key_ptr); 344 CHECK(next_first != next_second, 345 "keys must match", 346 "i: %d first: %lld second: %lld\n", i, 347 next_first, next_second); 348 349 key = next_first; 350 } 351 352 map_opts.map_flags = old_flags; 353 close(first); 354 close(second); 355 } 356 357 static void test_arraymap(unsigned int task, void *data) 358 { 359 int key, next_key, fd; 360 long long value; 361 362 fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, sizeof(key), sizeof(value), 2, NULL); 363 if (fd < 0) { 364 printf("Failed to create arraymap '%s'!\n", strerror(errno)); 365 exit(1); 366 } 367 368 key = 1; 369 value = 1234; 370 /* Insert key=1 element. */ 371 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); 372 373 value = 0; 374 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) < 0 && 375 errno == EEXIST); 376 377 /* Check that key=1 can be found. */ 378 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234); 379 380 key = 0; 381 /* Check that key=0 is also found and zero initialized. */ 382 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0); 383 384 /* key=0 and key=1 were inserted, check that key=2 cannot be inserted 385 * due to max_entries limit. 386 */ 387 key = 2; 388 assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) < 0 && 389 errno == E2BIG); 390 391 /* Check that key = 2 doesn't exist. */ 392 assert(bpf_map_lookup_elem(fd, &key, &value) < 0 && errno == ENOENT); 393 394 /* Iterate over two elements. */ 395 assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 && 396 next_key == 0); 397 assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 && 398 next_key == 0); 399 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 && 400 next_key == 1); 401 assert(bpf_map_get_next_key(fd, &next_key, &next_key) < 0 && 402 errno == ENOENT); 403 404 /* Delete shouldn't succeed. */ 405 key = 1; 406 assert(bpf_map_delete_elem(fd, &key) < 0 && errno == EINVAL); 407 408 close(fd); 409 } 410 411 static void test_arraymap_percpu(unsigned int task, void *data) 412 { 413 unsigned int nr_cpus = bpf_num_possible_cpus(); 414 BPF_DECLARE_PERCPU(long, values); 415 int key, next_key, fd, i; 416 417 fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, NULL, sizeof(key), 418 sizeof(bpf_percpu(values, 0)), 2, NULL); 419 if (fd < 0) { 420 printf("Failed to create arraymap '%s'!\n", strerror(errno)); 421 exit(1); 422 } 423 424 for (i = 0; i < nr_cpus; i++) 425 bpf_percpu(values, i) = i + 100; 426 427 key = 1; 428 /* Insert key=1 element. */ 429 assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0); 430 431 bpf_percpu(values, 0) = 0; 432 assert(bpf_map_update_elem(fd, &key, values, BPF_NOEXIST) < 0 && 433 errno == EEXIST); 434 435 /* Check that key=1 can be found. */ 436 assert(bpf_map_lookup_elem(fd, &key, values) == 0 && 437 bpf_percpu(values, 0) == 100); 438 439 key = 0; 440 /* Check that key=0 is also found and zero initialized. */ 441 assert(bpf_map_lookup_elem(fd, &key, values) == 0 && 442 bpf_percpu(values, 0) == 0 && 443 bpf_percpu(values, nr_cpus - 1) == 0); 444 445 /* Check that key=2 cannot be inserted due to max_entries limit. */ 446 key = 2; 447 assert(bpf_map_update_elem(fd, &key, values, BPF_EXIST) < 0 && 448 errno == E2BIG); 449 450 /* Check that key = 2 doesn't exist. */ 451 assert(bpf_map_lookup_elem(fd, &key, values) < 0 && errno == ENOENT); 452 453 /* Iterate over two elements. */ 454 assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 && 455 next_key == 0); 456 assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 && 457 next_key == 0); 458 assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 && 459 next_key == 1); 460 assert(bpf_map_get_next_key(fd, &next_key, &next_key) < 0 && 461 errno == ENOENT); 462 463 /* Delete shouldn't succeed. */ 464 key = 1; 465 assert(bpf_map_delete_elem(fd, &key) < 0 && errno == EINVAL); 466 467 close(fd); 468 } 469 470 static void test_arraymap_percpu_many_keys(void) 471 { 472 unsigned int nr_cpus = bpf_num_possible_cpus(); 473 BPF_DECLARE_PERCPU(long, values); 474 /* nr_keys is not too large otherwise the test stresses percpu 475 * allocator more than anything else 476 */ 477 unsigned int nr_keys = 2000; 478 int key, fd, i; 479 480 fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, NULL, sizeof(key), 481 sizeof(bpf_percpu(values, 0)), nr_keys, NULL); 482 if (fd < 0) { 483 printf("Failed to create per-cpu arraymap '%s'!\n", 484 strerror(errno)); 485 exit(1); 486 } 487 488 for (i = 0; i < nr_cpus; i++) 489 bpf_percpu(values, i) = i + 10; 490 491 for (key = 0; key < nr_keys; key++) 492 assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0); 493 494 for (key = 0; key < nr_keys; key++) { 495 for (i = 0; i < nr_cpus; i++) 496 bpf_percpu(values, i) = 0; 497 498 assert(bpf_map_lookup_elem(fd, &key, values) == 0); 499 500 for (i = 0; i < nr_cpus; i++) 501 assert(bpf_percpu(values, i) == i + 10); 502 } 503 504 close(fd); 505 } 506 507 static void test_devmap(unsigned int task, void *data) 508 { 509 int fd; 510 __u32 key, value; 511 512 fd = bpf_map_create(BPF_MAP_TYPE_DEVMAP, NULL, sizeof(key), sizeof(value), 2, NULL); 513 if (fd < 0) { 514 printf("Failed to create devmap '%s'!\n", strerror(errno)); 515 exit(1); 516 } 517 518 close(fd); 519 } 520 521 static void test_devmap_hash(unsigned int task, void *data) 522 { 523 int fd; 524 __u32 key, value; 525 526 fd = bpf_map_create(BPF_MAP_TYPE_DEVMAP_HASH, NULL, sizeof(key), sizeof(value), 2, NULL); 527 if (fd < 0) { 528 printf("Failed to create devmap_hash '%s'!\n", strerror(errno)); 529 exit(1); 530 } 531 532 close(fd); 533 } 534 535 static void test_queuemap(unsigned int task, void *data) 536 { 537 const int MAP_SIZE = 32; 538 __u32 vals[MAP_SIZE + MAP_SIZE/2], val; 539 int fd, i; 540 541 /* Fill test values to be used */ 542 for (i = 0; i < MAP_SIZE + MAP_SIZE/2; i++) 543 vals[i] = rand(); 544 545 /* Invalid key size */ 546 fd = bpf_map_create(BPF_MAP_TYPE_QUEUE, NULL, 4, sizeof(val), MAP_SIZE, &map_opts); 547 assert(fd < 0 && errno == EINVAL); 548 549 fd = bpf_map_create(BPF_MAP_TYPE_QUEUE, NULL, 0, sizeof(val), MAP_SIZE, &map_opts); 550 /* Queue map does not support BPF_F_NO_PREALLOC */ 551 if (map_opts.map_flags & BPF_F_NO_PREALLOC) { 552 assert(fd < 0 && errno == EINVAL); 553 return; 554 } 555 if (fd < 0) { 556 printf("Failed to create queuemap '%s'!\n", strerror(errno)); 557 exit(1); 558 } 559 560 /* Push MAP_SIZE elements */ 561 for (i = 0; i < MAP_SIZE; i++) 562 assert(bpf_map_update_elem(fd, NULL, &vals[i], 0) == 0); 563 564 /* Check that element cannot be pushed due to max_entries limit */ 565 assert(bpf_map_update_elem(fd, NULL, &val, 0) < 0 && 566 errno == E2BIG); 567 568 /* Peek element */ 569 assert(bpf_map_lookup_elem(fd, NULL, &val) == 0 && val == vals[0]); 570 571 /* Replace half elements */ 572 for (i = MAP_SIZE; i < MAP_SIZE + MAP_SIZE/2; i++) 573 assert(bpf_map_update_elem(fd, NULL, &vals[i], BPF_EXIST) == 0); 574 575 /* Pop all elements */ 576 for (i = MAP_SIZE/2; i < MAP_SIZE + MAP_SIZE/2; i++) 577 assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == 0 && 578 val == vals[i]); 579 580 /* Check that there are not elements left */ 581 assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) < 0 && 582 errno == ENOENT); 583 584 /* Check that non supported functions set errno to EINVAL */ 585 assert(bpf_map_delete_elem(fd, NULL) < 0 && errno == EINVAL); 586 assert(bpf_map_get_next_key(fd, NULL, NULL) < 0 && errno == EINVAL); 587 588 close(fd); 589 } 590 591 static void test_stackmap(unsigned int task, void *data) 592 { 593 const int MAP_SIZE = 32; 594 __u32 vals[MAP_SIZE + MAP_SIZE/2], val; 595 int fd, i; 596 597 /* Fill test values to be used */ 598 for (i = 0; i < MAP_SIZE + MAP_SIZE/2; i++) 599 vals[i] = rand(); 600 601 /* Invalid key size */ 602 fd = bpf_map_create(BPF_MAP_TYPE_STACK, NULL, 4, sizeof(val), MAP_SIZE, &map_opts); 603 assert(fd < 0 && errno == EINVAL); 604 605 fd = bpf_map_create(BPF_MAP_TYPE_STACK, NULL, 0, sizeof(val), MAP_SIZE, &map_opts); 606 /* Stack map does not support BPF_F_NO_PREALLOC */ 607 if (map_opts.map_flags & BPF_F_NO_PREALLOC) { 608 assert(fd < 0 && errno == EINVAL); 609 return; 610 } 611 if (fd < 0) { 612 printf("Failed to create stackmap '%s'!\n", strerror(errno)); 613 exit(1); 614 } 615 616 /* Push MAP_SIZE elements */ 617 for (i = 0; i < MAP_SIZE; i++) 618 assert(bpf_map_update_elem(fd, NULL, &vals[i], 0) == 0); 619 620 /* Check that element cannot be pushed due to max_entries limit */ 621 assert(bpf_map_update_elem(fd, NULL, &val, 0) < 0 && 622 errno == E2BIG); 623 624 /* Peek element */ 625 assert(bpf_map_lookup_elem(fd, NULL, &val) == 0 && val == vals[i - 1]); 626 627 /* Replace half elements */ 628 for (i = MAP_SIZE; i < MAP_SIZE + MAP_SIZE/2; i++) 629 assert(bpf_map_update_elem(fd, NULL, &vals[i], BPF_EXIST) == 0); 630 631 /* Pop all elements */ 632 for (i = MAP_SIZE + MAP_SIZE/2 - 1; i >= MAP_SIZE/2; i--) 633 assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) == 0 && 634 val == vals[i]); 635 636 /* Check that there are not elements left */ 637 assert(bpf_map_lookup_and_delete_elem(fd, NULL, &val) < 0 && 638 errno == ENOENT); 639 640 /* Check that non supported functions set errno to EINVAL */ 641 assert(bpf_map_delete_elem(fd, NULL) < 0 && errno == EINVAL); 642 assert(bpf_map_get_next_key(fd, NULL, NULL) < 0 && errno == EINVAL); 643 644 close(fd); 645 } 646 647 #include <sys/ioctl.h> 648 #include <arpa/inet.h> 649 #include <sys/select.h> 650 #include <linux/err.h> 651 #define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.bpf.o" 652 #define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.bpf.o" 653 #define SOCKMAP_TCP_MSG_PROG "./sockmap_tcp_msg_prog.bpf.o" 654 static void test_sockmap(unsigned int tasks, void *data) 655 { 656 struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_msg, *bpf_map_break; 657 int map_fd_msg = 0, map_fd_rx = 0, map_fd_tx = 0, map_fd_break; 658 struct bpf_object *parse_obj, *verdict_obj, *msg_obj; 659 int ports[] = {50200, 50201, 50202, 50204}; 660 int err, i, fd, udp, sfd[6] = {0xdeadbeef}; 661 u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0}; 662 int parse_prog, verdict_prog, msg_prog; 663 struct sockaddr_in addr; 664 int one = 1, s, sc, rc; 665 struct timeval to; 666 __u32 key, value; 667 pid_t pid[tasks]; 668 fd_set w; 669 670 /* Create some sockets to use with sockmap */ 671 for (i = 0; i < 2; i++) { 672 sfd[i] = socket(AF_INET, SOCK_STREAM, 0); 673 if (sfd[i] < 0) 674 goto out; 675 err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR, 676 (char *)&one, sizeof(one)); 677 if (err) { 678 printf("failed to setsockopt\n"); 679 goto out; 680 } 681 err = ioctl(sfd[i], FIONBIO, (char *)&one); 682 if (err < 0) { 683 printf("failed to ioctl\n"); 684 goto out; 685 } 686 memset(&addr, 0, sizeof(struct sockaddr_in)); 687 addr.sin_family = AF_INET; 688 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 689 addr.sin_port = htons(ports[i]); 690 err = bind(sfd[i], (struct sockaddr *)&addr, sizeof(addr)); 691 if (err < 0) { 692 printf("failed to bind: err %i: %i:%i\n", 693 err, i, sfd[i]); 694 goto out; 695 } 696 err = listen(sfd[i], 32); 697 if (err < 0) { 698 printf("failed to listen\n"); 699 goto out; 700 } 701 } 702 703 for (i = 2; i < 4; i++) { 704 sfd[i] = socket(AF_INET, SOCK_STREAM, 0); 705 if (sfd[i] < 0) 706 goto out; 707 err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR, 708 (char *)&one, sizeof(one)); 709 if (err) { 710 printf("set sock opt\n"); 711 goto out; 712 } 713 memset(&addr, 0, sizeof(struct sockaddr_in)); 714 addr.sin_family = AF_INET; 715 addr.sin_addr.s_addr = inet_addr("127.0.0.1"); 716 addr.sin_port = htons(ports[i - 2]); 717 err = connect(sfd[i], (struct sockaddr *)&addr, sizeof(addr)); 718 if (err) { 719 printf("failed to connect\n"); 720 goto out; 721 } 722 } 723 724 725 for (i = 4; i < 6; i++) { 726 sfd[i] = accept(sfd[i - 4], NULL, NULL); 727 if (sfd[i] < 0) { 728 printf("accept failed\n"); 729 goto out; 730 } 731 } 732 733 /* Test sockmap with connected sockets */ 734 fd = bpf_map_create(BPF_MAP_TYPE_SOCKMAP, NULL, 735 sizeof(key), sizeof(value), 736 6, NULL); 737 if (fd < 0) { 738 if (!libbpf_probe_bpf_map_type(BPF_MAP_TYPE_SOCKMAP, NULL)) { 739 printf("%s SKIP (unsupported map type BPF_MAP_TYPE_SOCKMAP)\n", 740 __func__); 741 skips++; 742 for (i = 0; i < 6; i++) 743 close(sfd[i]); 744 return; 745 } 746 747 printf("Failed to create sockmap %i\n", fd); 748 goto out_sockmap; 749 } 750 751 /* Test update with unsupported UDP socket */ 752 udp = socket(AF_INET, SOCK_DGRAM, 0); 753 i = 0; 754 err = bpf_map_update_elem(fd, &i, &udp, BPF_ANY); 755 if (err) { 756 printf("Failed socket update SOCK_DGRAM '%i:%i'\n", 757 i, udp); 758 goto out_sockmap; 759 } 760 close(udp); 761 762 /* Test update without programs */ 763 for (i = 0; i < 6; i++) { 764 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 765 if (err) { 766 printf("Failed noprog update sockmap '%i:%i'\n", 767 i, sfd[i]); 768 goto out_sockmap; 769 } 770 } 771 772 /* Test attaching/detaching bad fds */ 773 err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_PARSER, 0); 774 if (!err) { 775 printf("Failed invalid parser prog attach\n"); 776 goto out_sockmap; 777 } 778 779 err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_VERDICT, 0); 780 if (!err) { 781 printf("Failed invalid verdict prog attach\n"); 782 goto out_sockmap; 783 } 784 785 err = bpf_prog_attach(-1, fd, BPF_SK_MSG_VERDICT, 0); 786 if (!err) { 787 printf("Failed invalid msg verdict prog attach\n"); 788 goto out_sockmap; 789 } 790 791 err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0); 792 if (!err) { 793 printf("Failed unknown prog attach\n"); 794 goto out_sockmap; 795 } 796 797 err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER); 798 if (!err) { 799 printf("Failed empty parser prog detach\n"); 800 goto out_sockmap; 801 } 802 803 err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT); 804 if (!err) { 805 printf("Failed empty verdict prog detach\n"); 806 goto out_sockmap; 807 } 808 809 err = bpf_prog_detach(fd, BPF_SK_MSG_VERDICT); 810 if (!err) { 811 printf("Failed empty msg verdict prog detach\n"); 812 goto out_sockmap; 813 } 814 815 err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE); 816 if (!err) { 817 printf("Detach invalid prog successful\n"); 818 goto out_sockmap; 819 } 820 821 /* Load SK_SKB program and Attach */ 822 err = bpf_prog_test_load(SOCKMAP_PARSE_PROG, 823 BPF_PROG_TYPE_SK_SKB, &parse_obj, &parse_prog); 824 if (err) { 825 printf("Failed to load SK_SKB parse prog\n"); 826 goto out_sockmap; 827 } 828 829 err = bpf_prog_test_load(SOCKMAP_TCP_MSG_PROG, 830 BPF_PROG_TYPE_SK_MSG, &msg_obj, &msg_prog); 831 if (err) { 832 printf("Failed to load SK_SKB msg prog\n"); 833 goto out_sockmap; 834 } 835 836 err = bpf_prog_test_load(SOCKMAP_VERDICT_PROG, 837 BPF_PROG_TYPE_SK_SKB, &verdict_obj, &verdict_prog); 838 if (err) { 839 printf("Failed to load SK_SKB verdict prog\n"); 840 goto out_sockmap; 841 } 842 843 bpf_map_rx = bpf_object__find_map_by_name(verdict_obj, "sock_map_rx"); 844 if (!bpf_map_rx) { 845 printf("Failed to load map rx from verdict prog\n"); 846 goto out_sockmap; 847 } 848 849 map_fd_rx = bpf_map__fd(bpf_map_rx); 850 if (map_fd_rx < 0) { 851 printf("Failed to get map rx fd\n"); 852 goto out_sockmap; 853 } 854 855 bpf_map_tx = bpf_object__find_map_by_name(verdict_obj, "sock_map_tx"); 856 if (!bpf_map_tx) { 857 printf("Failed to load map tx from verdict prog\n"); 858 goto out_sockmap; 859 } 860 861 map_fd_tx = bpf_map__fd(bpf_map_tx); 862 if (map_fd_tx < 0) { 863 printf("Failed to get map tx fd\n"); 864 goto out_sockmap; 865 } 866 867 bpf_map_msg = bpf_object__find_map_by_name(verdict_obj, "sock_map_msg"); 868 if (!bpf_map_msg) { 869 printf("Failed to load map msg from msg_verdict prog\n"); 870 goto out_sockmap; 871 } 872 873 map_fd_msg = bpf_map__fd(bpf_map_msg); 874 if (map_fd_msg < 0) { 875 printf("Failed to get map msg fd\n"); 876 goto out_sockmap; 877 } 878 879 bpf_map_break = bpf_object__find_map_by_name(verdict_obj, "sock_map_break"); 880 if (!bpf_map_break) { 881 printf("Failed to load map tx from verdict prog\n"); 882 goto out_sockmap; 883 } 884 885 map_fd_break = bpf_map__fd(bpf_map_break); 886 if (map_fd_break < 0) { 887 printf("Failed to get map tx fd\n"); 888 goto out_sockmap; 889 } 890 891 err = bpf_prog_attach(parse_prog, map_fd_break, 892 BPF_SK_SKB_STREAM_PARSER, 0); 893 if (!err) { 894 printf("Allowed attaching SK_SKB program to invalid map\n"); 895 goto out_sockmap; 896 } 897 898 err = bpf_prog_attach(parse_prog, map_fd_rx, 899 BPF_SK_SKB_STREAM_PARSER, 0); 900 if (err) { 901 printf("Failed stream parser bpf prog attach\n"); 902 goto out_sockmap; 903 } 904 905 err = bpf_prog_attach(verdict_prog, map_fd_rx, 906 BPF_SK_SKB_STREAM_VERDICT, 0); 907 if (err) { 908 printf("Failed stream verdict bpf prog attach\n"); 909 goto out_sockmap; 910 } 911 912 err = bpf_prog_attach(msg_prog, map_fd_msg, BPF_SK_MSG_VERDICT, 0); 913 if (err) { 914 printf("Failed msg verdict bpf prog attach\n"); 915 goto out_sockmap; 916 } 917 918 err = bpf_prog_attach(verdict_prog, map_fd_rx, 919 __MAX_BPF_ATTACH_TYPE, 0); 920 if (!err) { 921 printf("Attached unknown bpf prog\n"); 922 goto out_sockmap; 923 } 924 925 /* Test map update elem afterwards fd lives in fd and map_fd */ 926 for (i = 2; i < 6; i++) { 927 err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY); 928 if (err) { 929 printf("Failed map_fd_rx update sockmap %i '%i:%i'\n", 930 err, i, sfd[i]); 931 goto out_sockmap; 932 } 933 err = bpf_map_update_elem(map_fd_tx, &i, &sfd[i], BPF_ANY); 934 if (err) { 935 printf("Failed map_fd_tx update sockmap %i '%i:%i'\n", 936 err, i, sfd[i]); 937 goto out_sockmap; 938 } 939 } 940 941 /* Test map delete elem and remove send/recv sockets */ 942 for (i = 2; i < 4; i++) { 943 err = bpf_map_delete_elem(map_fd_rx, &i); 944 if (err) { 945 printf("Failed delete sockmap rx %i '%i:%i'\n", 946 err, i, sfd[i]); 947 goto out_sockmap; 948 } 949 err = bpf_map_delete_elem(map_fd_tx, &i); 950 if (err) { 951 printf("Failed delete sockmap tx %i '%i:%i'\n", 952 err, i, sfd[i]); 953 goto out_sockmap; 954 } 955 } 956 957 /* Put sfd[2] (sending fd below) into msg map to test sendmsg bpf */ 958 i = 0; 959 err = bpf_map_update_elem(map_fd_msg, &i, &sfd[2], BPF_ANY); 960 if (err) { 961 printf("Failed map_fd_msg update sockmap %i\n", err); 962 goto out_sockmap; 963 } 964 965 /* Test map send/recv */ 966 for (i = 0; i < 2; i++) { 967 buf[0] = i; 968 buf[1] = 0x5; 969 sc = send(sfd[2], buf, 20, 0); 970 if (sc < 0) { 971 printf("Failed sockmap send\n"); 972 goto out_sockmap; 973 } 974 975 FD_ZERO(&w); 976 FD_SET(sfd[3], &w); 977 to.tv_sec = 30; 978 to.tv_usec = 0; 979 s = select(sfd[3] + 1, &w, NULL, NULL, &to); 980 if (s == -1) { 981 perror("Failed sockmap select()"); 982 goto out_sockmap; 983 } else if (!s) { 984 printf("Failed sockmap unexpected timeout\n"); 985 goto out_sockmap; 986 } 987 988 if (!FD_ISSET(sfd[3], &w)) { 989 printf("Failed sockmap select/recv\n"); 990 goto out_sockmap; 991 } 992 993 rc = recv(sfd[3], buf, sizeof(buf), 0); 994 if (rc < 0) { 995 printf("Failed sockmap recv\n"); 996 goto out_sockmap; 997 } 998 } 999 1000 /* Negative null entry lookup from datapath should be dropped */ 1001 buf[0] = 1; 1002 buf[1] = 12; 1003 sc = send(sfd[2], buf, 20, 0); 1004 if (sc < 0) { 1005 printf("Failed sockmap send\n"); 1006 goto out_sockmap; 1007 } 1008 1009 /* Push fd into same slot */ 1010 i = 2; 1011 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST); 1012 if (!err) { 1013 printf("Failed allowed sockmap dup slot BPF_NOEXIST\n"); 1014 goto out_sockmap; 1015 } 1016 1017 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 1018 if (err) { 1019 printf("Failed sockmap update new slot BPF_ANY\n"); 1020 goto out_sockmap; 1021 } 1022 1023 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST); 1024 if (err) { 1025 printf("Failed sockmap update new slot BPF_EXIST\n"); 1026 goto out_sockmap; 1027 } 1028 1029 /* Delete the elems without programs */ 1030 for (i = 2; i < 6; i++) { 1031 err = bpf_map_delete_elem(fd, &i); 1032 if (err) { 1033 printf("Failed delete sockmap %i '%i:%i'\n", 1034 err, i, sfd[i]); 1035 } 1036 } 1037 1038 /* Test having multiple maps open and set with programs on same fds */ 1039 err = bpf_prog_attach(parse_prog, fd, 1040 BPF_SK_SKB_STREAM_PARSER, 0); 1041 if (err) { 1042 printf("Failed fd bpf parse prog attach\n"); 1043 goto out_sockmap; 1044 } 1045 err = bpf_prog_attach(verdict_prog, fd, 1046 BPF_SK_SKB_STREAM_VERDICT, 0); 1047 if (err) { 1048 printf("Failed fd bpf verdict prog attach\n"); 1049 goto out_sockmap; 1050 } 1051 1052 for (i = 4; i < 6; i++) { 1053 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY); 1054 if (!err) { 1055 printf("Failed allowed duplicate programs in update ANY sockmap %i '%i:%i'\n", 1056 err, i, sfd[i]); 1057 goto out_sockmap; 1058 } 1059 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST); 1060 if (!err) { 1061 printf("Failed allowed duplicate program in update NOEXIST sockmap %i '%i:%i'\n", 1062 err, i, sfd[i]); 1063 goto out_sockmap; 1064 } 1065 err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST); 1066 if (!err) { 1067 printf("Failed allowed duplicate program in update EXIST sockmap %i '%i:%i'\n", 1068 err, i, sfd[i]); 1069 goto out_sockmap; 1070 } 1071 } 1072 1073 /* Test tasks number of forked operations */ 1074 for (i = 0; i < tasks; i++) { 1075 pid[i] = fork(); 1076 if (pid[i] == 0) { 1077 for (i = 0; i < 6; i++) { 1078 bpf_map_delete_elem(map_fd_tx, &i); 1079 bpf_map_delete_elem(map_fd_rx, &i); 1080 bpf_map_update_elem(map_fd_tx, &i, 1081 &sfd[i], BPF_ANY); 1082 bpf_map_update_elem(map_fd_rx, &i, 1083 &sfd[i], BPF_ANY); 1084 } 1085 exit(0); 1086 } else if (pid[i] == -1) { 1087 printf("Couldn't spawn #%d process!\n", i); 1088 exit(1); 1089 } 1090 } 1091 1092 for (i = 0; i < tasks; i++) { 1093 int status; 1094 1095 assert(waitpid(pid[i], &status, 0) == pid[i]); 1096 assert(status == 0); 1097 } 1098 1099 err = bpf_prog_detach2(parse_prog, map_fd_rx, __MAX_BPF_ATTACH_TYPE); 1100 if (!err) { 1101 printf("Detached an invalid prog type.\n"); 1102 goto out_sockmap; 1103 } 1104 1105 err = bpf_prog_detach2(parse_prog, map_fd_rx, BPF_SK_SKB_STREAM_PARSER); 1106 if (err) { 1107 printf("Failed parser prog detach\n"); 1108 goto out_sockmap; 1109 } 1110 1111 err = bpf_prog_detach2(verdict_prog, map_fd_rx, BPF_SK_SKB_STREAM_VERDICT); 1112 if (err) { 1113 printf("Failed parser prog detach\n"); 1114 goto out_sockmap; 1115 } 1116 1117 /* Test map close sockets and empty maps */ 1118 for (i = 0; i < 6; i++) { 1119 bpf_map_delete_elem(map_fd_tx, &i); 1120 bpf_map_delete_elem(map_fd_rx, &i); 1121 close(sfd[i]); 1122 } 1123 close(fd); 1124 close(map_fd_rx); 1125 bpf_object__close(parse_obj); 1126 bpf_object__close(msg_obj); 1127 bpf_object__close(verdict_obj); 1128 return; 1129 out: 1130 for (i = 0; i < 6; i++) 1131 close(sfd[i]); 1132 printf("Failed to create sockmap '%i:%s'!\n", i, strerror(errno)); 1133 exit(1); 1134 out_sockmap: 1135 for (i = 0; i < 6; i++) { 1136 if (map_fd_tx) 1137 bpf_map_delete_elem(map_fd_tx, &i); 1138 if (map_fd_rx) 1139 bpf_map_delete_elem(map_fd_rx, &i); 1140 close(sfd[i]); 1141 } 1142 close(fd); 1143 exit(1); 1144 } 1145 1146 #define MAPINMAP_PROG "./test_map_in_map.bpf.o" 1147 #define MAPINMAP_INVALID_PROG "./test_map_in_map_invalid.bpf.o" 1148 static void test_map_in_map(void) 1149 { 1150 struct bpf_object *obj; 1151 struct bpf_map *map; 1152 int mim_fd, fd, err; 1153 int pos = 0; 1154 struct bpf_map_info info = {}; 1155 __u32 len = sizeof(info); 1156 __u32 id = 0; 1157 libbpf_print_fn_t old_print_fn; 1158 1159 obj = bpf_object__open(MAPINMAP_PROG); 1160 1161 fd = bpf_map_create(BPF_MAP_TYPE_HASH, NULL, sizeof(int), sizeof(int), 2, NULL); 1162 if (fd < 0) { 1163 printf("Failed to create hashmap '%s'!\n", strerror(errno)); 1164 exit(1); 1165 } 1166 1167 map = bpf_object__find_map_by_name(obj, "mim_array"); 1168 if (!map) { 1169 printf("Failed to load array of maps from test prog\n"); 1170 goto out_map_in_map; 1171 } 1172 err = bpf_map__set_inner_map_fd(map, fd); 1173 if (err) { 1174 printf("Failed to set inner_map_fd for array of maps\n"); 1175 goto out_map_in_map; 1176 } 1177 1178 map = bpf_object__find_map_by_name(obj, "mim_hash"); 1179 if (!map) { 1180 printf("Failed to load hash of maps from test prog\n"); 1181 goto out_map_in_map; 1182 } 1183 err = bpf_map__set_inner_map_fd(map, fd); 1184 if (err) { 1185 printf("Failed to set inner_map_fd for hash of maps\n"); 1186 goto out_map_in_map; 1187 } 1188 1189 err = bpf_object__load(obj); 1190 if (err) { 1191 printf("Failed to load test prog\n"); 1192 goto out_map_in_map; 1193 } 1194 1195 map = bpf_object__find_map_by_name(obj, "mim_array"); 1196 if (!map) { 1197 printf("Failed to load array of maps from test prog\n"); 1198 goto out_map_in_map; 1199 } 1200 mim_fd = bpf_map__fd(map); 1201 if (mim_fd < 0) { 1202 printf("Failed to get descriptor for array of maps\n"); 1203 goto out_map_in_map; 1204 } 1205 1206 err = bpf_map_update_elem(mim_fd, &pos, &fd, 0); 1207 if (err) { 1208 printf("Failed to update array of maps\n"); 1209 goto out_map_in_map; 1210 } 1211 1212 map = bpf_object__find_map_by_name(obj, "mim_hash"); 1213 if (!map) { 1214 printf("Failed to load hash of maps from test prog\n"); 1215 goto out_map_in_map; 1216 } 1217 mim_fd = bpf_map__fd(map); 1218 if (mim_fd < 0) { 1219 printf("Failed to get descriptor for hash of maps\n"); 1220 goto out_map_in_map; 1221 } 1222 1223 err = bpf_map_update_elem(mim_fd, &pos, &fd, 0); 1224 if (err) { 1225 printf("Failed to update hash of maps\n"); 1226 goto out_map_in_map; 1227 } 1228 1229 close(fd); 1230 fd = -1; 1231 bpf_object__close(obj); 1232 1233 /* Test that failing bpf_object__create_map() destroys the inner map */ 1234 obj = bpf_object__open(MAPINMAP_INVALID_PROG); 1235 err = libbpf_get_error(obj); 1236 if (err) { 1237 printf("Failed to load %s program: %d %d", 1238 MAPINMAP_INVALID_PROG, err, errno); 1239 goto out_map_in_map; 1240 } 1241 1242 map = bpf_object__find_map_by_name(obj, "mim"); 1243 if (!map) { 1244 printf("Failed to load array of maps from test prog\n"); 1245 goto out_map_in_map; 1246 } 1247 1248 old_print_fn = libbpf_set_print(NULL); 1249 1250 err = bpf_object__load(obj); 1251 if (!err) { 1252 printf("Loading obj supposed to fail\n"); 1253 goto out_map_in_map; 1254 } 1255 1256 libbpf_set_print(old_print_fn); 1257 1258 /* Iterate over all maps to check whether the internal map 1259 * ("mim.internal") has been destroyed. 1260 */ 1261 while (true) { 1262 err = bpf_map_get_next_id(id, &id); 1263 if (err) { 1264 if (errno == ENOENT) 1265 break; 1266 printf("Failed to get next map: %d", errno); 1267 goto out_map_in_map; 1268 } 1269 1270 fd = bpf_map_get_fd_by_id(id); 1271 if (fd < 0) { 1272 if (errno == ENOENT) 1273 continue; 1274 printf("Failed to get map by id %u: %d", id, errno); 1275 goto out_map_in_map; 1276 } 1277 1278 err = bpf_map_get_info_by_fd(fd, &info, &len); 1279 if (err) { 1280 printf("Failed to get map info by fd %d: %d", fd, 1281 errno); 1282 goto out_map_in_map; 1283 } 1284 1285 if (!strcmp(info.name, "mim.inner")) { 1286 printf("Inner map mim.inner was not destroyed\n"); 1287 goto out_map_in_map; 1288 } 1289 1290 close(fd); 1291 } 1292 1293 bpf_object__close(obj); 1294 return; 1295 1296 out_map_in_map: 1297 if (fd >= 0) 1298 close(fd); 1299 exit(1); 1300 } 1301 1302 #define MAP_SIZE (32 * 1024) 1303 1304 static void test_map_large(void) 1305 { 1306 1307 struct bigkey { 1308 int a; 1309 char b[4096]; 1310 long long c; 1311 } key; 1312 int fd, i, value; 1313 1314 fd = bpf_map_create(BPF_MAP_TYPE_HASH, NULL, sizeof(key), sizeof(value), 1315 MAP_SIZE, &map_opts); 1316 if (fd < 0) { 1317 printf("Failed to create large map '%s'!\n", strerror(errno)); 1318 exit(1); 1319 } 1320 1321 for (i = 0; i < MAP_SIZE; i++) { 1322 key = (struct bigkey) { .c = i }; 1323 value = i; 1324 1325 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0); 1326 } 1327 1328 key.c = -1; 1329 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) < 0 && 1330 errno == E2BIG); 1331 1332 /* Iterate through all elements. */ 1333 assert(bpf_map_get_next_key(fd, NULL, &key) == 0); 1334 key.c = -1; 1335 for (i = 0; i < MAP_SIZE; i++) 1336 assert(bpf_map_get_next_key(fd, &key, &key) == 0); 1337 assert(bpf_map_get_next_key(fd, &key, &key) < 0 && errno == ENOENT); 1338 1339 key.c = 0; 1340 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0); 1341 key.a = 1; 1342 assert(bpf_map_lookup_elem(fd, &key, &value) < 0 && errno == ENOENT); 1343 1344 close(fd); 1345 } 1346 1347 #define run_parallel(N, FN, DATA) \ 1348 printf("Fork %u tasks to '" #FN "'\n", N); \ 1349 __run_parallel(N, FN, DATA) 1350 1351 static void __run_parallel(unsigned int tasks, 1352 void (*fn)(unsigned int task, void *data), 1353 void *data) 1354 { 1355 pid_t pid[tasks]; 1356 int i; 1357 1358 fflush(stdout); 1359 1360 for (i = 0; i < tasks; i++) { 1361 pid[i] = fork(); 1362 if (pid[i] == 0) { 1363 fn(i, data); 1364 exit(0); 1365 } else if (pid[i] == -1) { 1366 printf("Couldn't spawn #%d process!\n", i); 1367 exit(1); 1368 } 1369 } 1370 1371 for (i = 0; i < tasks; i++) { 1372 int status; 1373 1374 assert(waitpid(pid[i], &status, 0) == pid[i]); 1375 assert(status == 0); 1376 } 1377 } 1378 1379 static void test_map_stress(void) 1380 { 1381 run_parallel(100, test_hashmap_walk, NULL); 1382 run_parallel(100, test_hashmap, NULL); 1383 run_parallel(100, test_hashmap_percpu, NULL); 1384 run_parallel(100, test_hashmap_sizes, NULL); 1385 1386 run_parallel(100, test_arraymap, NULL); 1387 run_parallel(100, test_arraymap_percpu, NULL); 1388 } 1389 1390 #define TASKS 100 1391 1392 #define DO_UPDATE 1 1393 #define DO_DELETE 0 1394 1395 #define MAP_RETRIES 20 1396 #define MAX_DELAY_US 50000 1397 #define MIN_DELAY_RANGE_US 5000 1398 1399 static bool retry_for_again_or_busy(int err) 1400 { 1401 return (err == EAGAIN || err == EBUSY); 1402 } 1403 1404 int map_update_retriable(int map_fd, const void *key, const void *value, int flags, int attempts, 1405 retry_for_error_fn need_retry) 1406 { 1407 int delay = rand() % MIN_DELAY_RANGE_US; 1408 1409 while (bpf_map_update_elem(map_fd, key, value, flags)) { 1410 if (!attempts || !need_retry(errno)) 1411 return -errno; 1412 1413 if (delay <= MAX_DELAY_US / 2) 1414 delay *= 2; 1415 1416 usleep(delay); 1417 attempts--; 1418 } 1419 1420 return 0; 1421 } 1422 1423 static int map_delete_retriable(int map_fd, const void *key, int attempts) 1424 { 1425 int delay = rand() % MIN_DELAY_RANGE_US; 1426 1427 while (bpf_map_delete_elem(map_fd, key)) { 1428 if (!attempts || (errno != EAGAIN && errno != EBUSY)) 1429 return -errno; 1430 1431 if (delay <= MAX_DELAY_US / 2) 1432 delay *= 2; 1433 1434 usleep(delay); 1435 attempts--; 1436 } 1437 1438 return 0; 1439 } 1440 1441 static void test_update_delete(unsigned int fn, void *data) 1442 { 1443 int do_update = ((int *)data)[1]; 1444 int fd = ((int *)data)[0]; 1445 int i, key, value, err; 1446 1447 if (fn & 1) 1448 test_hashmap_walk(fn, NULL); 1449 for (i = fn; i < MAP_SIZE; i += TASKS) { 1450 key = value = i; 1451 1452 if (do_update) { 1453 err = map_update_retriable(fd, &key, &value, BPF_NOEXIST, MAP_RETRIES, 1454 retry_for_again_or_busy); 1455 if (err) 1456 printf("error %d %d\n", err, errno); 1457 assert(err == 0); 1458 err = map_update_retriable(fd, &key, &value, BPF_EXIST, MAP_RETRIES, 1459 retry_for_again_or_busy); 1460 if (err) 1461 printf("error %d %d\n", err, errno); 1462 assert(err == 0); 1463 } else { 1464 err = map_delete_retriable(fd, &key, MAP_RETRIES); 1465 if (err) 1466 printf("error %d %d\n", err, errno); 1467 assert(err == 0); 1468 } 1469 } 1470 } 1471 1472 static void test_map_parallel(void) 1473 { 1474 int i, fd, key = 0, value = 0, j = 0; 1475 int data[2]; 1476 1477 fd = bpf_map_create(BPF_MAP_TYPE_HASH, NULL, sizeof(key), sizeof(value), 1478 MAP_SIZE, &map_opts); 1479 if (fd < 0) { 1480 printf("Failed to create map for parallel test '%s'!\n", 1481 strerror(errno)); 1482 exit(1); 1483 } 1484 1485 again: 1486 /* Use the same fd in children to add elements to this map: 1487 * child_0 adds key=0, key=1024, key=2048, ... 1488 * child_1 adds key=1, key=1025, key=2049, ... 1489 * child_1023 adds key=1023, ... 1490 */ 1491 data[0] = fd; 1492 data[1] = DO_UPDATE; 1493 run_parallel(TASKS, test_update_delete, data); 1494 1495 /* Check that key=0 is already there. */ 1496 assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) < 0 && 1497 errno == EEXIST); 1498 1499 /* Check that all elements were inserted. */ 1500 assert(bpf_map_get_next_key(fd, NULL, &key) == 0); 1501 key = -1; 1502 for (i = 0; i < MAP_SIZE; i++) 1503 assert(bpf_map_get_next_key(fd, &key, &key) == 0); 1504 assert(bpf_map_get_next_key(fd, &key, &key) < 0 && errno == ENOENT); 1505 1506 /* Another check for all elements */ 1507 for (i = 0; i < MAP_SIZE; i++) { 1508 key = MAP_SIZE - i - 1; 1509 1510 assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && 1511 value == key); 1512 } 1513 1514 /* Now let's delete all elements in parallel. */ 1515 data[1] = DO_DELETE; 1516 run_parallel(TASKS, test_update_delete, data); 1517 1518 /* Nothing should be left. */ 1519 key = -1; 1520 assert(bpf_map_get_next_key(fd, NULL, &key) < 0 && errno == ENOENT); 1521 assert(bpf_map_get_next_key(fd, &key, &key) < 0 && errno == ENOENT); 1522 1523 key = 0; 1524 bpf_map_delete_elem(fd, &key); 1525 if (j++ < 5) 1526 goto again; 1527 close(fd); 1528 } 1529 1530 static void test_map_rdonly(void) 1531 { 1532 int fd, key = 0, value = 0; 1533 __u32 old_flags; 1534 1535 old_flags = map_opts.map_flags; 1536 map_opts.map_flags |= BPF_F_RDONLY; 1537 fd = bpf_map_create(BPF_MAP_TYPE_HASH, NULL, sizeof(key), sizeof(value), 1538 MAP_SIZE, &map_opts); 1539 map_opts.map_flags = old_flags; 1540 if (fd < 0) { 1541 printf("Failed to create map for read only test '%s'!\n", 1542 strerror(errno)); 1543 exit(1); 1544 } 1545 1546 key = 1; 1547 value = 1234; 1548 /* Try to insert key=1 element. */ 1549 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) < 0 && 1550 errno == EPERM); 1551 1552 /* Check that key=1 is not found. */ 1553 assert(bpf_map_lookup_elem(fd, &key, &value) < 0 && errno == ENOENT); 1554 assert(bpf_map_get_next_key(fd, &key, &value) < 0 && errno == ENOENT); 1555 1556 close(fd); 1557 } 1558 1559 static void test_map_wronly_hash(void) 1560 { 1561 int fd, key = 0, value = 0; 1562 __u32 old_flags; 1563 1564 old_flags = map_opts.map_flags; 1565 map_opts.map_flags |= BPF_F_WRONLY; 1566 fd = bpf_map_create(BPF_MAP_TYPE_HASH, NULL, sizeof(key), sizeof(value), 1567 MAP_SIZE, &map_opts); 1568 map_opts.map_flags = old_flags; 1569 if (fd < 0) { 1570 printf("Failed to create map for write only test '%s'!\n", 1571 strerror(errno)); 1572 exit(1); 1573 } 1574 1575 key = 1; 1576 value = 1234; 1577 /* Insert key=1 element. */ 1578 assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0); 1579 1580 /* Check that reading elements and keys from the map is not allowed. */ 1581 assert(bpf_map_lookup_elem(fd, &key, &value) < 0 && errno == EPERM); 1582 assert(bpf_map_get_next_key(fd, &key, &value) < 0 && errno == EPERM); 1583 1584 close(fd); 1585 } 1586 1587 static void test_map_wronly_stack_or_queue(enum bpf_map_type map_type) 1588 { 1589 int fd, value = 0; 1590 __u32 old_flags; 1591 1592 1593 assert(map_type == BPF_MAP_TYPE_QUEUE || 1594 map_type == BPF_MAP_TYPE_STACK); 1595 old_flags = map_opts.map_flags; 1596 map_opts.map_flags |= BPF_F_WRONLY; 1597 fd = bpf_map_create(map_type, NULL, 0, sizeof(value), MAP_SIZE, &map_opts); 1598 map_opts.map_flags = old_flags; 1599 /* Stack/Queue maps do not support BPF_F_NO_PREALLOC */ 1600 if (map_opts.map_flags & BPF_F_NO_PREALLOC) { 1601 assert(fd < 0 && errno == EINVAL); 1602 return; 1603 } 1604 if (fd < 0) { 1605 printf("Failed to create map '%s'!\n", strerror(errno)); 1606 exit(1); 1607 } 1608 1609 value = 1234; 1610 assert(bpf_map_update_elem(fd, NULL, &value, BPF_ANY) == 0); 1611 1612 /* Peek element should fail */ 1613 assert(bpf_map_lookup_elem(fd, NULL, &value) < 0 && errno == EPERM); 1614 1615 /* Pop element should fail */ 1616 assert(bpf_map_lookup_and_delete_elem(fd, NULL, &value) < 0 && 1617 errno == EPERM); 1618 1619 close(fd); 1620 } 1621 1622 static void test_map_wronly(void) 1623 { 1624 test_map_wronly_hash(); 1625 test_map_wronly_stack_or_queue(BPF_MAP_TYPE_STACK); 1626 test_map_wronly_stack_or_queue(BPF_MAP_TYPE_QUEUE); 1627 } 1628 1629 static void prepare_reuseport_grp(int type, int map_fd, size_t map_elem_size, 1630 __s64 *fds64, __u64 *sk_cookies, 1631 unsigned int n) 1632 { 1633 socklen_t optlen, addrlen; 1634 struct sockaddr_in6 s6; 1635 const __u32 index0 = 0; 1636 const int optval = 1; 1637 unsigned int i; 1638 u64 sk_cookie; 1639 void *value; 1640 __s32 fd32; 1641 __s64 fd64; 1642 int err; 1643 1644 s6.sin6_family = AF_INET6; 1645 s6.sin6_addr = in6addr_any; 1646 s6.sin6_port = 0; 1647 addrlen = sizeof(s6); 1648 optlen = sizeof(sk_cookie); 1649 1650 for (i = 0; i < n; i++) { 1651 fd64 = socket(AF_INET6, type, 0); 1652 CHECK(fd64 == -1, "socket()", 1653 "sock_type:%d fd64:%lld errno:%d\n", 1654 type, fd64, errno); 1655 1656 err = setsockopt(fd64, SOL_SOCKET, SO_REUSEPORT, 1657 &optval, sizeof(optval)); 1658 CHECK(err == -1, "setsockopt(SO_REUSEPORT)", 1659 "err:%d errno:%d\n", err, errno); 1660 1661 /* reuseport_array does not allow unbound sk */ 1662 if (map_elem_size == sizeof(__u64)) 1663 value = &fd64; 1664 else { 1665 assert(map_elem_size == sizeof(__u32)); 1666 fd32 = (__s32)fd64; 1667 value = &fd32; 1668 } 1669 err = bpf_map_update_elem(map_fd, &index0, value, BPF_ANY); 1670 CHECK(err >= 0 || errno != EINVAL, 1671 "reuseport array update unbound sk", 1672 "sock_type:%d err:%d errno:%d\n", 1673 type, err, errno); 1674 1675 err = bind(fd64, (struct sockaddr *)&s6, sizeof(s6)); 1676 CHECK(err == -1, "bind()", 1677 "sock_type:%d err:%d errno:%d\n", type, err, errno); 1678 1679 if (i == 0) { 1680 err = getsockname(fd64, (struct sockaddr *)&s6, 1681 &addrlen); 1682 CHECK(err == -1, "getsockname()", 1683 "sock_type:%d err:%d errno:%d\n", 1684 type, err, errno); 1685 } 1686 1687 err = getsockopt(fd64, SOL_SOCKET, SO_COOKIE, &sk_cookie, 1688 &optlen); 1689 CHECK(err == -1, "getsockopt(SO_COOKIE)", 1690 "sock_type:%d err:%d errno:%d\n", type, err, errno); 1691 1692 if (type == SOCK_STREAM) { 1693 /* 1694 * reuseport_array does not allow 1695 * non-listening tcp sk. 1696 */ 1697 err = bpf_map_update_elem(map_fd, &index0, value, 1698 BPF_ANY); 1699 CHECK(err >= 0 || errno != EINVAL, 1700 "reuseport array update non-listening sk", 1701 "sock_type:%d err:%d errno:%d\n", 1702 type, err, errno); 1703 err = listen(fd64, 0); 1704 CHECK(err == -1, "listen()", 1705 "sock_type:%d, err:%d errno:%d\n", 1706 type, err, errno); 1707 } 1708 1709 fds64[i] = fd64; 1710 sk_cookies[i] = sk_cookie; 1711 } 1712 } 1713 1714 static void test_reuseport_array(void) 1715 { 1716 #define REUSEPORT_FD_IDX(err, last) ({ (err) ? last : !last; }) 1717 1718 const __u32 array_size = 4, index0 = 0, index3 = 3; 1719 int types[2] = { SOCK_STREAM, SOCK_DGRAM }, type; 1720 __u64 grpa_cookies[2], sk_cookie, map_cookie; 1721 __s64 grpa_fds64[2] = { -1, -1 }, fd64 = -1; 1722 const __u32 bad_index = array_size; 1723 int map_fd, err, t, f; 1724 __u32 fds_idx = 0; 1725 int fd; 1726 1727 map_fd = bpf_map_create(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, NULL, 1728 sizeof(__u32), sizeof(__u64), array_size, NULL); 1729 CHECK(map_fd < 0, "reuseport array create", 1730 "map_fd:%d, errno:%d\n", map_fd, errno); 1731 1732 /* Test lookup/update/delete with invalid index */ 1733 err = bpf_map_delete_elem(map_fd, &bad_index); 1734 CHECK(err >= 0 || errno != E2BIG, "reuseport array del >=max_entries", 1735 "err:%d errno:%d\n", err, errno); 1736 1737 err = bpf_map_update_elem(map_fd, &bad_index, &fd64, BPF_ANY); 1738 CHECK(err >= 0 || errno != E2BIG, 1739 "reuseport array update >=max_entries", 1740 "err:%d errno:%d\n", err, errno); 1741 1742 err = bpf_map_lookup_elem(map_fd, &bad_index, &map_cookie); 1743 CHECK(err >= 0 || errno != ENOENT, 1744 "reuseport array update >=max_entries", 1745 "err:%d errno:%d\n", err, errno); 1746 1747 /* Test lookup/delete non existence elem */ 1748 err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie); 1749 CHECK(err >= 0 || errno != ENOENT, 1750 "reuseport array lookup not-exist elem", 1751 "err:%d errno:%d\n", err, errno); 1752 err = bpf_map_delete_elem(map_fd, &index3); 1753 CHECK(err >= 0 || errno != ENOENT, 1754 "reuseport array del not-exist elem", 1755 "err:%d errno:%d\n", err, errno); 1756 1757 for (t = 0; t < ARRAY_SIZE(types); t++) { 1758 type = types[t]; 1759 1760 prepare_reuseport_grp(type, map_fd, sizeof(__u64), grpa_fds64, 1761 grpa_cookies, ARRAY_SIZE(grpa_fds64)); 1762 1763 /* Test BPF_* update flags */ 1764 /* BPF_EXIST failure case */ 1765 err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 1766 BPF_EXIST); 1767 CHECK(err >= 0 || errno != ENOENT, 1768 "reuseport array update empty elem BPF_EXIST", 1769 "sock_type:%d err:%d errno:%d\n", 1770 type, err, errno); 1771 fds_idx = REUSEPORT_FD_IDX(err, fds_idx); 1772 1773 /* BPF_NOEXIST success case */ 1774 err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 1775 BPF_NOEXIST); 1776 CHECK(err < 0, 1777 "reuseport array update empty elem BPF_NOEXIST", 1778 "sock_type:%d err:%d errno:%d\n", 1779 type, err, errno); 1780 fds_idx = REUSEPORT_FD_IDX(err, fds_idx); 1781 1782 /* BPF_EXIST success case. */ 1783 err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 1784 BPF_EXIST); 1785 CHECK(err < 0, 1786 "reuseport array update same elem BPF_EXIST", 1787 "sock_type:%d err:%d errno:%d\n", type, err, errno); 1788 fds_idx = REUSEPORT_FD_IDX(err, fds_idx); 1789 1790 /* BPF_NOEXIST failure case */ 1791 err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 1792 BPF_NOEXIST); 1793 CHECK(err >= 0 || errno != EEXIST, 1794 "reuseport array update non-empty elem BPF_NOEXIST", 1795 "sock_type:%d err:%d errno:%d\n", 1796 type, err, errno); 1797 fds_idx = REUSEPORT_FD_IDX(err, fds_idx); 1798 1799 /* BPF_ANY case (always succeed) */ 1800 err = bpf_map_update_elem(map_fd, &index3, &grpa_fds64[fds_idx], 1801 BPF_ANY); 1802 CHECK(err < 0, 1803 "reuseport array update same sk with BPF_ANY", 1804 "sock_type:%d err:%d errno:%d\n", type, err, errno); 1805 1806 fd64 = grpa_fds64[fds_idx]; 1807 sk_cookie = grpa_cookies[fds_idx]; 1808 1809 /* The same sk cannot be added to reuseport_array twice */ 1810 err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_ANY); 1811 CHECK(err >= 0 || errno != EBUSY, 1812 "reuseport array update same sk with same index", 1813 "sock_type:%d err:%d errno:%d\n", 1814 type, err, errno); 1815 1816 err = bpf_map_update_elem(map_fd, &index0, &fd64, BPF_ANY); 1817 CHECK(err >= 0 || errno != EBUSY, 1818 "reuseport array update same sk with different index", 1819 "sock_type:%d err:%d errno:%d\n", 1820 type, err, errno); 1821 1822 /* Test delete elem */ 1823 err = bpf_map_delete_elem(map_fd, &index3); 1824 CHECK(err < 0, "reuseport array delete sk", 1825 "sock_type:%d err:%d errno:%d\n", 1826 type, err, errno); 1827 1828 /* Add it back with BPF_NOEXIST */ 1829 err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_NOEXIST); 1830 CHECK(err < 0, 1831 "reuseport array re-add with BPF_NOEXIST after del", 1832 "sock_type:%d err:%d errno:%d\n", type, err, errno); 1833 1834 /* Test cookie */ 1835 err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie); 1836 CHECK(err < 0 || sk_cookie != map_cookie, 1837 "reuseport array lookup re-added sk", 1838 "sock_type:%d err:%d errno:%d sk_cookie:0x%llx map_cookie:0x%llxn", 1839 type, err, errno, sk_cookie, map_cookie); 1840 1841 /* Test elem removed by close() */ 1842 for (f = 0; f < ARRAY_SIZE(grpa_fds64); f++) 1843 close(grpa_fds64[f]); 1844 err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie); 1845 CHECK(err >= 0 || errno != ENOENT, 1846 "reuseport array lookup after close()", 1847 "sock_type:%d err:%d errno:%d\n", 1848 type, err, errno); 1849 } 1850 1851 /* Test SOCK_RAW */ 1852 fd64 = socket(AF_INET6, SOCK_RAW, IPPROTO_UDP); 1853 CHECK(fd64 == -1, "socket(SOCK_RAW)", "err:%d errno:%d\n", 1854 err, errno); 1855 err = bpf_map_update_elem(map_fd, &index3, &fd64, BPF_NOEXIST); 1856 CHECK(err >= 0 || errno != ENOTSUPP, "reuseport array update SOCK_RAW", 1857 "err:%d errno:%d\n", err, errno); 1858 close(fd64); 1859 1860 /* Close the 64 bit value map */ 1861 close(map_fd); 1862 1863 /* Test 32 bit fd */ 1864 map_fd = bpf_map_create(BPF_MAP_TYPE_REUSEPORT_SOCKARRAY, NULL, 1865 sizeof(__u32), sizeof(__u32), array_size, NULL); 1866 CHECK(map_fd < 0, "reuseport array create", 1867 "map_fd:%d, errno:%d\n", map_fd, errno); 1868 prepare_reuseport_grp(SOCK_STREAM, map_fd, sizeof(__u32), &fd64, 1869 &sk_cookie, 1); 1870 fd = fd64; 1871 err = bpf_map_update_elem(map_fd, &index3, &fd, BPF_NOEXIST); 1872 CHECK(err < 0, "reuseport array update 32 bit fd", 1873 "err:%d errno:%d\n", err, errno); 1874 err = bpf_map_lookup_elem(map_fd, &index3, &map_cookie); 1875 CHECK(err >= 0 || errno != ENOSPC, 1876 "reuseport array lookup 32 bit fd", 1877 "err:%d errno:%d\n", err, errno); 1878 close(fd); 1879 close(map_fd); 1880 } 1881 1882 static void run_all_tests(void) 1883 { 1884 test_hashmap(0, NULL); 1885 test_hashmap_percpu(0, NULL); 1886 test_hashmap_walk(0, NULL); 1887 test_hashmap_zero_seed(); 1888 1889 test_arraymap(0, NULL); 1890 test_arraymap_percpu(0, NULL); 1891 1892 test_arraymap_percpu_many_keys(); 1893 1894 test_devmap(0, NULL); 1895 test_devmap_hash(0, NULL); 1896 test_sockmap(0, NULL); 1897 1898 test_map_large(); 1899 test_map_parallel(); 1900 test_map_stress(); 1901 1902 test_map_rdonly(); 1903 test_map_wronly(); 1904 1905 test_reuseport_array(); 1906 1907 test_queuemap(0, NULL); 1908 test_stackmap(0, NULL); 1909 1910 test_map_in_map(); 1911 } 1912 1913 #define DEFINE_TEST(name) extern void test_##name(void); 1914 #include <map_tests/tests.h> 1915 #undef DEFINE_TEST 1916 1917 int main(void) 1918 { 1919 srand(time(NULL)); 1920 1921 libbpf_set_strict_mode(LIBBPF_STRICT_ALL); 1922 1923 map_opts.map_flags = 0; 1924 run_all_tests(); 1925 1926 map_opts.map_flags = BPF_F_NO_PREALLOC; 1927 run_all_tests(); 1928 1929 #define DEFINE_TEST(name) test_##name(); 1930 #include <map_tests/tests.h> 1931 #undef DEFINE_TEST 1932 1933 printf("test_maps: OK, %d SKIPPED\n", skips); 1934 return 0; 1935 } 1936