-
Notifications
You must be signed in to change notification settings - Fork 300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
aya+ebpf: Implement read+write methods for PerfEventArray #649
base: main
Are you sure you want to change the base?
Conversation
❌ Deploy Preview for aya-rs-docs failed.Built without sensitive environment variables
|
// According to the Linux manual, `bpf_perf_event_read_value` is preferred over `bpf_perf_event_read`. | ||
let ret = bpf_perf_event_read_value( |
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.
bpf_perf_event_read_value
is available starting with kernel 4.15, for version prior you need to use bpf_perf_event_read
.
Could you add a kernel version check (cached of course) to handle those ancient versions?
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.
yes! good idea
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.
Unfortunately it doesn't seem that easy, because the return type is different between bpf_perf_event_read
and bpf_perf_event_read_value
, and because the aya's functions to compare kernel versions are not available in bpf
🙁 . I think that I will rather state the minimum required version in the doc, and create a "legacy" version of the PerfEventArray if support for old kernels is required.
if ret == 0 { | ||
Ok(buf.assume_init()) | ||
} else { | ||
Err(ret) |
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 think this is wrong and this should grab the errno.
Err(ret) | |
Err(Error::last_os_error()) |
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.
The manual reads
Return 0 on success, or a negative error in case of failure.
And the patch (I had it in a bookmark, I should find the link to the current kernel source code) is quite clear: IIUC errno isn't involved here, it does things like
if (unlikely(size != sizeof(struct bpf_perf_event_value)))
return -EINVAL;
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.
That's annoying, well I suppose you can use from_raw_os_error with the value directly then...
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.
Could you write an integration test?
Yes, but how do I open the perf event? |
Sorry, a dependency on what? I think you should make whatever you need public so that your test is representative of real usage. |
I've used the crate perf_event_open_sys for step 1 (see the PR's description) to test what I've implemented. I'll make what I need public :) |
@TheElectronWill, this pull request is now in conflict and requires a rebase. |
0d1a2f9
to
7dfbc8d
Compare
7dfbc8d
to
2458eae
Compare
Okay, I've added integration tests! I've failed to run the tests on my machine, with a rather weird error
```
warning: error: could not compile `integration-ebpf` (bin "bpf_probe_read") due to 2 previous errors
error: failed to run custom build command for
= note: 16:13:28 [ERROR] fatal error: "Inline asm not supported by this streamer because we don't have an asm parser for this target\n"
|
do the integration tests run for you on |
2458eae
to
352ec0e
Compare
Solution to my aforementioned problem: update bpf-linker by running |
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.
Reviewed 2 of 2 files at r1, 9 of 9 files at r2, all commit messages.
Reviewable status: all files reviewed, 17 unresolved discussions (waiting on @marysaka and @TheElectronWill)
aya/src/maps/perf/perf_event_array.rs
line 209 at r1 (raw file):
/// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] /// if `bpf_map_update_elem` fails. pub fn set(&mut self, index: u32, value: i32) -> Result<(), MapError> {
is value a file descriptor? can we use AsFd instead of a raw i32?
aya/src/programs/perf_event.rs
line 55 at r2 (raw file):
} /// Fields included in the event samples
period
aya/src/programs/perf_event.rs
line 59 at r2 (raw file):
pub struct SampleType(u64); /// "Wake up" overflow notification policy.
did you mean to put all these changes in the second commit? I think you should just squash the two, they don't seem to be cleanly separated.
aya/src/programs/perf_event.rs
line 63 at r2 (raw file):
#[derive(Debug, Clone)] pub enum WakeUpPolicy { /// Wake up after n events
missing period here and below.
aya/src/programs/perf_event.rs
line 64 at r2 (raw file):
pub enum WakeUpPolicy { /// Wake up after n events WakeupEvents(u32),
these names stutter (WakeUpPolicy::WakeupFoo). can we do better?
bpf/aya-bpf/src/maps/perf/perf_event_array.rs
line 22 at r1 (raw file):
/// The minimum kernel version required to read perf_event values using [PerfEventArray] is 4.15. /// This concerns the functions [`read_current_cpu()`], [`read_at_index()`] and [`read()`]. ///
why this blank line?
bpf/aya-bpf/src/maps/perf/perf_event_array.rs
line 76 at r1 (raw file):
fn output<C: BpfContext>(&self, ctx: &C, data: &T, flags: u64) -> Result<(), i64> { unsafe { let ret = bpf_perf_event_output(
please reduce the scope of unsafe. let ret = unsafe { ...}; if ret == 0 { Ok(()) } else { ... }
bpf/aya-bpf/src/maps/perf/perf_event_array.rs
line 101 at r1 (raw file):
fn read(&self, flags: u64) -> Result<bpf_perf_event_value, i64> { let mut buf = MaybeUninit::<bpf_perf_event_value>::uninit(); unsafe {
same here
bpf/aya-bpf/src/maps/perf/perf_event_array.rs
line 102 at r1 (raw file):
let mut buf = MaybeUninit::<bpf_perf_event_value>::uninit(); unsafe { // According to the Linux manual, `bpf_perf_event_read_value` is preferred over `bpf_perf_event_read`.
citation?
test/integration-ebpf/src/perf_events.rs
line 29 at r2 (raw file):
#[perf_event] pub fn on_perf_event(ctx: PerfEventContext) -> i64 { match read_event(&ctx).map(|res| write_output(&ctx, res)) {
s/map/and_then/ - currently this throws away the inner error.
test/integration-ebpf/src/perf_events.rs
line 30 at r2 (raw file):
pub fn on_perf_event(ctx: PerfEventContext) -> i64 { match read_event(&ctx).map(|res| write_output(&ctx, res)) { Ok(_) => 0,
s/_/()/ to avoid the appearance of throwing away something meaningful
test/integration-test/src/tests/perf_events.rs
line 69 at r2 (raw file):
// sleep a little bit, then poll the values from the buffer std::thread::sleep(Duration::from_secs(2));
this is more than a little bit. why do we need to sleep so long? can we poll the fd instead?
test/integration-test/src/tests/perf_events.rs
line 76 at r2 (raw file):
// read the events and check that the returned data is correct let mut events_data: [BytesMut; BUF_PAGE_COUNT] = std::array::from_fn(|_| BytesMut::new());
why does this need more than one of these? i would imagine a single buffer that is reused.
test/integration-test/src/tests/perf_events.rs
line 80 at r2 (raw file):
for data_buf in events_data.iter_mut().take(event_stats.read) { // You must ensure that the definition of the struct (here `EventData`) is the same
these comments are rather strange. who is "you"? consider anchoring such a comment on the relevant types and making them symmetrical (i.e. the comment on the bpf should reference the userspace definition and vice versa)
352ec0e
to
6d73d12
Compare
It could be any i32, but that would make no sense for a
man bpf-helpers reads:
I've changed the test to wait for
We could use only one, here I wanted to test reading potentially multiple events at once. |
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.
In the future, please reply in reviewable if it isn't too inconvenient. The review is stateful, and so it's difficult for me to continue it when your replies are not anchored to the discussions to which they belong.
Reviewed 6 of 6 files at r3, all commit messages.
Reviewable status: all files reviewed, 11 unresolved discussions (waiting on @marysaka and @TheElectronWill)
test/integration-ebpf/src/perf_events.rs
line 12 at r3 (raw file):
}; /// Data sent by the bpf program to userspace.
nit: this doc comment on a non-pub item will never be seen in rustdoc.
test/integration-test/src/tests/perf_events.rs
line 69 at r2 (raw file):
Previously, tamird (Tamir Duberstein) wrote…
this is more than a little bit. why do we need to sleep so long? can we poll the fd instead?
if you search around, you'll see we have another test that uses raw epoll, do you think that would be preferable to this polling loop? that might still be async, but it doesn't use the async perf event array.
test/integration-test/src/tests/perf_events.rs
line 12 at r3 (raw file):
use test_log::test; /// Data sent by the bpf program to userspace.
ditto
test/integration-test/src/tests/perf_events.rs
line 27 at r3 (raw file):
const WAIT_TIMEOUT: Duration = Duration::from_secs(1); /// Opens an hardware perf_event for testing.
ditto
test/integration-test/src/tests/perf_events.rs
line 28 at r3 (raw file):
/// Opens an hardware perf_event for testing. // Beware: this returns an `OwnedFd`, which means that the file descriptor is closed on drop.
I think this is an odd comment that describes the semantics of OwnedFd, which has its own docs.
test/integration-test/src/tests/perf_events.rs
line 96 at r3 (raw file):
// read the events and check that the returned data is correct let mut events_data: [BytesMut; BUF_PAGE_COUNT] = std::array::from_fn(|_| BytesMut::new()); let events_stats = buf
would you mind destructuring event_stats
? we should probably assert on the number of dropped events, but it's easy to miss the existence of that field because of the point access.
same in the async version please
test/integration-test/src/tests/perf_events.rs
line 102 at r3 (raw file):
for data_buf in events_data.iter_mut().take(events_stats.read) { let ptr = data_buf.as_ptr() as *const EventData; let data: EventData = unsafe { ptr.read_unaligned() };
let EventData { cpu_id, tag } = unsafe { ptr.read_unaligned };
?
same in the async version please
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.
Reviewable status: all files reviewed, 11 unresolved discussions (waiting on @marysaka and @tamird)
aya/src/programs/perf_event.rs
line 64 at r2 (raw file):
Previously, tamird (Tamir Duberstein) wrote…
these names stutter (WakeUpPolicy::WakeupFoo). can we do better?
Done.
test/integration-ebpf/src/perf_events.rs
line 12 at r3 (raw file):
Previously, tamird (Tamir Duberstein) wrote…
nit: this doc comment on a non-pub item will never be seen in rustdoc.
I agree, however it shows up in IDE popups, which is quite handy when working on the project, isn't it?
test/integration-test/src/tests/perf_events.rs
line 69 at r2 (raw file):
Previously, tamird (Tamir Duberstein) wrote…
if you search around, you'll see we have another test that uses raw epoll, do you think that would be preferable to this polling loop? that might still be async, but it doesn't use the async perf event array.
I think that it would be better for a real app. For this test... I don't know, because readable()
has some internal logic and doesn't simply check the file descriptor. It may be good to test this logic, since the file descriptor readiness is tested in the async version.
test/integration-test/src/tests/perf_events.rs
line 28 at r3 (raw file):
Previously, tamird (Tamir Duberstein) wrote…
I think this is an odd comment that describes the semantics of OwnedFd, which has its own docs.
removed.
test/integration-test/src/tests/perf_events.rs
line 96 at r3 (raw file):
Previously, tamird (Tamir Duberstein) wrote…
would you mind destructuring
event_stats
? we should probably assert on the number of dropped events, but it's easy to miss the existence of that field because of the point access.same in the async version please
Good idea! I do that.
test/integration-test/src/tests/perf_events.rs
line 102 at r3 (raw file):
Previously, tamird (Tamir Duberstein) wrote…
let EventData { cpu_id, tag } = unsafe { ptr.read_unaligned };
?same in the async version please
Done.
6d73d12
to
6d62690
Compare
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.
Reviewed 1 of 1 files at r4, all commit messages.
Reviewable status: all files reviewed, 8 unresolved discussions (waiting on @marysaka and @TheElectronWill)
aya/src/programs/perf_event.rs
line 64 at r2 (raw file):
Previously, TheElectronWill (Guillaume Raffin) wrote…
Done.
They still stutter. What am I missing?
test/integration-ebpf/src/perf_events.rs
line 12 at r3 (raw file):
Previously, TheElectronWill (Guillaume Raffin) wrote…
I agree, however it shows up in IDE popups, which is quite handy when working on the project, isn't it?
Is that not the case with a non-doc comment? If so TIL and this is fine.
test/integration-test/src/tests/perf_events.rs
line 69 at r2 (raw file):
Previously, TheElectronWill (Guillaume Raffin) wrote…
I think that it would be better for a real app. For this test... I don't know, because
readable()
has some internal logic and doesn't simply check the file descriptor. It may be good to test this logic, since the file descriptor readiness is tested in the async version.
Okay. I think 200ms is rather long, do you know how long this takes in practice? I would expect an interval of 10ms or so.
6d62690
to
1b37cfc
Compare
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.
Reviewable status: all files reviewed, 8 unresolved discussions (waiting on @marysaka and @tamird)
aya/src/programs/perf_event.rs
line 64 at r2 (raw file):
Previously, tamird (Tamir Duberstein) wrote…
They still stutter. What am I missing?
in the latest revision it's WakeupPolicy
test/integration-ebpf/src/perf_events.rs
line 12 at r3 (raw file):
Previously, tamird (Tamir Duberstein) wrote…
Is that not the case with a non-doc comment? If so TIL and this is fine.
a normal comment does not show up on hover
test/integration-test/src/tests/perf_events.rs
line 69 at r2 (raw file):
Previously, tamird (Tamir Duberstein) wrote…
Okay. I think 200ms is rather long, do you know how long this takes in practice? I would expect an interval of 10ms or so.
The program is attached to the software clock, I believe that the events won't arrive before the first tick of the clock. I can increase the frequency, though :)
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.
Reviewed 1 of 1 files at r5, all commit messages.
Reviewable status: all files reviewed, 5 unresolved discussions (waiting on @marysaka and @TheElectronWill)
aya/src/programs/perf_event.rs
line 64 at r2 (raw file):
Previously, TheElectronWill (Guillaume Raffin) wrote…
in the latest revision it's
WakeupPolicy
The word Wakeup is in both the enum name and both its variants, which produces a stutter.
test/integration-test/src/tests/perf_events.rs
line 69 at r2 (raw file):
Previously, TheElectronWill (Guillaume Raffin) wrote…
The program is attached to the software clock, I believe that the events won't arrive before the first tick of the clock. I can increase the frequency, though :)
Ah, so this is computed from the frequency. Can we do the math here instead of hard coding?
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.
Dismissed @marysaka from 3 discussions.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @marysaka and @TheElectronWill)
3e7734a
to
2dc52fb
Compare
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.
Reviewable status: 9 of 11 files reviewed, 2 unresolved discussions (waiting on @marysaka and @tamird)
aya/src/programs/perf_event.rs
line 64 at r2 (raw file):
Previously, tamird (Tamir Duberstein) wrote…
The word Wakeup is in both the enum name and both its variants, which produces a stutter.
Oh, right! Sorry, I don't know why but I was focused on the case (WakeUp vs Wakeup)... Fixed (for real this time).
test/integration-test/src/tests/perf_events.rs
line 69 at r2 (raw file):
Previously, tamird (Tamir Duberstein) wrote…
Ah, so this is computed from the frequency. Can we do the math here instead of hard coding?
Yes, that's much better indeed.
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.
Reviewed 3 of 3 files at r6, all commit messages.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @marysaka and @TheElectronWill)
test/integration-test/src/tests/perf_events.rs
line 69 at r2 (raw file):
Previously, TheElectronWill (Guillaume Raffin) wrote…
Yes, that's much better indeed.
I think I'm confused now, the sampling is now a period rather than a frequency?
2dc52fb
to
ab51f9c
Compare
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.
Reviewable status: 10 of 11 files reviewed, 1 unresolved discussion (waiting on @marysaka and @tamird)
test/integration-test/src/tests/perf_events.rs
line 69 at r2 (raw file):
Previously, tamird (Tamir Duberstein) wrote…
I think I'm confused now, the sampling is now a period rather than a frequency?
Uh oh, I've tried both ways and forgot to revert one change... Good catch.
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 think you'll need to run cargo xtask api --bless
Reviewed 1 of 1 files at r7, all commit messages.
Reviewable status: complete! all files reviewed, all discussions resolved (waiting on @marysaka)
ab51f9c
to
1b311f1
Compare
Hey @alessandrod, this pull request changes the Aya Public API and requires your review. |
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.
cargo xtask public-api --bless
completed :check:
Reviewable status: 11 of 13 files reviewed, all discussions resolved (waiting on @marysaka)
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.
Reviewed 2 of 2 files at r8, all commit messages.
Reviewable status: complete! all files reviewed, all discussions resolved (waiting on @alessandrod and @marysaka)
@TheElectronWill, this pull request is now in conflict and requires a rebase. |
1b311f1
to
e714ca8
Compare
This allow to read _and_ write a PerfEventArray, from userspace _and_ kernel.
e714ca8
to
0aeb379
Compare
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.
My hunch is that we should have two separate types - I don't think it's ever desiderable to call open() and set() on the same map, and having both in the same type seems confusing. I'm not sure what the best names would be, maybe PerfEventByteArray and PerfEventArray? Not sure
pub fn output_at_index<C: BpfContext>(&self, ctx: &C, index: u32, data: &T, flags: u32) { | ||
let flags = u64::from(flags) << 32 | u64::from(index); | ||
unsafe { | ||
fn output<C: BpfContext>(&self, ctx: &C, data: &T, flags: u64) -> Result<(), i64> { |
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.
Can you explain why this change? I find it more confusing than the old API.
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.
Having both index
and flags
looked subtly wrong, because the flags
parameter of the bpf function is actually used either as an index, or as a flag, never both at the same time (and not with a 32-bits shift). If I'm not mistaken, either:
- you want to write at a specific
index: u32
and you setflags = (index as u64) & BPF_F_INDEX_MASK
- or you want to write using a specific
flag: u64
(usually a constant defined in the bpf library, likeBPF_F_CURRENT_CPU
) and you setflags = flag
See man bpf_helpers:
The flags are used to indicate the index in map for
which the value must be put, masked with
BPF_F_INDEX_MASK. Alternatively, flags can be set
to BPF_F_CURRENT_CPU to indicate that the index of
the current CPU core should be used.
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.
Having both index and flags looked subtly wrong, because the flags parameter of the bpf function is actually used either as an index, or as a flag
I don't think so? The flags argument can be used to pass both an index and flags. The index just happens to be the low 32 bits. IOW, I might want to output to an index AND pass some flags
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 wonder if there are other flags than BPF_F_CURRENT_CPU
for this call?
If I do flags = u64::from(BPF_F_CURRENT_CPU) << 32 | u64::from(index)
the flags looks weird to me: which element is going to be written? In any case, BPF_F_CURRENT_CPU
is not shifted in the bcc examples.
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.
If I do flags = u64::from(BPF_F_CURRENT_CPU) << 32 | u64::from(index)
You get EINVAL, because you've set some invalid bits in the upper bits.
In any case, BPF_F_CURRENT_CPU is not shifted in the bcc examples
Neither do we
I wonder if there are other flags than BPF_F_CURRENT_CPU for this call?
It's a generic flags argument. More flags could be added in the future, and if that were to happen it shouldn't break our APIs
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.
Neither do we
Didn't self.output_at_index(ctx, BPF_F_CURRENT_CPU as u32, data, flags)
discard the higher 32-bits of BPF_F_CURRENT_CPU
and then apply the shift?
I understand the need for a generic future-proof flag
, I will add it back.
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.
Neither do we
Didn't
self.output_at_index(ctx, BPF_F_CURRENT_CPU as u32, data, flags)
discard the higher 32-bits ofBPF_F_CURRENT_CPU
and then apply the shift?
let flags = u64::from(flags) << 32 | u64::from(index);
Yes but the shift is applied to flags, not index (BPF_F_CURRENT_CPU).
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.
Ah that's right. Yet, u64::from(BPF_F_CURRENT_CPU as u32)
is not BPF_F_CURRENT_CPU
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.
it is if you look at _MASK and consider that kernel APIs are stable so the mask can't change
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.
*revelation moment* Okay, I understand now, sorry for the confusion. The API confused me a little bit.
May I offer to add the index+flags back, but with something like (maybe without the INDEX_MASK):
let flags_for_bpf = (u64::from(index) & BPF_F_INDEX_MASK) | flags;
so that it's more obvious to the reader and will continue to work even if new flags are added?
/// | ||
/// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] | ||
/// if `bpf_map_update_elem` fails. | ||
pub fn set<FD: AsFd>(&mut self, index: u32, value: &FD) -> Result<(), MapError> { |
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.
What happens if I set an index that has already been open()
-ed?
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.
Well, I have not tested this case. If the fd has already been opened, it could stay open? The doc does not give any clear hint about this case.
pub struct SampleType(u64); | ||
|
||
/// "Wake up" overflow notification policy. | ||
/// Overflows are generated only by sampling events. |
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.
Missing newline between the two lines. The format is:
[summary]
[newline]
[paragraphs separated by newlines]
@TheElectronWill, this pull request is now in conflict and requires a rebase. |
I agree with the idea. There's already a |
Hey @alessandrod, this pull request changes the Aya Public API and requires your review. |
@TheElectronWill, this pull request is now in conflict and requires a rebase. |
@TheElectronWill, this pull request is now in conflict and requires a rebase. |
This allows to read and write a PerfEventArray, from userspace and kernel.
Thanks to these modifications, one can read perf events from ebpf code!
Usage
PerfEventArray<i32>
PerfEventArray<MyValue>
(you can create a struct to carry the info you need, for instance)PerfEventArray
using aPerfEventArrayBuffer
See the integration test for more details.
What is it for?
This can be useful to read performance counters from the kernel space, a method which I have evaluated in my research work.
This change is