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
andmax_entries
must be set to0
.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 kernelstruct sock
pointer for LSM or tracing programs.sk
is astruct 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 socketfd
or update existing storage.BPF_NOEXIST
will create storage for socketfd
only if it did not already exist, otherwise the call will fail with-EEXIST
.BPF_EXIST
will update existing storage for socketfd
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/