BPF_MAP_TYPE_ARRAY_OF_MAPS 和 BPF_MAP_TYPE_HASH_OF_MAPS¶
注意
BPF_MAP_TYPE_ARRAY_OF_MAPS
和BPF_MAP_TYPE_HASH_OF_MAPS
是在内核版本 4.12 中引入的
BPF_MAP_TYPE_ARRAY_OF_MAPS
和 BPF_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);
}