xref: /linux/Documentation/bpf/map_array.rst (revision 6dfafbd0299a60bfb5d5e277fdf100037c7ded07)
1.. SPDX-License-Identifier: GPL-2.0-only
2.. Copyright (C) 2022 Red Hat, Inc.
3
4================================================
5BPF_MAP_TYPE_ARRAY and BPF_MAP_TYPE_PERCPU_ARRAY
6================================================
7
8.. note::
9   - ``BPF_MAP_TYPE_ARRAY`` was introduced in kernel version 3.19
10   - ``BPF_MAP_TYPE_PERCPU_ARRAY`` was introduced in version 4.6
11
12``BPF_MAP_TYPE_ARRAY`` and ``BPF_MAP_TYPE_PERCPU_ARRAY`` provide generic array
13storage. The key type is an unsigned 32-bit integer (4 bytes) and the map is
14of constant size. The size of the array is defined in ``max_entries`` at
15creation time. All array elements are pre-allocated and zero initialized when
16created. ``BPF_MAP_TYPE_PERCPU_ARRAY`` uses a different memory region for each
17CPU whereas ``BPF_MAP_TYPE_ARRAY`` uses the same memory region. The value
18stored can be of any size for ``BPF_MAP_TYPE_ARRAY`` and not more than
19``PCPU_MIN_UNIT_SIZE`` (32 kB) for ``BPF_MAP_TYPE_PERCPU_ARRAY``. All
20array elements are aligned to 8 bytes.
21
22Since kernel 5.5, memory mapping may be enabled for ``BPF_MAP_TYPE_ARRAY`` by
23setting the flag ``BPF_F_MMAPABLE``. The map definition is page-aligned and
24starts on the first page. Sufficient page-sized and page-aligned blocks of
25memory are allocated to store all array values, starting on the second page,
26which in some cases will result in over-allocation of memory. The benefit of
27using this is increased performance and ease of use since userspace programs
28would not be required to use helper functions to access and mutate data.
29
30Usage
31=====
32
33Kernel BPF
34----------
35
36bpf_map_lookup_elem()
37~~~~~~~~~~~~~~~~~~~~~
38
39.. code-block:: c
40
41   void *bpf_map_lookup_elem(struct bpf_map *map, const void *key)
42
43Array elements can be retrieved using the ``bpf_map_lookup_elem()`` helper.
44This helper returns a pointer into the array element, so to avoid data races
45with userspace reading the value, the user must use primitives like
46``__sync_fetch_and_add()`` when updating the value in-place.
47
48bpf_map_update_elem()
49~~~~~~~~~~~~~~~~~~~~~
50
51.. code-block:: c
52
53   long bpf_map_update_elem(struct bpf_map *map, const void *key, const void *value, u64 flags)
54
55Array elements can be updated using the ``bpf_map_update_elem()`` helper.
56
57``bpf_map_update_elem()`` returns 0 on success, or negative error in case of
58failure.
59
60Since the array is of constant size, ``bpf_map_delete_elem()`` is not supported.
61To clear an array element, you may use ``bpf_map_update_elem()`` to insert a
62zero value to that index.
63
64Per CPU Array
65-------------
66
67Values stored in ``BPF_MAP_TYPE_ARRAY`` can be accessed by multiple programs
68across different CPUs. To restrict storage to a single CPU, you may use a
69``BPF_MAP_TYPE_PERCPU_ARRAY``.
70
71When using a ``BPF_MAP_TYPE_PERCPU_ARRAY`` the ``bpf_map_update_elem()`` and
72``bpf_map_lookup_elem()`` helpers automatically access the slot for the current
73CPU.
74
75bpf_map_lookup_percpu_elem()
76~~~~~~~~~~~~~~~~~~~~~~~~~~~~
77
78.. code-block:: c
79
80   void *bpf_map_lookup_percpu_elem(struct bpf_map *map, const void *key, u32 cpu)
81
82The ``bpf_map_lookup_percpu_elem()`` helper can be used to lookup the array
83value for a specific CPU. Returns value on success , or ``NULL`` if no entry was
84found or ``cpu`` is invalid.
85
86Concurrency
87-----------
88
89Since kernel version 5.1, the BPF infrastructure provides ``struct bpf_spin_lock``
90to synchronize access.
91
92Userspace
93---------
94
95Access from userspace uses libbpf APIs with the same names as above, with
96the map identified by its ``fd``.
97
98Examples
99========
100
101Please see the ``tools/testing/selftests/bpf`` directory for functional
102examples. The code samples below demonstrate API usage.
103
104Kernel BPF
105----------
106
107This snippet shows how to declare an array in a BPF program.
108
109.. code-block:: c
110
111    struct {
112            __uint(type, BPF_MAP_TYPE_ARRAY);
113            __type(key, u32);
114            __type(value, long);
115            __uint(max_entries, 256);
116    } my_map SEC(".maps");
117
118
119This example BPF program shows how to access an array element.
120
121.. code-block:: c
122
123    int bpf_prog(struct __sk_buff *skb)
124    {
125            struct iphdr ip;
126            int index;
127            long *value;
128
129            if (bpf_skb_load_bytes(skb, ETH_HLEN, &ip, sizeof(ip)) < 0)
130                    return 0;
131
132            index = ip.protocol;
133            value = bpf_map_lookup_elem(&my_map, &index);
134            if (value)
135                    __sync_fetch_and_add(value, skb->len);
136
137            return 0;
138    }
139
140Userspace
141---------
142
143BPF_MAP_TYPE_ARRAY
144~~~~~~~~~~~~~~~~~~
145
146This snippet shows how to create an array, using ``bpf_map_create_opts`` to
147set flags.
148
149.. code-block:: c
150
151    #include <bpf/libbpf.h>
152    #include <bpf/bpf.h>
153
154    int create_array()
155    {
156            int fd;
157            LIBBPF_OPTS(bpf_map_create_opts, opts, .map_flags = BPF_F_MMAPABLE);
158
159            fd = bpf_map_create(BPF_MAP_TYPE_ARRAY,
160                                "example_array",       /* name */
161                                sizeof(__u32),         /* key size */
162                                sizeof(long),          /* value size */
163                                256,                   /* max entries */
164                                &opts);                /* create opts */
165            return fd;
166    }
167
168This snippet shows how to initialize the elements of an array.
169
170.. code-block:: c
171
172    int initialize_array(int fd)
173    {
174            __u32 i;
175            long value;
176            int ret;
177
178            for (i = 0; i < 256; i++) {
179                    value = i;
180                    ret = bpf_map_update_elem(fd, &i, &value, BPF_ANY);
181                    if (ret < 0)
182                            return ret;
183            }
184
185            return ret;
186    }
187
188This snippet shows how to retrieve an element value from an array.
189
190.. code-block:: c
191
192    int lookup(int fd)
193    {
194            __u32 index = 42;
195            long value;
196            int ret;
197
198            ret = bpf_map_lookup_elem(fd, &index, &value);
199            if (ret < 0)
200                    return ret;
201
202            /* use value here */
203            assert(value == 42);
204
205            return ret;
206    }
207
208BPF_MAP_TYPE_PERCPU_ARRAY
209~~~~~~~~~~~~~~~~~~~~~~~~~
210
211This snippet shows how to initialize the elements of a per CPU array.
212
213.. code-block:: c
214
215    int initialize_array(int fd)
216    {
217            int ncpus = libbpf_num_possible_cpus();
218            long values[ncpus];
219            __u32 i, j;
220            int ret;
221
222            for (i = 0; i < 256 ; i++) {
223                    for (j = 0; j < ncpus; j++)
224                            values[j] = i;
225                    ret = bpf_map_update_elem(fd, &i, &values, BPF_ANY);
226                    if (ret < 0)
227                            return ret;
228            }
229
230            return ret;
231    }
232
233This snippet shows how to access the per CPU elements of an array value.
234
235.. code-block:: c
236
237    int lookup(int fd)
238    {
239            int ncpus = libbpf_num_possible_cpus();
240            __u32 index = 42, j;
241            long values[ncpus];
242            int ret;
243
244            ret = bpf_map_lookup_elem(fd, &index, &values);
245            if (ret < 0)
246                    return ret;
247
248            for (j = 0; j < ncpus; j++) {
249                    /* Use per CPU value here */
250                    assert(values[j] == 42);
251            }
252
253            return ret;
254    }
255
256Semantics
257=========
258
259As shown in the example above, when accessing a ``BPF_MAP_TYPE_PERCPU_ARRAY``
260in userspace, each value is an array with ``ncpus`` elements.
261
262When calling ``bpf_map_update_elem()`` the flag ``BPF_NOEXIST`` can not be used
263for these maps.
264