Skip to content

Commit 68f2bc4

Browse files
authored
Merge pull request #8 from pythonbpf/test-workflow
Add support for using struct as value_type in hashmap
2 parents ccce772 + 8ac2d67 commit 68f2bc4

File tree

3 files changed

+45
-3
lines changed

3 files changed

+45
-3
lines changed

src/bindings/main.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ PYBIND11_MODULE(pylibbpf, m) {
6565
.def("get_key_size", &BpfMap::get_key_size)
6666
.def("get_value_size", &BpfMap::get_value_size)
6767
.def("get_max_entries", &BpfMap::get_max_entries)
68+
.def("set_value_struct", &BpfMap::set_value_struct,
69+
py::arg("struct_name"))
70+
.def("get_value_struct_name", &BpfMap::get_value_struct_name)
71+
.def("has_struct_value", &BpfMap::has_struct_value)
6872
.def("__getitem__", &BpfMap::lookup, py::arg("key"))
6973
.def("__setitem__", &BpfMap::update, py::arg("key"), py::arg("value"))
7074
.def("__delitem__", &BpfMap::delete_elem, py::arg("key"));

src/core/bpf_map.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "core/bpf_map.h"
22
#include "core/bpf_exception.h"
33
#include "core/bpf_object.h"
4+
#include "utils/struct_parser.h"
45
#include <algorithm>
56
#include <cerrno>
67
#include <cstring>
@@ -25,6 +26,24 @@ BpfMap::BpfMap(std::shared_ptr<BpfObject> parent, struct bpf_map *raw_map,
2526
value_size_ = bpf_map__value_size(map_);
2627
}
2728

29+
void BpfMap::set_value_struct(const std::string &struct_name) {
30+
auto parent = parent_obj_.lock();
31+
if (!parent) {
32+
throw BpfException("Parent BpfObject no longer exists");
33+
}
34+
35+
struct_parser_ = parent->get_struct_parser();
36+
if (!struct_parser_) {
37+
throw BpfException("No struct definitions available in BpfObject");
38+
}
39+
40+
if (!struct_parser_->has_struct(struct_name)) {
41+
throw BpfException("Unknown struct: " + struct_name);
42+
}
43+
44+
value_struct_name_ = struct_name;
45+
}
46+
2847
py::object BpfMap::lookup(const py::object &key) const {
2948
if (map_fd_ < 0)
3049
throw BpfException("Map '" + map_name_ + "' is not initialized properly");
@@ -42,7 +61,7 @@ py::object BpfMap::lookup(const py::object &key) const {
4261
value_span.data(), value_size_, BPF_ANY);
4362
if (ret < 0) {
4463
if (ret == -ENOENT)
45-
throw py::key_error("Key not found in map '" + map_name_ + "'");
64+
return py::none();
4665
throw BpfException("Failed to lookup key in map '" + map_name_ +
4766
"': " + std::strerror(-ret));
4867
}
@@ -215,7 +234,13 @@ void BpfMap::python_to_bytes_inplace(const py::object &obj,
215234
}
216235
}
217236

218-
py::object BpfMap::bytes_to_python(std::span<const uint8_t> data) {
237+
py::object BpfMap::bytes_to_python(std::span<const uint8_t> data) const {
238+
// NOTE: Struct parsing for value type
239+
if (struct_parser_ && !value_struct_name_.empty()) {
240+
py::bytes py_data(reinterpret_cast<const char *>(data.data()), data.size());
241+
return struct_parser_->parse(value_struct_name_, py_data);
242+
}
243+
219244
if (data.size() == 4) {
220245
uint32_t value;
221246
std::memcpy(&value, data.data(), 4);

src/core/bpf_map.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <vector>
1010

1111
class BpfObject;
12+
class StructParser;
1213

1314
namespace py = pybind11;
1415

@@ -20,6 +21,11 @@ class BpfMap : public std::enable_shared_from_this<BpfMap> {
2021
std::string map_name_;
2122
__u32 key_size_, value_size_;
2223

24+
// TODO: For now, we'll only support struct parsing for value types
25+
// later we can extend this to keys
26+
std::shared_ptr<StructParser> struct_parser_;
27+
std::string value_struct_name_;
28+
2329
template <size_t StackSize = 64> struct BufferManager {
2430
std::array<uint8_t, StackSize> stack_buf;
2531
std::vector<uint8_t> heap_buf;
@@ -52,6 +58,7 @@ class BpfMap : public std::enable_shared_from_this<BpfMap> {
5258
py::dict items() const;
5359
py::list keys() const;
5460
py::list values() const;
61+
void set_value_struct(const std::string &struct_name);
5562

5663
[[nodiscard]] std::string get_name() const { return map_name_; }
5764
[[nodiscard]] int get_fd() const { return map_fd_; }
@@ -62,11 +69,17 @@ class BpfMap : public std::enable_shared_from_this<BpfMap> {
6269
[[nodiscard]] std::shared_ptr<BpfObject> get_parent() const {
6370
return parent_obj_.lock();
6471
}
72+
[[nodiscard]] std::string get_value_struct_name() const {
73+
return value_struct_name_;
74+
}
75+
[[nodiscard]] bool has_struct_value() const {
76+
return !value_struct_name_.empty();
77+
}
6578

6679
private:
6780
static void python_to_bytes_inplace(const py::object &obj,
6881
std::span<uint8_t> buffer);
69-
static py::object bytes_to_python(std::span<const uint8_t> data);
82+
py::object bytes_to_python(std::span<const uint8_t> data) const;
7083
};
7184

7285
#endif // PYLIBBPF_BPF_MAP_H

0 commit comments

Comments
 (0)