root/tools/testing/selftests/bpf/test_maps.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. test_hashmap
  2. test_hashmap_sizes
  3. test_hashmap_percpu
  4. helper_fill_hashmap
  5. test_hashmap_walk
  6. test_hashmap_zero_seed
  7. test_arraymap
  8. test_arraymap_percpu
  9. test_arraymap_percpu_many_keys
  10. test_devmap
  11. test_devmap_hash
  12. test_queuemap
  13. test_stackmap
  14. test_sockmap
  15. test_map_in_map
  16. test_map_large
  17. __run_parallel
  18. test_map_stress
  19. test_update_delete
  20. test_map_parallel
  21. test_map_rdonly
  22. test_map_wronly
  23. prepare_reuseport_grp
  24. test_reuseport_array
  25. run_all_tests
  26. main

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

/* [<][>][^][v][top][bottom][index][help] */