BPF_MAP_TYPE_ARRAY_OF_MAPS 和 BPF_MAP_TYPE_HASH_OF_MAPS

注意

  • BPF_MAP_TYPE_ARRAY_OF_MAPSBPF_MAP_TYPE_HASH_OF_MAPS 在内核版本 4.12 中引入

BPF_MAP_TYPE_ARRAY_OF_MAPSBPF_MAP_TYPE_HASH_OF_MAPS 为映射中的映射存储提供通用支持。支持一层嵌套,其中外部映射包含单一类型的内部映射的实例,例如 array_of_maps->sock_map

创建外部映射时,使用内部映射实例来初始化外部映射保留的有关其内部映射的元数据。此内部映射具有与外部映射分开的生命周期,并且可以在创建外部映射后删除。

外部映射支持使用系统调用 API 从用户空间查找、更新和删除元素。BPF 程序只允许在外部映射中进行元素查找。

注意

  • 不支持多层嵌套。

  • 任何 BPF 映射类型都可以用作内部映射,但 BPF_MAP_TYPE_PROG_ARRAY 除外。

  • BPF 程序无法更新或删除外部映射条目。

对于 BPF_MAP_TYPE_ARRAY_OF_MAPS,键是无符号 32 位整数索引,指向数组。该数组是固定大小的,具有 max_entries 个元素,这些元素在创建时被初始化为零。

对于 BPF_MAP_TYPE_HASH_OF_MAPS,可以在定义映射时选择键类型。内核负责分配和释放键/值对,直到您指定的最大条目限制。默认情况下,哈希映射使用哈希表元素的预分配。BPF_F_NO_PREALLOC 标志可用于在内存开销过大时禁用预分配。

用法

内核 BPF 辅助函数

bpf_map_lookup_elem()

void *bpf_map_lookup_elem(struct bpf_map *map, const void *key)

可以使用 bpf_map_lookup_elem() 辅助函数检索内部映射。此辅助函数返回指向内部映射的指针,如果未找到条目,则返回 NULL

示例

内核 BPF 示例

此代码片段显示如何在 BPF 程序中创建和初始化 devmap 数组。请注意,只能使用系统调用 API 从用户空间修改外部数组。

struct inner_map {
        __uint(type, BPF_MAP_TYPE_DEVMAP);
        __uint(max_entries, 10);
        __type(key, __u32);
        __type(value, __u32);
} inner_map1 SEC(".maps"), inner_map2 SEC(".maps");

struct {
        __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
        __uint(max_entries, 2);
        __type(key, __u32);
        __array(values, struct inner_map);
} outer_map SEC(".maps") = {
        .values = { &inner_map1,
                    &inner_map2 }
};

有关外部映射的声明式初始化的更多示例,请参阅 tools/testing/selftests/bpf 中的 progs/test_btf_map_in_map.c

用户空间

此代码片段显示如何创建基于数组的外部映射

int create_outer_array(int inner_fd) {
        LIBBPF_OPTS(bpf_map_create_opts, opts, .inner_map_fd = inner_fd);
        int fd;

        fd = bpf_map_create(BPF_MAP_TYPE_ARRAY_OF_MAPS,
                            "example_array",       /* name */
                            sizeof(__u32),         /* key size */
                            sizeof(__u32),         /* value size */
                            256,                   /* max entries */
                            &opts);                /* create opts */
        return fd;
}

此代码片段显示如何将内部映射添加到外部映射

int add_devmap(int outer_fd, int index, const char *name) {
        int fd;

        fd = bpf_map_create(BPF_MAP_TYPE_DEVMAP, name,
                            sizeof(__u32), sizeof(__u32), 256, NULL);
        if (fd < 0)
                return fd;

        return bpf_map_update_elem(outer_fd, &index, &fd, BPF_ANY);
}

参考