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/