KFunc bpf_wq_init
Initialize a workqueue.
Definition
This kfunc initializes a workqueue 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 workqueue. A workqueue is a mechanism to schedule work to be executed asynchronously. After initialization a callback function can be associated with the workqueue 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 workqueue.
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);
}