Skip to content

Lesson 4: User Space eBPF Map Operations

eBPF is a new technology for me.

  1. Which APIs should I use?

  2. What are the parameters and return values of these APIs? Where can I find this information?

  3. How do these APIs work together organically to implement a feature?

1. Feature Overview

This first lesson focuses on using eBPF map APIs purely from user space. The next lesson will cover kernel-space map creation and element insertion, followed by user-space retrieval and iteration of map elements for display.

User-space program (test_maps.c):

  • Demonstrates eBPF map creation, deletion, update, lookup, and other operation APIs

  • Supports graceful exit (Ctrl+C)

2. Compilation and Execution

Execute the make command in the src/user_map directory, which will generate the executable in the current directory.

3. Core API Functions

Before writing code, let's familiarize ourselves with the main API functions we'll be using.

1. Create Map: bpf_map_create

Function definition:

Definition

c
int bpf_map_create(enum bpf_map_type map_type, const char *map_name, __u32 key_size, __u32 value_size, __u32 max_entries, const struct bpf_map_create_opts *opts);

Parameters

  • map_type: type of the map to create
  • map_name: name of the map
  • key_size: size of the key in bytes
  • value_size: size of the value in bytes
  • max_entries: maximum number of entries in the map
  • opts: options for the map creation

Documentation link: https://docs.ebpf.io/ebpf-library/libbpf/userspace/bpf_map_create/

2. Create and Update Elements: bpf_map_update_elem

Definition

c
int bpf_map_update_elem(int fd, const void *key, const void *value, __u64 flags);

Parameters

  • fd: file descriptor of the map to update
  • key: pointer to memory containing bytes of the key
  • value: pointer to memory containing bytes of the value
  • flags: flags passed to kernel for this operation

Return

0, on success; negative error, otherwise

What can be passed as the last parameter in the function? Looking at the source code, we can see the definition:

c
/* flags for BPF_MAP_UPDATE_ELEM command */
enum {
	BPF_ANY		= 0, /* create new element or update existing */
	BPF_NOEXIST	= 1, /* create new element if it didn't exist */
	BPF_EXIST	= 2, /* update existing element */
	BPF_F_LOCK	= 4, /* spin_lock-ed map_lookup/map_update */
};

The explanation for each enum value is quite clear.

Documentation link: https://docs.ebpf.io/ebpf-library/libbpf/userspace/bpf_map_update_elem/

3. Lookup Element in Map: bpf_map_lookup_elem

Definition

c
int bpf_map_lookup_elem(int fd, const void *key, void *value);

Parameters

  • fd: file descriptor of the map to lookup element in
  • key: pointer to memory containing bytes of the key used for lookup
  • value: pointer to memory in which looked up value will be stored

Return

0, on success; negative error, otherwise

Documentation link: https://docs.ebpf.io/ebpf-library/libbpf/userspace/bpf_map_lookup_elem/

4. Lookup and Delete Element in Map: bpf_map_lookup_and_delete_elem

Definition

c
int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value);

Parameters

  • fd: file descriptor of the map to lookup element in
  • key: pointer to memory containing bytes of the key used for lookup
  • value: pointer to memory in which looked up value will be stored

Return

0, on success; negative error, otherwise

Documentation link: https://docs.ebpf.io/ebpf-library/libbpf/userspace/bpf_map_lookup_and_delete_elem/

5. Delete Element from Map: bpf_map_delete_elem

Definition

c
int bpf_map_delete_elem(int fd, const void *key);

Parameters

  • fd: file descriptor of the map to delete element from
  • key: pointer to memory containing bytes of the key

Return

0, on success; negative error, otherwise

Documentation link: https://docs.ebpf.io/ebpf-library/libbpf/userspace/bpf_map_delete_elem/

6. Iterate Over Map: bpf_map_get_next_key

Definition

c
int bpf_map_get_next_key(int fd, const void *key, void *next_key);

Parameters

  • fd: file descriptor of the map to get the next key from
  • key: pointer to memory containing bytes of the key used for lookup
  • next_key: pointer to memory in which the next key will be stored

Return

0, on success; negative error, otherwise

Documentation link: https://docs.ebpf.io/ebpf-library/libbpf/userspace/bpf_map_get_next_key/

4. Questions and Clarifications

Observant readers will notice an important detail.

When calling map-related APIs in user-space programs, the first parameter passed is always the map's file descriptor.

However, when calling map-related APIs in kernel-space eBPF programs, the first parameter passed is always a pointer to the map variable.

By reading the following link:

https://docs.ebpf.io/linux/helper-function/bpf_map_update_elem/

We can see that the bpf_map_update_elem called in kernel space is a helper function.

Its function prototype is located in the /usr/include/bpf/bpf_helper_defs.h file:

c
static long (*bpf_map_update_elem)(void *map, const void *key, const void *value, __u64 flags) = (void *) 2;

The bpf_map_update_elem called in user space is a userspace library function.

Its function prototype is located in the /usr/include/bpf/bpf.h file:

c
LIBBPF_API int bpf_map_update_elem(int fd, const void *key, const void *value, __u64 flags);

Therefore, both approaches to using the map-related APIs are correct for their respective contexts.

https://docs.ebpf.io/ebpf-library/libbpf/userspace/bpf_map__update_elem/

Note that in this link, the function is bpf_map__update_elem - there are two underscores between "map" and "update".

Released under the MIT License.