Skip to content

KFunc bpf_wq_init

v6.10

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:

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);
}