/* * Copyright (c) 2017 Politecnico di Torino * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "BPF.h" #include "catch.hpp" #include #include #include TEST_CASE("test array table", "[array_table]") { const std::string BPF_PROGRAM = R"( BPF_TABLE("hash", int, int, myhash, 128); BPF_TABLE("array", int, int, myarray, 128); )"; // turn off the rw_engine ebpf::BPF bpf(0, nullptr, false); ebpf::StatusTuple res(0); res = bpf.init(BPF_PROGRAM); REQUIRE(res.ok()); ebpf::BPFArrayTable t = bpf.get_array_table("myarray"); SECTION("bad table type") { // try to get table of wrong type auto f1 = [&](){ bpf.get_array_table("myhash"); }; REQUIRE_THROWS(f1()); } SECTION("standard methods") { int i, v1, v2; i = 1; v1 = 42; // update element res = t.update_value(i, v1); REQUIRE(res.ok()); res = t.get_value(i, v2); REQUIRE(res.ok()); REQUIRE(v2 == 42); // update another element i = 2; v1 = 69; res = t.update_value(i, v1); REQUIRE(res.ok()); res = t.get_value(i, v2); REQUIRE(res.ok()); REQUIRE(v2 == 69); // get non existing element i = 1024; res = t.get_value(i, v2); REQUIRE(!res.ok()); } SECTION("full table") { // random number generator std::mt19937 rng; rng.seed(std::random_device()()); std::uniform_int_distribution dist; std::vector localtable(128); for(int i = 0; i < 128; i++) { int v = dist(rng); res = t.update_value(i, v); REQUIRE(res.ok()); // save it in the local table to compare later on localtable[i] = v; } std::vector offlinetable = t.get_table_offline(); REQUIRE(localtable == offlinetable); } } #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) TEST_CASE("percpu array table", "[percpu_array_table]") { const std::string BPF_PROGRAM = R"( BPF_PERCPU_HASH(myhash, int, u64, 128); BPF_PERCPU_ARRAY(myarray, u64, 64); )"; ebpf::BPF bpf; ebpf::StatusTuple res(0); res = bpf.init(BPF_PROGRAM); REQUIRE(res.ok()); ebpf::BPFPercpuArrayTable t = bpf.get_percpu_array_table("myarray"); size_t ncpus = ebpf::BPFTable::get_possible_cpu_count(); SECTION("bad table type") { // try to get table of wrong type auto f1 = [&](){ bpf.get_percpu_array_table("myhash"); }; REQUIRE_THROWS(f1()); } SECTION("standard methods") { int i; std::vector v1(ncpus); std::vector v2; for (size_t j = 0; j < ncpus; j++) { v1[j] = 42 * j; } i = 1; // update element res = t.update_value(i, v1); REQUIRE(res.ok()); res = t.get_value(i, v2); REQUIRE(res.ok()); REQUIRE(v2.size() == ncpus); for (size_t j = 0; j < ncpus; j++) { REQUIRE(v2.at(j) == 42 * j); } // get non existing element i = 1024; res = t.get_value(i, v2); REQUIRE(!res.ok()); } } #endif