map_of_maps.rst 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. .. SPDX-License-Identifier: GPL-2.0-only
  2. .. Copyright (C) 2022 Red Hat, Inc.
  3. ========================================================
  4. BPF_MAP_TYPE_ARRAY_OF_MAPS and BPF_MAP_TYPE_HASH_OF_MAPS
  5. ========================================================
  6. .. note::
  7. - ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` and ``BPF_MAP_TYPE_HASH_OF_MAPS`` were
  8. introduced in kernel version 4.12
  9. ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` and ``BPF_MAP_TYPE_HASH_OF_MAPS`` provide general
  10. purpose support for map in map storage. One level of nesting is supported, where
  11. an outer map contains instances of a single type of inner map, for example
  12. ``array_of_maps->sock_map``.
  13. When creating an outer map, an inner map instance is used to initialize the
  14. metadata that the outer map holds about its inner maps. This inner map has a
  15. separate lifetime from the outer map and can be deleted after the outer map has
  16. been created.
  17. The outer map supports element lookup, update and delete from user space using
  18. the syscall API. A BPF program is only allowed to do element lookup in the outer
  19. map.
  20. .. note::
  21. - Multi-level nesting is not supported.
  22. - Any BPF map type can be used as an inner map, except for
  23. ``BPF_MAP_TYPE_PROG_ARRAY``.
  24. - A BPF program cannot update or delete outer map entries.
  25. For ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` the key is an unsigned 32-bit integer index
  26. into the array. The array is a fixed size with ``max_entries`` elements that are
  27. zero initialized when created.
  28. For ``BPF_MAP_TYPE_HASH_OF_MAPS`` the key type can be chosen when defining the
  29. map. The kernel is responsible for allocating and freeing key/value pairs, up to
  30. the max_entries limit that you specify. Hash maps use pre-allocation of hash
  31. table elements by default. The ``BPF_F_NO_PREALLOC`` flag can be used to disable
  32. pre-allocation when it is too memory expensive.
  33. Usage
  34. =====
  35. Kernel BPF Helper
  36. -----------------
  37. bpf_map_lookup_elem()
  38. ~~~~~~~~~~~~~~~~~~~~~
  39. .. code-block:: c
  40. void *bpf_map_lookup_elem(struct bpf_map *map, const void *key)
  41. Inner maps can be retrieved using the ``bpf_map_lookup_elem()`` helper. This
  42. helper returns a pointer to the inner map, or ``NULL`` if no entry was found.
  43. Examples
  44. ========
  45. Kernel BPF Example
  46. ------------------
  47. This snippet shows how to create and initialise an array of devmaps in a BPF
  48. program. Note that the outer array can only be modified from user space using
  49. the syscall API.
  50. .. code-block:: c
  51. struct inner_map {
  52. __uint(type, BPF_MAP_TYPE_DEVMAP);
  53. __uint(max_entries, 10);
  54. __type(key, __u32);
  55. __type(value, __u32);
  56. } inner_map1 SEC(".maps"), inner_map2 SEC(".maps");
  57. struct {
  58. __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
  59. __uint(max_entries, 2);
  60. __type(key, __u32);
  61. __array(values, struct inner_map);
  62. } outer_map SEC(".maps") = {
  63. .values = { &inner_map1,
  64. &inner_map2 }
  65. };
  66. See ``progs/test_btf_map_in_map.c`` in ``tools/testing/selftests/bpf`` for more
  67. examples of declarative initialisation of outer maps.
  68. User Space
  69. ----------
  70. This snippet shows how to create an array based outer map:
  71. .. code-block:: c
  72. int create_outer_array(int inner_fd) {
  73. LIBBPF_OPTS(bpf_map_create_opts, opts, .inner_map_fd = inner_fd);
  74. int fd;
  75. fd = bpf_map_create(BPF_MAP_TYPE_ARRAY_OF_MAPS,
  76. "example_array", /* name */
  77. sizeof(__u32), /* key size */
  78. sizeof(__u32), /* value size */
  79. 256, /* max entries */
  80. &opts); /* create opts */
  81. return fd;
  82. }
  83. This snippet shows how to add an inner map to an outer map:
  84. .. code-block:: c
  85. int add_devmap(int outer_fd, int index, const char *name) {
  86. int fd;
  87. fd = bpf_map_create(BPF_MAP_TYPE_DEVMAP, name,
  88. sizeof(__u32), sizeof(__u32), 256, NULL);
  89. if (fd < 0)
  90. return fd;
  91. return bpf_map_update_elem(outer_fd, &index, &fd, BPF_ANY);
  92. }
  93. References
  94. ==========
  95. - https://lore.kernel.org/netdev/20170322170035.923581-3-kafai@fb.com/
  96. - https://lore.kernel.org/netdev/20170322170035.923581-4-kafai@fb.com/