BPF_MAP_TYPE_QUEUE 和 BPF_MAP_TYPE_STACK

注意

  • BPF_MAP_TYPE_QUEUEBPF_MAP_TYPE_STACK 在内核版本 4.20 中引入。

BPF_MAP_TYPE_QUEUE 为 BPF 程序提供 FIFO(先进先出)存储,BPF_MAP_TYPE_STACK 提供 LIFO(后进先出)存储。这些映射支持通过各自的辅助函数暴露给 BPF 程序的 peek(查看)、pop(弹出)和 push(压入)操作。这些操作通过以下方式使用现有的 bpf 系统调用暴露给用户空间应用程序:

  • BPF_MAP_LOOKUP_ELEM -> 查看

  • BPF_MAP_LOOKUP_AND_DELETE_ELEM -> 弹出

  • BPF_MAP_UPDATE_ELEM -> 压入

BPF_MAP_TYPE_QUEUEBPF_MAP_TYPE_STACK 不支持 BPF_F_NO_PREALLOC

用法

内核 BPF

bpf_map_push_elem()

long bpf_map_push_elem(struct bpf_map *map, const void *value, u64 flags)

可以使用 bpf_map_push_elem 辅助函数将元素 value 添加到队列或栈中。flags 参数必须设置为 BPF_ANYBPF_EXIST。如果 flags 设置为 BPF_EXIST,则当队列或栈已满时,最旧的元素将被移除以为 value 的添加腾出空间。成功时返回 0,失败时返回负错误码。

bpf_map_peek_elem()

long bpf_map_peek_elem(struct bpf_map *map, void *value)

此辅助函数从队列或栈中获取一个元素 value 而不将其移除。成功时返回 0,失败时返回负错误码。

bpf_map_pop_elem()

long bpf_map_pop_elem(struct bpf_map *map, void *value)

此辅助函数从队列或栈中移除一个元素到 value 中。成功时返回 0,失败时返回负错误码。

用户空间

bpf_map_update_elem()

int bpf_map_update_elem (int fd, const void *key, const void *value, __u64 flags)

用户空间程序可以使用 libbpf 的 bpf_map_update_elem 函数将 value 压入队列或栈中。key 参数必须设置为 NULLflags 必须设置为 BPF_ANYBPF_EXIST,其语义与 bpf_map_push_elem 内核辅助函数相同。成功时返回 0,失败时返回负错误码。

bpf_map_lookup_elem()

int bpf_map_lookup_elem (int fd, const void *key, void *value)

用户空间程序可以使用 libbpf 的 bpf_map_lookup_elem 函数查看队列或栈头部的 valuekey 参数必须设置为 NULL。成功时返回 0,失败时返回负错误码。

bpf_map_lookup_and_delete_elem()

int bpf_map_lookup_and_delete_elem (int fd, const void *key, void *value)

用户空间程序可以使用 libbpf 的 bpf_map_lookup_and_delete_elem 函数从队列或栈的头部弹出一个 valuekey 参数必须设置为 NULL。成功时返回 0,失败时返回负错误码。

示例

内核 BPF

此代码片段展示了如何在 BPF 程序中声明一个队列

struct {
        __uint(type, BPF_MAP_TYPE_QUEUE);
        __type(value, __u32);
        __uint(max_entries, 10);
} queue SEC(".maps");

用户空间

此代码片段展示了如何使用 libbpf 的低级 API 从用户空间创建队列

int create_queue()
{
        return bpf_map_create(BPF_MAP_TYPE_QUEUE,
                              "sample_queue", /* name */
                              0,              /* key size, must be zero */
                              sizeof(__u32),  /* value size */
                              10,             /* max entries */
                              NULL);          /* create options */
}

参考资料

https://lwn.net/ml/netdev/153986858555.9127.14517764371945179514.stgit@kernel/