Skip to content

Conversation

@etsal
Copy link
Contributor

@etsal etsal commented Dec 9, 2025

Add libbpf-rs support for interacting with BPF streams from Rust code. The interface provides the option to either directly specify the prog fd/stream id, or to hide the details behind a Stream abstraction.

Copy link
Collaborator

@danielocfb danielocfb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @etsal, thanks for the pull request. Left a few comments with suggestions for improvement/clarifying questions. Can you please make sure to add tests for the functionality?

In general it feels as if Stream should likely implement io::Read to enable proper interop with other Rust components.

@etsal
Copy link
Contributor Author

etsal commented Dec 10, 2025

Thank you for the review, I will update the PR accordingly and post here to confirm it's ready for review. Ack to all comments, though I have a couple followup questions (inline).

@etsal
Copy link
Contributor Author

etsal commented Dec 10, 2025

Updated the code and added tests. The interface now presents the streams only indirectly and without exposing the type itself unless the user opts to create an instance directly. I think the code now is more idiomatic and looks a lot less like C.

@etsal etsal force-pushed the streams branch 3 times, most recently from ad9d89b to 2b0bad2 Compare December 10, 2025 21:24
@etsal
Copy link
Contributor Author

etsal commented Dec 10, 2025

The failing tests looks like are caused the test VMs' kernel being < 6.17?

Copy link
Collaborator

@danielocfb danielocfb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me now. Left a few more coments/questions/suggestions; please take another look. Please also fix CI so we can merge.

libbpf_sys::bpf_prog_stream_read(
self.prog_fd.as_raw_fd(),
self.stream_id,
buf.as_mut_ptr() as *mut c_void,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
buf.as_mut_ptr() as *mut c_void,
buf.as_mut_ptr().cast()

self.stream_id,
buf.as_mut_ptr() as *mut c_void,
buf.len().try_into().unwrap(),
&mut c_opts as *mut bpf_prog_stream_read_opts,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
&mut c_opts as *mut bpf_prog_stream_read_opts,
&raw mut c_opts,

let mut stdout = prog.stdout();
let mut buf = [0u8; 1024];

// The read itself should succeed and return 0 bytes
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I misreading or does the comment state the opposite of what is being asserted?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, the condition in the assert!() was wrong.


volatile u64 i;

/* Trigger a may_goto timeout to emit a streams error. */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this may_goto timeout is a way to force the kernel to emit data to stderr, is that how it works? And there is no way to write to a stream directly? And what are the requirements for may_goto to be available? Is it just a certain LLVM version? Or kernel config? It's also not exactly clear what happens if it's not available. Will the test still work?

If there is no easier way to trigger a stream write, can you please expand the comment a bit to make it clear who does what and in response to what exactly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah pretty much, unfortunatley there isn't a straightforward way to directly emit to stdout/stderr. Only stderr can contain data, and that is generated by the BPF runtime in the kernel rather than the program itself. I'll expand the comment to explain.

For may_goto: It's been available since 6.9, and it works regardless of compiler version because there are compatiblity macros to handle older LLVM versions.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use bpf_stream_printk (convenience macro over bpf_stream_vprintk) to write to either stream, triggering a may_goto timeout error also means a 250ms delay.

}
}


Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to remove spurious formatting changes. Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I ran rustfmt on the file directly and there seem to be some extra newlines already present in the file. I'll remove them from the diff.

@danielocfb
Copy link
Collaborator

danielocfb commented Dec 10, 2025

The failing tests looks like are caused the test VMs' kernel being < 6.17?

If that's the case you can mark them as ignored for now.

#[ignore = "requires kernel with kprobe multi support"]

At the moment we just use whatever kernel the Ubuntu image ships with. Right now that seems to be 6.11 (https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md)

Add an abstraction for reading BPF Streams. This commit
introduces the wrappers around the libbpf-sys method.

Signed-off-by: Emil Tsalapatis <[email protected]>
Add tests for BPF Streams. The tests access both the stdout
and stderr streams, and ensure the code works regardless of
whether there is ready data.

Signed-off-by: Emil Tsalapatis <[email protected]>
@etsal
Copy link
Contributor Author

etsal commented Dec 12, 2025

Clippy seems to be failing on unrelated code.

@etsal
Copy link
Contributor Author

etsal commented Dec 12, 2025

Not sure why clippy is hitting these errors, they are for pre-existing code.

@danielocfb
Copy link
Collaborator

It's failing because you don't use all functions provided by the common module, which your new test_stream module uses, so Rust complains about unused code.

I fixed it up and merged. Thanks for the pull request!

@danielocfb danielocfb closed this Dec 12, 2025
@etsal
Copy link
Contributor Author

etsal commented Dec 12, 2025

Thank you for the detailed feedback!

danielocfb pushed a commit to d-e-s-o/libbpf-rs that referenced this pull request Dec 15, 2025
Add a CHANGELOG entry for pull request libbpf#1284, which added support for
accessing BPF stdout and stderr streams.

Signed-off-by: Daniel Müller <[email protected]>
danielocfb pushed a commit that referenced this pull request Dec 15, 2025
Add a CHANGELOG entry for pull request #1284, which added support for
accessing BPF stdout and stderr streams.

Signed-off-by: Daniel Müller <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants