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