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/