-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
bcc/python: Add support for API 'bpf_attach_perf_event_raw' in BPF py… #3571
bcc/python: Add support for API 'bpf_attach_perf_event_raw' in BPF py… #3571
Conversation
[buildbot, test this please] |
@davemarchevsky could you help take a look? |
src/python/bcc/__init__.py
Outdated
@@ -22,6 +22,7 @@ | |||
import errno | |||
import sys | |||
import platform | |||
import bcc |
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's this import being used for?
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.
@davemarchevsky Hi Dave,
This import is not needed. Thanks for the catch. I will remove this in next revision.
src/python/bcc/libbcc.py
Outdated
@@ -147,6 +147,9 @@ | |||
lib.bpf_attach_perf_event.argtype = [ct.c_int, ct.c_uint, ct.c_uint, ct.c_ulonglong, ct.c_ulonglong, | |||
ct.c_int, ct.c_int, ct.c_int] | |||
|
|||
lib.bpf_attach_perf_event_raw.restype = ct.c_int | |||
lib.bpf_attach_perf_event_raw.argtype = [ct.Structure, ct.c_uint, ct.c_uint, ct.c_uint, ct.c_uint] |
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 the ctype struct Perf.perf_event_attr()
be used as the first type here?
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.
@davemarchevsky
Sure, I will make the changes to use perf_event_attr
as first type.
Does changes below looks good ?
index 959296e3..d888473b 100644
--- a/src/python/bcc/libbcc.py
+++ b/src/python/bcc/libbcc.py
@@ -147,6 +147,10 @@ lib.bpf_attach_perf_event.restype = ct.c_int
lib.bpf_attach_perf_event.argtype = [ct.c_int, ct.c_uint, ct.c_uint, ct.c_ulonglong, ct.c_ulonglong,
ct.c_int, ct.c_int, ct.c_int]
+from .perf import Perf
+lib.bpf_attach_perf_event_raw.restype = ct.c_int
+lib.bpf_attach_perf_event_raw.argtype = [Perf.perf_event_attr, ct.c_uint, ct.c_uint, ct.c_uint, ct.c_uint]
+
lib.bpf_close_perf_event_fd.restype = ct.c_int
lib.bpf_close_perf_event_fd.argtype = [ct.c_int]
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.
you may need to do perf_event_attr()
, but otherwise looks good
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 checking Dave @davemarchevsky
I have updated pull request with the changes you suggested and also corrected the type of event attr in testcase to proper one. Please review the updated changes.
66efced
to
6916302
Compare
[buildbot, ok to test] |
src/python/bcc/libbcc.py
Outdated
@@ -147,6 +147,10 @@ | |||
lib.bpf_attach_perf_event.argtype = [ct.c_int, ct.c_uint, ct.c_uint, ct.c_ulonglong, ct.c_ulonglong, | |||
ct.c_int, ct.c_int, ct.c_int] | |||
|
|||
from .perf import Perf |
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 move this import to the top of the file?
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.
@davemarchevsky Hi Dave,
I had tried putting it to top of file ( right after import of ctypes
) , but there is import dependency on lib
with that change.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.6/site-packages/bcc/__init__.py", line 26, in <module>
from .libbcc import lib, bcc_symbol, bcc_symbol_option, bcc_stacktrace_build_id, _SYM_CB_TYPE
File "/usr/lib/python3.6/site-packages/bcc/libbcc.py", line 16, in <module>
from .perf import Perf
File "/usr/lib/python3.6/site-packages/bcc/perf.py", line 17, in <module>
from .utils import get_online_cpus
File "/usr/lib/python3.6/site-packages/bcc/utils.py", line 20, in <module>
from .libbcc import lib
ImportError: cannot import name 'lib'
I can put it at top but after we define lib
.
index 959296e3..ea19406b 100644
--- a/src/python/bcc/libbcc.py
+++ b/src/python/bcc/libbcc.py
@@ -16,6 +16,7 @@ import ctypes as ct
lib = ct.CDLL("libbcc.so.0", use_errno=True)
+from .perf import Perf
# keep in sync with bcc_common.h
lib.bpf_module_create_b.restype = ct.c_void_p
lib.bpf_module_create_b.argtypes = [ct.c_char_p, ct.c_char_p, ct.c_uint,
@@ -147,6 +148,9 @@ lib.bpf_attach_perf_event.restype = ct.c_int
lib.bpf_attach_perf_event.argtype = [ct.c_int, ct.c_uint, ct.c_uint, ct.c_ulonglong, ct.c_ulonglong,
ct.c_int, ct.c_int, ct.c_int]
+lib.bpf_attach_perf_event_raw.restype = ct.c_int
+lib.bpf_attach_perf_event_raw.argtype = [Perf.perf_event_attr(), ct.c_uint, ct.c_uint, ct.c_uint, ct.c_uint]
+
lib.bpf_close_perf_event_fd.restype = ct.c_int
lib.bpf_close_perf_event_fd.argtype = [ct.c_int]
Does that look fine ?
Thanks
Athira
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, I see what you mean. I think it's still preferable to keep imports as close to the beginning of the file as possible, even if this one needs to follow the lib
line
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, will move this import to begining of file after lib
line
I tried running @@ -29,14 +29,11 @@
int on_sample_hit(struct bpf_perf_event_data *ctx) {
struct key_t key = {};
get_key(&key);
- u64 addr;
- struct bpf_perf_event_data_kern *kctx;
- struct perf_sample_data *data;
+ u64 addr = 0;
- kctx = (struct bpf_perf_event_data_kern *)ctx;
- bpf_probe_read(&data, sizeof(struct perf_sample_data*), &(kctx->data));
- if (data)
- bpf_probe_read(&addr, sizeof(u64), &(data->addr));
+ if(bpf_probe_read_kernel(&addr, sizeof(addr), &ctx->addr)) {
+ bpf_trace_printk("error in bpf_probe_read_kernel!\\n");
+ }
bpf_trace_printk("Hit a sample with pid: %ld, comm: %s, addr: 0x%llx\\n", key.pid, key.name, addr);
return 0;
@@ -47,11 +44,11 @@
b = BPF(text=bpf_text)
try:
event_attr = Perf.perf_event_attr()
- event_attr.type = 0
+ event_attr.type = Perf.PERF_TYPE_HARDWARE
event_attr.config = PerfHWConfig.CACHE_MISSES
event_attr.sample_period = 1000000
- event_attr.sample_type = 0x8
- event_attr.exclude_kernel = 1;
+ event_attr.sample_type = 0x8 # PERF_SAMPLE_ADDR
+ event_attr.exclude_kernel = 1
b.attach_perf_event_raw(attr=event_attr, fn_name="on_sample_hit", pid=-1, cpu=-1)
except Exception:
print("Failed to attach to a raw event. Please check the event attr used") Aside from a few nit-level fixes in the python 'runner', the real change here is to not treat |
@yonghong-song tells me that |
Sure, Thanks for the help. I could read the |
@athira-rajeev which kernel is your test environment running? |
This part of my previous suggestion was definitely incorrect + if(bpf_probe_read_kernel(&addr, sizeof(addr), &ctx->addr)) {
+ bpf_trace_printk("error in bpf_probe_read_kernel!\\n");
+ } The way you're reading I think the nit-level changes suggested in my previous long comment are still valid, though. |
Hi Dave @davemarchevsky I used upstream kernel and |
Sure, I will make those nit-level changes in next version |
…thon interface Add python interface for attach_perf_event_raw to bcc. The bpf_attach_perf_event_raw API provide flexibility to use advanced features of perf events with BPF. Presently, this API is available to use in BPF programs via C and C++ interface. Patch enables support to use in python interface. Patch also adds testcase under 'tests/python' which uses the newly added python interface 'attach_perf_event_raw'. Signed-off-by: Athira Rajeev <[email protected]>
6916302
to
38821fe
Compare
@davemarchevsky Hi Dave, |
LGTM. Thanks for the contribution! I figured out why I wasn't seeing actual addrs. Two issues:
powerpc will try to set ->addr on any perf event with PERF_SAMPLE_ADDR enabled, while my x86 machine requires I tried to set this additional field on the perf_event in this test and still was not seeing non-zero addrs. This was because the ctypes Structure didn't have So this unearthed two quick improvements that I'll make:
|
@davemarchevsky Thanks Dave for review and merging. Great we could find these improvements. Please tag me in your next changes and I can contribute with testing them in powerpc platform. Thanks |
This commit brings the Perf.perf_event_attr ctype in line with version 6 of struct perf_event_attr (see uapi/linux/perf_event.h kernel header). Specifically: * All named fields are added, including field names within anonymous unions and bitfields * Perf.perf_event_attr now complains when a field which isn't part of the ctype struct is set. * Goal here is to prevent users from setting a recently-added field - which we haven't updated the ctype _fields_ to include - and getting confused when it doesn't propagate to the perf_event_open syscall. This bit me in iovisor#3571 and I am pretty familiar with bcc internals so I'd like to prevent this from confusing others down the line. * Perf.perf_event_attr's 'flags' field is removed as it was a standin for the bitfields. The _old_ profile.py was the only script in bcc tools that I could find using this. The last bullet is a breaking change. Although `tools/old/profile.py` has been migrated to use the bitfield it was flipping using `flags`, there could be some scripts out in the wild which break. I don't think this is likely: this stuff hasn't been significantly touched since 2016 and I suspect if users of the python interface were writing lots of perf_event programs we would've seen more python tools or activity here. Regardless, there is probably a way to keep `flags` field working while also exposing named bitfields, but I suspect it'll be ugly and wanted to see if anyone thought it was necessary.
This commit brings the Perf.perf_event_attr ctype in line with version 6 of struct perf_event_attr (see uapi/linux/perf_event.h kernel header). Specifically: * All named fields are added, including field names within anonymous unions and bitfields * Perf.perf_event_attr now complains when a field which isn't part of the ctype struct is set. * Goal here is to prevent users from setting a recently-added field - which we haven't updated the ctype _fields_ to include - and getting confused when it doesn't propagate to the perf_event_open syscall. This bit me in iovisor#3571 and I am pretty familiar with bcc internals so I'd like to prevent this from confusing others down the line. * Perf.perf_event_attr's 'flags' field is removed as it was a standin for the bitfields. The _old_ profile.py was the only script in bcc tools that I could find using this. The last bullet is a breaking change. Although `tools/old/profile.py` has been migrated to use the bitfield it was flipping using `flags`, there could be some scripts out in the wild which break. I don't think this is likely: this stuff hasn't been significantly touched since 2016 and I suspect if users of the python interface were writing lots of perf_event programs we would've seen more python tools or activity here. Regardless, there is probably a way to keep `flags` field working while also exposing named bitfields, but I suspect it'll be ugly and wanted to see if anyone thought it was necessary.
This commit brings the Perf.perf_event_attr ctype in line with version 6 of struct perf_event_attr (see uapi/linux/perf_event.h kernel header). Specifically: * All named fields are added, including field names within anonymous unions and bitfields * Perf.perf_event_attr now complains when a field which isn't part of the ctype struct is set. * Goal here is to prevent users from setting a recently-added field - which we haven't updated the ctype _fields_ to include - and getting confused when it doesn't propagate to the perf_event_open syscall. This bit me in iovisor#3571 and I am pretty familiar with bcc internals so I'd like to prevent this from confusing others down the line. * Perf.perf_event_attr's 'flags' field is removed as it was a standin for the bitfields. The _old_ profile.py was the only script in bcc tools that I could find using this. The last bullet is a breaking change. Although `tools/old/profile.py` has been migrated to use the bitfield it was flipping using `flags`, there could be some scripts out in the wild which break. I don't think this is likely: this stuff hasn't been significantly touched since 2016 and I suspect if users of the python interface were writing lots of perf_event programs we would've seen more python tools or activity here. Regardless, there is probably a way to keep `flags` field working while also exposing named bitfields, but I suspect it'll be ugly and wanted to see if anyone thought it was necessary.
This commit brings the Perf.perf_event_attr ctype in line with version 6 of struct perf_event_attr (see uapi/linux/perf_event.h kernel header). Specifically: * All named fields are added, including field names within anonymous unions and bitfields * Perf.perf_event_attr now complains when a field which isn't part of the ctype struct is set. * Goal here is to prevent users from setting a recently-added field - which we haven't updated the ctype _fields_ to include - and getting confused when it doesn't propagate to the perf_event_open syscall. This bit me in #3571 and I am pretty familiar with bcc internals so I'd like to prevent this from confusing others down the line. * Perf.perf_event_attr's 'flags' field is removed as it was a standin for the bitfields. The _old_ profile.py was the only script in bcc tools that I could find using this. The last bullet is a breaking change. Although `tools/old/profile.py` has been migrated to use the bitfield it was flipping using `flags`, there could be some scripts out in the wild which break. I don't think this is likely: this stuff hasn't been significantly touched since 2016 and I suspect if users of the python interface were writing lots of perf_event programs we would've seen more python tools or activity here. Regardless, there is probably a way to keep `flags` field working while also exposing named bitfields, but I suspect it'll be ugly and wanted to see if anyone thought it was necessary.
This commit brings the Perf.perf_event_attr ctype in line with version 6 of struct perf_event_attr (see uapi/linux/perf_event.h kernel header). Specifically: * All named fields are added, including field names within anonymous unions and bitfields * Perf.perf_event_attr now complains when a field which isn't part of the ctype struct is set. * Goal here is to prevent users from setting a recently-added field - which we haven't updated the ctype _fields_ to include - and getting confused when it doesn't propagate to the perf_event_open syscall. This bit me in iovisor#3571 and I am pretty familiar with bcc internals so I'd like to prevent this from confusing others down the line. * Perf.perf_event_attr's 'flags' field is removed as it was a standin for the bitfields. The _old_ profile.py was the only script in bcc tools that I could find using this. The last bullet is a breaking change. Although `tools/old/profile.py` has been migrated to use the bitfield it was flipping using `flags`, there could be some scripts out in the wild which break. I don't think this is likely: this stuff hasn't been significantly touched since 2016 and I suspect if users of the python interface were writing lots of perf_event programs we would've seen more python tools or activity here. Regardless, there is probably a way to keep `flags` field working while also exposing named bitfields, but I suspect it'll be ugly and wanted to see if anyone thought it was necessary.
This commit brings the Perf.perf_event_attr ctype in line with version 6 of struct perf_event_attr (see uapi/linux/perf_event.h kernel header). Specifically: * All named fields are added, including field names within anonymous unions and bitfields * Perf.perf_event_attr now complains when a field which isn't part of the ctype struct is set. * Goal here is to prevent users from setting a recently-added field - which we haven't updated the ctype _fields_ to include - and getting confused when it doesn't propagate to the perf_event_open syscall. This bit me in iovisor#3571 and I am pretty familiar with bcc internals so I'd like to prevent this from confusing others down the line. * Perf.perf_event_attr's 'flags' field is removed as it was a standin for the bitfields. The _old_ profile.py was the only script in bcc tools that I could find using this. The last bullet is a breaking change. Although `tools/old/profile.py` has been migrated to use the bitfield it was flipping using `flags`, there could be some scripts out in the wild which break. I don't think this is likely: this stuff hasn't been significantly touched since 2016 and I suspect if users of the python interface were writing lots of perf_event programs we would've seen more python tools or activity here. Regardless, there is probably a way to keep `flags` field working while also exposing named bitfields, but I suspect it'll be ugly and wanted to see if anyone thought it was necessary.
…thon interface
Add python interface for attach_perf_event_raw to bcc.
The bpf_attach_perf_event_raw API provide flexibility to use
advanced features of perf events with BPF. Presently, this
API is available to use in BPF programs via C and C++ interface.
Patch enables support to use in python interface.
Patch also adds testcase under 'tests/python' which uses
the newly added python interface 'attach_perf_event_raw'.
Signed-off-by: Athira Rajeev [email protected]