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 为 map-in-map 存储提供了通用支持。支持一层嵌套,其中外部 map 包含单一类型内部 map 的实例,例如 array_of_maps->sock_map

创建外部 map 时,使用内部 map 实例来初始化外部 map 持有的关于其内部 map 的元数据。这个内部 map 的生命周期与外部 map 分开,并且可以在外部 map 创建后删除。

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

注意

  • 不支持多层嵌套。

  • 除了 BPF_MAP_TYPE_PROG_ARRAY,任何 BPF map 类型都可以用作内部 map。

  • BPF 程序不能更新或删除外部 map 条目。

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

对于 BPF_MAP_TYPE_HASH_OF_MAPS,可以在定义 map 时选择键类型。内核负责分配和释放键/值对,直到您指定的 max_entries 限制。哈希 map 默认使用预分配哈希表元素。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() 帮助函数检索内部 map。如果未找到条目,此帮助函数返回指向内部 map 的指针,或 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 }
};

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

用户空间

此片段展示了如何创建基于数组的外部 map

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;
}

此片段展示了如何将内部 map 添加到外部 map

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);
}

参考