linux/tools/testing/selftests/bpf/test_maps.c
<<
>>
Prefs
   1/*
   2 * Testsuite for eBPF maps
   3 *
   4 * Copyright (c) 2014 PLUMgrid, http://plumgrid.com
   5 * Copyright (c) 2016 Facebook
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of version 2 of the GNU General Public
   9 * License as published by the Free Software Foundation.
  10 */
  11
  12#include <stdio.h>
  13#include <unistd.h>
  14#include <errno.h>
  15#include <string.h>
  16#include <assert.h>
  17#include <stdlib.h>
  18
  19#include <sys/wait.h>
  20#include <sys/resource.h>
  21
  22#include <linux/bpf.h>
  23
  24#include <bpf/bpf.h>
  25#include <bpf/libbpf.h>
  26#include "bpf_util.h"
  27
  28static int map_flags;
  29
  30static void test_hashmap(int task, void *data)
  31{
  32        long long key, next_key, first_key, value;
  33        int fd;
  34
  35        fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
  36                            2, map_flags);
  37        if (fd < 0) {
  38                printf("Failed to create hashmap '%s'!\n", strerror(errno));
  39                exit(1);
  40        }
  41
  42        key = 1;
  43        value = 1234;
  44        /* Insert key=1 element. */
  45        assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
  46
  47        value = 0;
  48        /* BPF_NOEXIST means add new element if it doesn't exist. */
  49        assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
  50               /* key=1 already exists. */
  51               errno == EEXIST);
  52
  53        /* -1 is an invalid flag. */
  54        assert(bpf_map_update_elem(fd, &key, &value, -1) == -1 &&
  55               errno == EINVAL);
  56
  57        /* Check that key=1 can be found. */
  58        assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234);
  59
  60        key = 2;
  61        /* Check that key=2 is not found. */
  62        assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
  63
  64        /* BPF_EXIST means update existing element. */
  65        assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 &&
  66               /* key=2 is not there. */
  67               errno == ENOENT);
  68
  69        /* Insert key=2 element. */
  70        assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
  71
  72        /* key=1 and key=2 were inserted, check that key=0 cannot be
  73         * inserted due to max_entries limit.
  74         */
  75        key = 0;
  76        assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
  77               errno == E2BIG);
  78
  79        /* Update existing element, though the map is full. */
  80        key = 1;
  81        assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0);
  82        key = 2;
  83        assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
  84        key = 3;
  85        assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
  86               errno == E2BIG);
  87
  88        /* Check that key = 0 doesn't exist. */
  89        key = 0;
  90        assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
  91
  92        /* Iterate over two elements. */
  93        assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 &&
  94               (first_key == 1 || first_key == 2));
  95        assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
  96               (next_key == first_key));
  97        assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
  98               (next_key == 1 || next_key == 2) &&
  99               (next_key != first_key));
 100        assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 &&
 101               errno == ENOENT);
 102
 103        /* Delete both elements. */
 104        key = 1;
 105        assert(bpf_map_delete_elem(fd, &key) == 0);
 106        key = 2;
 107        assert(bpf_map_delete_elem(fd, &key) == 0);
 108        assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
 109
 110        key = 0;
 111        /* Check that map is empty. */
 112        assert(bpf_map_get_next_key(fd, NULL, &next_key) == -1 &&
 113               errno == ENOENT);
 114        assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 &&
 115               errno == ENOENT);
 116
 117        close(fd);
 118}
 119
 120static void test_hashmap_sizes(int task, void *data)
 121{
 122        int fd, i, j;
 123
 124        for (i = 1; i <= 512; i <<= 1)
 125                for (j = 1; j <= 1 << 18; j <<= 1) {
 126                        fd = bpf_create_map(BPF_MAP_TYPE_HASH, i, j,
 127                                            2, map_flags);
 128                        if (fd < 0) {
 129                                if (errno == ENOMEM)
 130                                        return;
 131                                printf("Failed to create hashmap key=%d value=%d '%s'\n",
 132                                       i, j, strerror(errno));
 133                                exit(1);
 134                        }
 135                        close(fd);
 136                        usleep(10); /* give kernel time to destroy */
 137                }
 138}
 139
 140static void test_hashmap_percpu(int task, void *data)
 141{
 142        unsigned int nr_cpus = bpf_num_possible_cpus();
 143        BPF_DECLARE_PERCPU(long, value);
 144        long long key, next_key, first_key;
 145        int expected_key_mask = 0;
 146        int fd, i;
 147
 148        fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_HASH, sizeof(key),
 149                            sizeof(bpf_percpu(value, 0)), 2, map_flags);
 150        if (fd < 0) {
 151                printf("Failed to create hashmap '%s'!\n", strerror(errno));
 152                exit(1);
 153        }
 154
 155        for (i = 0; i < nr_cpus; i++)
 156                bpf_percpu(value, i) = i + 100;
 157
 158        key = 1;
 159        /* Insert key=1 element. */
 160        assert(!(expected_key_mask & key));
 161        assert(bpf_map_update_elem(fd, &key, value, BPF_ANY) == 0);
 162        expected_key_mask |= key;
 163
 164        /* BPF_NOEXIST means add new element if it doesn't exist. */
 165        assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 &&
 166               /* key=1 already exists. */
 167               errno == EEXIST);
 168
 169        /* -1 is an invalid flag. */
 170        assert(bpf_map_update_elem(fd, &key, value, -1) == -1 &&
 171               errno == EINVAL);
 172
 173        /* Check that key=1 can be found. Value could be 0 if the lookup
 174         * was run from a different CPU.
 175         */
 176        bpf_percpu(value, 0) = 1;
 177        assert(bpf_map_lookup_elem(fd, &key, value) == 0 &&
 178               bpf_percpu(value, 0) == 100);
 179
 180        key = 2;
 181        /* Check that key=2 is not found. */
 182        assert(bpf_map_lookup_elem(fd, &key, value) == -1 && errno == ENOENT);
 183
 184        /* BPF_EXIST means update existing element. */
 185        assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == -1 &&
 186               /* key=2 is not there. */
 187               errno == ENOENT);
 188
 189        /* Insert key=2 element. */
 190        assert(!(expected_key_mask & key));
 191        assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == 0);
 192        expected_key_mask |= key;
 193
 194        /* key=1 and key=2 were inserted, check that key=0 cannot be
 195         * inserted due to max_entries limit.
 196         */
 197        key = 0;
 198        assert(bpf_map_update_elem(fd, &key, value, BPF_NOEXIST) == -1 &&
 199               errno == E2BIG);
 200
 201        /* Check that key = 0 doesn't exist. */
 202        assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
 203
 204        /* Iterate over two elements. */
 205        assert(bpf_map_get_next_key(fd, NULL, &first_key) == 0 &&
 206               ((expected_key_mask & first_key) == first_key));
 207        while (!bpf_map_get_next_key(fd, &key, &next_key)) {
 208                if (first_key) {
 209                        assert(next_key == first_key);
 210                        first_key = 0;
 211                }
 212                assert((expected_key_mask & next_key) == next_key);
 213                expected_key_mask &= ~next_key;
 214
 215                assert(bpf_map_lookup_elem(fd, &next_key, value) == 0);
 216
 217                for (i = 0; i < nr_cpus; i++)
 218                        assert(bpf_percpu(value, i) == i + 100);
 219
 220                key = next_key;
 221        }
 222        assert(errno == ENOENT);
 223
 224        /* Update with BPF_EXIST. */
 225        key = 1;
 226        assert(bpf_map_update_elem(fd, &key, value, BPF_EXIST) == 0);
 227
 228        /* Delete both elements. */
 229        key = 1;
 230        assert(bpf_map_delete_elem(fd, &key) == 0);
 231        key = 2;
 232        assert(bpf_map_delete_elem(fd, &key) == 0);
 233        assert(bpf_map_delete_elem(fd, &key) == -1 && errno == ENOENT);
 234
 235        key = 0;
 236        /* Check that map is empty. */
 237        assert(bpf_map_get_next_key(fd, NULL, &next_key) == -1 &&
 238               errno == ENOENT);
 239        assert(bpf_map_get_next_key(fd, &key, &next_key) == -1 &&
 240               errno == ENOENT);
 241
 242        close(fd);
 243}
 244
 245static void test_hashmap_walk(int task, void *data)
 246{
 247        int fd, i, max_entries = 1000;
 248        long long key, value, next_key;
 249        bool next_key_valid = true;
 250
 251        fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
 252                            max_entries, map_flags);
 253        if (fd < 0) {
 254                printf("Failed to create hashmap '%s'!\n", strerror(errno));
 255                exit(1);
 256        }
 257
 258        for (i = 0; i < max_entries; i++) {
 259                key = i; value = key;
 260                assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
 261        }
 262
 263        for (i = 0; bpf_map_get_next_key(fd, !i ? NULL : &key,
 264                                         &next_key) == 0; i++) {
 265                key = next_key;
 266                assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
 267        }
 268
 269        assert(i == max_entries);
 270
 271        assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
 272        for (i = 0; next_key_valid; i++) {
 273                next_key_valid = bpf_map_get_next_key(fd, &key, &next_key) == 0;
 274                assert(bpf_map_lookup_elem(fd, &key, &value) == 0);
 275                value++;
 276                assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == 0);
 277                key = next_key;
 278        }
 279
 280        assert(i == 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                assert(value - 1 == key);
 287        }
 288
 289        assert(i == max_entries);
 290        close(fd);
 291}
 292
 293static void test_arraymap(int task, void *data)
 294{
 295        int key, next_key, fd;
 296        long long value;
 297
 298        fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(key), sizeof(value),
 299                            2, 0);
 300        if (fd < 0) {
 301                printf("Failed to create arraymap '%s'!\n", strerror(errno));
 302                exit(1);
 303        }
 304
 305        key = 1;
 306        value = 1234;
 307        /* Insert key=1 element. */
 308        assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
 309
 310        value = 0;
 311        assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
 312               errno == EEXIST);
 313
 314        /* Check that key=1 can be found. */
 315        assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 1234);
 316
 317        key = 0;
 318        /* Check that key=0 is also found and zero initialized. */
 319        assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0);
 320
 321        /* key=0 and key=1 were inserted, check that key=2 cannot be inserted
 322         * due to max_entries limit.
 323         */
 324        key = 2;
 325        assert(bpf_map_update_elem(fd, &key, &value, BPF_EXIST) == -1 &&
 326               errno == E2BIG);
 327
 328        /* Check that key = 2 doesn't exist. */
 329        assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
 330
 331        /* Iterate over two elements. */
 332        assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 &&
 333               next_key == 0);
 334        assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
 335               next_key == 0);
 336        assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
 337               next_key == 1);
 338        assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 &&
 339               errno == ENOENT);
 340
 341        /* Delete shouldn't succeed. */
 342        key = 1;
 343        assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL);
 344
 345        close(fd);
 346}
 347
 348static void test_arraymap_percpu(int task, void *data)
 349{
 350        unsigned int nr_cpus = bpf_num_possible_cpus();
 351        BPF_DECLARE_PERCPU(long, values);
 352        int key, next_key, fd, i;
 353
 354        fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
 355                            sizeof(bpf_percpu(values, 0)), 2, 0);
 356        if (fd < 0) {
 357                printf("Failed to create arraymap '%s'!\n", strerror(errno));
 358                exit(1);
 359        }
 360
 361        for (i = 0; i < nr_cpus; i++)
 362                bpf_percpu(values, i) = i + 100;
 363
 364        key = 1;
 365        /* Insert key=1 element. */
 366        assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0);
 367
 368        bpf_percpu(values, 0) = 0;
 369        assert(bpf_map_update_elem(fd, &key, values, BPF_NOEXIST) == -1 &&
 370               errno == EEXIST);
 371
 372        /* Check that key=1 can be found. */
 373        assert(bpf_map_lookup_elem(fd, &key, values) == 0 &&
 374               bpf_percpu(values, 0) == 100);
 375
 376        key = 0;
 377        /* Check that key=0 is also found and zero initialized. */
 378        assert(bpf_map_lookup_elem(fd, &key, values) == 0 &&
 379               bpf_percpu(values, 0) == 0 &&
 380               bpf_percpu(values, nr_cpus - 1) == 0);
 381
 382        /* Check that key=2 cannot be inserted due to max_entries limit. */
 383        key = 2;
 384        assert(bpf_map_update_elem(fd, &key, values, BPF_EXIST) == -1 &&
 385               errno == E2BIG);
 386
 387        /* Check that key = 2 doesn't exist. */
 388        assert(bpf_map_lookup_elem(fd, &key, values) == -1 && errno == ENOENT);
 389
 390        /* Iterate over two elements. */
 391        assert(bpf_map_get_next_key(fd, NULL, &next_key) == 0 &&
 392               next_key == 0);
 393        assert(bpf_map_get_next_key(fd, &key, &next_key) == 0 &&
 394               next_key == 0);
 395        assert(bpf_map_get_next_key(fd, &next_key, &next_key) == 0 &&
 396               next_key == 1);
 397        assert(bpf_map_get_next_key(fd, &next_key, &next_key) == -1 &&
 398               errno == ENOENT);
 399
 400        /* Delete shouldn't succeed. */
 401        key = 1;
 402        assert(bpf_map_delete_elem(fd, &key) == -1 && errno == EINVAL);
 403
 404        close(fd);
 405}
 406
 407static void test_arraymap_percpu_many_keys(void)
 408{
 409        unsigned int nr_cpus = bpf_num_possible_cpus();
 410        BPF_DECLARE_PERCPU(long, values);
 411        /* nr_keys is not too large otherwise the test stresses percpu
 412         * allocator more than anything else
 413         */
 414        unsigned int nr_keys = 2000;
 415        int key, fd, i;
 416
 417        fd = bpf_create_map(BPF_MAP_TYPE_PERCPU_ARRAY, sizeof(key),
 418                            sizeof(bpf_percpu(values, 0)), nr_keys, 0);
 419        if (fd < 0) {
 420                printf("Failed to create per-cpu arraymap '%s'!\n",
 421                       strerror(errno));
 422                exit(1);
 423        }
 424
 425        for (i = 0; i < nr_cpus; i++)
 426                bpf_percpu(values, i) = i + 10;
 427
 428        for (key = 0; key < nr_keys; key++)
 429                assert(bpf_map_update_elem(fd, &key, values, BPF_ANY) == 0);
 430
 431        for (key = 0; key < nr_keys; key++) {
 432                for (i = 0; i < nr_cpus; i++)
 433                        bpf_percpu(values, i) = 0;
 434
 435                assert(bpf_map_lookup_elem(fd, &key, values) == 0);
 436
 437                for (i = 0; i < nr_cpus; i++)
 438                        assert(bpf_percpu(values, i) == i + 10);
 439        }
 440
 441        close(fd);
 442}
 443
 444static void test_devmap(int task, void *data)
 445{
 446        int fd;
 447        __u32 key, value;
 448
 449        fd = bpf_create_map(BPF_MAP_TYPE_DEVMAP, sizeof(key), sizeof(value),
 450                            2, 0);
 451        if (fd < 0) {
 452                printf("Failed to create arraymap '%s'!\n", strerror(errno));
 453                exit(1);
 454        }
 455
 456        close(fd);
 457}
 458
 459#include <sys/socket.h>
 460#include <sys/ioctl.h>
 461#include <arpa/inet.h>
 462#include <sys/select.h>
 463#include <linux/err.h>
 464#define SOCKMAP_PARSE_PROG "./sockmap_parse_prog.o"
 465#define SOCKMAP_VERDICT_PROG "./sockmap_verdict_prog.o"
 466__maybe_unused static void test_sockmap(int tasks, void *data)
 467{
 468        int one = 1, map_fd_rx = 0, map_fd_tx = 0, map_fd_break, s, sc, rc;
 469        struct bpf_map *bpf_map_rx, *bpf_map_tx, *bpf_map_break;
 470        int ports[] = {50200, 50201, 50202, 50204};
 471        int err, i, fd, udp, sfd[6] = {0xdeadbeef};
 472        u8 buf[20] = {0x0, 0x5, 0x3, 0x2, 0x1, 0x0};
 473        int parse_prog, verdict_prog;
 474        struct sockaddr_in addr;
 475        struct bpf_object *obj;
 476        struct timeval to;
 477        __u32 key, value;
 478        pid_t pid[tasks];
 479        fd_set w;
 480
 481        /* Create some sockets to use with sockmap */
 482        for (i = 0; i < 2; i++) {
 483                sfd[i] = socket(AF_INET, SOCK_STREAM, 0);
 484                if (sfd[i] < 0)
 485                        goto out;
 486                err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR,
 487                                 (char *)&one, sizeof(one));
 488                if (err) {
 489                        printf("failed to setsockopt\n");
 490                        goto out;
 491                }
 492                err = ioctl(sfd[i], FIONBIO, (char *)&one);
 493                if (err < 0) {
 494                        printf("failed to ioctl\n");
 495                        goto out;
 496                }
 497                memset(&addr, 0, sizeof(struct sockaddr_in));
 498                addr.sin_family = AF_INET;
 499                addr.sin_addr.s_addr = inet_addr("127.0.0.1");
 500                addr.sin_port = htons(ports[i]);
 501                err = bind(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
 502                if (err < 0) {
 503                        printf("failed to bind: err %i: %i:%i\n",
 504                               err, i, sfd[i]);
 505                        goto out;
 506                }
 507                err = listen(sfd[i], 32);
 508                if (err < 0) {
 509                        printf("failed to listen\n");
 510                        goto out;
 511                }
 512        }
 513
 514        for (i = 2; i < 4; i++) {
 515                sfd[i] = socket(AF_INET, SOCK_STREAM, 0);
 516                if (sfd[i] < 0)
 517                        goto out;
 518                err = setsockopt(sfd[i], SOL_SOCKET, SO_REUSEADDR,
 519                                 (char *)&one, sizeof(one));
 520                if (err) {
 521                        printf("set sock opt\n");
 522                        goto out;
 523                }
 524                memset(&addr, 0, sizeof(struct sockaddr_in));
 525                addr.sin_family = AF_INET;
 526                addr.sin_addr.s_addr = inet_addr("127.0.0.1");
 527                addr.sin_port = htons(ports[i - 2]);
 528                err = connect(sfd[i], (struct sockaddr *)&addr, sizeof(addr));
 529                if (err) {
 530                        printf("failed to connect\n");
 531                        goto out;
 532                }
 533        }
 534
 535
 536        for (i = 4; i < 6; i++) {
 537                sfd[i] = accept(sfd[i - 4], NULL, NULL);
 538                if (sfd[i] < 0) {
 539                        printf("accept failed\n");
 540                        goto out;
 541                }
 542        }
 543
 544        /* Test sockmap with connected sockets */
 545        fd = bpf_create_map(BPF_MAP_TYPE_SOCKMAP,
 546                            sizeof(key), sizeof(value),
 547                            6, 0);
 548        if (fd < 0) {
 549                printf("Failed to create sockmap %i\n", fd);
 550                goto out_sockmap;
 551        }
 552
 553        /* Test update with unsupported UDP socket */
 554        udp = socket(AF_INET, SOCK_DGRAM, 0);
 555        i = 0;
 556        err = bpf_map_update_elem(fd, &i, &udp, BPF_ANY);
 557        if (!err) {
 558                printf("Failed socket SOCK_DGRAM allowed '%i:%i'\n",
 559                       i, udp);
 560                goto out_sockmap;
 561        }
 562
 563        /* Test update without programs */
 564        for (i = 0; i < 6; i++) {
 565                err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
 566                if (err) {
 567                        printf("Failed noprog update sockmap '%i:%i'\n",
 568                               i, sfd[i]);
 569                        goto out_sockmap;
 570                }
 571        }
 572
 573        /* Test attaching/detaching bad fds */
 574        err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_PARSER, 0);
 575        if (!err) {
 576                printf("Failed invalid parser prog attach\n");
 577                goto out_sockmap;
 578        }
 579
 580        err = bpf_prog_attach(-1, fd, BPF_SK_SKB_STREAM_VERDICT, 0);
 581        if (!err) {
 582                printf("Failed invalid verdict prog attach\n");
 583                goto out_sockmap;
 584        }
 585
 586        err = bpf_prog_attach(-1, fd, __MAX_BPF_ATTACH_TYPE, 0);
 587        if (!err) {
 588                printf("Failed unknown prog attach\n");
 589                goto out_sockmap;
 590        }
 591
 592        err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_PARSER);
 593        if (err) {
 594                printf("Failed empty parser prog detach\n");
 595                goto out_sockmap;
 596        }
 597
 598        err = bpf_prog_detach(fd, BPF_SK_SKB_STREAM_VERDICT);
 599        if (err) {
 600                printf("Failed empty verdict prog detach\n");
 601                goto out_sockmap;
 602        }
 603
 604        err = bpf_prog_detach(fd, __MAX_BPF_ATTACH_TYPE);
 605        if (!err) {
 606                printf("Detach invalid prog successful\n");
 607                goto out_sockmap;
 608        }
 609
 610        /* Load SK_SKB program and Attach */
 611        err = bpf_prog_load(SOCKMAP_PARSE_PROG,
 612                            BPF_PROG_TYPE_SK_SKB, &obj, &parse_prog);
 613        if (err) {
 614                printf("Failed to load SK_SKB parse prog\n");
 615                goto out_sockmap;
 616        }
 617
 618        err = bpf_prog_load(SOCKMAP_VERDICT_PROG,
 619                            BPF_PROG_TYPE_SK_SKB, &obj, &verdict_prog);
 620        if (err) {
 621                printf("Failed to load SK_SKB verdict prog\n");
 622                goto out_sockmap;
 623        }
 624
 625        bpf_map_rx = bpf_object__find_map_by_name(obj, "sock_map_rx");
 626        if (IS_ERR(bpf_map_rx)) {
 627                printf("Failed to load map rx from verdict prog\n");
 628                goto out_sockmap;
 629        }
 630
 631        map_fd_rx = bpf_map__fd(bpf_map_rx);
 632        if (map_fd_rx < 0) {
 633                printf("Failed to get map fd\n");
 634                goto out_sockmap;
 635        }
 636
 637        bpf_map_tx = bpf_object__find_map_by_name(obj, "sock_map_tx");
 638        if (IS_ERR(bpf_map_tx)) {
 639                printf("Failed to load map tx from verdict prog\n");
 640                goto out_sockmap;
 641        }
 642
 643        map_fd_tx = bpf_map__fd(bpf_map_tx);
 644        if (map_fd_tx < 0) {
 645                printf("Failed to get map tx fd\n");
 646                goto out_sockmap;
 647        }
 648
 649        bpf_map_break = bpf_object__find_map_by_name(obj, "sock_map_break");
 650        if (IS_ERR(bpf_map_break)) {
 651                printf("Failed to load map tx from verdict prog\n");
 652                goto out_sockmap;
 653        }
 654
 655        map_fd_break = bpf_map__fd(bpf_map_break);
 656        if (map_fd_break < 0) {
 657                printf("Failed to get map tx fd\n");
 658                goto out_sockmap;
 659        }
 660
 661        err = bpf_prog_attach(parse_prog, map_fd_break,
 662                              BPF_SK_SKB_STREAM_PARSER, 0);
 663        if (!err) {
 664                printf("Allowed attaching SK_SKB program to invalid map\n");
 665                goto out_sockmap;
 666        }
 667
 668        err = bpf_prog_attach(parse_prog, map_fd_rx,
 669                      BPF_SK_SKB_STREAM_PARSER, 0);
 670        if (err) {
 671                printf("Failed stream parser bpf prog attach\n");
 672                goto out_sockmap;
 673        }
 674
 675        err = bpf_prog_attach(verdict_prog, map_fd_rx,
 676                              BPF_SK_SKB_STREAM_VERDICT, 0);
 677        if (err) {
 678                printf("Failed stream verdict bpf prog attach\n");
 679                goto out_sockmap;
 680        }
 681
 682        err = bpf_prog_attach(verdict_prog, map_fd_rx,
 683                              __MAX_BPF_ATTACH_TYPE, 0);
 684        if (!err) {
 685                printf("Attached unknown bpf prog\n");
 686                goto out_sockmap;
 687        }
 688
 689        /* Test map update elem afterwards fd lives in fd and map_fd */
 690        for (i = 0; i < 6; i++) {
 691                err = bpf_map_update_elem(map_fd_rx, &i, &sfd[i], BPF_ANY);
 692                if (err) {
 693                        printf("Failed map_fd_rx update sockmap %i '%i:%i'\n",
 694                               err, i, sfd[i]);
 695                        goto out_sockmap;
 696                }
 697                err = bpf_map_update_elem(map_fd_tx, &i, &sfd[i], BPF_ANY);
 698                if (err) {
 699                        printf("Failed map_fd_tx update sockmap %i '%i:%i'\n",
 700                               err, i, sfd[i]);
 701                        goto out_sockmap;
 702                }
 703        }
 704
 705        /* Test map delete elem and remove send/recv sockets */
 706        for (i = 2; i < 4; i++) {
 707                err = bpf_map_delete_elem(map_fd_rx, &i);
 708                if (err) {
 709                        printf("Failed delete sockmap rx %i '%i:%i'\n",
 710                               err, i, sfd[i]);
 711                        goto out_sockmap;
 712                }
 713                err = bpf_map_delete_elem(map_fd_tx, &i);
 714                if (err) {
 715                        printf("Failed delete sockmap tx %i '%i:%i'\n",
 716                               err, i, sfd[i]);
 717                        goto out_sockmap;
 718                }
 719        }
 720
 721        /* Test map send/recv */
 722        for (i = 0; i < 2; i++) {
 723                buf[0] = i;
 724                buf[1] = 0x5;
 725                sc = send(sfd[2], buf, 20, 0);
 726                if (sc < 0) {
 727                        printf("Failed sockmap send\n");
 728                        goto out_sockmap;
 729                }
 730
 731                FD_ZERO(&w);
 732                FD_SET(sfd[3], &w);
 733                to.tv_sec = 1;
 734                to.tv_usec = 0;
 735                s = select(sfd[3] + 1, &w, NULL, NULL, &to);
 736                if (s == -1) {
 737                        perror("Failed sockmap select()");
 738                        goto out_sockmap;
 739                } else if (!s) {
 740                        printf("Failed sockmap unexpected timeout\n");
 741                        goto out_sockmap;
 742                }
 743
 744                if (!FD_ISSET(sfd[3], &w)) {
 745                        printf("Failed sockmap select/recv\n");
 746                        goto out_sockmap;
 747                }
 748
 749                rc = recv(sfd[3], buf, sizeof(buf), 0);
 750                if (rc < 0) {
 751                        printf("Failed sockmap recv\n");
 752                        goto out_sockmap;
 753                }
 754        }
 755
 756        /* Negative null entry lookup from datapath should be dropped */
 757        buf[0] = 1;
 758        buf[1] = 12;
 759        sc = send(sfd[2], buf, 20, 0);
 760        if (sc < 0) {
 761                printf("Failed sockmap send\n");
 762                goto out_sockmap;
 763        }
 764
 765        /* Push fd into same slot */
 766        i = 2;
 767        err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST);
 768        if (!err) {
 769                printf("Failed allowed sockmap dup slot BPF_NOEXIST\n");
 770                goto out_sockmap;
 771        }
 772
 773        err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
 774        if (err) {
 775                printf("Failed sockmap update new slot BPF_ANY\n");
 776                goto out_sockmap;
 777        }
 778
 779        err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST);
 780        if (err) {
 781                printf("Failed sockmap update new slot BPF_EXIST\n");
 782                goto out_sockmap;
 783        }
 784
 785        /* Delete the elems without programs */
 786        for (i = 0; i < 6; i++) {
 787                err = bpf_map_delete_elem(fd, &i);
 788                if (err) {
 789                        printf("Failed delete sockmap %i '%i:%i'\n",
 790                               err, i, sfd[i]);
 791                }
 792        }
 793
 794        /* Test having multiple maps open and set with programs on same fds */
 795        err = bpf_prog_attach(parse_prog, fd,
 796                              BPF_SK_SKB_STREAM_PARSER, 0);
 797        if (err) {
 798                printf("Failed fd bpf parse prog attach\n");
 799                goto out_sockmap;
 800        }
 801        err = bpf_prog_attach(verdict_prog, fd,
 802                              BPF_SK_SKB_STREAM_VERDICT, 0);
 803        if (err) {
 804                printf("Failed fd bpf verdict prog attach\n");
 805                goto out_sockmap;
 806        }
 807
 808        for (i = 4; i < 6; i++) {
 809                err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_ANY);
 810                if (!err) {
 811                        printf("Failed allowed duplicate programs in update ANY sockmap %i '%i:%i'\n",
 812                               err, i, sfd[i]);
 813                        goto out_sockmap;
 814                }
 815                err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_NOEXIST);
 816                if (!err) {
 817                        printf("Failed allowed duplicate program in update NOEXIST sockmap  %i '%i:%i'\n",
 818                               err, i, sfd[i]);
 819                        goto out_sockmap;
 820                }
 821                err = bpf_map_update_elem(fd, &i, &sfd[i], BPF_EXIST);
 822                if (!err) {
 823                        printf("Failed allowed duplicate program in update EXIST sockmap  %i '%i:%i'\n",
 824                               err, i, sfd[i]);
 825                        goto out_sockmap;
 826                }
 827        }
 828
 829        /* Test tasks number of forked operations */
 830        for (i = 0; i < tasks; i++) {
 831                pid[i] = fork();
 832                if (pid[i] == 0) {
 833                        for (i = 0; i < 6; i++) {
 834                                bpf_map_delete_elem(map_fd_tx, &i);
 835                                bpf_map_delete_elem(map_fd_rx, &i);
 836                                bpf_map_update_elem(map_fd_tx, &i,
 837                                                    &sfd[i], BPF_ANY);
 838                                bpf_map_update_elem(map_fd_rx, &i,
 839                                                    &sfd[i], BPF_ANY);
 840                        }
 841                        exit(0);
 842                } else if (pid[i] == -1) {
 843                        printf("Couldn't spawn #%d process!\n", i);
 844                        exit(1);
 845                }
 846        }
 847
 848        for (i = 0; i < tasks; i++) {
 849                int status;
 850
 851                assert(waitpid(pid[i], &status, 0) == pid[i]);
 852                assert(status == 0);
 853        }
 854
 855        err = bpf_prog_detach(map_fd_rx, __MAX_BPF_ATTACH_TYPE);
 856        if (!err) {
 857                printf("Detached an invalid prog type.\n");
 858                goto out_sockmap;
 859        }
 860
 861        err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_PARSER);
 862        if (err) {
 863                printf("Failed parser prog detach\n");
 864                goto out_sockmap;
 865        }
 866
 867        err = bpf_prog_detach(map_fd_rx, BPF_SK_SKB_STREAM_VERDICT);
 868        if (err) {
 869                printf("Failed parser prog detach\n");
 870                goto out_sockmap;
 871        }
 872
 873        /* Test map close sockets and empty maps */
 874        for (i = 0; i < 6; i++) {
 875                bpf_map_delete_elem(map_fd_tx, &i);
 876                bpf_map_delete_elem(map_fd_rx, &i);
 877                close(sfd[i]);
 878        }
 879        close(fd);
 880        close(map_fd_rx);
 881        bpf_object__close(obj);
 882        return;
 883out:
 884        for (i = 0; i < 6; i++)
 885                close(sfd[i]);
 886        printf("Failed to create sockmap '%i:%s'!\n", i, strerror(errno));
 887        exit(1);
 888out_sockmap:
 889        for (i = 0; i < 6; i++) {
 890                if (map_fd_tx)
 891                        bpf_map_delete_elem(map_fd_tx, &i);
 892                if (map_fd_rx)
 893                        bpf_map_delete_elem(map_fd_rx, &i);
 894                close(sfd[i]);
 895        }
 896        close(fd);
 897        exit(1);
 898}
 899
 900#define MAP_SIZE (32 * 1024)
 901
 902static void test_map_large(void)
 903{
 904        struct bigkey {
 905                int a;
 906                char b[116];
 907                long long c;
 908        } key;
 909        int fd, i, value;
 910
 911        fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
 912                            MAP_SIZE, map_flags);
 913        if (fd < 0) {
 914                printf("Failed to create large map '%s'!\n", strerror(errno));
 915                exit(1);
 916        }
 917
 918        for (i = 0; i < MAP_SIZE; i++) {
 919                key = (struct bigkey) { .c = i };
 920                value = i;
 921
 922                assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == 0);
 923        }
 924
 925        key.c = -1;
 926        assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
 927               errno == E2BIG);
 928
 929        /* Iterate through all elements. */
 930        assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
 931        key.c = -1;
 932        for (i = 0; i < MAP_SIZE; i++)
 933                assert(bpf_map_get_next_key(fd, &key, &key) == 0);
 934        assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
 935
 936        key.c = 0;
 937        assert(bpf_map_lookup_elem(fd, &key, &value) == 0 && value == 0);
 938        key.a = 1;
 939        assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
 940
 941        close(fd);
 942}
 943
 944#define run_parallel(N, FN, DATA) \
 945        printf("Fork %d tasks to '" #FN "'\n", N); \
 946        __run_parallel(N, FN, DATA)
 947
 948static void __run_parallel(int tasks, void (*fn)(int task, void *data),
 949                           void *data)
 950{
 951        pid_t pid[tasks];
 952        int i;
 953
 954        for (i = 0; i < tasks; i++) {
 955                pid[i] = fork();
 956                if (pid[i] == 0) {
 957                        fn(i, data);
 958                        exit(0);
 959                } else if (pid[i] == -1) {
 960                        printf("Couldn't spawn #%d process!\n", i);
 961                        exit(1);
 962                }
 963        }
 964
 965        for (i = 0; i < tasks; i++) {
 966                int status;
 967
 968                assert(waitpid(pid[i], &status, 0) == pid[i]);
 969                assert(status == 0);
 970        }
 971}
 972
 973__maybe_unused static void test_map_stress(void)
 974{
 975        run_parallel(100, test_hashmap, NULL);
 976        run_parallel(100, test_hashmap_percpu, NULL);
 977        run_parallel(100, test_hashmap_sizes, NULL);
 978        run_parallel(100, test_hashmap_walk, NULL);
 979
 980        run_parallel(100, test_arraymap, NULL);
 981        run_parallel(100, test_arraymap_percpu, NULL);
 982}
 983
 984#define TASKS 1024
 985
 986#define DO_UPDATE 1
 987#define DO_DELETE 0
 988
 989static void test_update_delete(int fn, void *data)
 990{
 991        int do_update = ((int *)data)[1];
 992        int fd = ((int *)data)[0];
 993        int i, key, value;
 994
 995        for (i = fn; i < MAP_SIZE; i += TASKS) {
 996                key = value = i;
 997
 998                if (do_update) {
 999                        assert(bpf_map_update_elem(fd, &key, &value,
1000                                                   BPF_NOEXIST) == 0);
1001                        assert(bpf_map_update_elem(fd, &key, &value,
1002                                                   BPF_EXIST) == 0);
1003                } else {
1004                        assert(bpf_map_delete_elem(fd, &key) == 0);
1005                }
1006        }
1007}
1008
1009__maybe_unused static void test_map_parallel(void)
1010{
1011        int i, fd, key = 0, value = 0;
1012        int data[2];
1013
1014        fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
1015                            MAP_SIZE, map_flags);
1016        if (fd < 0) {
1017                printf("Failed to create map for parallel test '%s'!\n",
1018                       strerror(errno));
1019                exit(1);
1020        }
1021
1022        /* Use the same fd in children to add elements to this map:
1023         * child_0 adds key=0, key=1024, key=2048, ...
1024         * child_1 adds key=1, key=1025, key=2049, ...
1025         * child_1023 adds key=1023, ...
1026         */
1027        data[0] = fd;
1028        data[1] = DO_UPDATE;
1029        run_parallel(TASKS, test_update_delete, data);
1030
1031        /* Check that key=0 is already there. */
1032        assert(bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST) == -1 &&
1033               errno == EEXIST);
1034
1035        /* Check that all elements were inserted. */
1036        assert(bpf_map_get_next_key(fd, NULL, &key) == 0);
1037        key = -1;
1038        for (i = 0; i < MAP_SIZE; i++)
1039                assert(bpf_map_get_next_key(fd, &key, &key) == 0);
1040        assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
1041
1042        /* Another check for all elements */
1043        for (i = 0; i < MAP_SIZE; i++) {
1044                key = MAP_SIZE - i - 1;
1045
1046                assert(bpf_map_lookup_elem(fd, &key, &value) == 0 &&
1047                       value == key);
1048        }
1049
1050        /* Now let's delete all elemenets in parallel. */
1051        data[1] = DO_DELETE;
1052        run_parallel(TASKS, test_update_delete, data);
1053
1054        /* Nothing should be left. */
1055        key = -1;
1056        assert(bpf_map_get_next_key(fd, NULL, &key) == -1 && errno == ENOENT);
1057        assert(bpf_map_get_next_key(fd, &key, &key) == -1 && errno == ENOENT);
1058}
1059
1060static void test_map_rdonly(void)
1061{
1062        int fd, key = 0, value = 0;
1063
1064        fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
1065                            MAP_SIZE, map_flags | BPF_F_RDONLY);
1066        if (fd < 0) {
1067                printf("Failed to create map for read only test '%s'!\n",
1068                       strerror(errno));
1069                exit(1);
1070        }
1071
1072        key = 1;
1073        value = 1234;
1074        /* Insert key=1 element. */
1075        assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == -1 &&
1076               errno == EPERM);
1077
1078        /* Check that key=2 is not found. */
1079        assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == ENOENT);
1080        assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == ENOENT);
1081}
1082
1083static void test_map_wronly(void)
1084{
1085        int fd, key = 0, value = 0;
1086
1087        fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(key), sizeof(value),
1088                            MAP_SIZE, map_flags | BPF_F_WRONLY);
1089        if (fd < 0) {
1090                printf("Failed to create map for read only test '%s'!\n",
1091                       strerror(errno));
1092                exit(1);
1093        }
1094
1095        key = 1;
1096        value = 1234;
1097        /* Insert key=1 element. */
1098        assert(bpf_map_update_elem(fd, &key, &value, BPF_ANY) == 0);
1099
1100        /* Check that key=2 is not found. */
1101        assert(bpf_map_lookup_elem(fd, &key, &value) == -1 && errno == EPERM);
1102        assert(bpf_map_get_next_key(fd, &key, &value) == -1 && errno == EPERM);
1103}
1104
1105static void run_all_tests(void)
1106{
1107        test_hashmap(0, NULL);
1108        test_hashmap_percpu(0, NULL);
1109        test_hashmap_walk(0, NULL);
1110
1111        test_arraymap(0, NULL);
1112        test_arraymap_percpu(0, NULL);
1113
1114        test_arraymap_percpu_many_keys();
1115
1116        test_devmap(0, NULL);
1117
1118#if 0
1119        RHEL7 - SOCKMAP is unsupported
1120        test_sockmap(0, NULL);
1121#endif
1122
1123        test_map_large();
1124
1125#ifndef __s390x__
1126        test_map_parallel();
1127        test_map_stress();
1128#endif
1129
1130        test_map_rdonly();
1131        test_map_wronly();
1132}
1133
1134int main(void)
1135{
1136        struct rlimit rinf = { RLIM_INFINITY, RLIM_INFINITY };
1137
1138        setrlimit(RLIMIT_MEMLOCK, &rinf);
1139
1140        map_flags = 0;
1141        run_all_tests();
1142
1143        map_flags = BPF_F_NO_PREALLOC;
1144        run_all_tests();
1145
1146        printf("test_maps: OK\n");
1147        return 0;
1148}
1149