1
0

map_array.rst 7.4 KB

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