Skip to content

How to generate atomic_fetch_add() BPF instruction? #1268

@nplrkn

Description

@nplrkn

Two previous issues (#947 and #588) have explained that it is possible to use intrinsics such as atomic_xadd_relaxed() to generate BPF atomic instructions.

However, it does not seem possible to do a BPF atomic "add and fetch" this way.

Suppose seq_num is a *mut u32. The following compiles ok.

atomic_xadd_relaxed(seq_num, 1);  

But this fails to compile.

let prev_value = atomic_xadd_relaxed(seq_num, 1);  
info!(&cxt, "Prev value {}", prev_value); 

with ERROR llvm: :0:0: in function ebpf_downlink i32 (ptr): Invalid usage of the XADD return value.

From inspecting the bytecode with bpftool, the issue is that the BPF_FETCH modifier (defined at https://www.rfc-editor.org/rfc/rfc9669.html#name-atomic-operations) is not being set, so it's not surprising that this code that tries to use a return value doesn't work.

From https://www.kernel.org/doc/html/v5.17/bpf/instruction-set.html#atomic-operations, when BPF_FETCH is set, "these operations also overwrite src_reg with the value that was in memory before it was modified".

If I patch the eBPF bytecode, I can see the above in action.

Instruction as shown by bpftool without BPF_FETCH:
(c3) lock *(u32 *)(r0 +0) += r1

Instruction in patched bytecode as shown by bpftool with BPF_FETCH:
(c3) r1 = atomic_fetch_add((u32 *)(r0 +0), r1)

So: how do I generate an atomic_fetch_add() BPF instruction without patching the bytecode?

If there is no way to do that, would it be possible to have a fix/enhancement?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions