EBPF Maps: How to Update Using Bpftool from Command Line

EBPF Maps: How to Update Using Bpftool from Command Line

I am using tc to attach my eBPF (C code compiled using clang), to network.

I am using eBPF Maps to store some data.

Specifically, I am using bpf_map_update_elem to update eBPF Maps from within the BPF Program, but I want to also change the contents of the map from outside the program.

Map structure:

struct rt_val {
    int ifaceno;
    int macaddr[6];
};
union key_4 {
    __u32 b32[2];
    __u8 b8[8];
};
struct bpf_map_def SEC("maps") lpm_map_fwd = {
    .type = BPF_MAP_TYPE_LPM_TRIE,
    .key_size = 8,
    .value_size = sizeof(struct rt_val),
    .max_entries = 50,
    .map_flags = BPF_F_NO_PREALLOC,
};

Map updation, and lookup are fine.

But i want to dynamically change the contents of the eBPF Map, from outside the program execution.

Any comments/suggestion regarding the same would be much appreciated!

Resources:

System Specifics:

  • uname -r: 4.15.0-47-generic
  • OS: Ubuntu 18

1 Answer

You already found all the tools you need to update eBPF maps from user space.

bpf()

The bpf(cmd, attr, size) system call is used to perform the update. The cmd passed as first argument indicates what type of operation you want to perform: in your case, that would be BPF_MAP_UPDATE_ELEM. Then the manual page you linked explains how to build attr: in your case (for map updates), it should be:

struct {    /* Used by BPF_MAP_*_ELEM and BPF_MAP_GET_NEXT_KEY commands */
        __u32         map_fd;
        __aligned_u64 key;
        union {
                __aligned_u64 value;
                /* [...] */
        };
        __u64         flags;
};

Meaning you should build a union bpf_attr and pass it the file descriptor to the map, the key of the entry you want to update, the new value for that key, and possibly some flags.

The file descriptor for the map can be obtained:

  • from the path under the BPF virtual file system, if the map has been pinned beforehand,
  • from the id of the map, with another call to the bpf() system call, using the BPF_MAP_GET_FD_BY_ID command,
  • (or as a return value from the call to bpf() that created the map, but not in the case you used tc to load the program).

Note that libbpf (shipped with kernel or mirrored on GitHub) provides wrappers around the bpf() system call and can make things easier.

bpftool

In practice, you do not need to reimplement all of this. As you mentioned in the title, bpftool allows you to update maps from command line, without having to reimplement the whole process.

Get bpftool

Edit: On Ubuntu 19.10 (eoan), bpftool is packaged as part of the linux-tools-common package. Read below for instructions for older releases.

As of this writing, bpftool has not been packaged for Debian/Ubuntu, which means that you have to build it from source. It is shipped with the kernel, so it takes time to download, but building is actually very simple:

 $ git clone git://
 $ cd linux
 $ cd tools/bpf/bpftool
 $ make
(# make install)
(# make doc doc-install)

Alternatively, there is an unofficial version packaged on this page (disclaimer: from my company). The packaged binary was statically built and should work on all x86_64 Linux machines.

David Miller
Author

David Miller

David Miller brings 15 years of experience in global economics, personal finance strategy, and market dynamics. He specializes in turning complex economic trends into actionable insights for everyday readers.