BPF_MAP_TYPE_SK_STORAGE

注意

  • BPF_MAP_TYPE_SK_STORAGE 在核心版本 5.2 中引入

BPF_MAP_TYPE_SK_STORAGE 用於為 BPF 程式提供套接字本地儲存。型別為 BPF_MAP_TYPE_SK_STORAGE 的對映宣告要提供的儲存型別,並作為訪問套接字本地儲存的控制代碼。型別為 BPF_MAP_TYPE_SK_STORAGE 的對映的值儲存在每個套接字本地,而不是儲存在對映中。核心負責在請求時為套接字分配儲存空間,並在對映或套接字被刪除時釋放儲存空間。

注意

  • 鍵型別必須是 intmax_entries 必須設定為 0

  • 建立套接字本地儲存對映時必須使用 BPF_F_NO_PREALLOC 標誌。

用法

核心 BPF

bpf_sk_storage_get()

void *bpf_sk_storage_get(struct bpf_map *map, void *sk, void *value, u64 flags)

可以使用 bpf_sk_storage_get() 助手從套接字 sk 中檢索 map 的套接字本地儲存。如果使用 BPF_LOCAL_STORAGE_GET_F_CREATE 標誌,則 bpf_sk_storage_get() 將為 sk 建立儲存(如果它尚不存在)。value 可以與 BPF_LOCAL_STORAGE_GET_F_CREATE 一起使用來初始化儲存值,否則它將被零初始化。成功時返回指向儲存的指標,失敗時返回 NULL

注意

  • sk 是 LSM 或跟蹤程式的核心 struct sock 指標。

  • sk 是其他程式型別的 struct bpf_sock 指標。

bpf_sk_storage_delete()

long bpf_sk_storage_delete(struct bpf_map *map, void *sk)

可以使用 bpf_sk_storage_delete() 助手從套接字 sk 中刪除 map 的套接字本地儲存。成功時返回 0,失敗時返回負錯誤碼。

使用者空間

bpf_map_update_elem()

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

可以使用 bpf_map_update_elem() libbpf 函式將對映 map_fd 的套接字本地儲存新增到或更新到套接字。套接字由儲存在指標 key 中的 socket fd 標識。指標 value 包含要新增到或更新到套接字 fd 的資料。value 的型別和大小應與對映定義的值型別相同。

flags 引數可用於控制更新行為

  • BPF_ANY 將為 socket fd 建立儲存或更新現有儲存。

  • BPF_NOEXIST 將僅在 socket fd 不存在時建立儲存,否則呼叫將以 -EEXIST 失敗。

  • BPF_EXIST 將在 socket fd 已經存在時更新其現有儲存,否則呼叫將以 -ENOENT 失敗。

成功時返回 0,失敗時返回負錯誤碼。

bpf_map_lookup_elem()

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

可以使用 bpf_map_lookup_elem() libbpf 函式從套接字中檢索對映 map_fd 的套接字本地儲存。儲存是從由儲存在指標 key 中的 socket fd 標識的套接字中檢索的。成功時返回 0,失敗時返回負錯誤碼。

bpf_map_delete_elem()

int bpf_map_delete_elem(int map_fd, const void *key)

可以使用 bpf_map_delete_elem() libbpf 函式從套接字中刪除對映 map_fd 的套接字本地儲存。儲存是從由儲存在指標 key 中的 socket fd 標識的套接字中刪除的。成功時返回 0,失敗時返回負錯誤碼。

示例

核心 BPF

此程式碼片段展示瞭如何在 BPF 程式中宣告套接字本地儲存

struct {
        __uint(type, BPF_MAP_TYPE_SK_STORAGE);
        __uint(map_flags, BPF_F_NO_PREALLOC);
        __type(key, int);
        __type(value, struct my_storage);
} socket_storage SEC(".maps");

此程式碼片段展示瞭如何在 BPF 程式中檢索套接字本地儲存

SEC("sockops")
int _sockops(struct bpf_sock_ops *ctx)
{
        struct my_storage *storage;
        struct bpf_sock *sk;

        sk = ctx->sk;
        if (!sk)
                return 1;

        storage = bpf_sk_storage_get(&socket_storage, sk, 0,
                                     BPF_LOCAL_STORAGE_GET_F_CREATE);
        if (!storage)
                return 1;

        /* Use 'storage' here */

        return 1;
}

請參閱 tools/testing/selftests/bpf 目錄以獲取功能示例。

參考資料

https://lwn.net/ml/netdev/20190426171103.61892-1-kafai@fb.com/