| .. 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) | |
| 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() | |
| ~~~~~~~~~~~~~~~~~~~~~~~ | |
| .. code-block:: c | |
| 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() | |
| ~~~~~~~~~~~~~~~~~~~~~ | |
| .. code-block:: c | |
| 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() | |
| ~~~~~~~~~~~~~~~~~~~~~ | |
| .. code-block:: c | |
| 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() | |
| ~~~~~~~~~~~~~~~~~~~~~ | |
| .. code-block:: c | |
| 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: | |
| .. 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/ |