2022-12-09 14:24:01 +03:00
.. SPDX-License-Identifier: GPL-2.0-only
.. Copyright (C) 2022 Red Hat, Inc.
=======================
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()
~~~~~~~~~~~~~~~~~~~~
.. code-block :: c
void *bpf_sk_storage_get(struct bpf_map * map, void *sk, void * value, u64 flags)
2022-12-12 13:16:00 +03:00
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
2022-12-09 14:24:01 +03:00
`` 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()
~~~~~~~~~~~~~~~~~~~~~~~
.. code-block :: c
long bpf_sk_storage_delete(struct bpf_map *map, void * sk)
2022-12-12 13:16:00 +03:00
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.
2022-12-09 14:24:01 +03:00
User space
----------
bpf_map_update_elem()
~~~~~~~~~~~~~~~~~~~~~
.. code-block :: c
int bpf_map_update_elem(int map_fd, const void *key, const void * value, __u64 flags)
2022-12-12 13:16:00 +03:00
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.
2022-12-09 14:24:01 +03:00
2022-12-12 13:16:00 +03:00
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 `` .
2022-12-09 14:24:01 +03:00
Returns `` 0 `` on success, or negative error in case of failure.
bpf_map_lookup_elem()
~~~~~~~~~~~~~~~~~~~~~
.. code-block :: c
int bpf_map_lookup_elem(int map_fd, const void *key, void * value)
2022-12-12 13:16:00 +03:00
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.
2022-12-09 14:24:01 +03:00
bpf_map_delete_elem()
~~~~~~~~~~~~~~~~~~~~~
.. code-block :: c
int bpf_map_delete_elem(int map_fd, const void *key)
2022-12-12 13:16:00 +03:00
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.
2022-12-09 14:24:01 +03:00
Examples
========
Kernel BPF
----------
This snippet shows how to declare socket-local storage in a BPF program:
.. code-block :: c
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:
.. code-block :: c
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/