Commit | Line | Data |
---|---|---|
f3212ad5 DH |
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 | ||
37 | Socket-local storage can be retrieved using the ``bpf_sk_storage_get()`` | |
38 | helper. The helper gets the storage from ``sk`` that is associated with ``map``. | |
39 | If the ``BPF_LOCAL_STORAGE_GET_F_CREATE`` flag is used then | |
40 | ``bpf_sk_storage_get()`` will create the storage for ``sk`` if it does not | |
41 | already exist. ``value`` can be used together with | |
42 | ``BPF_LOCAL_STORAGE_GET_F_CREATE`` to initialize the storage value, otherwise it | |
43 | will be zero initialized. Returns a pointer to the storage on success, or | |
44 | ``NULL`` in case of failure. | |
45 | ||
46 | .. note:: | |
47 | - ``sk`` is a kernel ``struct sock`` pointer for LSM or tracing programs. | |
48 | - ``sk`` is a ``struct bpf_sock`` pointer for other program types. | |
49 | ||
50 | bpf_sk_storage_delete() | |
51 | ~~~~~~~~~~~~~~~~~~~~~~~ | |
52 | ||
53 | .. code-block:: c | |
54 | ||
55 | long bpf_sk_storage_delete(struct bpf_map *map, void *sk) | |
56 | ||
57 | Socket-local storage can be deleted using the ``bpf_sk_storage_delete()`` | |
58 | helper. The helper deletes the storage from ``sk`` that is identified by | |
59 | ``map``. Returns ``0`` on success, or negative error in case of failure. | |
60 | ||
61 | User space | |
62 | ---------- | |
63 | ||
64 | bpf_map_update_elem() | |
65 | ~~~~~~~~~~~~~~~~~~~~~ | |
66 | ||
67 | .. code-block:: c | |
68 | ||
69 | int bpf_map_update_elem(int map_fd, const void *key, const void *value, __u64 flags) | |
70 | ||
71 | Socket-local storage for the socket identified by ``key`` belonging to | |
72 | ``map_fd`` can be added or updated using the ``bpf_map_update_elem()`` libbpf | |
73 | function. ``key`` must be a pointer to a valid ``fd`` in the user space | |
74 | program. The ``flags`` parameter can be used to control the update behaviour: | |
75 | ||
76 | - ``BPF_ANY`` will create storage for ``fd`` or update existing storage. | |
77 | - ``BPF_NOEXIST`` will create storage for ``fd`` only if it did not already | |
78 | exist, otherwise the call will fail with ``-EEXIST``. | |
79 | - ``BPF_EXIST`` will update existing storage for ``fd`` if it already exists, | |
80 | otherwise the call will fail with ``-ENOENT``. | |
81 | ||
82 | Returns ``0`` on success, or negative error in case of failure. | |
83 | ||
84 | bpf_map_lookup_elem() | |
85 | ~~~~~~~~~~~~~~~~~~~~~ | |
86 | ||
87 | .. code-block:: c | |
88 | ||
89 | int bpf_map_lookup_elem(int map_fd, const void *key, void *value) | |
90 | ||
91 | Socket-local storage for the socket identified by ``key`` belonging to | |
92 | ``map_fd`` can be retrieved using the ``bpf_map_lookup_elem()`` libbpf | |
93 | function. ``key`` must be a pointer to a valid ``fd`` in the user space | |
94 | program. Returns ``0`` on success, or negative error in case of failure. | |
95 | ||
96 | bpf_map_delete_elem() | |
97 | ~~~~~~~~~~~~~~~~~~~~~ | |
98 | ||
99 | .. code-block:: c | |
100 | ||
101 | int bpf_map_delete_elem(int map_fd, const void *key) | |
102 | ||
103 | Socket-local storage for the socket identified by ``key`` belonging to | |
104 | ``map_fd`` can be deleted using the ``bpf_map_delete_elem()`` libbpf | |
105 | function. Returns ``0`` on success, or negative error in case of failure. | |
106 | ||
107 | Examples | |
108 | ======== | |
109 | ||
110 | Kernel BPF | |
111 | ---------- | |
112 | ||
113 | This snippet shows how to declare socket-local storage in a BPF program: | |
114 | ||
115 | .. code-block:: c | |
116 | ||
117 | struct { | |
118 | __uint(type, BPF_MAP_TYPE_SK_STORAGE); | |
119 | __uint(map_flags, BPF_F_NO_PREALLOC); | |
120 | __type(key, int); | |
121 | __type(value, struct my_storage); | |
122 | } socket_storage SEC(".maps"); | |
123 | ||
124 | This snippet shows how to retrieve socket-local storage in a BPF program: | |
125 | ||
126 | .. code-block:: c | |
127 | ||
128 | SEC("sockops") | |
129 | int _sockops(struct bpf_sock_ops *ctx) | |
130 | { | |
131 | struct my_storage *storage; | |
132 | struct bpf_sock *sk; | |
133 | ||
134 | sk = ctx->sk; | |
135 | if (!sk) | |
136 | return 1; | |
137 | ||
138 | storage = bpf_sk_storage_get(&socket_storage, sk, 0, | |
139 | BPF_LOCAL_STORAGE_GET_F_CREATE); | |
140 | if (!storage) | |
141 | return 1; | |
142 | ||
143 | /* Use 'storage' here */ | |
144 | ||
145 | return 1; | |
146 | } | |
147 | ||
148 | ||
149 | Please see the ``tools/testing/selftests/bpf`` directory for functional | |
150 | examples. | |
151 | ||
152 | References | |
153 | ========== | |
154 | ||
155 | https://lwn.net/ml/netdev/20190426171103.61892-1-kafai@fb.com/ |