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