BPF_MAP_TYPE_SK_STORAGE

注意

  • BPF_MAP_TYPE_SK_STORAGE 在内核版本 5.2 中引入

BPF_MAP_TYPE_SK_STORAGE 用于为 BPF 程序提供套接字本地存储。类型为 BPF_MAP_TYPE_SK_STORAGE 的 map 声明要提供的存储类型,并充当访问套接字本地存储的句柄。类型为 BPF_MAP_TYPE_SK_STORAGE 的 map 的值存储在每个套接字本地,而不是与 map 存储在一起。内核负责在请求时为套接字分配存储空间,并在删除 map 或套接字时释放存储空间。

注意

  • 键类型必须为 intmax_entries 必须设置为 0

  • 创建套接字本地存储的 map 时,必须使用 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 标志,则如果 sk 的存储尚不存在,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 map_fd 的套接字本地存储添加到套接字或更新。套接字由指针 key 中存储的 socket fd 标识。指针 value 包含要添加到套接字 fd 或更新的数据。value 的类型和大小应与 map 定义的值类型相同。

可以使用 flags 参数来控制更新行为

  • BPF_ANY 将为 socket fd 创建存储空间或更新现有存储空间。

  • 仅当 socket fd 尚未存在时,BPF_NOEXIST 才会为其创建存储空间,否则调用将失败并返回 -EEXIST

  • 如果 socket fd 的存储空间已存在,则 BPF_EXIST 将更新该存储空间,否则调用将失败并返回 -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 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 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/[email protected]/