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
的映射的值存储在每个套接字本地,而不是存储在映射中。内核负责在请求时为套接字分配存储空间,并在映射或套接字被删除时释放存储空间。
注意
键类型必须是
int
,max_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
将为 socketfd
创建存储或更新现有存储。BPF_NOEXIST
将仅在 socketfd
不存在时创建存储,否则调用将以-EEXIST
失败。BPF_EXIST
将在 socketfd
已经存在时更新其现有存储,否则调用将以-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/