bpf: Add bpf_user_ringbuf_drain() helper
In a prior change, we added a new BPF_MAP_TYPE_USER_RINGBUF map type which
will allow user-space applications to publish messages to a ring buffer
that is consumed by a BPF program in kernel-space. In order for this
map-type to be useful, it will require a BPF helper function that BPF
programs can invoke to drain samples from the ring buffer, and invoke
callbacks on those samples. This change adds that capability via a new BPF
helper function:
bpf_user_ringbuf_drain(struct bpf_map *map, void *callback_fn, void *ctx,
u64 flags)
BPF programs may invoke this function to run callback_fn() on a series of
samples in the ring buffer. callback_fn() has the following signature:
long callback_fn(struct bpf_dynptr *dynptr, void *context);
Samples are provided to the callback in the form of struct bpf_dynptr *'s,
which the program can read using BPF helper functions for querying
struct bpf_dynptr's.
In order to support bpf_ringbuf_drain(), a new PTR_TO_DYNPTR register
type is added to the verifier to reflect a dynptr that was allocated by
a helper function and passed to a BPF program. Unlike PTR_TO_STACK
dynptrs which are allocated on the stack by a BPF program, PTR_TO_DYNPTR
dynptrs need not use reference tracking, as the BPF helper is trusted to
properly free the dynptr before returning. The verifier currently only
supports PTR_TO_DYNPTR registers that are also DYNPTR_TYPE_LOCAL.
Note that while the corresponding user-space libbpf logic will be added
in a subsequent patch, this patch does contain an implementation of the
.map_poll() callback for BPF_MAP_TYPE_USER_RINGBUF maps. This
.map_poll() callback guarantees that an epoll-waiting user-space
producer will receive at least one event notification whenever at least
one sample is drained in an invocation of bpf_user_ringbuf_drain(),
provided that the function is not invoked with the BPF_RB_NO_WAKEUP
flag. If the BPF_RB_FORCE_WAKEUP flag is provided, a wakeup
notification is sent even if no sample was drained.
Signed-off-by: David Vernet <void@manifault.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20220920000100.477320-3-void@manifault.com
This commit is contained in:
committed by
Andrii Nakryiko
parent
583c1f4201
commit
2057156738
@@ -5388,6 +5388,43 @@ union bpf_attr {
|
||||
* Return
|
||||
* Current *ktime*.
|
||||
*
|
||||
* long bpf_user_ringbuf_drain(struct bpf_map *map, void *callback_fn, void *ctx, u64 flags)
|
||||
* Description
|
||||
* Drain samples from the specified user ring buffer, and invoke
|
||||
* the provided callback for each such sample:
|
||||
*
|
||||
* long (\*callback_fn)(struct bpf_dynptr \*dynptr, void \*ctx);
|
||||
*
|
||||
* If **callback_fn** returns 0, the helper will continue to try
|
||||
* and drain the next sample, up to a maximum of
|
||||
* BPF_MAX_USER_RINGBUF_SAMPLES samples. If the return value is 1,
|
||||
* the helper will skip the rest of the samples and return. Other
|
||||
* return values are not used now, and will be rejected by the
|
||||
* verifier.
|
||||
* Return
|
||||
* The number of drained samples if no error was encountered while
|
||||
* draining samples, or 0 if no samples were present in the ring
|
||||
* buffer. If a user-space producer was epoll-waiting on this map,
|
||||
* and at least one sample was drained, they will receive an event
|
||||
* notification notifying them of available space in the ring
|
||||
* buffer. If the BPF_RB_NO_WAKEUP flag is passed to this
|
||||
* function, no wakeup notification will be sent. If the
|
||||
* BPF_RB_FORCE_WAKEUP flag is passed, a wakeup notification will
|
||||
* be sent even if no sample was drained.
|
||||
*
|
||||
* On failure, the returned value is one of the following:
|
||||
*
|
||||
* **-EBUSY** if the ring buffer is contended, and another calling
|
||||
* context was concurrently draining the ring buffer.
|
||||
*
|
||||
* **-EINVAL** if user-space is not properly tracking the ring
|
||||
* buffer due to the producer position not being aligned to 8
|
||||
* bytes, a sample not being aligned to 8 bytes, or the producer
|
||||
* position not matching the advertised length of a sample.
|
||||
*
|
||||
* **-E2BIG** if user-space has tried to publish a sample which is
|
||||
* larger than the size of the ring buffer, or which cannot fit
|
||||
* within a struct bpf_dynptr.
|
||||
*/
|
||||
#define __BPF_FUNC_MAPPER(FN) \
|
||||
FN(unspec), \
|
||||
@@ -5599,6 +5636,7 @@ union bpf_attr {
|
||||
FN(tcp_raw_check_syncookie_ipv4), \
|
||||
FN(tcp_raw_check_syncookie_ipv6), \
|
||||
FN(ktime_get_tai_ns), \
|
||||
FN(user_ringbuf_drain), \
|
||||
/* */
|
||||
|
||||
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
|
||||
|
||||
Reference in New Issue
Block a user