-
Notifications
You must be signed in to change notification settings - Fork 136
Add BPF_MAP_TYPE_RINGBUF support with RingBufMap #251
Conversation
c696c65
to
46aeb32
Compare
RINGBUF is a relatively new addition to the kernel. Should I put it behind a feature gate (default disabled)? |
Hello @yobiscus It looks great! I feel interested in this PR a lot. Thanks for your But first, it would be better to fix the build failure issue. I also feel embarassed Currently the default kernel of ubuntu 20.04 LTS is v5.4 which does not support |
Hey @rhdxmr, thanks for your interest. Personally I have been testing on Centos 8.5, which uses a slightly more awkward versioning system for the kernel (kernel version is 4.18 officially, but in reality it has all the BPF features of kernel 5.9). I'll spin up a 20.04 VM and fix the build here with conditional compilation. It might take me a few days to learn about conditional compilation and to juggle other priorities, so thanks in advance for your patience :) |
Hey, @yobiscus
4.18 + BPF of 5.9?! That sounds peculiar to me. But I'm just curious about why
It's absolutely fine. Thank you for your effort. |
I fixed the build in Ubuntu 20.04 and confirmed that use of ringbuf still works when the feature is explicitly enabled (on systems that support it). I realize documentation and examples may be useful to add as well. I can add those once we're happy with the implementation. |
Hello @yobiscus I checked your code carefully and I leaved review messages. I hope this review helpful. |
@yobiscus Sorry to nudge you on this, should we expect a follow up patch? I'd be keen on merging this functionality, and I think this patchset is 95% there. |
@rsdy no problem, apologies for the delay. I was preoccupied with other duties over the last couple of weekends. Let me try to address all outstanding issues this coming weekend. |
AFAIK all review comments have been addressed. Please let me know if there are other outstanding items. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your follow-up modifications.
I added some comment.
And please modify your new 3 commit messages to contain Signed-off-by
trailer.
/// not get accessed (read or written) through any other pointer. | ||
/// | ||
/// This pointer is already assumed to be non-null since it was checked in RingBufMap::reserve. | ||
pub unsafe fn as_mut(&self) -> &mut T { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a brief usage you showed before,
it is convenient to make use of this method if it works correctly.
Users can directly assign values to the fields of the returned mutable reference.
However, I am still worried the safety of this method..
In BPF program, how can users make sure that the pointer is properly aligned?
I heard that the pointer arithmetic is not permitted in the BPF program.
I tried ptr as usize % mem::align_of::<T>()
but the resulting BPF bytecode is rejected by BPF verifier.
And passing a struct by value and calling write_unaligned seems not incur double copy.
Fields of a struct are directly written to the place where bpf_ringbuf_reserve returns.
I guess the copy is opted out.
I inspected a resulting BPF bytecode.
But I am not sure that all types of data will show the same result.
I just tested a structure that has 5 fields and the size of the struct is 24 bytes.
let fut = stream.for_each(move |events| { | ||
s.start_send((name.clone(), events)).unwrap(); | ||
future::ready(()) | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've used this branch to write some production-ish code and I have some feedback.
This works like a charm but I think the API here is a bit restrictive because there's no easy way to listen on ringbufs individually. Example case: I want to start my own async task for each ringbuf to forward incoming events to a TCP connection. With this approach, I'll have to filter all events to look for particular ringbufs that interest me, then likely forward these events through an mpsc queue, etc. etc.
Instead, I propose to store ringbufs in a separate HashMap
:
let fut = stream.for_each(move |events| { | |
s.start_send((name.clone(), events)).unwrap(); | |
future::ready(()) | |
}); | |
let mut ringbufs = HashMap::new(); | |
... | |
ringbufs.insert(name, stream); |
and make it publicly accessible from struct Loaded
, e.g.:
pub struct Loaded {
pub events: mpsc::UnboundedReceiver<(String, <PerfMessageStream as Stream>::Item)>,
//...
pub ringbufs: HashMap<String, RingBufMessageStream>,
}
This would also simplify the implementation.
What do you think? cc @rhdxmr
@yobiscus and thanks for working on this, it's an awesome feature! :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nbaksalyar that makes a lot of sense.
I'm afraid this PR is a bit stale, so at this stage we might need another revision, + we can't merge without DCO from @yobiscus . Hang in there for another week or so to see if they re-appear, and we can figure out a way forward if not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the much needed poke @nbaksalyar :) I am currently updating my environment so that it is compatible with the latest redbpf changes. I have rebased my changes against the main branch and hope to push something functional tomorrow.
Unfortunately I have not found time to address @rhdxmr comments above, specifically the comment about pointer alignment. There's a bit of a learning curve needed to address this which I don't currently have bandwidth for. Any help closing on these issues after I rebase my branch is very much appreciated!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pushed and signed-off. Sorry I wasn't able to implement your suggestion @nbaksalyar. Since this content is feature gated, would it be okay to merge this as is and address the comments after-the-fact, even if the changes are not backwards compatible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, no worries! I can help with making this change if you'd like @yobiscus.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks everyone, this looks good, once the CI passes I can merge this!
Signed-off-by: Jonathan Gravel <jo@stashed.dev>
Closes #161.