Skip to content

Commit 3c8c6de

Browse files
Add basic class along with exception and attach
Signed-off-by: varun-r-mallya <[email protected]>
1 parent ecefff6 commit 3c8c6de

File tree

8 files changed

+156
-53
lines changed

8 files changed

+156
-53
lines changed

CMakeLists.txt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
cmake_minimum_required(VERSION 3.16) # 4.0 does not exist
1+
cmake_minimum_required(VERSION 4.0)
22
project(pylibbpf)
33

44
# pybind11
5+
include_directories(${CMAKE_SOURCE_DIR}/src)
56
add_subdirectory(pybind11)
6-
pybind11_add_module(pylibbpf src/main.cpp)
7+
pybind11_add_module(pylibbpf src/core/bpf_program.h src/core/bpf_exception.h
8+
src/bindings/main.cpp src/core/bpf_program.cpp)
79

810
# --- libbpf build rules ---
911
set(LIBBPF_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libbpf/src)
@@ -12,8 +14,8 @@ set(LIBBPF_A ${LIBBPF_BUILD_DIR}/libbpf.a)
1214

1315
add_custom_command(
1416
OUTPUT ${LIBBPF_A}
15-
COMMAND make BUILD_STATIC_ONLY=1 OBJDIR=${LIBBPF_BUILD_DIR} -C
16-
${LIBBPF_SRC_DIR}
17+
COMMAND make BUILD_STATIC_ONLY=1 OBJDIR=${LIBBPF_BUILD_DIR} CFLAGS="-fPIC"
18+
LDFLAGS="-fPIC" -C ${LIBBPF_SRC_DIR}
1719
WORKING_DIRECTORY ${LIBBPF_SRC_DIR}
1820
COMMENT "Building libbpf.a"
1921
VERBATIM)
@@ -33,7 +35,7 @@ set_target_properties(
3335
add_dependencies(libbpf_static libbpf_build)
3436

3537
# Link pybind11 module against libbpf
36-
target_link_libraries(pylibbpf PRIVATE libbpf_static)
38+
target_link_libraries(pylibbpf PRIVATE libbpf_static elf)
3739

3840
# Version info for Python extension
3941
target_compile_definitions(pylibbpf

src/bindings/main.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include <pybind11/pybind11.h>
2+
#define STRINGIFY(x) #x
3+
#define MACRO_STRINGIFY(x) STRINGIFY(x)
4+
5+
extern "C" {
6+
#include "libbpf.h"
7+
}
8+
#include "core/bpf_program.h"
9+
#include "core/bpf_exception.h"
10+
11+
namespace py = pybind11;
12+
13+
PYBIND11_MODULE(pylibbpf, m) {
14+
m.doc() = R"pbdoc(
15+
Pylibbpf - libbpf bindings for Python
16+
-----------------------
17+
18+
.. currentmodule:: pylibbpf
19+
20+
.. autosummary::
21+
:toctree: _generate
22+
23+
BpfProgram
24+
BpfException
25+
)pbdoc";
26+
27+
// Register the custom exception
28+
py::register_exception<BpfException>(m, "BpfException");
29+
30+
py::class_<BpfProgram>(m, "BpfProgram")
31+
.def(py::init<const std::string&>())
32+
.def(py::init<const std::string&, const std::string&>())
33+
.def("load", &BpfProgram::load)
34+
.def("attach", &BpfProgram::attach)
35+
// .def("detach", &BpfProgram::detach)
36+
.def("is_loaded", &BpfProgram::is_loaded)
37+
.def("is_attached", &BpfProgram::is_attached);
38+
39+
#ifdef VERSION_INFO
40+
m.attr("__version__") = MACRO_STRINGIFY(VERSION_INFO);
41+
#else
42+
m.attr("__version__") = "dev";
43+
#endif
44+
}

src/core/bpf_exception.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#ifndef PYLIBBPF_BPF_EXCEPTION_H
2+
#define PYLIBBPF_BPF_EXCEPTION_H
3+
4+
#include <stdexcept>
5+
#include <string>
6+
7+
class BpfException final : public std::runtime_error {
8+
public:
9+
explicit BpfException(const std::string& message)
10+
: std::runtime_error(message) {}
11+
12+
explicit BpfException(const char* message)
13+
: std::runtime_error(message) {}
14+
};
15+
16+
#endif // PYLIBBPF_BPF_EXCEPTION_H

src/core/bpf_program.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#include "bpf_program.h"
2+
#include "bpf_exception.h"
3+
#include <filesystem>
4+
5+
BpfProgram::BpfProgram(const std::string& object_path, const std::string& program_name)
6+
: obj_(nullptr), prog_(nullptr), link_(nullptr),
7+
object_path_(object_path), program_name_(program_name) {
8+
}
9+
10+
BpfProgram::~BpfProgram() {
11+
//TODO: detach here as well
12+
if (obj_) {
13+
bpf_object__close(obj_);
14+
}
15+
}
16+
17+
bool BpfProgram::load() {
18+
// Open the eBPF object file
19+
obj_ = bpf_object__open_file(object_path_.c_str(), nullptr);
20+
if (libbpf_get_error(obj_)) {
21+
throw BpfException("Failed to open BPF object file: " + object_path_);
22+
}
23+
24+
// Find the program by name (if specified)
25+
if (!program_name_.empty()) {
26+
prog_ = bpf_object__find_program_by_name(obj_, program_name_.c_str());
27+
if (!prog_) {
28+
throw BpfException("Program '" + program_name_ + "' not found in object");
29+
}
30+
} else {
31+
// Use the first program if no name specified
32+
prog_ = bpf_object__next_program(obj_, nullptr);
33+
if (!prog_) {
34+
throw BpfException("No programs found in object file");
35+
}
36+
}
37+
38+
// Load the eBPF object into the kernel
39+
if (bpf_object__load(obj_)) {
40+
throw BpfException("Failed to load BPF object into kernel");
41+
}
42+
43+
return true;
44+
}
45+
46+
bool BpfProgram::attach() {
47+
if (!prog_) {
48+
throw BpfException("Program not loaded");
49+
}
50+
51+
link_ = bpf_program__attach(prog_);
52+
if (libbpf_get_error(link_)) {
53+
link_ = nullptr;
54+
throw BpfException("Failed to attach BPF program");
55+
}
56+
57+
return true;
58+
}

src/core/bpf_program.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#ifndef PYLIBBPF_BPF_PROGRAM_H
2+
#define PYLIBBPF_BPF_PROGRAM_H
3+
4+
#include "libbpf.h"
5+
#include <pybind11/stl.h>
6+
#include <string>
7+
8+
namespace py = pybind11;
9+
10+
class BpfProgram {
11+
private:
12+
struct bpf_object* obj_;
13+
struct bpf_program* prog_;
14+
struct bpf_link* link_;
15+
std::string object_path_;
16+
std::string program_name_;
17+
18+
public:
19+
explicit BpfProgram(const std::string& object_path, const std::string& program_name = "");
20+
~BpfProgram();
21+
22+
bool load();
23+
bool attach();
24+
25+
bool is_loaded() const { return obj_ != nullptr; }
26+
bool is_attached() const { return link_ != nullptr; }
27+
};
28+
29+
#endif //PYLIBBPF_BPF_PROGRAM_H

src/main.cpp

Lines changed: 0 additions & 46 deletions
This file was deleted.

tests/execve2.o

2.34 KB
Binary file not shown.

tests/test_basic.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33

44
def test_main():
55
assert m.__version__ == "0.0.1"
6-
assert m.add(1, 2) == 3
7-
assert m.subtract(1, 2) == -1
6+
prog = m.BpfProgram("tests/execve2.o")
7+
print(prog)

0 commit comments

Comments
 (0)