0001
0002
0003 #include <stdio.h>
0004 #include <errno.h>
0005 #include <string.h>
0006
0007 #include <bpf/bpf.h>
0008 #include <bpf/libbpf.h>
0009
0010 #include <test_maps.h>
0011
0012 static int nr_cpus;
0013
0014 static void map_batch_update(int map_fd, __u32 max_entries, int *keys,
0015 __s64 *values, bool is_pcpu)
0016 {
0017 int i, j, err;
0018 int cpu_offset = 0;
0019 DECLARE_LIBBPF_OPTS(bpf_map_batch_opts, opts,
0020 .elem_flags = 0,
0021 .flags = 0,
0022 );
0023
0024 for (i = 0; i < max_entries; i++) {
0025 keys[i] = i;
0026 if (is_pcpu) {
0027 cpu_offset = i * nr_cpus;
0028 for (j = 0; j < nr_cpus; j++)
0029 (values + cpu_offset)[j] = i + 1 + j;
0030 } else {
0031 values[i] = i + 1;
0032 }
0033 }
0034
0035 err = bpf_map_update_batch(map_fd, keys, values, &max_entries, &opts);
0036 CHECK(err, "bpf_map_update_batch()", "error:%s\n", strerror(errno));
0037 }
0038
0039 static void map_batch_verify(int *visited, __u32 max_entries, int *keys,
0040 __s64 *values, bool is_pcpu)
0041 {
0042 int i, j;
0043 int cpu_offset = 0;
0044
0045 memset(visited, 0, max_entries * sizeof(*visited));
0046 for (i = 0; i < max_entries; i++) {
0047 if (is_pcpu) {
0048 cpu_offset = i * nr_cpus;
0049 for (j = 0; j < nr_cpus; j++) {
0050 __s64 value = (values + cpu_offset)[j];
0051 CHECK(keys[i] + j + 1 != value,
0052 "key/value checking",
0053 "error: i %d j %d key %d value %lld\n", i,
0054 j, keys[i], value);
0055 }
0056 } else {
0057 CHECK(keys[i] + 1 != values[i], "key/value checking",
0058 "error: i %d key %d value %lld\n", i, keys[i],
0059 values[i]);
0060 }
0061 visited[i] = 1;
0062 }
0063 for (i = 0; i < max_entries; i++) {
0064 CHECK(visited[i] != 1, "visited checking",
0065 "error: keys array at index %d missing\n", i);
0066 }
0067 }
0068
0069 static void __test_map_lookup_and_update_batch(bool is_pcpu)
0070 {
0071 int map_fd, *keys, *visited;
0072 __u32 count, total, total_success;
0073 const __u32 max_entries = 10;
0074 __u64 batch = 0;
0075 int err, step, value_size;
0076 void *values;
0077 DECLARE_LIBBPF_OPTS(bpf_map_batch_opts, opts,
0078 .elem_flags = 0,
0079 .flags = 0,
0080 );
0081
0082 map_fd = bpf_map_create(is_pcpu ? BPF_MAP_TYPE_PERCPU_ARRAY : BPF_MAP_TYPE_ARRAY,
0083 "array_map", sizeof(int), sizeof(__s64), max_entries, NULL);
0084 CHECK(map_fd == -1,
0085 "bpf_map_create()", "error:%s\n", strerror(errno));
0086
0087 value_size = sizeof(__s64);
0088 if (is_pcpu)
0089 value_size *= nr_cpus;
0090
0091 keys = calloc(max_entries, sizeof(*keys));
0092 values = calloc(max_entries, value_size);
0093 visited = calloc(max_entries, sizeof(*visited));
0094 CHECK(!keys || !values || !visited, "malloc()", "error:%s\n",
0095 strerror(errno));
0096
0097
0098 total_success = 0;
0099 for (step = 1; step < max_entries; step++) {
0100 map_batch_update(map_fd, max_entries, keys, values, is_pcpu);
0101 map_batch_verify(visited, max_entries, keys, values, is_pcpu);
0102 memset(keys, 0, max_entries * sizeof(*keys));
0103 memset(values, 0, max_entries * value_size);
0104 batch = 0;
0105 total = 0;
0106
0107
0108
0109 count = step;
0110 while (true) {
0111 err = bpf_map_lookup_batch(map_fd,
0112 total ? &batch : NULL,
0113 &batch, keys + total,
0114 values + total * value_size,
0115 &count, &opts);
0116
0117 CHECK((err && errno != ENOENT), "lookup with steps",
0118 "error: %s\n", strerror(errno));
0119
0120 total += count;
0121 if (err)
0122 break;
0123
0124 }
0125
0126 CHECK(total != max_entries, "lookup with steps",
0127 "total = %u, max_entries = %u\n", total, max_entries);
0128
0129 map_batch_verify(visited, max_entries, keys, values, is_pcpu);
0130
0131 total_success++;
0132 }
0133
0134 CHECK(total_success == 0, "check total_success",
0135 "unexpected failure\n");
0136
0137 free(keys);
0138 free(values);
0139 free(visited);
0140 }
0141
0142 static void array_map_batch_ops(void)
0143 {
0144 __test_map_lookup_and_update_batch(false);
0145 printf("test_%s:PASS\n", __func__);
0146 }
0147
0148 static void array_percpu_map_batch_ops(void)
0149 {
0150 __test_map_lookup_and_update_batch(true);
0151 printf("test_%s:PASS\n", __func__);
0152 }
0153
0154 void test_array_map_batch_ops(void)
0155 {
0156 nr_cpus = libbpf_num_possible_cpus();
0157
0158 CHECK(nr_cpus < 0, "nr_cpus checking",
0159 "error: get possible cpus failed");
0160
0161 array_map_batch_ops();
0162 array_percpu_map_batch_ops();
0163 }