Skip to content

Commit ec003a2

Browse files
addd example and support for load and attach
1 parent 9fb3ab3 commit ec003a2

File tree

6 files changed

+84
-18
lines changed

6 files changed

+84
-18
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ _generate/
99
build/
1010
*venv/
1111
.idea/
12+
sudo-python.sh

README.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
# Py-libbpf
2+
<p align="center">
3+
<a href="https://www.python.org/downloads/release/python-3080/"><img src="https://img.shields.io/badge/python-3.8-blue.svg"></a>
4+
<a href="https://pypi.org/project/pylibbpf"><img src="https://badge.fury.io/py/pylibbpf.svg"></a>
5+
</p>
26
This library provides Python bindings for libbpf on Linux to make loading of eBPF object files easier. This is meant to
37
be used along with `pythonbpf`, the eBPF Python DSL compiler. This library makes it possible to attach these programs to
48
events in the kernel right from inside Python.
59

6-
# Warning
7-
IN DEVELOPMENT. DO NOT USE.
10+
# IN DEVELOPMENT. DO NOT USE.
811

912
## Prerequisites
1013

@@ -19,12 +22,19 @@ Just clone this repository and pip install. Note the `--recursive` option which
1922
needed for the pybind11 submodule:
2023

2124
```bash
25+
sudo apt install libelf-dev
2226
git clone --recursive https://github.com/varun-r-mallya/pylibbpf.git
2327
pip install .
2428
```
2529

2630
With the `setup.py` file included in this example, the `pip install` command will
2731
invoke CMake and build the pybind11 module as specified in `CMakeLists.txt`.
2832

33+
## Development
34+
Do this before running to make sure Python can manipulate bpf programs without sudo
35+
```bash
36+
sudo setcap cap_bpf,cap_sys_admin+ep /usr/bin/python3.12
37+
```
38+
2939
## Building the documentation
3040
The documentation here is still boilerplate.

examples/execve.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from pythonbpf import bpf, map, section, bpfglobal, BPF
2+
from ctypes import c_void_p, c_int64, c_int32, c_uint64
3+
from pythonbpf.helpers import ktime
4+
from pythonbpf.maps import HashMap
5+
import time
6+
7+
@bpf
8+
@map
9+
def last() -> HashMap:
10+
return HashMap(key=c_uint64, value=c_uint64, max_entries=1)
11+
12+
13+
@bpf
14+
@section("tracepoint/syscalls/sys_enter_execve")
15+
def hello(ctx: c_void_p) -> c_int32:
16+
print("entered")
17+
print("multi constant support")
18+
return c_int32(0)
19+
20+
21+
@bpf
22+
@section("tracepoint/syscalls/sys_exit_execve")
23+
def hello_again(ctx: c_void_p) -> c_int64:
24+
print("exited")
25+
key = 0
26+
tsp = last().lookup(key)
27+
print(tsp)
28+
ts = ktime()
29+
return c_int64(0)
30+
31+
32+
@bpf
33+
@bpfglobal
34+
def LICENSE() -> str:
35+
return "GPL"
36+
37+
b = BPF()
38+
b.load_and_attach()
39+
while True:
40+
print("running")
41+
time.sleep(1)

src/bindings/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ PYBIND11_MODULE(pylibbpf, m) {
3333
.def("load", &BpfProgram::load)
3434
.def("attach", &BpfProgram::attach)
3535
// .def("detach", &BpfProgram::detach)
36+
.def("load_and_attach", &BpfProgram::load_and_attach)
3637
.def("is_loaded", &BpfProgram::is_loaded)
3738
.def("is_attached", &BpfProgram::is_attached);
3839

src/core/bpf_program.cpp

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
#include "bpf_program.h"
22
#include "bpf_exception.h"
33
#include <filesystem>
4+
#include <utility>
45

5-
BpfProgram::BpfProgram(const std::string& object_path, const std::string& program_name)
6+
BpfProgram::BpfProgram(std::string object_path, std::string program_name)
67
: obj_(nullptr), prog_(nullptr), link_(nullptr),
7-
object_path_(object_path), program_name_(program_name) {
8+
object_path_(std::move(object_path)), program_name_(std::move(program_name)) {
89
}
910

1011
BpfProgram::~BpfProgram() {
@@ -28,9 +29,12 @@ bool BpfProgram::load() {
2829
throw BpfException("Program '" + program_name_ + "' not found in object");
2930
}
3031
} else {
31-
// Use the first program if no name specified
32-
prog_ = bpf_object__next_program(obj_, nullptr);
33-
if (!prog_) {
32+
while ((prog_ = bpf_object__next_program(obj_, prog_)) != nullptr) {
33+
programs.emplace_back(prog_, nullptr);
34+
}
35+
36+
// throw if no programs found
37+
if (programs.empty()) {
3438
throw BpfException("No programs found in object file");
3539
}
3640
}
@@ -44,15 +48,23 @@ bool BpfProgram::load() {
4448
}
4549

4650
bool BpfProgram::attach() {
47-
if (!prog_) {
48-
throw BpfException("Program not loaded");
49-
}
51+
for (auto [prog, link] : programs)
52+
{
53+
if (!prog) {
54+
throw BpfException("Program not loaded");
55+
}
5056

51-
link_ = bpf_program__attach(prog_);
52-
if (libbpf_get_error(link_)) {
53-
link_ = nullptr;
54-
throw BpfException("Failed to attach BPF program");
57+
link = bpf_program__attach(prog);
58+
if (libbpf_get_error(link)) {
59+
link = nullptr;
60+
throw BpfException("Failed to attach BPF program");
61+
}
5562
}
5663

5764
return true;
5865
}
66+
67+
void BpfProgram::load_and_attach() {
68+
load();
69+
attach();
70+
}

src/core/bpf_program.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,17 @@ class BpfProgram {
1414
struct bpf_link* link_;
1515
std::string object_path_;
1616
std::string program_name_;
17-
17+
std::vector<std::pair<bpf_program*, bpf_link*>> programs;
1818
public:
19-
explicit BpfProgram(const std::string& object_path, const std::string& program_name = "");
19+
explicit BpfProgram(std::string object_path, std::string program_name = "");
2020
~BpfProgram();
2121

2222
bool load();
2323
bool attach();
24+
void load_and_attach();
2425

25-
bool is_loaded() const { return obj_ != nullptr; }
26-
bool is_attached() const { return link_ != nullptr; }
26+
[[nodiscard]] bool is_loaded() const { return obj_ != nullptr; }
27+
[[nodiscard]] bool is_attached() const { return link_ != nullptr; }
2728
};
2829

2930
#endif //PYLIBBPF_BPF_PROGRAM_H

0 commit comments

Comments
 (0)