Donald Hunter | f3212ad | 2022-12-09 11:24:01 +0000 | [diff] [blame] | 1 | .. SPDX-License-Identifier: GPL-2.0-only |
| 2 | .. Copyright (C) 2022 Red Hat, Inc. |
| 3 | |
| 4 | ======================= |
| 5 | BPF_MAP_TYPE_SK_STORAGE |
| 6 | ======================= |
| 7 | |
| 8 | .. note:: |
| 9 | - ``BPF_MAP_TYPE_SK_STORAGE`` was introduced in kernel version 5.2 |
| 10 | |
| 11 | ``BPF_MAP_TYPE_SK_STORAGE`` is used to provide socket-local storage for BPF |
| 12 | programs. A map of type ``BPF_MAP_TYPE_SK_STORAGE`` declares the type of storage |
| 13 | to be provided and acts as the handle for accessing the socket-local |
| 14 | storage. The values for maps of type ``BPF_MAP_TYPE_SK_STORAGE`` are stored |
| 15 | locally with each socket instead of with the map. The kernel is responsible for |
| 16 | allocating storage for a socket when requested and for freeing the storage when |
| 17 | either the map or the socket is deleted. |
| 18 | |
| 19 | .. note:: |
| 20 | - The key type must be ``int`` and ``max_entries`` must be set to ``0``. |
| 21 | - The ``BPF_F_NO_PREALLOC`` flag must be used when creating a map for |
| 22 | socket-local storage. |
| 23 | |
| 24 | Usage |
| 25 | ===== |
| 26 | |
| 27 | Kernel BPF |
| 28 | ---------- |
| 29 | |
| 30 | bpf_sk_storage_get() |
| 31 | ~~~~~~~~~~~~~~~~~~~~ |
| 32 | |
| 33 | .. code-block:: c |
| 34 | |
| 35 | void *bpf_sk_storage_get(struct bpf_map *map, void *sk, void *value, u64 flags) |
| 36 | |
Donald Hunter | d2b497a | 2022-12-12 10:16:00 +0000 | [diff] [blame] | 37 | Socket-local storage for ``map`` can be retrieved from socket ``sk`` using the |
| 38 | ``bpf_sk_storage_get()`` helper. If the ``BPF_LOCAL_STORAGE_GET_F_CREATE`` |
| 39 | flag is used then ``bpf_sk_storage_get()`` will create the storage for ``sk`` |
| 40 | if it does not already exist. ``value`` can be used together with |
| 41 | ``BPF_LOCAL_STORAGE_GET_F_CREATE`` to initialize the storage value, otherwise |
| 42 | it will be zero initialized. Returns a pointer to the storage on success, or |
Donald Hunter | f3212ad | 2022-12-09 11:24:01 +0000 | [diff] [blame] | 43 | ``NULL`` in case of failure. |
| 44 | |
| 45 | .. note:: |
| 46 | - ``sk`` is a kernel ``struct sock`` pointer for LSM or tracing programs. |
| 47 | - ``sk`` is a ``struct bpf_sock`` pointer for other program types. |
| 48 | |
| 49 | bpf_sk_storage_delete() |
| 50 | ~~~~~~~~~~~~~~~~~~~~~~~ |
| 51 | |
| 52 | .. code-block:: c |
| 53 | |
| 54 | long bpf_sk_storage_delete(struct bpf_map *map, void *sk) |
| 55 | |
Donald Hunter | d2b497a | 2022-12-12 10:16:00 +0000 | [diff] [blame] | 56 | Socket-local storage for ``map`` can be deleted from socket ``sk`` using the |
| 57 | ``bpf_sk_storage_delete()`` helper. Returns ``0`` on success, or negative |
| 58 | error in case of failure. |
Donald Hunter | f3212ad | 2022-12-09 11:24:01 +0000 | [diff] [blame] | 59 | |
| 60 | User space |
| 61 | ---------- |
| 62 | |
| 63 | bpf_map_update_elem() |
| 64 | ~~~~~~~~~~~~~~~~~~~~~ |
| 65 | |
| 66 | .. code-block:: c |
| 67 | |
| 68 | int bpf_map_update_elem(int map_fd, const void *key, const void *value, __u64 flags) |
| 69 | |
Donald Hunter | d2b497a | 2022-12-12 10:16:00 +0000 | [diff] [blame] | 70 | Socket-local storage for map ``map_fd`` can be added or updated locally to a |
| 71 | socket using the ``bpf_map_update_elem()`` libbpf function. The socket is |
| 72 | identified by a `socket` ``fd`` stored in the pointer ``key``. The pointer |
| 73 | ``value`` has the data to be added or updated to the socket ``fd``. The type |
| 74 | and size of ``value`` should be the same as the value type of the map |
| 75 | definition. |
Donald Hunter | f3212ad | 2022-12-09 11:24:01 +0000 | [diff] [blame] | 76 | |
Donald Hunter | d2b497a | 2022-12-12 10:16:00 +0000 | [diff] [blame] | 77 | The ``flags`` parameter can be used to control the update behaviour: |
| 78 | |
| 79 | - ``BPF_ANY`` will create storage for `socket` ``fd`` or update existing storage. |
| 80 | - ``BPF_NOEXIST`` will create storage for `socket` ``fd`` only if it did not |
| 81 | already exist, otherwise the call will fail with ``-EEXIST``. |
| 82 | - ``BPF_EXIST`` will update existing storage for `socket` ``fd`` if it already |
| 83 | exists, otherwise the call will fail with ``-ENOENT``. |
Donald Hunter | f3212ad | 2022-12-09 11:24:01 +0000 | [diff] [blame] | 84 | |
| 85 | Returns ``0`` on success, or negative error in case of failure. |
| 86 | |
| 87 | bpf_map_lookup_elem() |
| 88 | ~~~~~~~~~~~~~~~~~~~~~ |
| 89 | |
| 90 | .. code-block:: c |
| 91 | |
| 92 | int bpf_map_lookup_elem(int map_fd, const void *key, void *value) |
| 93 | |
Donald Hunter | d2b497a | 2022-12-12 10:16:00 +0000 | [diff] [blame] | 94 | Socket-local storage for map ``map_fd`` can be retrieved from a socket using |
| 95 | the ``bpf_map_lookup_elem()`` libbpf function. The storage is retrieved from |
| 96 | the socket identified by a `socket` ``fd`` stored in the pointer |
| 97 | ``key``. Returns ``0`` on success, or negative error in case of failure. |
Donald Hunter | f3212ad | 2022-12-09 11:24:01 +0000 | [diff] [blame] | 98 | |
| 99 | bpf_map_delete_elem() |
| 100 | ~~~~~~~~~~~~~~~~~~~~~ |
| 101 | |
| 102 | .. code-block:: c |
| 103 | |
| 104 | int bpf_map_delete_elem(int map_fd, const void *key) |
| 105 | |
Donald Hunter | d2b497a | 2022-12-12 10:16:00 +0000 | [diff] [blame] | 106 | Socket-local storage for map ``map_fd`` can be deleted from a socket using the |
| 107 | ``bpf_map_delete_elem()`` libbpf function. The storage is deleted from the |
| 108 | socket identified by a `socket` ``fd`` stored in the pointer ``key``. Returns |
| 109 | ``0`` on success, or negative error in case of failure. |
Donald Hunter | f3212ad | 2022-12-09 11:24:01 +0000 | [diff] [blame] | 110 | |
| 111 | Examples |
| 112 | ======== |
| 113 | |
| 114 | Kernel BPF |
| 115 | ---------- |
| 116 | |
| 117 | This snippet shows how to declare socket-local storage in a BPF program: |
| 118 | |
| 119 | .. code-block:: c |
| 120 | |
| 121 | struct { |
| 122 | __uint(type, BPF_MAP_TYPE_SK_STORAGE); |
| 123 | __uint(map_flags, BPF_F_NO_PREALLOC); |
| 124 | __type(key, int); |
| 125 | __type(value, struct my_storage); |
| 126 | } socket_storage SEC(".maps"); |
| 127 | |
| 128 | This snippet shows how to retrieve socket-local storage in a BPF program: |
| 129 | |
| 130 | .. code-block:: c |
| 131 | |
| 132 | SEC("sockops") |
| 133 | int _sockops(struct bpf_sock_ops *ctx) |
| 134 | { |
| 135 | struct my_storage *storage; |
| 136 | struct bpf_sock *sk; |
| 137 | |
| 138 | sk = ctx->sk; |
| 139 | if (!sk) |
| 140 | return 1; |
| 141 | |
| 142 | storage = bpf_sk_storage_get(&socket_storage, sk, 0, |
| 143 | BPF_LOCAL_STORAGE_GET_F_CREATE); |
| 144 | if (!storage) |
| 145 | return 1; |
| 146 | |
| 147 | /* Use 'storage' here */ |
| 148 | |
| 149 | return 1; |
| 150 | } |
| 151 | |
| 152 | |
| 153 | Please see the ``tools/testing/selftests/bpf`` directory for functional |
| 154 | examples. |
| 155 | |
| 156 | References |
| 157 | ========== |
| 158 | |
| 159 | https://lwn.net/ml/netdev/20190426171103.61892-1-kafai@fb.com/ |