blob: b7661021d6595bfc0e783edafdb5fea095f2f7bb [file] [log] [blame]
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
// Copyright (c) 2020 Anton Protopopov
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "map_helpers.h"
#define warn(...) fprintf(stderr, __VA_ARGS__)
static bool batch_map_ops = true; /* hope for the best */
static int
dump_hash_iter(int map_fd, void *keys, __u32 key_size,
void *values, __u32 value_size, __u32 *count,
void *invalid_key)
{
__u8 key[key_size], next_key[key_size];
__u32 n = 0;
int i, err;
/* First get keys */
__builtin_memcpy(key, invalid_key, key_size);
while (n < *count) {
err = bpf_map_get_next_key(map_fd, key, next_key);
if (err && errno != ENOENT) {
return -1;
} else if (err) {
break;
}
__builtin_memcpy(key, next_key, key_size);
__builtin_memcpy(keys + key_size * n, next_key, key_size);
n++;
}
/* Now read values */
for (i = 0; i < n; i++) {
err = bpf_map_lookup_elem(map_fd, keys + key_size * i,
values + value_size * i);
if (err)
return -1;
}
*count = n;
return 0;
}
static int
dump_hash_batch(int map_fd, void *keys, __u32 key_size,
void *values, __u32 value_size, __u32 *count)
{
void *in = NULL, *out;
__u32 n, n_read = 0;
int err = 0;
while (n_read < *count && !err) {
n = *count - n_read;
err = bpf_map_lookup_batch(map_fd, &in, &out,
keys + n_read * key_size,
values + n_read * value_size,
&n, NULL);
if (err && errno != ENOENT) {
return -1;
}
n_read += n;
in = out;
}
*count = n_read;
return 0;
}
int dump_hash(int map_fd,
void *keys, __u32 key_size,
void *values, __u32 value_size,
__u32 *count, void *invalid_key)
{
int err;
if (!keys || !values || !count || !key_size || !value_size) {
errno = EINVAL;
return -1;
}
if (batch_map_ops) {
err = dump_hash_batch(map_fd, keys, key_size,
values, value_size, count);
if (err) {
if (errno != EINVAL) {
return -1;
/* assume that batch operations are not
* supported and try non-batch mode */
batch_map_ops = false;
}
}
}
if (!invalid_key) {
errno = EINVAL;
return -1;
}
return dump_hash_iter(map_fd, keys, key_size,
values, value_size, count, invalid_key);
}