|  | .. 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/ |