Libbpf eBPF macro BPF_PROG2
The BPF_PROG2
macro makes it easier to write programs for program types that receive []u64
contexts such as BPF_PROG_TYPE_TRACING
programs. It improves upon the older BPF_PROG
macro.
Definition
#define BPF_PROG2(name, args...) \
name(unsigned long long *ctx); \
static __always_inline typeof(name(0)) \
____##name(unsigned long long *ctx ___bpf_ctx_decl(args)); \
typeof(name(0)) name(unsigned long long *ctx) \
{ \
return ____##name(ctx ___bpf_ctx_arg(args)); \
} \
static __always_inline typeof(name(0)) \
____##name(unsigned long long *ctx ___bpf_ctx_decl(args))
Usage
This macro is useful when using program types that have a []u64
context type (typically written as unsigned long long *
).
Conventionally with these program contexts, the arguments to the program are put in this array. So the first argument would be in ctx[0]
, the second in ctx[1]
. It is up to the program author to cast them into their actual type.
The BPF_PROG2
macro allows you to write your program with a normal function signature, the macro will then do the casting for you.
This macro also accounts for an edge case in the struct{u64, u64}
for example. Since the context is a translation of the arguments passed, it to can use one or two slots depending on the type. The BPF_PROG2
handles this in the background, which is what improved over the BPF_PROG
version of this macro.
Note
The original context will stay available as ctx
, if you ever wish to access it manually or need to pass it to a helper or kfunc. Therefor, the variable name ctx
should not be reused in arguments or function body.
Example
The bpfptr_t
is actually the following type:
struct {
union {
void *kernel;
void __user *user;
};
bool is_kernel : 1;
}
Which, with padding is 16 bytes and thus requires BPF_PROG2
to correctly cast the arguments.
SEC("fexit/__sys_bpf")
int BPF_PROG2(sys_bpf, int, cmd, bpfptr_t, uattr, unsigned int, size, int, ret)
{
bpf_printf("BPF syscall returned with: %d", ret);
return 0;
}