147 lines
4.1 KiB
ReStructuredText
147 lines
4.1 KiB
ReStructuredText
|
.. SPDX-License-Identifier: GPL-2.0-only
|
||
|
.. Copyright (C) 2022 Red Hat, Inc.
|
||
|
|
||
|
=========================================
|
||
|
BPF_MAP_TYPE_QUEUE and BPF_MAP_TYPE_STACK
|
||
|
=========================================
|
||
|
|
||
|
.. note::
|
||
|
- ``BPF_MAP_TYPE_QUEUE`` and ``BPF_MAP_TYPE_STACK`` were introduced
|
||
|
in kernel version 4.20
|
||
|
|
||
|
``BPF_MAP_TYPE_QUEUE`` provides FIFO storage and ``BPF_MAP_TYPE_STACK``
|
||
|
provides LIFO storage for BPF programs. These maps support peek, pop and
|
||
|
push operations that are exposed to BPF programs through the respective
|
||
|
helpers. These operations are exposed to userspace applications using
|
||
|
the existing ``bpf`` syscall in the following way:
|
||
|
|
||
|
- ``BPF_MAP_LOOKUP_ELEM`` -> peek
|
||
|
- ``BPF_MAP_LOOKUP_AND_DELETE_ELEM`` -> pop
|
||
|
- ``BPF_MAP_UPDATE_ELEM`` -> push
|
||
|
|
||
|
``BPF_MAP_TYPE_QUEUE`` and ``BPF_MAP_TYPE_STACK`` do not support
|
||
|
``BPF_F_NO_PREALLOC``.
|
||
|
|
||
|
Usage
|
||
|
=====
|
||
|
|
||
|
Kernel BPF
|
||
|
----------
|
||
|
|
||
|
bpf_map_push_elem()
|
||
|
~~~~~~~~~~~~~~~~~~~
|
||
|
|
||
|
.. code-block:: c
|
||
|
|
||
|
long bpf_map_push_elem(struct bpf_map *map, const void *value, u64 flags)
|
||
|
|
||
|
An element ``value`` can be added to a queue or stack using the
|
||
|
``bpf_map_push_elem`` helper. The ``flags`` parameter must be set to
|
||
|
``BPF_ANY`` or ``BPF_EXIST``. If ``flags`` is set to ``BPF_EXIST`` then,
|
||
|
when the queue or stack is full, the oldest element will be removed to
|
||
|
make room for ``value`` to be added. Returns ``0`` on success, or
|
||
|
negative error in case of failure.
|
||
|
|
||
|
bpf_map_peek_elem()
|
||
|
~~~~~~~~~~~~~~~~~~~
|
||
|
|
||
|
.. code-block:: c
|
||
|
|
||
|
long bpf_map_peek_elem(struct bpf_map *map, void *value)
|
||
|
|
||
|
This helper fetches an element ``value`` from a queue or stack without
|
||
|
removing it. Returns ``0`` on success, or negative error in case of
|
||
|
failure.
|
||
|
|
||
|
bpf_map_pop_elem()
|
||
|
~~~~~~~~~~~~~~~~~~
|
||
|
|
||
|
.. code-block:: c
|
||
|
|
||
|
long bpf_map_pop_elem(struct bpf_map *map, void *value)
|
||
|
|
||
|
This helper removes an element into ``value`` from a queue or
|
||
|
stack. Returns ``0`` on success, or negative error in case of failure.
|
||
|
|
||
|
|
||
|
Userspace
|
||
|
---------
|
||
|
|
||
|
bpf_map_update_elem()
|
||
|
~~~~~~~~~~~~~~~~~~~~~
|
||
|
|
||
|
.. code-block:: c
|
||
|
|
||
|
int bpf_map_update_elem (int fd, const void *key, const void *value, __u64 flags)
|
||
|
|
||
|
A userspace program can push ``value`` onto a queue or stack using libbpf's
|
||
|
``bpf_map_update_elem`` function. The ``key`` parameter must be set to
|
||
|
``NULL`` and ``flags`` must be set to ``BPF_ANY`` or ``BPF_EXIST``, with the
|
||
|
same semantics as the ``bpf_map_push_elem`` kernel helper. Returns ``0`` on
|
||
|
success, or negative error in case of failure.
|
||
|
|
||
|
bpf_map_lookup_elem()
|
||
|
~~~~~~~~~~~~~~~~~~~~~
|
||
|
|
||
|
.. code-block:: c
|
||
|
|
||
|
int bpf_map_lookup_elem (int fd, const void *key, void *value)
|
||
|
|
||
|
A userspace program can peek at the ``value`` at the head of a queue or stack
|
||
|
using the libbpf ``bpf_map_lookup_elem`` function. The ``key`` parameter must be
|
||
|
set to ``NULL``. Returns ``0`` on success, or negative error in case of
|
||
|
failure.
|
||
|
|
||
|
bpf_map_lookup_and_delete_elem()
|
||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
|
||
|
.. code-block:: c
|
||
|
|
||
|
int bpf_map_lookup_and_delete_elem (int fd, const void *key, void *value)
|
||
|
|
||
|
A userspace program can pop a ``value`` from the head of a queue or stack using
|
||
|
the libbpf ``bpf_map_lookup_and_delete_elem`` function. The ``key`` parameter
|
||
|
must be set to ``NULL``. Returns ``0`` on success, or negative error in case of
|
||
|
failure.
|
||
|
|
||
|
Examples
|
||
|
========
|
||
|
|
||
|
Kernel BPF
|
||
|
----------
|
||
|
|
||
|
This snippet shows how to declare a queue in a BPF program:
|
||
|
|
||
|
.. code-block:: c
|
||
|
|
||
|
struct {
|
||
|
__uint(type, BPF_MAP_TYPE_QUEUE);
|
||
|
__type(value, __u32);
|
||
|
__uint(max_entries, 10);
|
||
|
} queue SEC(".maps");
|
||
|
|
||
|
|
||
|
Userspace
|
||
|
---------
|
||
|
|
||
|
This snippet shows how to use libbpf's low-level API to create a queue from
|
||
|
userspace:
|
||
|
|
||
|
.. code-block:: c
|
||
|
|
||
|
int create_queue()
|
||
|
{
|
||
|
return bpf_map_create(BPF_MAP_TYPE_QUEUE,
|
||
|
"sample_queue", /* name */
|
||
|
0, /* key size, must be zero */
|
||
|
sizeof(__u32), /* value size */
|
||
|
10, /* max entries */
|
||
|
NULL); /* create options */
|
||
|
}
|
||
|
|
||
|
|
||
|
References
|
||
|
==========
|
||
|
|
||
|
https://lwn.net/ml/netdev/153986858555.9127.14517764371945179514.stgit@kernel/
|