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

參考