131 lines · plain
1.. SPDX-License-Identifier: GPL-2.0-only2.. Copyright (C) 2022 Red Hat, Inc.3 4========================================================5BPF_MAP_TYPE_ARRAY_OF_MAPS and BPF_MAP_TYPE_HASH_OF_MAPS6========================================================7 8.. note::9 - ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` and ``BPF_MAP_TYPE_HASH_OF_MAPS`` were10 introduced in kernel version 4.1211 12``BPF_MAP_TYPE_ARRAY_OF_MAPS`` and ``BPF_MAP_TYPE_HASH_OF_MAPS`` provide general13purpose support for map in map storage. One level of nesting is supported, where14an outer map contains instances of a single type of inner map, for example15``array_of_maps->sock_map``.16 17When creating an outer map, an inner map instance is used to initialize the18metadata that the outer map holds about its inner maps. This inner map has a19separate lifetime from the outer map and can be deleted after the outer map has20been created.21 22The outer map supports element lookup, update and delete from user space using23the syscall API. A BPF program is only allowed to do element lookup in the outer24map.25 26.. note::27 - Multi-level nesting is not supported.28 - Any BPF map type can be used as an inner map, except for29 ``BPF_MAP_TYPE_PROG_ARRAY``.30 - A BPF program cannot update or delete outer map entries.31 32For ``BPF_MAP_TYPE_ARRAY_OF_MAPS`` the key is an unsigned 32-bit integer index33into the array. The array is a fixed size with ``max_entries`` elements that are34zero initialized when created.35 36For ``BPF_MAP_TYPE_HASH_OF_MAPS`` the key type can be chosen when defining the37map. The kernel is responsible for allocating and freeing key/value pairs, up to38the max_entries limit that you specify. Hash maps use pre-allocation of hash39table elements by default. The ``BPF_F_NO_PREALLOC`` flag can be used to disable40pre-allocation when it is too memory expensive.41 42Usage43=====44 45Kernel BPF Helper46-----------------47 48bpf_map_lookup_elem()49~~~~~~~~~~~~~~~~~~~~~50 51.. code-block:: c52 53 void *bpf_map_lookup_elem(struct bpf_map *map, const void *key)54 55Inner maps can be retrieved using the ``bpf_map_lookup_elem()`` helper. This56helper returns a pointer to the inner map, or ``NULL`` if no entry was found.57 58Examples59========60 61Kernel BPF Example62------------------63 64This snippet shows how to create and initialise an array of devmaps in a BPF65program. Note that the outer array can only be modified from user space using66the syscall API.67 68.. code-block:: c69 70 struct inner_map {71 __uint(type, BPF_MAP_TYPE_DEVMAP);72 __uint(max_entries, 10);73 __type(key, __u32);74 __type(value, __u32);75 } inner_map1 SEC(".maps"), inner_map2 SEC(".maps");76 77 struct {78 __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);79 __uint(max_entries, 2);80 __type(key, __u32);81 __array(values, struct inner_map);82 } outer_map SEC(".maps") = {83 .values = { &inner_map1,84 &inner_map2 }85 };86 87See ``progs/test_btf_map_in_map.c`` in ``tools/testing/selftests/bpf`` for more88examples of declarative initialisation of outer maps.89 90User Space91----------92 93This snippet shows how to create an array based outer map:94 95.. code-block:: c96 97 int create_outer_array(int inner_fd) {98 LIBBPF_OPTS(bpf_map_create_opts, opts, .inner_map_fd = inner_fd);99 int fd;100 101 fd = bpf_map_create(BPF_MAP_TYPE_ARRAY_OF_MAPS,102 "example_array", /* name */103 sizeof(__u32), /* key size */104 sizeof(__u32), /* value size */105 256, /* max entries */106 &opts); /* create opts */107 return fd;108 }109 110 111This snippet shows how to add an inner map to an outer map:112 113.. code-block:: c114 115 int add_devmap(int outer_fd, int index, const char *name) {116 int fd;117 118 fd = bpf_map_create(BPF_MAP_TYPE_DEVMAP, name,119 sizeof(__u32), sizeof(__u32), 256, NULL);120 if (fd < 0)121 return fd;122 123 return bpf_map_update_elem(outer_fd, &index, &fd, BPF_ANY);124 }125 126References127==========128 129- https://lore.kernel.org/netdev/20170322170035.923581-3-kafai@fb.com/130- https://lore.kernel.org/netdev/20170322170035.923581-4-kafai@fb.com/131