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_OF_MAPS and BPF_MAP_TYPE_HA 5 BPF_MAP_TYPE_ARRAY_OF_MAPS and BPF_MAP_TYPE_HASH_OF_MAPS 6 ============================================== 6 ======================================================== 7 7 8 .. note:: 8 .. note:: 9 - ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` and ``BPF_ 9 - ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` and ``BPF_MAP_TYPE_HASH_OF_MAPS`` were 10 introduced in kernel version 4.12 10 introduced in kernel version 4.12 11 11 12 ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` and ``BPF_MAP_T 12 ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` and ``BPF_MAP_TYPE_HASH_OF_MAPS`` provide general 13 purpose support for map in map storage. One le 13 purpose support for map in map storage. One level of nesting is supported, where 14 an outer map contains instances of a single ty 14 an outer map contains instances of a single type of inner map, for example 15 ``array_of_maps->sock_map``. 15 ``array_of_maps->sock_map``. 16 16 17 When creating an outer map, an inner map insta 17 When creating an outer map, an inner map instance is used to initialize the 18 metadata that the outer map holds about its in 18 metadata that the outer map holds about its inner maps. This inner map has a 19 separate lifetime from the outer map and can b 19 separate lifetime from the outer map and can be deleted after the outer map has 20 been created. 20 been created. 21 21 22 The outer map supports element lookup, update 22 The outer map supports element lookup, update and delete from user space using 23 the syscall API. A BPF program is only allowed 23 the syscall API. A BPF program is only allowed to do element lookup in the outer 24 map. 24 map. 25 25 26 .. note:: 26 .. note:: 27 - Multi-level nesting is not supported. 27 - Multi-level nesting is not supported. 28 - Any BPF map type can be used as an inner 28 - Any BPF map type can be used as an inner map, except for 29 ``BPF_MAP_TYPE_PROG_ARRAY``. 29 ``BPF_MAP_TYPE_PROG_ARRAY``. 30 - A BPF program cannot update or delete out 30 - A BPF program cannot update or delete outer map entries. 31 31 32 For ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` the key is 32 For ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` the key is an unsigned 32-bit integer index 33 into the array. The array is a fixed size with 33 into the array. The array is a fixed size with ``max_entries`` elements that are 34 zero initialized when created. 34 zero initialized when created. 35 35 36 For ``BPF_MAP_TYPE_HASH_OF_MAPS`` the key type 36 For ``BPF_MAP_TYPE_HASH_OF_MAPS`` the key type can be chosen when defining the 37 map. The kernel is responsible for allocating 37 map. The kernel is responsible for allocating and freeing key/value pairs, up to 38 the max_entries limit that you specify. Hash m 38 the max_entries limit that you specify. Hash maps use pre-allocation of hash 39 table elements by default. The ``BPF_F_NO_PREA 39 table elements by default. The ``BPF_F_NO_PREALLOC`` flag can be used to disable 40 pre-allocation when it is too memory expensive 40 pre-allocation when it is too memory expensive. 41 41 42 Usage 42 Usage 43 ===== 43 ===== 44 44 45 Kernel BPF Helper 45 Kernel BPF Helper 46 ----------------- 46 ----------------- 47 47 48 bpf_map_lookup_elem() 48 bpf_map_lookup_elem() 49 ~~~~~~~~~~~~~~~~~~~~~ 49 ~~~~~~~~~~~~~~~~~~~~~ 50 50 51 .. code-block:: c 51 .. code-block:: c 52 52 53 void *bpf_map_lookup_elem(struct bpf_map *m 53 void *bpf_map_lookup_elem(struct bpf_map *map, const void *key) 54 54 55 Inner maps can be retrieved using the ``bpf_ma 55 Inner maps can be retrieved using the ``bpf_map_lookup_elem()`` helper. This 56 helper returns a pointer to the inner map, or 56 helper returns a pointer to the inner map, or ``NULL`` if no entry was found. 57 57 58 Examples 58 Examples 59 ======== 59 ======== 60 60 61 Kernel BPF Example 61 Kernel BPF Example 62 ------------------ 62 ------------------ 63 63 64 This snippet shows how to create and initialis 64 This snippet shows how to create and initialise an array of devmaps in a BPF 65 program. Note that the outer array can only be 65 program. Note that the outer array can only be modified from user space using 66 the syscall API. 66 the syscall API. 67 67 68 .. code-block:: c 68 .. code-block:: c 69 69 70 struct inner_map { 70 struct inner_map { 71 __uint(type, BPF_MAP_TYPE_DEVMAP); 71 __uint(type, BPF_MAP_TYPE_DEVMAP); 72 __uint(max_entries, 10); 72 __uint(max_entries, 10); 73 __type(key, __u32); 73 __type(key, __u32); 74 __type(value, __u32); 74 __type(value, __u32); 75 } inner_map1 SEC(".maps"), inner_map2 SEC( 75 } inner_map1 SEC(".maps"), inner_map2 SEC(".maps"); 76 76 77 struct { 77 struct { 78 __uint(type, BPF_MAP_TYPE_ARRAY_OF 78 __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); 79 __uint(max_entries, 2); 79 __uint(max_entries, 2); 80 __type(key, __u32); 80 __type(key, __u32); 81 __array(values, struct inner_map); 81 __array(values, struct inner_map); 82 } outer_map SEC(".maps") = { 82 } outer_map SEC(".maps") = { 83 .values = { &inner_map1, 83 .values = { &inner_map1, 84 &inner_map2 } 84 &inner_map2 } 85 }; 85 }; 86 86 87 See ``progs/test_btf_map_in_map.c`` in ``tools 87 See ``progs/test_btf_map_in_map.c`` in ``tools/testing/selftests/bpf`` for more 88 examples of declarative initialisation of oute 88 examples of declarative initialisation of outer maps. 89 89 90 User Space 90 User Space 91 ---------- 91 ---------- 92 92 93 This snippet shows how to create an array base 93 This snippet shows how to create an array based outer map: 94 94 95 .. code-block:: c 95 .. code-block:: c 96 96 97 int create_outer_array(int inner_fd) { 97 int create_outer_array(int inner_fd) { 98 LIBBPF_OPTS(bpf_map_create_opts, o 98 LIBBPF_OPTS(bpf_map_create_opts, opts, .inner_map_fd = inner_fd); 99 int fd; 99 int fd; 100 100 101 fd = bpf_map_create(BPF_MAP_TYPE_A 101 fd = bpf_map_create(BPF_MAP_TYPE_ARRAY_OF_MAPS, 102 "example_array 102 "example_array", /* name */ 103 sizeof(__u32), 103 sizeof(__u32), /* key size */ 104 sizeof(__u32), 104 sizeof(__u32), /* value size */ 105 256, 105 256, /* max entries */ 106 &opts); 106 &opts); /* create opts */ 107 return fd; 107 return fd; 108 } 108 } 109 109 110 110 111 This snippet shows how to add an inner map to 111 This snippet shows how to add an inner map to an outer map: 112 112 113 .. code-block:: c 113 .. code-block:: c 114 114 115 int add_devmap(int outer_fd, int index, co 115 int add_devmap(int outer_fd, int index, const char *name) { 116 int fd; 116 int fd; 117 117 118 fd = bpf_map_create(BPF_MAP_TYPE_D 118 fd = bpf_map_create(BPF_MAP_TYPE_DEVMAP, name, 119 sizeof(__u32), 119 sizeof(__u32), sizeof(__u32), 256, NULL); 120 if (fd < 0) 120 if (fd < 0) 121 return fd; 121 return fd; 122 122 123 return bpf_map_update_elem(outer_f 123 return bpf_map_update_elem(outer_fd, &index, &fd, BPF_ANY); 124 } 124 } 125 125 126 References 126 References 127 ========== 127 ========== 128 128 129 - https://lore.kernel.org/netdev/2017032217003 129 - https://lore.kernel.org/netdev/20170322170035.923581-3-kafai@fb.com/ 130 - https://lore.kernel.org/netdev/2017032217003 130 - https://lore.kernel.org/netdev/20170322170035.923581-4-kafai@fb.com/
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.