| .. SPDX-License-Identifier: GPL-2.0-only |
| .. Copyright (C) 2022 Red Hat, Inc. |
| |
| ======================================================== |
| BPF_MAP_TYPE_ARRAY_OF_MAPS and BPF_MAP_TYPE_HASH_OF_MAPS |
| ======================================================== |
| |
| .. note:: |
| - ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` and ``BPF_MAP_TYPE_HASH_OF_MAPS`` were |
| introduced in kernel version 4.12 |
| |
| ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` and ``BPF_MAP_TYPE_HASH_OF_MAPS`` provide general |
| purpose support for map in map storage. One level of nesting is supported, where |
| an outer map contains instances of a single type of inner map, for example |
| ``array_of_maps->sock_map``. |
| |
| When creating an outer map, an inner map instance is used to initialize the |
| metadata that the outer map holds about its inner maps. This inner map has a |
| separate lifetime from the outer map and can be deleted after the outer map has |
| been created. |
| |
| The outer map supports element lookup, update and delete from user space using |
| the syscall API. A BPF program is only allowed to do element lookup in the outer |
| map. |
| |
| .. note:: |
| - Multi-level nesting is not supported. |
| - Any BPF map type can be used as an inner map, except for |
| ``BPF_MAP_TYPE_PROG_ARRAY``. |
| - A BPF program cannot update or delete outer map entries. |
| |
| For ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` the key is an unsigned 32-bit integer index |
| into the array. The array is a fixed size with ``max_entries`` elements that are |
| zero initialized when created. |
| |
| For ``BPF_MAP_TYPE_HASH_OF_MAPS`` the key type can be chosen when defining the |
| map. The kernel is responsible for allocating and freeing key/value pairs, up to |
| the max_entries limit that you specify. Hash maps use pre-allocation of hash |
| table elements by default. The ``BPF_F_NO_PREALLOC`` flag can be used to disable |
| pre-allocation when it is too memory expensive. |
| |
| Usage |
| ===== |
| |
| Kernel BPF Helper |
| ----------------- |
| |
| bpf_map_lookup_elem() |
| ~~~~~~~~~~~~~~~~~~~~~ |
| |
| .. code-block:: c |
| |
| void *bpf_map_lookup_elem(struct bpf_map *map, const void *key) |
| |
| Inner maps can be retrieved using the ``bpf_map_lookup_elem()`` helper. This |
| helper returns a pointer to the inner map, or ``NULL`` if no entry was found. |
| |
| Examples |
| ======== |
| |
| Kernel BPF Example |
| ------------------ |
| |
| This snippet shows how to create and initialise an array of devmaps in a BPF |
| program. Note that the outer array can only be modified from user space using |
| the syscall API. |
| |
| .. code-block:: c |
| |
| struct inner_map { |
| __uint(type, BPF_MAP_TYPE_DEVMAP); |
| __uint(max_entries, 10); |
| __type(key, __u32); |
| __type(value, __u32); |
| } inner_map1 SEC(".maps"), inner_map2 SEC(".maps"); |
| |
| struct { |
| __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); |
| __uint(max_entries, 2); |
| __type(key, __u32); |
| __array(values, struct inner_map); |
| } outer_map SEC(".maps") = { |
| .values = { &inner_map1, |
| &inner_map2 } |
| }; |
| |
| See ``progs/test_btf_map_in_map.c`` in ``tools/testing/selftests/bpf`` for more |
| examples of declarative initialisation of outer maps. |
| |
| User Space |
| ---------- |
| |
| This snippet shows how to create an array based outer map: |
| |
| .. code-block:: c |
| |
| int create_outer_array(int inner_fd) { |
| LIBBPF_OPTS(bpf_map_create_opts, opts, .inner_map_fd = inner_fd); |
| int fd; |
| |
| fd = bpf_map_create(BPF_MAP_TYPE_ARRAY_OF_MAPS, |
| "example_array", /* name */ |
| sizeof(__u32), /* key size */ |
| sizeof(__u32), /* value size */ |
| 256, /* max entries */ |
| &opts); /* create opts */ |
| return fd; |
| } |
| |
| |
| This snippet shows how to add an inner map to an outer map: |
| |
| .. code-block:: c |
| |
| int add_devmap(int outer_fd, int index, const char *name) { |
| int fd; |
| |
| fd = bpf_map_create(BPF_MAP_TYPE_DEVMAP, name, |
| sizeof(__u32), sizeof(__u32), 256, NULL); |
| if (fd < 0) |
| return fd; |
| |
| return bpf_map_update_elem(outer_fd, &index, &fd, BPF_ANY); |
| } |
| |
| References |
| ========== |
| |
| - https://lore.kernel.org/netdev/20170322170035.923581-3-kafai@fb.com/ |
| - https://lore.kernel.org/netdev/20170322170035.923581-4-kafai@fb.com/ |