1f720b848SDonald Hunter.. SPDX-License-Identifier: GPL-2.0-only 2f720b848SDonald Hunter.. Copyright (C) 2022 Red Hat, Inc. 3f720b848SDonald Hunter 4f720b848SDonald Hunter======================================================== 5f720b848SDonald HunterBPF_MAP_TYPE_ARRAY_OF_MAPS and BPF_MAP_TYPE_HASH_OF_MAPS 6f720b848SDonald Hunter======================================================== 7f720b848SDonald Hunter 8f720b848SDonald Hunter.. note:: 9f720b848SDonald Hunter - ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` and ``BPF_MAP_TYPE_HASH_OF_MAPS`` were 10f720b848SDonald Hunter introduced in kernel version 4.12 11f720b848SDonald Hunter 12f720b848SDonald Hunter``BPF_MAP_TYPE_ARRAY_OF_MAPS`` and ``BPF_MAP_TYPE_HASH_OF_MAPS`` provide general 13f720b848SDonald Hunterpurpose support for map in map storage. One level of nesting is supported, where 14f720b848SDonald Hunteran outer map contains instances of a single type of inner map, for example 15f720b848SDonald Hunter``array_of_maps->sock_map``. 16f720b848SDonald Hunter 17f720b848SDonald HunterWhen creating an outer map, an inner map instance is used to initialize the 18f720b848SDonald Huntermetadata that the outer map holds about its inner maps. This inner map has a 19f720b848SDonald Hunterseparate lifetime from the outer map and can be deleted after the outer map has 20f720b848SDonald Hunterbeen created. 21f720b848SDonald Hunter 22f720b848SDonald HunterThe outer map supports element lookup, update and delete from user space using 23f720b848SDonald Hunterthe syscall API. A BPF program is only allowed to do element lookup in the outer 24f720b848SDonald Huntermap. 25f720b848SDonald Hunter 26f720b848SDonald Hunter.. note:: 27f720b848SDonald Hunter - Multi-level nesting is not supported. 28f720b848SDonald Hunter - Any BPF map type can be used as an inner map, except for 29f720b848SDonald Hunter ``BPF_MAP_TYPE_PROG_ARRAY``. 30f720b848SDonald Hunter - A BPF program cannot update or delete outer map entries. 31f720b848SDonald Hunter 32f720b848SDonald HunterFor ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` the key is an unsigned 32-bit integer index 33f720b848SDonald Hunterinto the array. The array is a fixed size with ``max_entries`` elements that are 34f720b848SDonald Hunterzero initialized when created. 35f720b848SDonald Hunter 36f720b848SDonald HunterFor ``BPF_MAP_TYPE_HASH_OF_MAPS`` the key type can be chosen when defining the 37f720b848SDonald Huntermap. The kernel is responsible for allocating and freeing key/value pairs, up to 38f720b848SDonald Hunterthe max_entries limit that you specify. Hash maps use pre-allocation of hash 39f720b848SDonald Huntertable elements by default. The ``BPF_F_NO_PREALLOC`` flag can be used to disable 40f720b848SDonald Hunterpre-allocation when it is too memory expensive. 41f720b848SDonald Hunter 42f720b848SDonald HunterUsage 43f720b848SDonald Hunter===== 44f720b848SDonald Hunter 45f720b848SDonald HunterKernel BPF Helper 46f720b848SDonald Hunter----------------- 47f720b848SDonald Hunter 48*539886a3SDonald Hunterbpf_map_lookup_elem() 49*539886a3SDonald Hunter~~~~~~~~~~~~~~~~~~~~~ 50*539886a3SDonald Hunter 51*539886a3SDonald Hunter.. code-block:: c 52*539886a3SDonald Hunter 53f720b848SDonald Hunter void *bpf_map_lookup_elem(struct bpf_map *map, const void *key) 54f720b848SDonald Hunter 55f720b848SDonald HunterInner maps can be retrieved using the ``bpf_map_lookup_elem()`` helper. This 56f720b848SDonald Hunterhelper returns a pointer to the inner map, or ``NULL`` if no entry was found. 57f720b848SDonald Hunter 58f720b848SDonald HunterExamples 59f720b848SDonald Hunter======== 60f720b848SDonald Hunter 61f720b848SDonald HunterKernel BPF Example 62f720b848SDonald Hunter------------------ 63f720b848SDonald Hunter 64f720b848SDonald HunterThis snippet shows how to create and initialise an array of devmaps in a BPF 65f720b848SDonald Hunterprogram. Note that the outer array can only be modified from user space using 66f720b848SDonald Hunterthe syscall API. 67f720b848SDonald Hunter 68f720b848SDonald Hunter.. code-block:: c 69f720b848SDonald Hunter 70f720b848SDonald Hunter struct inner_map { 71f720b848SDonald Hunter __uint(type, BPF_MAP_TYPE_DEVMAP); 72f720b848SDonald Hunter __uint(max_entries, 10); 73f720b848SDonald Hunter __type(key, __u32); 74f720b848SDonald Hunter __type(value, __u32); 75f720b848SDonald Hunter } inner_map1 SEC(".maps"), inner_map2 SEC(".maps"); 76f720b848SDonald Hunter 77f720b848SDonald Hunter struct { 78f720b848SDonald Hunter __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); 79f720b848SDonald Hunter __uint(max_entries, 2); 80f720b848SDonald Hunter __type(key, __u32); 81f720b848SDonald Hunter __array(values, struct inner_map); 82f720b848SDonald Hunter } outer_map SEC(".maps") = { 83f720b848SDonald Hunter .values = { &inner_map1, 84f720b848SDonald Hunter &inner_map2 } 85f720b848SDonald Hunter }; 86f720b848SDonald Hunter 87f720b848SDonald HunterSee ``progs/test_btf_map_in_map.c`` in ``tools/testing/selftests/bpf`` for more 88f720b848SDonald Hunterexamples of declarative initialisation of outer maps. 89f720b848SDonald Hunter 90f720b848SDonald HunterUser Space 91f720b848SDonald Hunter---------- 92f720b848SDonald Hunter 93f720b848SDonald HunterThis snippet shows how to create an array based outer map: 94f720b848SDonald Hunter 95f720b848SDonald Hunter.. code-block:: c 96f720b848SDonald Hunter 97f720b848SDonald Hunter int create_outer_array(int inner_fd) { 98f720b848SDonald Hunter LIBBPF_OPTS(bpf_map_create_opts, opts, .inner_map_fd = inner_fd); 99f720b848SDonald Hunter int fd; 100f720b848SDonald Hunter 101f720b848SDonald Hunter fd = bpf_map_create(BPF_MAP_TYPE_ARRAY_OF_MAPS, 102f720b848SDonald Hunter "example_array", /* name */ 103f720b848SDonald Hunter sizeof(__u32), /* key size */ 104f720b848SDonald Hunter sizeof(__u32), /* value size */ 105f720b848SDonald Hunter 256, /* max entries */ 106f720b848SDonald Hunter &opts); /* create opts */ 107f720b848SDonald Hunter return fd; 108f720b848SDonald Hunter } 109f720b848SDonald Hunter 110f720b848SDonald Hunter 111f720b848SDonald HunterThis snippet shows how to add an inner map to an outer map: 112f720b848SDonald Hunter 113f720b848SDonald Hunter.. code-block:: c 114f720b848SDonald Hunter 115f720b848SDonald Hunter int add_devmap(int outer_fd, int index, const char *name) { 116f720b848SDonald Hunter int fd; 117f720b848SDonald Hunter 118f720b848SDonald Hunter fd = bpf_map_create(BPF_MAP_TYPE_DEVMAP, name, 119f720b848SDonald Hunter sizeof(__u32), sizeof(__u32), 256, NULL); 120f720b848SDonald Hunter if (fd < 0) 121f720b848SDonald Hunter return fd; 122f720b848SDonald Hunter 123f720b848SDonald Hunter return bpf_map_update_elem(outer_fd, &index, &fd, BPF_ANY); 124f720b848SDonald Hunter } 125f720b848SDonald Hunter 126f720b848SDonald HunterReferences 127f720b848SDonald Hunter========== 128f720b848SDonald Hunter 129f720b848SDonald Hunter- https://lore.kernel.org/netdev/20170322170035.923581-3-kafai@fb.com/ 130f720b848SDonald Hunter- https://lore.kernel.org/netdev/20170322170035.923581-4-kafai@fb.com/ 131