Skip to content

Commit 63f378c

Browse files
authored
Merge pull request #51 from pythonbpf/bcc_examples
Port BCC tutorial examples to PythonBPF
2 parents 0d4ebf7 + 37af7d2 commit 63f378c

25 files changed

+1943
-144
lines changed

BCC-Examples/hello_fields.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from pythonbpf import bpf, section, bpfglobal, BPF, trace_fields
2+
from ctypes import c_void_p, c_int64
3+
4+
5+
@bpf
6+
@section("tracepoint/syscalls/sys_enter_clone")
7+
def hello_world(ctx: c_void_p) -> c_int64:
8+
print("Hello, World!")
9+
return 0 # type: ignore [return-value]
10+
11+
12+
@bpf
13+
@bpfglobal
14+
def LICENSE() -> str:
15+
return "GPL"
16+
17+
18+
# Compile and load
19+
b = BPF()
20+
b.load()
21+
b.attach_all()
22+
23+
# header
24+
print(f"{'TIME(s)':<18} {'COMM':<16} {'PID':<6} {'MESSAGE'}")
25+
26+
# format output
27+
while True:
28+
try:
29+
(task, pid, cpu, flags, ts, msg) = trace_fields()
30+
except ValueError:
31+
continue
32+
except KeyboardInterrupt:
33+
exit()
34+
print(f"{ts:<18} {task:<16} {pid:<6} {msg}")

BCC-Examples/hello_perf_output.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
from pythonbpf import bpf, map, struct, section, bpfglobal, BPF
2+
from pythonbpf.helper import ktime, pid, comm
3+
from pythonbpf.maps import PerfEventArray
4+
from ctypes import c_void_p, c_int64
5+
6+
7+
@bpf
8+
@struct
9+
class data_t:
10+
pid: c_int64
11+
ts: c_int64
12+
comm: str(16) # type: ignore [valid-type]
13+
14+
15+
@bpf
16+
@map
17+
def events() -> PerfEventArray:
18+
return PerfEventArray(key_size=c_int64, value_size=c_int64)
19+
20+
21+
@bpf
22+
@section("tracepoint/syscalls/sys_enter_clone")
23+
def hello(ctx: c_void_p) -> c_int64:
24+
dataobj = data_t()
25+
dataobj.pid, dataobj.ts = pid(), ktime()
26+
comm(dataobj.comm)
27+
events.output(dataobj)
28+
return 0 # type: ignore [return-value]
29+
30+
31+
@bpf
32+
@bpfglobal
33+
def LICENSE() -> str:
34+
return "GPL"
35+
36+
37+
# Compile and load
38+
b = BPF()
39+
b.load()
40+
b.attach_all()
41+
42+
start = 0
43+
44+
45+
def callback(cpu, event):
46+
global start
47+
if start == 0:
48+
start = event.ts
49+
ts = (event.ts - start) / 1e9
50+
print(f"[CPU {cpu}] PID: {event.pid}, TS: {ts}, COMM: {event.comm.decode()}")
51+
52+
53+
perf = b["events"].open_perf_buffer(callback, struct_name="data_t")
54+
print("Starting to poll... (Ctrl+C to stop)")
55+
print("Try running: fork() or clone() system calls to trigger events")
56+
57+
try:
58+
while True:
59+
b["events"].poll(1000)
60+
except KeyboardInterrupt:
61+
print("Stopping...")

BCC-Examples/hello_world.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from pythonbpf import bpf, section, bpfglobal, BPF, trace_pipe
2+
from ctypes import c_void_p, c_int64
3+
4+
5+
@bpf
6+
@section("tracepoint/syscalls/sys_enter_clone")
7+
def hello_world(ctx: c_void_p) -> c_int64:
8+
print("Hello, World!")
9+
return 0 # type: ignore [return-value]
10+
11+
12+
@bpf
13+
@bpfglobal
14+
def LICENSE() -> str:
15+
return "GPL"
16+
17+
18+
# Compile and load
19+
b = BPF()
20+
b.load()
21+
b.attach_all()
22+
23+
trace_pipe()

BCC-Examples/sync_count.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from pythonbpf import bpf, map, section, bpfglobal, BPF, trace_fields
2+
from pythonbpf.helper import ktime
3+
from pythonbpf.maps import HashMap
4+
5+
from ctypes import c_void_p, c_int64
6+
7+
8+
@bpf
9+
@map
10+
def last() -> HashMap:
11+
return HashMap(key=c_int64, value=c_int64, max_entries=2)
12+
13+
14+
@bpf
15+
@section("tracepoint/syscalls/sys_enter_sync")
16+
def do_trace(ctx: c_void_p) -> c_int64:
17+
ts_key, cnt_key = 0, 1
18+
tsp, cntp = last.lookup(ts_key), last.lookup(cnt_key)
19+
if not cntp:
20+
last.update(cnt_key, 0)
21+
cntp = last.lookup(cnt_key)
22+
if tsp:
23+
delta = ktime() - tsp
24+
if delta < 1000000000:
25+
time_ms = delta // 1000000
26+
print(f"{time_ms} {cntp}")
27+
last.delete(ts_key)
28+
else:
29+
last.update(ts_key, ktime())
30+
last.update(cnt_key, cntp + 1)
31+
return 0 # type: ignore [return-value]
32+
33+
34+
@bpf
35+
@bpfglobal
36+
def LICENSE() -> str:
37+
return "GPL"
38+
39+
40+
# Compile and load
41+
b = BPF()
42+
b.load()
43+
b.attach_all()
44+
45+
print("Tracing for quick sync's... Ctrl-C to end")
46+
47+
# format output
48+
start = 0
49+
while True:
50+
try:
51+
task, pid, cpu, flags, ts, msg = trace_fields()
52+
if start == 0:
53+
start = ts
54+
ts -= start
55+
ms, cnt = msg.split()
56+
print(f"At time {ts} s: Multiple syncs detected, last {ms} ms ago. Count {cnt}")
57+
except KeyboardInterrupt:
58+
exit()

BCC-Examples/sync_perf_output.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
from pythonbpf import bpf, map, struct, section, bpfglobal, BPF
2+
from pythonbpf.helper import ktime
3+
from pythonbpf.maps import HashMap
4+
from pythonbpf.maps import PerfEventArray
5+
from ctypes import c_void_p, c_int64
6+
7+
8+
@bpf
9+
@struct
10+
class data_t:
11+
ts: c_int64
12+
ms: c_int64
13+
14+
15+
@bpf
16+
@map
17+
def events() -> PerfEventArray:
18+
return PerfEventArray(key_size=c_int64, value_size=c_int64)
19+
20+
21+
@bpf
22+
@map
23+
def last() -> HashMap:
24+
return HashMap(key=c_int64, value=c_int64, max_entries=1)
25+
26+
27+
@bpf
28+
@section("tracepoint/syscalls/sys_enter_sync")
29+
def do_trace(ctx: c_void_p) -> c_int64:
30+
dat, dat.ts, key = data_t(), ktime(), 0
31+
tsp = last.lookup(key)
32+
if tsp:
33+
delta = ktime() - tsp
34+
if delta < 1000000000:
35+
dat.ms = delta // 1000000
36+
events.output(dat)
37+
last.delete(key)
38+
else:
39+
last.update(key, ktime())
40+
return 0 # type: ignore [return-value]
41+
42+
43+
@bpf
44+
@bpfglobal
45+
def LICENSE() -> str:
46+
return "GPL"
47+
48+
49+
# Compile and load
50+
b = BPF()
51+
b.load()
52+
b.attach_all()
53+
54+
print("Tracing for quick sync's... Ctrl-C to end")
55+
56+
# format output
57+
start = 0
58+
59+
60+
def callback(cpu, event):
61+
global start
62+
if start == 0:
63+
start = event.ts
64+
event.ts -= start
65+
print(
66+
f"At time {event.ts / 1e9} s: Multiple sync detected, Last sync: {event.ms} ms ago"
67+
)
68+
69+
70+
perf = b["events"].open_perf_buffer(callback, struct_name="data_t")
71+
print("Starting to poll... (Ctrl+C to stop)")
72+
print("Try running: fork() or clone() system calls to trigger events")
73+
74+
try:
75+
while True:
76+
b["events"].poll(1000)
77+
except KeyboardInterrupt:
78+
print("Stopping...")

BCC-Examples/sync_timing.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
from pythonbpf import bpf, map, section, bpfglobal, BPF, trace_fields
2+
from pythonbpf.helper import ktime
3+
from pythonbpf.maps import HashMap
4+
5+
from ctypes import c_void_p, c_int64
6+
7+
8+
@bpf
9+
@map
10+
def last() -> HashMap:
11+
return HashMap(key=c_int64, value=c_int64, max_entries=1)
12+
13+
14+
@bpf
15+
@section("tracepoint/syscalls/sys_enter_sync")
16+
def do_trace(ctx: c_void_p) -> c_int64:
17+
key = 0
18+
tsp = last.lookup(key)
19+
if tsp:
20+
delta = ktime() - tsp
21+
if delta < 1000000000:
22+
time_ms = delta // 1000000
23+
print(f"{time_ms}")
24+
last.delete(key)
25+
else:
26+
last.update(key, ktime())
27+
return 0 # type: ignore [return-value]
28+
29+
30+
@bpf
31+
@bpfglobal
32+
def LICENSE() -> str:
33+
return "GPL"
34+
35+
36+
# Compile and load
37+
b = BPF()
38+
b.load()
39+
b.attach_all()
40+
41+
print("Tracing for quick sync's... Ctrl-C to end")
42+
43+
# format output
44+
start = 0
45+
while True:
46+
try:
47+
task, pid, cpu, flags, ts, ms = trace_fields()
48+
if start == 0:
49+
start = ts
50+
ts -= start
51+
print(f"At time {ts} s: Multiple syncs detected, last {ms} ms ago")
52+
except KeyboardInterrupt:
53+
exit()

BCC-Examples/sys_sync.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from pythonbpf import bpf, section, bpfglobal, BPF, trace_pipe
2+
from ctypes import c_void_p, c_int64
3+
4+
5+
@bpf
6+
@section("tracepoint/syscalls/sys_enter_sync")
7+
def hello_world(ctx: c_void_p) -> c_int64:
8+
print("sys_sync() called")
9+
return c_int64(0)
10+
11+
12+
@bpf
13+
@bpfglobal
14+
def LICENSE() -> str:
15+
return "GPL"
16+
17+
18+
# Compile and load
19+
b = BPF()
20+
b.load()
21+
b.attach_all()
22+
print("Tracing sys_sync()... Ctrl-C to end.")
23+
trace_pipe()

0 commit comments

Comments
 (0)