// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) // Copyright (c) 2020 Anton Protopopov #include #include #include #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); }