return StatusTuple(0);
}
+StatusTuple BPFTable::get_table_offline(
+ std::vector<std::pair<std::string, std::string>> &res) {
+ StatusTuple r(0);
+ int err;
+
+ auto key = std::unique_ptr<void, decltype(::free)*>(::malloc(desc.key_size),
+ ::free);
+ auto value = std::unique_ptr<void, decltype(::free)*>(::malloc(desc.leaf_size),
+ ::free);
+ std::string key_str;
+ std::string value_str;
+
+ if (desc.type == BPF_MAP_TYPE_ARRAY ||
+ desc.type == BPF_MAP_TYPE_PROG_ARRAY ||
+ desc.type == BPF_MAP_TYPE_PERF_EVENT_ARRAY ||
+ desc.type == BPF_MAP_TYPE_PERCPU_ARRAY ||
+ desc.type == BPF_MAP_TYPE_CGROUP_ARRAY ||
+ desc.type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
+ desc.type == BPF_MAP_TYPE_DEVMAP ||
+ desc.type == BPF_MAP_TYPE_CPUMAP ||
+ desc.type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) {
+ // For arrays, just iterate over all indices
+ for (size_t i = 0; i < desc.max_entries; i++) {
+ err = bpf_lookup_elem(desc.fd, &i, value.get());
+ if (err < 0 && errno == ENOENT) {
+ // Element is not present, skip it
+ continue;
+ } else if (err < 0) {
+ // Other error, abort
+ return StatusTuple(-1, "Error looking up value: %s", std::strerror(errno));
+ }
+
+ r = key_to_string(&i, key_str);
+ if (r.code() != 0)
+ return r;
+
+ r = leaf_to_string(value.get(), value_str);
+ if (r.code() != 0)
+ return r;
+ res.emplace_back(key_str, value_str);
+ }
+ } else {
+ res.clear();
+ // For other maps, try to use the first() and next() interfaces
+ if (!this->first(key.get()))
+ return StatusTuple(0);
+
+ while (true) {
+ if (!this->lookup(key.get(), value.get()))
+ break;
+ r = key_to_string(key.get(), key_str);
+ if (r.code() != 0)
+ return r;
+
+ r = leaf_to_string(value.get(), value_str);
+ if (r.code() != 0)
+ return r;
+ res.emplace_back(key_str, value_str);
+ if (!this->next(key.get(), key.get()))
+ break;
+ }
+ }
+
+ return StatusTuple(0);
+}
+
size_t BPFTable::get_possible_cpu_count() { return get_possible_cpus().size(); }
BPFStackTable::BPFStackTable(const TableDesc& desc, bool use_debug_file,
ebpf::BPF *bpf(new ebpf::BPF);
ebpf::StatusTuple res(0);
+ std::vector<std::pair<std::string, std::string>> elements;
res = bpf->init(BPF_PROGRAM);
REQUIRE(res.code() == 0);
std::string value;
res = t.update_value("0x07", "0x42");
REQUIRE(res.code() == 0);
- res = t.get_value("0x07", value);
+ res = t.get_value("0x7", value);
REQUIRE(res.code() == 0);
REQUIRE(value == "0x42");
res = t.get_value("0x11", value);
REQUIRE(res.code() != 0);
- // clear table
res = t.update_value("0x15", "0x888");
REQUIRE(res.code() == 0);
- auto elements = bpf->get_hash_table<int, int>("myhash").get_table_offline();
+ res = t.get_table_offline(elements);
+ REQUIRE(res.code() == 0);
REQUIRE(elements.size() == 2);
+
+ // check that elements match what is in the table
+ for (auto &it : elements) {
+ if (it.first == "0x15") {
+ REQUIRE(it.second == "0x888");
+ } else if (it.first == "0x7") {
+ REQUIRE(it.second == "0x42");
+ } else {
+ FAIL("Element " + it.first + " should not be on the table", it.first);
+ }
+ }
+
res = t.clear_table_non_atomic();
REQUIRE(res.code() == 0);
- elements = bpf->get_hash_table<int, int>("myhash").get_table_offline();
+ res = t.get_table_offline(elements);
+ REQUIRE(res.code() == 0);
REQUIRE(elements.size() == 0);
// delete bpf_module, call to key/leaf printf/scanf must fail