Types of eBPF maps¶
This document describes the different types of eBPF maps available, and goes into details about the individual map types. The purpose is to help choose the right type based on the individual use-case. Creating and interacting with maps are described in another document here: eBPF maps.
The different types of maps available, are defined by enum
bpf_map_type
in include/uapi/linux/bpf.h. These type definition
“names” are needed when creating the map. Example of bpf_map_type
,
but remember to lookup latest available maps in the source code.
enum bpf_map_type {
BPF_MAP_TYPE_UNSPEC,
BPF_MAP_TYPE_HASH,
BPF_MAP_TYPE_ARRAY,
BPF_MAP_TYPE_PROG_ARRAY,
BPF_MAP_TYPE_PERF_EVENT_ARRAY,
BPF_MAP_TYPE_PERCPU_HASH,
BPF_MAP_TYPE_PERCPU_ARRAY,
BPF_MAP_TYPE_STACK_TRACE,
BPF_MAP_TYPE_CGROUP_ARRAY,
BPF_MAP_TYPE_LRU_HASH,
BPF_MAP_TYPE_LRU_PERCPU_HASH,
};
Implementation details¶
In-order to understand and follow the descriptions of the different map types, in is useful for the reader to understand how a map type is implemented by the kernel.
On the kernel side, implementing a map type requires defining some
function call (pointers) via struct bpf_map_ops. The eBPF programs
(and userspace) have access to the functions calls
map_lookup_elem
, map_update_elem
and map_delete_elem
,
which get invoked from eBPF via bpf-helpers in kernel/bpf/helpers.c,
or via userspace the bpf syscall (as described in eBPF maps).
Creating a map requires supplying the following configuration attributes: map_type, key_size, value_size, max_entries and map_flags.
BPF_MAP_TYPE_ARRAY¶
Implementation defined in kernel/bpf/arraymap.c via struct bpf_map_ops array_ops.
As the name BPF_MAP_TYPE_ARRAY
indicates, this can be seen as an
array. All array elements are pre-allocated and zero initialized at
init time. Key is an index in array and can only be 4 bytes (32-bit).
The constant size is defined by max_entries
. This init-time
constant also implies bpf_map_delete_elem (array_map_delete_elem)
is an invalid operation.
Optimized for fastest possible lookup. The size is constant for the life of the eBPF program, which allows verifier+JIT to perform a wider range of optimizations. E.g. array_map_lookup_elem() may be ‘inlined’ by JIT.
Small size gotcha, the value_size
is rounded up to 8 bytes.
Example usage BPF_MAP_TYPE_ARRAY, based on samples/bpf/sockex1_kern.c:
struct bpf_map_def SEC("maps") my_map = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(u32),
.value_size = sizeof(long),
.max_entries = 256,
};
u32 index = 42;
long *value;
value = bpf_map_lookup_elem(&my_map, &index);
if (value)
__sync_fetch_and_add(value, 1);
The lookup (from kernel side) bpf_map_lookup_elem()
returns a pointer
into the array element. To avoid data races with userspace reading
the value, the API-user must use primitives like __sync_fetch_and_add()
when updating the value in-place.