166 lines · c
1// SPDX-License-Identifier: GPL-2.02 3#include <stdio.h>4#include <errno.h>5#include <string.h>6#include <unistd.h>7 8#include <bpf/bpf.h>9#include <bpf/libbpf.h>10 11#include <test_maps.h>12 13static int nr_cpus;14 15static void map_batch_update(int map_fd, __u32 max_entries, int *keys,16 __s64 *values, bool is_pcpu)17{18 int i, j, err;19 int cpu_offset = 0;20 DECLARE_LIBBPF_OPTS(bpf_map_batch_opts, opts,21 .elem_flags = 0,22 .flags = 0,23 );24 25 for (i = 0; i < max_entries; i++) {26 keys[i] = i;27 if (is_pcpu) {28 cpu_offset = i * nr_cpus;29 for (j = 0; j < nr_cpus; j++)30 (values + cpu_offset)[j] = i + 1 + j;31 } else {32 values[i] = i + 1;33 }34 }35 36 err = bpf_map_update_batch(map_fd, keys, values, &max_entries, &opts);37 CHECK(err, "bpf_map_update_batch()", "error:%s\n", strerror(errno));38}39 40static void map_batch_verify(int *visited, __u32 max_entries, int *keys,41 __s64 *values, bool is_pcpu)42{43 int i, j;44 int cpu_offset = 0;45 46 memset(visited, 0, max_entries * sizeof(*visited));47 for (i = 0; i < max_entries; i++) {48 if (is_pcpu) {49 cpu_offset = i * nr_cpus;50 for (j = 0; j < nr_cpus; j++) {51 __s64 value = (values + cpu_offset)[j];52 CHECK(keys[i] + j + 1 != value,53 "key/value checking",54 "error: i %d j %d key %d value %lld\n", i,55 j, keys[i], value);56 }57 } else {58 CHECK(keys[i] + 1 != values[i], "key/value checking",59 "error: i %d key %d value %lld\n", i, keys[i],60 values[i]);61 }62 visited[i] = 1;63 }64 for (i = 0; i < max_entries; i++) {65 CHECK(visited[i] != 1, "visited checking",66 "error: keys array at index %d missing\n", i);67 }68}69 70static void __test_map_lookup_and_update_batch(bool is_pcpu)71{72 int map_fd, *keys, *visited;73 __u32 count, total, total_success;74 const __u32 max_entries = 10;75 __u64 batch = 0;76 int err, step, value_size;77 void *values;78 DECLARE_LIBBPF_OPTS(bpf_map_batch_opts, opts,79 .elem_flags = 0,80 .flags = 0,81 );82 83 map_fd = bpf_map_create(is_pcpu ? BPF_MAP_TYPE_PERCPU_ARRAY : BPF_MAP_TYPE_ARRAY,84 "array_map", sizeof(int), sizeof(__s64), max_entries, NULL);85 CHECK(map_fd == -1,86 "bpf_map_create()", "error:%s\n", strerror(errno));87 88 value_size = sizeof(__s64);89 if (is_pcpu)90 value_size *= nr_cpus;91 92 keys = calloc(max_entries, sizeof(*keys));93 values = calloc(max_entries, value_size);94 visited = calloc(max_entries, sizeof(*visited));95 CHECK(!keys || !values || !visited, "malloc()", "error:%s\n",96 strerror(errno));97 98 /* test 1: lookup in a loop with various steps. */99 total_success = 0;100 for (step = 1; step < max_entries; step++) {101 map_batch_update(map_fd, max_entries, keys, values, is_pcpu);102 map_batch_verify(visited, max_entries, keys, values, is_pcpu);103 memset(keys, 0, max_entries * sizeof(*keys));104 memset(values, 0, max_entries * value_size);105 batch = 0;106 total = 0;107 /* iteratively lookup/delete elements with 'step'108 * elements each.109 */110 count = step;111 while (true) {112 err = bpf_map_lookup_batch(map_fd,113 total ? &batch : NULL,114 &batch, keys + total,115 values + total * value_size,116 &count, &opts);117 118 CHECK((err && errno != ENOENT), "lookup with steps",119 "error: %s\n", strerror(errno));120 121 total += count;122 if (err)123 break;124 125 }126 127 CHECK(total != max_entries, "lookup with steps",128 "total = %u, max_entries = %u\n", total, max_entries);129 130 map_batch_verify(visited, max_entries, keys, values, is_pcpu);131 132 total_success++;133 }134 135 CHECK(total_success == 0, "check total_success",136 "unexpected failure\n");137 138 free(keys);139 free(values);140 free(visited);141 close(map_fd);142}143 144static void array_map_batch_ops(void)145{146 __test_map_lookup_and_update_batch(false);147 printf("test_%s:PASS\n", __func__);148}149 150static void array_percpu_map_batch_ops(void)151{152 __test_map_lookup_and_update_batch(true);153 printf("test_%s:PASS\n", __func__);154}155 156void test_array_map_batch_ops(void)157{158 nr_cpus = libbpf_num_possible_cpus();159 160 CHECK(nr_cpus < 0, "nr_cpus checking",161 "error: get possible cpus failed");162 163 array_map_batch_ops();164 array_percpu_map_batch_ops();165}166