Linux Audio

Check our new training course

Embedded Linux training

Mar 31-Apr 8, 2025
Register
Loading...
v6.13.7
  1.. SPDX-License-Identifier: GPL-2.0-only
  2.. Copyright (C) 2022 Red Hat, Inc.
  3
  4========================================================
  5BPF_MAP_TYPE_ARRAY_OF_MAPS and BPF_MAP_TYPE_HASH_OF_MAPS
  6========================================================
  7
  8.. note::
  9   - ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` and ``BPF_MAP_TYPE_HASH_OF_MAPS`` were
 10     introduced in kernel version 4.12
 11
 12``BPF_MAP_TYPE_ARRAY_OF_MAPS`` and ``BPF_MAP_TYPE_HASH_OF_MAPS`` provide general
 13purpose support for map in map storage. One level of nesting is supported, where
 14an outer map contains instances of a single type of inner map, for example
 15``array_of_maps->sock_map``.
 16
 17When creating an outer map, an inner map instance is used to initialize the
 18metadata that the outer map holds about its inner maps. This inner map has a
 19separate lifetime from the outer map and can be deleted after the outer map has
 20been created.
 21
 22The outer map supports element lookup, update and delete from user space using
 23the syscall API. A BPF program is only allowed to do element lookup in the outer
 24map.
 25
 26.. note::
 27   - Multi-level nesting is not supported.
 28   - Any BPF map type can be used as an inner map, except for
 29     ``BPF_MAP_TYPE_PROG_ARRAY``.
 30   - A BPF program cannot update or delete outer map entries.
 31
 32For ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` the key is an unsigned 32-bit integer index
 33into the array. The array is a fixed size with ``max_entries`` elements that are
 34zero initialized when created.
 35
 36For ``BPF_MAP_TYPE_HASH_OF_MAPS`` the key type can be chosen when defining the
 37map. The kernel is responsible for allocating and freeing key/value pairs, up to
 38the max_entries limit that you specify. Hash maps use pre-allocation of hash
 39table elements by default. The ``BPF_F_NO_PREALLOC`` flag can be used to disable
 40pre-allocation when it is too memory expensive.
 41
 42Usage
 43=====
 44
 45Kernel BPF Helper
 46-----------------
 47
 48bpf_map_lookup_elem()
 49~~~~~~~~~~~~~~~~~~~~~
 50
 51.. code-block:: c
 52
 53   void *bpf_map_lookup_elem(struct bpf_map *map, const void *key)
 54
 55Inner maps can be retrieved using the ``bpf_map_lookup_elem()`` helper. This
 56helper returns a pointer to the inner map, or ``NULL`` if no entry was found.
 57
 58Examples
 59========
 60
 61Kernel BPF Example
 62------------------
 63
 64This snippet shows how to create and initialise an array of devmaps in a BPF
 65program. Note that the outer array can only be modified from user space using
 66the syscall API.
 67
 68.. code-block:: c
 69
 70    struct inner_map {
 71            __uint(type, BPF_MAP_TYPE_DEVMAP);
 72            __uint(max_entries, 10);
 73            __type(key, __u32);
 74            __type(value, __u32);
 75    } inner_map1 SEC(".maps"), inner_map2 SEC(".maps");
 76
 77    struct {
 78            __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
 79            __uint(max_entries, 2);
 80            __type(key, __u32);
 81            __array(values, struct inner_map);
 82    } outer_map SEC(".maps") = {
 83            .values = { &inner_map1,
 84                        &inner_map2 }
 85    };
 86
 87See ``progs/test_btf_map_in_map.c`` in ``tools/testing/selftests/bpf`` for more
 88examples of declarative initialisation of outer maps.
 89
 90User Space
 91----------
 92
 93This snippet shows how to create an array based outer map:
 94
 95.. code-block:: c
 96
 97    int create_outer_array(int inner_fd) {
 98            LIBBPF_OPTS(bpf_map_create_opts, opts, .inner_map_fd = inner_fd);
 99            int fd;
100
101            fd = bpf_map_create(BPF_MAP_TYPE_ARRAY_OF_MAPS,
102                                "example_array",       /* name */
103                                sizeof(__u32),         /* key size */
104                                sizeof(__u32),         /* value size */
105                                256,                   /* max entries */
106                                &opts);                /* create opts */
107            return fd;
108    }
109
110
111This snippet shows how to add an inner map to an outer map:
112
113.. code-block:: c
114
115    int add_devmap(int outer_fd, int index, const char *name) {
116            int fd;
117
118            fd = bpf_map_create(BPF_MAP_TYPE_DEVMAP, name,
119                                sizeof(__u32), sizeof(__u32), 256, NULL);
120            if (fd < 0)
121                    return fd;
122
123            return bpf_map_update_elem(outer_fd, &index, &fd, BPF_ANY);
124    }
125
126References
127==========
128
129- https://lore.kernel.org/netdev/20170322170035.923581-3-kafai@fb.com/
130- https://lore.kernel.org/netdev/20170322170035.923581-4-kafai@fb.com/
v6.2
  1.. SPDX-License-Identifier: GPL-2.0-only
  2.. Copyright (C) 2022 Red Hat, Inc.
  3
  4========================================================
  5BPF_MAP_TYPE_ARRAY_OF_MAPS and BPF_MAP_TYPE_HASH_OF_MAPS
  6========================================================
  7
  8.. note::
  9   - ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` and ``BPF_MAP_TYPE_HASH_OF_MAPS`` were
 10     introduced in kernel version 4.12
 11
 12``BPF_MAP_TYPE_ARRAY_OF_MAPS`` and ``BPF_MAP_TYPE_HASH_OF_MAPS`` provide general
 13purpose support for map in map storage. One level of nesting is supported, where
 14an outer map contains instances of a single type of inner map, for example
 15``array_of_maps->sock_map``.
 16
 17When creating an outer map, an inner map instance is used to initialize the
 18metadata that the outer map holds about its inner maps. This inner map has a
 19separate lifetime from the outer map and can be deleted after the outer map has
 20been created.
 21
 22The outer map supports element lookup, update and delete from user space using
 23the syscall API. A BPF program is only allowed to do element lookup in the outer
 24map.
 25
 26.. note::
 27   - Multi-level nesting is not supported.
 28   - Any BPF map type can be used as an inner map, except for
 29     ``BPF_MAP_TYPE_PROG_ARRAY``.
 30   - A BPF program cannot update or delete outer map entries.
 31
 32For ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` the key is an unsigned 32-bit integer index
 33into the array. The array is a fixed size with ``max_entries`` elements that are
 34zero initialized when created.
 35
 36For ``BPF_MAP_TYPE_HASH_OF_MAPS`` the key type can be chosen when defining the
 37map. The kernel is responsible for allocating and freeing key/value pairs, up to
 38the max_entries limit that you specify. Hash maps use pre-allocation of hash
 39table elements by default. The ``BPF_F_NO_PREALLOC`` flag can be used to disable
 40pre-allocation when it is too memory expensive.
 41
 42Usage
 43=====
 44
 45Kernel BPF Helper
 46-----------------
 47
 48bpf_map_lookup_elem()
 49~~~~~~~~~~~~~~~~~~~~~
 50
 51.. code-block:: c
 52
 53   void *bpf_map_lookup_elem(struct bpf_map *map, const void *key)
 54
 55Inner maps can be retrieved using the ``bpf_map_lookup_elem()`` helper. This
 56helper returns a pointer to the inner map, or ``NULL`` if no entry was found.
 57
 58Examples
 59========
 60
 61Kernel BPF Example
 62------------------
 63
 64This snippet shows how to create and initialise an array of devmaps in a BPF
 65program. Note that the outer array can only be modified from user space using
 66the syscall API.
 67
 68.. code-block:: c
 69
 70    struct inner_map {
 71            __uint(type, BPF_MAP_TYPE_DEVMAP);
 72            __uint(max_entries, 10);
 73            __type(key, __u32);
 74            __type(value, __u32);
 75    } inner_map1 SEC(".maps"), inner_map2 SEC(".maps");
 76
 77    struct {
 78            __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
 79            __uint(max_entries, 2);
 80            __type(key, __u32);
 81            __array(values, struct inner_map);
 82    } outer_map SEC(".maps") = {
 83            .values = { &inner_map1,
 84                        &inner_map2 }
 85    };
 86
 87See ``progs/test_btf_map_in_map.c`` in ``tools/testing/selftests/bpf`` for more
 88examples of declarative initialisation of outer maps.
 89
 90User Space
 91----------
 92
 93This snippet shows how to create an array based outer map:
 94
 95.. code-block:: c
 96
 97    int create_outer_array(int inner_fd) {
 98            LIBBPF_OPTS(bpf_map_create_opts, opts, .inner_map_fd = inner_fd);
 99            int fd;
100
101            fd = bpf_map_create(BPF_MAP_TYPE_ARRAY_OF_MAPS,
102                                "example_array",       /* name */
103                                sizeof(__u32),         /* key size */
104                                sizeof(__u32),         /* value size */
105                                256,                   /* max entries */
106                                &opts);                /* create opts */
107            return fd;
108    }
109
110
111This snippet shows how to add an inner map to an outer map:
112
113.. code-block:: c
114
115    int add_devmap(int outer_fd, int index, const char *name) {
116            int fd;
117
118            fd = bpf_map_create(BPF_MAP_TYPE_DEVMAP, name,
119                                sizeof(__u32), sizeof(__u32), 256, NULL);
120            if (fd < 0)
121                    return fd;
122
123            return bpf_map_update_elem(outer_fd, &index, &fd, BPF_ANY);
124    }
125
126References
127==========
128
129- https://lore.kernel.org/netdev/20170322170035.923581-3-kafai@fb.com/
130- https://lore.kernel.org/netdev/20170322170035.923581-4-kafai@fb.com/