Skip to content

Commit

Permalink
cc: add BPFTable::get_offline_table (iovisor#1978)
Browse files Browse the repository at this point in the history
get_offline_table is missing in the BPFTable class.

Add it and some test cases.

Signed-off-by: Mauricio Vasquez B <[email protected]>
  • Loading branch information
mauriciovasquezbernal authored and yonghong-song committed Sep 21, 2018
1 parent 6ce918b commit c7ccd5b
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 4 deletions.
66 changes: 66 additions & 0 deletions src/cc/api/BPFTable.cc
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,72 @@ StatusTuple BPFTable::clear_table_non_atomic() {
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,
Expand Down
1 change: 1 addition & 0 deletions src/cc/api/BPFTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class BPFTable : public BPFTableBase<void, void> {
StatusTuple remove_value(const std::string& key_str);

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();
};
Expand Down
22 changes: 18 additions & 4 deletions tests/cc/test_bpf_table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ TEST_CASE("test bpf table", "[bpf_table]") {

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);

Expand All @@ -37,7 +38,7 @@ TEST_CASE("test bpf table", "[bpf_table]") {
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");

Expand All @@ -54,14 +55,27 @@ TEST_CASE("test bpf table", "[bpf_table]") {
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
Expand Down

0 comments on commit c7ccd5b

Please sign in to comment.