linux/tools/testing/selftests/bpf/map_tests/lpm_trie_map_batch_ops.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2
   3#include <arpa/inet.h>
   4#include <linux/bpf.h>
   5#include <netinet/in.h>
   6#include <stdio.h>
   7#include <errno.h>
   8#include <string.h>
   9#include <stdlib.h>
  10
  11#include <bpf/bpf.h>
  12#include <bpf/libbpf.h>
  13
  14#include <test_maps.h>
  15
  16struct test_lpm_key {
  17        __u32 prefix;
  18        struct in_addr ipv4;
  19};
  20
  21static void map_batch_update(int map_fd, __u32 max_entries,
  22                             struct test_lpm_key *keys, int *values)
  23{
  24        __u32 i;
  25        int err;
  26        char buff[16] = { 0 };
  27        DECLARE_LIBBPF_OPTS(bpf_map_batch_opts, opts,
  28                .elem_flags = 0,
  29                .flags = 0,
  30        );
  31
  32        for (i = 0; i < max_entries; i++) {
  33                keys[i].prefix = 32;
  34                snprintf(buff, 16, "192.168.1.%d", i + 1);
  35                inet_pton(AF_INET, buff, &keys[i].ipv4);
  36                values[i] = i + 1;
  37        }
  38
  39        err = bpf_map_update_batch(map_fd, keys, values, &max_entries, &opts);
  40        CHECK(err, "bpf_map_update_batch()", "error:%s\n", strerror(errno));
  41}
  42
  43static void map_batch_verify(int *visited, __u32 max_entries,
  44                             struct test_lpm_key *keys, int *values)
  45{
  46        char buff[16] = { 0 };
  47        int lower_byte = 0;
  48        __u32 i;
  49
  50        memset(visited, 0, max_entries * sizeof(*visited));
  51        for (i = 0; i < max_entries; i++) {
  52                inet_ntop(AF_INET, &keys[i].ipv4, buff, 32);
  53                CHECK(sscanf(buff, "192.168.1.%d", &lower_byte) == EOF,
  54                      "sscanf()", "error: i %d\n", i);
  55                CHECK(lower_byte != values[i], "key/value checking",
  56                      "error: i %d key %s value %d\n", i, buff, values[i]);
  57                visited[i] = 1;
  58        }
  59        for (i = 0; i < max_entries; i++) {
  60                CHECK(visited[i] != 1, "visited checking",
  61                      "error: keys array at index %d missing\n", i);
  62        }
  63}
  64
  65void test_lpm_trie_map_batch_ops(void)
  66{
  67        struct bpf_create_map_attr xattr = {
  68                .name = "lpm_trie_map",
  69                .map_type = BPF_MAP_TYPE_LPM_TRIE,
  70                .key_size = sizeof(struct test_lpm_key),
  71                .value_size = sizeof(int),
  72                .map_flags = BPF_F_NO_PREALLOC,
  73        };
  74        struct test_lpm_key *keys, key;
  75        int map_fd, *values, *visited;
  76        __u32 step, count, total, total_success;
  77        const __u32 max_entries = 10;
  78        __u64 batch = 0;
  79        int err;
  80        DECLARE_LIBBPF_OPTS(bpf_map_batch_opts, opts,
  81                .elem_flags = 0,
  82                .flags = 0,
  83        );
  84
  85        xattr.max_entries = max_entries;
  86        map_fd = bpf_create_map_xattr(&xattr);
  87        CHECK(map_fd == -1, "bpf_create_map_xattr()", "error:%s\n",
  88              strerror(errno));
  89
  90        keys = malloc(max_entries * sizeof(struct test_lpm_key));
  91        values = malloc(max_entries * sizeof(int));
  92        visited = malloc(max_entries * sizeof(int));
  93        CHECK(!keys || !values || !visited, "malloc()", "error:%s\n",
  94              strerror(errno));
  95
  96        total_success = 0;
  97        for (step = 1; step < max_entries; step++) {
  98                map_batch_update(map_fd, max_entries, keys, values);
  99                map_batch_verify(visited, max_entries, keys, values);
 100                memset(keys, 0, max_entries * sizeof(*keys));
 101                memset(values, 0, max_entries * sizeof(*values));
 102                batch = 0;
 103                total = 0;
 104                /* iteratively lookup/delete elements with 'step'
 105                 * elements each.
 106                 */
 107                count = step;
 108                while (true) {
 109                        err = bpf_map_lookup_batch(map_fd,
 110                                total ? &batch : NULL, &batch,
 111                                keys + total, values + total, &count, &opts);
 112
 113                        CHECK((err && errno != ENOENT), "lookup with steps",
 114                              "error: %s\n", strerror(errno));
 115
 116                        total += count;
 117                        if (err)
 118                                break;
 119                }
 120
 121                CHECK(total != max_entries, "lookup with steps",
 122                      "total = %u, max_entries = %u\n", total, max_entries);
 123
 124                map_batch_verify(visited, max_entries, keys, values);
 125
 126                total = 0;
 127                count = step;
 128                while (total < max_entries) {
 129                        if (max_entries - total < step)
 130                                count = max_entries - total;
 131                        err = bpf_map_delete_batch(map_fd, keys + total, &count,
 132                                                   &opts);
 133                        CHECK((err && errno != ENOENT), "delete batch",
 134                              "error: %s\n", strerror(errno));
 135                        total += count;
 136                        if (err)
 137                                break;
 138                }
 139                CHECK(total != max_entries, "delete with steps",
 140                      "total = %u, max_entries = %u\n", total, max_entries);
 141
 142                /* check map is empty, errono == ENOENT */
 143                err = bpf_map_get_next_key(map_fd, NULL, &key);
 144                CHECK(!err || errno != ENOENT, "bpf_map_get_next_key()",
 145                      "error: %s\n", strerror(errno));
 146
 147                total_success++;
 148        }
 149
 150        CHECK(total_success == 0, "check total_success",
 151              "unexpected failure\n");
 152
 153        printf("%s:PASS\n", __func__);
 154
 155        free(keys);
 156        free(values);
 157        free(visited);
 158}
 159