KFunc bpf_wq_init
Initialize a work-queue.
Definition
This kfunc initializes a work-queue which allows eBPF programs to schedule work to be executed asynchronously.
wq
: A pointer to a struct bpf_wq
which must reside in a map value.
p__map
: A pointer to a map that contains the wq
as value.
flags
: Flags to allow for future extensions.
Returns
Return 0
on success, or a negative error code on failure.
int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags)
Usage
This is the first step in using a work-queue. A work-queue is a mechanism to schedule work to be executed asynchronously. After initialization a callback function can be associated with the work-queue using the bpf_wq_set_callback_impl
kfunc and the work can be started using the bpf_wq_start
kfunc.
The callback will be called asynchronously sometime after the current eBPF program has finished executing whenever the scheduler decides to run the work-queue.
Program types
The following program types can make use of this kfunc:
BPF_PROG_TYPE_CGROUP_SKB
BPF_PROG_TYPE_CGROUP_SOCK_ADDR
BPF_PROG_TYPE_LSM
BPF_PROG_TYPE_LWT_IN
BPF_PROG_TYPE_LWT_OUT
BPF_PROG_TYPE_LWT_SEG6LOCAL
BPF_PROG_TYPE_LWT_XMIT
BPF_PROG_TYPE_NETFILTER
BPF_PROG_TYPE_SCHED_ACT
BPF_PROG_TYPE_SCHED_CLS
BPF_PROG_TYPE_SK_SKB
BPF_PROG_TYPE_SOCKET_FILTER
BPF_PROG_TYPE_STRUCT_OPS
BPF_PROG_TYPE_SYSCALL
BPF_PROG_TYPE_TRACING
BPF_PROG_TYPE_XDP
Example
Example
/* Copyright (c) 2024 Benjamin Tissoires */
#include <bpf/bpf_helpers.h>
char _license[] SEC("license") = "GPL";
struct elem {
struct bpf_wq w;
};
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 2);
__type(key, int);
__type(value, struct elem);
} array SEC(".maps");
__u32 ok;
__u32 ok_sleepable;
void bpf_kfunc_common_test(void) __ksym;
static int test_elem_callback(void *map, int *key,
int (callback_fn)(void *map, int *key, struct bpf_wq *wq))
{
struct elem init = {}, *val;
struct bpf_wq *wq;
if ((ok & (1 << *key) ||
(ok_sleepable & (1 << *key))))
return -22;
if (map == &lru &&
bpf_map_update_elem(map, key, &init, 0))
return -1;
val = bpf_map_lookup_elem(map, key);
if (!val)
return -2;
wq = &val->w;
if (bpf_wq_init(wq, map, 0) != 0)
return -3;
if (bpf_wq_set_callback(wq, callback_fn, 0))
return -4;
if (bpf_wq_start(wq, 0))
return -5;
return 0;
}
/* callback for non sleepable workqueue */
static int wq_callback(void *map, int *key, struct bpf_wq *work)
{
bpf_kfunc_common_test();
ok |= (1 << *key);
return 0;
}
SEC("tc")
long test_call_array_sleepable(void *ctx)
{
int key = 0;
return test_elem_callback(&array, &key, wq_cb_sleepable);
}