Commit c7ccd5b7 authored by Mauricio Vásquez's avatar Mauricio Vásquez Committed by yonghong-song

cc: add BPFTable::get_offline_table (#1978)

get_offline_table is missing in the BPFTable class.

Add it and some test cases.
Signed-off-by: default avatarMauricio Vasquez B <mauricio.vasquez@polito.it>
parent 6ce918bd
...@@ -180,6 +180,72 @@ StatusTuple BPFTable::clear_table_non_atomic() { ...@@ -180,6 +180,72 @@ StatusTuple BPFTable::clear_table_non_atomic() {
return StatusTuple(0); 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(); } size_t BPFTable::get_possible_cpu_count() { return get_possible_cpus().size(); }
BPFStackTable::BPFStackTable(const TableDesc& desc, bool use_debug_file, BPFStackTable::BPFStackTable(const TableDesc& desc, bool use_debug_file,
......
...@@ -104,6 +104,7 @@ class BPFTable : public BPFTableBase<void, void> { ...@@ -104,6 +104,7 @@ class BPFTable : public BPFTableBase<void, void> {
StatusTuple remove_value(const std::string& key_str); StatusTuple remove_value(const std::string& key_str);
StatusTuple clear_table_non_atomic(); StatusTuple clear_table_non_atomic();
StatusTuple get_table_offline(std::vector<std::pair<std::string, std::string>> &res);
static size_t get_possible_cpu_count(); static size_t get_possible_cpu_count();
}; };
......
...@@ -28,6 +28,7 @@ TEST_CASE("test bpf table", "[bpf_table]") { ...@@ -28,6 +28,7 @@ TEST_CASE("test bpf table", "[bpf_table]") {
ebpf::BPF *bpf(new ebpf::BPF); ebpf::BPF *bpf(new ebpf::BPF);
ebpf::StatusTuple res(0); ebpf::StatusTuple res(0);
std::vector<std::pair<std::string, std::string>> elements;
res = bpf->init(BPF_PROGRAM); res = bpf->init(BPF_PROGRAM);
REQUIRE(res.code() == 0); REQUIRE(res.code() == 0);
...@@ -37,7 +38,7 @@ TEST_CASE("test bpf table", "[bpf_table]") { ...@@ -37,7 +38,7 @@ TEST_CASE("test bpf table", "[bpf_table]") {
std::string value; std::string value;
res = t.update_value("0x07", "0x42"); res = t.update_value("0x07", "0x42");
REQUIRE(res.code() == 0); REQUIRE(res.code() == 0);
res = t.get_value("0x07", value); res = t.get_value("0x7", value);
REQUIRE(res.code() == 0); REQUIRE(res.code() == 0);
REQUIRE(value == "0x42"); REQUIRE(value == "0x42");
...@@ -54,14 +55,27 @@ TEST_CASE("test bpf table", "[bpf_table]") { ...@@ -54,14 +55,27 @@ TEST_CASE("test bpf table", "[bpf_table]") {
res = t.get_value("0x11", value); res = t.get_value("0x11", value);
REQUIRE(res.code() != 0); REQUIRE(res.code() != 0);
// clear table
res = t.update_value("0x15", "0x888"); res = t.update_value("0x15", "0x888");
REQUIRE(res.code() == 0); 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); 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(); res = t.clear_table_non_atomic();
REQUIRE(res.code() == 0); 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); REQUIRE(elements.size() == 0);
// delete bpf_module, call to key/leaf printf/scanf must fail // delete bpf_module, call to key/leaf printf/scanf must fail
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment