Commit e9bd8cbd authored by Pedro Tammela's avatar Pedro Tammela Committed by Alexei Starovoitov

bpf: selftests: Add tests for batched ops in LPM trie maps

Uses the already existing infrastructure for testing batched ops.
The testing code is essentially the same, with minor tweaks for this use
case.
Suggested-by: default avatarJamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: default avatarPedro Tammela <pctammela@mojatatu.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20210323025058.315763-3-pctammela@gmail.com
parent f56387c5
// SPDX-License-Identifier: GPL-2.0
#include <arpa/inet.h>
#include <linux/bpf.h>
#include <netinet/in.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include <test_maps.h>
struct test_lpm_key {
__u32 prefix;
struct in_addr ipv4;
};
static void map_batch_update(int map_fd, __u32 max_entries,
struct test_lpm_key *keys, int *values)
{
__u32 i;
int err;
char buff[16] = { 0 };
DECLARE_LIBBPF_OPTS(bpf_map_batch_opts, opts,
.elem_flags = 0,
.flags = 0,
);
for (i = 0; i < max_entries; i++) {
keys[i].prefix = 32;
snprintf(buff, 16, "192.168.1.%d", i + 1);
inet_pton(AF_INET, buff, &keys[i].ipv4);
values[i] = i + 1;
}
err = bpf_map_update_batch(map_fd, keys, values, &max_entries, &opts);
CHECK(err, "bpf_map_update_batch()", "error:%s\n", strerror(errno));
}
static void map_batch_verify(int *visited, __u32 max_entries,
struct test_lpm_key *keys, int *values)
{
char buff[16] = { 0 };
int lower_byte = 0;
__u32 i;
memset(visited, 0, max_entries * sizeof(*visited));
for (i = 0; i < max_entries; i++) {
inet_ntop(AF_INET, &keys[i].ipv4, buff, 32);
CHECK(sscanf(buff, "192.168.1.%d", &lower_byte) == EOF,
"sscanf()", "error: i %d\n", i);
CHECK(lower_byte != values[i], "key/value checking",
"error: i %d key %s value %d\n", i, buff, values[i]);
visited[i] = 1;
}
for (i = 0; i < max_entries; i++) {
CHECK(visited[i] != 1, "visited checking",
"error: keys array at index %d missing\n", i);
}
}
void test_lpm_trie_map_batch_ops(void)
{
struct bpf_create_map_attr xattr = {
.name = "lpm_trie_map",
.map_type = BPF_MAP_TYPE_LPM_TRIE,
.key_size = sizeof(struct test_lpm_key),
.value_size = sizeof(int),
.map_flags = BPF_F_NO_PREALLOC,
};
struct test_lpm_key *keys, key;
int map_fd, *values, *visited;
__u32 step, count, total, total_success;
const __u32 max_entries = 10;
__u64 batch = 0;
int err;
DECLARE_LIBBPF_OPTS(bpf_map_batch_opts, opts,
.elem_flags = 0,
.flags = 0,
);
xattr.max_entries = max_entries;
map_fd = bpf_create_map_xattr(&xattr);
CHECK(map_fd == -1, "bpf_create_map_xattr()", "error:%s\n",
strerror(errno));
keys = malloc(max_entries * sizeof(struct test_lpm_key));
values = malloc(max_entries * sizeof(int));
visited = malloc(max_entries * sizeof(int));
CHECK(!keys || !values || !visited, "malloc()", "error:%s\n",
strerror(errno));
total_success = 0;
for (step = 1; step < max_entries; step++) {
map_batch_update(map_fd, max_entries, keys, values);
map_batch_verify(visited, max_entries, keys, values);
memset(keys, 0, max_entries * sizeof(*keys));
memset(values, 0, max_entries * sizeof(*values));
batch = 0;
total = 0;
/* iteratively lookup/delete elements with 'step'
* elements each.
*/
count = step;
while (true) {
err = bpf_map_lookup_batch(map_fd,
total ? &batch : NULL, &batch,
keys + total, values + total, &count, &opts);
CHECK((err && errno != ENOENT), "lookup with steps",
"error: %s\n", strerror(errno));
total += count;
if (err)
break;
}
CHECK(total != max_entries, "lookup with steps",
"total = %u, max_entries = %u\n", total, max_entries);
map_batch_verify(visited, max_entries, keys, values);
total = 0;
count = step;
while (total < max_entries) {
if (max_entries - total < step)
count = max_entries - total;
err = bpf_map_delete_batch(map_fd, keys + total, &count,
&opts);
CHECK((err && errno != ENOENT), "delete batch",
"error: %s\n", strerror(errno));
total += count;
if (err)
break;
}
CHECK(total != max_entries, "delete with steps",
"total = %u, max_entries = %u\n", total, max_entries);
/* check map is empty, errono == ENOENT */
err = bpf_map_get_next_key(map_fd, NULL, &key);
CHECK(!err || errno != ENOENT, "bpf_map_get_next_key()",
"error: %s\n", strerror(errno));
total_success++;
}
CHECK(total_success == 0, "check total_success",
"unexpected failure\n");
printf("%s:PASS\n", __func__);
free(keys);
free(values);
free(visited);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment