BPF_MAP_TYPE_SK_STORAGE

Note

  • BPF_MAP_TYPE_SK_STORAGE was introduced in kernel version 5.2

BPF_MAP_TYPE_SK_STORAGE is used to provide socket-local storage for BPF programs. A map of type BPF_MAP_TYPE_SK_STORAGE declares the type of storage to be provided and acts as the handle for accessing the socket-local storage. The values for maps of type BPF_MAP_TYPE_SK_STORAGE are stored locally with each socket instead of with the map. The kernel is responsible for allocating storage for a socket when requested and for freeing the storage when either the map or the socket is deleted.

Note

  • The key type must be int and max_entries must be set to 0.

  • The BPF_F_NO_PREALLOC flag must be used when creating a map for socket-local storage.

Usage

Kernel BPF

bpf_sk_storage_get()

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

Socket-local storage for map can be retrieved from socket sk using the bpf_sk_storage_get() helper. If the BPF_LOCAL_STORAGE_GET_F_CREATE flag is used then bpf_sk_storage_get() will create the storage for sk if it does not already exist. value can be used together with BPF_LOCAL_STORAGE_GET_F_CREATE to initialize the storage value, otherwise it will be zero initialized. Returns a pointer to the storage on success, or NULL in case of failure.

Note

  • sk is a kernel struct sock pointer for LSM or tracing programs.

  • sk is a struct bpf_sock pointer for other program types.

bpf_sk_storage_delete()

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

Socket-local storage for map can be deleted from socket sk using the bpf_sk_storage_delete() helper. Returns 0 on success, or negative error in case of failure.

User space

bpf_map_update_elem()

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

Socket-local storage for map map_fd can be added or updated locally to a socket using the bpf_map_update_elem() libbpf function. The socket is identified by a socket fd stored in the pointer key. The pointer value has the data to be added or updated to the socket fd. The type and size of value should be the same as the value type of the map definition.

The flags parameter can be used to control the update behaviour:

  • BPF_ANY will create storage for socket fd or update existing storage.

  • BPF_NOEXIST will create storage for socket fd only if it did not already exist, otherwise the call will fail with -EEXIST.

  • BPF_EXIST will update existing storage for socket fd if it already exists, otherwise the call will fail with -ENOENT.

Returns 0 on success, or negative error in case of failure.

bpf_map_lookup_elem()

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

Socket-local storage for map map_fd can be retrieved from a socket using the bpf_map_lookup_elem() libbpf function. The storage is retrieved from the socket identified by a socket fd stored in the pointer key. Returns 0 on success, or negative error in case of failure.

bpf_map_delete_elem()

int bpf_map_delete_elem(int map_fd, const void *key)

Socket-local storage for map map_fd can be deleted from a socket using the bpf_map_delete_elem() libbpf function. The storage is deleted from the socket identified by a socket fd stored in the pointer key. Returns 0 on success, or negative error in case of failure.

Examples

Kernel BPF

This snippet shows how to declare socket-local storage in a BPF program:

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");

This snippet shows how to retrieve socket-local storage in a BPF program:

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;
}

Please see the tools/testing/selftests/bpf directory for functional examples.

References

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