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