1*387f9dfdSAndroid Build Coastguard Worker /* 2*387f9dfdSAndroid Build Coastguard Worker * Copyright (c) 2017 Politecnico di Torino 3*387f9dfdSAndroid Build Coastguard Worker * 4*387f9dfdSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*387f9dfdSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*387f9dfdSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*387f9dfdSAndroid Build Coastguard Worker * 8*387f9dfdSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*387f9dfdSAndroid Build Coastguard Worker * 10*387f9dfdSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*387f9dfdSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*387f9dfdSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*387f9dfdSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*387f9dfdSAndroid Build Coastguard Worker * limitations under the License. 15*387f9dfdSAndroid Build Coastguard Worker */ 16*387f9dfdSAndroid Build Coastguard Worker 17*387f9dfdSAndroid Build Coastguard Worker #include "BPF.h" 18*387f9dfdSAndroid Build Coastguard Worker 19*387f9dfdSAndroid Build Coastguard Worker #include "catch.hpp" 20*387f9dfdSAndroid Build Coastguard Worker 21*387f9dfdSAndroid Build Coastguard Worker #include <random> 22*387f9dfdSAndroid Build Coastguard Worker #include <iostream> 23*387f9dfdSAndroid Build Coastguard Worker 24*387f9dfdSAndroid Build Coastguard Worker #include <linux/version.h> 25*387f9dfdSAndroid Build Coastguard Worker 26*387f9dfdSAndroid Build Coastguard Worker TEST_CASE("test array table", "[array_table]") { 27*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"( 28*387f9dfdSAndroid Build Coastguard Worker BPF_TABLE("hash", int, int, myhash, 128); 29*387f9dfdSAndroid Build Coastguard Worker BPF_TABLE("array", int, int, myarray, 128); 30*387f9dfdSAndroid Build Coastguard Worker )"; 31*387f9dfdSAndroid Build Coastguard Worker 32*387f9dfdSAndroid Build Coastguard Worker // turn off the rw_engine 33*387f9dfdSAndroid Build Coastguard Worker ebpf::BPF bpf(0, nullptr, false); 34*387f9dfdSAndroid Build Coastguard Worker ebpf::StatusTuple res(0); 35*387f9dfdSAndroid Build Coastguard Worker res = bpf.init(BPF_PROGRAM); 36*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 37*387f9dfdSAndroid Build Coastguard Worker 38*387f9dfdSAndroid Build Coastguard Worker ebpf::BPFArrayTable<int> t = bpf.get_array_table<int>("myarray"); 39*387f9dfdSAndroid Build Coastguard Worker 40*387f9dfdSAndroid Build Coastguard Worker SECTION("bad table type") { 41*387f9dfdSAndroid Build Coastguard Worker // try to get table of wrong type __anona86befce0102()42*387f9dfdSAndroid Build Coastguard Worker auto f1 = [&](){ 43*387f9dfdSAndroid Build Coastguard Worker bpf.get_array_table<int>("myhash"); 44*387f9dfdSAndroid Build Coastguard Worker }; 45*387f9dfdSAndroid Build Coastguard Worker 46*387f9dfdSAndroid Build Coastguard Worker REQUIRE_THROWS(f1()); 47*387f9dfdSAndroid Build Coastguard Worker } 48*387f9dfdSAndroid Build Coastguard Worker 49*387f9dfdSAndroid Build Coastguard Worker SECTION("standard methods") { 50*387f9dfdSAndroid Build Coastguard Worker int i, v1, v2; 51*387f9dfdSAndroid Build Coastguard Worker i = 1; 52*387f9dfdSAndroid Build Coastguard Worker v1 = 42; 53*387f9dfdSAndroid Build Coastguard Worker // update element 54*387f9dfdSAndroid Build Coastguard Worker res = t.update_value(i, v1); 55*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 56*387f9dfdSAndroid Build Coastguard Worker res = t.get_value(i, v2); 57*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 58*387f9dfdSAndroid Build Coastguard Worker REQUIRE(v2 == 42); 59*387f9dfdSAndroid Build Coastguard Worker 60*387f9dfdSAndroid Build Coastguard Worker // update another element 61*387f9dfdSAndroid Build Coastguard Worker i = 2; 62*387f9dfdSAndroid Build Coastguard Worker v1 = 69; 63*387f9dfdSAndroid Build Coastguard Worker res = t.update_value(i, v1); 64*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 65*387f9dfdSAndroid Build Coastguard Worker res = t.get_value(i, v2); 66*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 67*387f9dfdSAndroid Build Coastguard Worker REQUIRE(v2 == 69); 68*387f9dfdSAndroid Build Coastguard Worker 69*387f9dfdSAndroid Build Coastguard Worker // get non existing element 70*387f9dfdSAndroid Build Coastguard Worker i = 1024; 71*387f9dfdSAndroid Build Coastguard Worker res = t.get_value(i, v2); 72*387f9dfdSAndroid Build Coastguard Worker REQUIRE(!res.ok()); 73*387f9dfdSAndroid Build Coastguard Worker } 74*387f9dfdSAndroid Build Coastguard Worker 75*387f9dfdSAndroid Build Coastguard Worker SECTION("full table") { 76*387f9dfdSAndroid Build Coastguard Worker // random number generator 77*387f9dfdSAndroid Build Coastguard Worker std::mt19937 rng; 78*387f9dfdSAndroid Build Coastguard Worker rng.seed(std::random_device()()); 79*387f9dfdSAndroid Build Coastguard Worker std::uniform_int_distribution<int> dist; 80*387f9dfdSAndroid Build Coastguard Worker 81*387f9dfdSAndroid Build Coastguard Worker std::vector<int> localtable(128); 82*387f9dfdSAndroid Build Coastguard Worker 83*387f9dfdSAndroid Build Coastguard Worker for(int i = 0; i < 128; i++) { 84*387f9dfdSAndroid Build Coastguard Worker int v = dist(rng); 85*387f9dfdSAndroid Build Coastguard Worker 86*387f9dfdSAndroid Build Coastguard Worker res = t.update_value(i, v); 87*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 88*387f9dfdSAndroid Build Coastguard Worker 89*387f9dfdSAndroid Build Coastguard Worker // save it in the local table to compare later on 90*387f9dfdSAndroid Build Coastguard Worker localtable[i] = v; 91*387f9dfdSAndroid Build Coastguard Worker } 92*387f9dfdSAndroid Build Coastguard Worker 93*387f9dfdSAndroid Build Coastguard Worker std::vector<int> offlinetable = t.get_table_offline(); 94*387f9dfdSAndroid Build Coastguard Worker REQUIRE(localtable == offlinetable); 95*387f9dfdSAndroid Build Coastguard Worker } 96*387f9dfdSAndroid Build Coastguard Worker } 97*387f9dfdSAndroid Build Coastguard Worker 98*387f9dfdSAndroid Build Coastguard Worker #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) 99*387f9dfdSAndroid Build Coastguard Worker TEST_CASE("percpu array table", "[percpu_array_table]") { 100*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"( 101*387f9dfdSAndroid Build Coastguard Worker BPF_PERCPU_HASH(myhash, int, u64, 128); 102*387f9dfdSAndroid Build Coastguard Worker BPF_PERCPU_ARRAY(myarray, u64, 64); 103*387f9dfdSAndroid Build Coastguard Worker )"; 104*387f9dfdSAndroid Build Coastguard Worker 105*387f9dfdSAndroid Build Coastguard Worker ebpf::BPF bpf; 106*387f9dfdSAndroid Build Coastguard Worker ebpf::StatusTuple res(0); 107*387f9dfdSAndroid Build Coastguard Worker res = bpf.init(BPF_PROGRAM); 108*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 109*387f9dfdSAndroid Build Coastguard Worker 110*387f9dfdSAndroid Build Coastguard Worker ebpf::BPFPercpuArrayTable<uint64_t> t = bpf.get_percpu_array_table<uint64_t>("myarray"); 111*387f9dfdSAndroid Build Coastguard Worker size_t ncpus = ebpf::BPFTable::get_possible_cpu_count(); 112*387f9dfdSAndroid Build Coastguard Worker 113*387f9dfdSAndroid Build Coastguard Worker SECTION("bad table type") { 114*387f9dfdSAndroid Build Coastguard Worker // try to get table of wrong type __anona86befce0202()115*387f9dfdSAndroid Build Coastguard Worker auto f1 = [&](){ 116*387f9dfdSAndroid Build Coastguard Worker bpf.get_percpu_array_table<uint64_t>("myhash"); 117*387f9dfdSAndroid Build Coastguard Worker }; 118*387f9dfdSAndroid Build Coastguard Worker 119*387f9dfdSAndroid Build Coastguard Worker REQUIRE_THROWS(f1()); 120*387f9dfdSAndroid Build Coastguard Worker } 121*387f9dfdSAndroid Build Coastguard Worker 122*387f9dfdSAndroid Build Coastguard Worker SECTION("standard methods") { 123*387f9dfdSAndroid Build Coastguard Worker int i; 124*387f9dfdSAndroid Build Coastguard Worker std::vector<uint64_t> v1(ncpus); 125*387f9dfdSAndroid Build Coastguard Worker std::vector<uint64_t> v2; 126*387f9dfdSAndroid Build Coastguard Worker 127*387f9dfdSAndroid Build Coastguard Worker for (size_t j = 0; j < ncpus; j++) { 128*387f9dfdSAndroid Build Coastguard Worker v1[j] = 42 * j; 129*387f9dfdSAndroid Build Coastguard Worker } 130*387f9dfdSAndroid Build Coastguard Worker 131*387f9dfdSAndroid Build Coastguard Worker i = 1; 132*387f9dfdSAndroid Build Coastguard Worker // update element 133*387f9dfdSAndroid Build Coastguard Worker res = t.update_value(i, v1); 134*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 135*387f9dfdSAndroid Build Coastguard Worker res = t.get_value(i, v2); 136*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 137*387f9dfdSAndroid Build Coastguard Worker REQUIRE(v2.size() == ncpus); 138*387f9dfdSAndroid Build Coastguard Worker for (size_t j = 0; j < ncpus; j++) { 139*387f9dfdSAndroid Build Coastguard Worker REQUIRE(v2.at(j) == 42 * j); 140*387f9dfdSAndroid Build Coastguard Worker } 141*387f9dfdSAndroid Build Coastguard Worker 142*387f9dfdSAndroid Build Coastguard Worker // get non existing element 143*387f9dfdSAndroid Build Coastguard Worker i = 1024; 144*387f9dfdSAndroid Build Coastguard Worker res = t.get_value(i, v2); 145*387f9dfdSAndroid Build Coastguard Worker REQUIRE(!res.ok()); 146*387f9dfdSAndroid Build Coastguard Worker } 147*387f9dfdSAndroid Build Coastguard Worker } 148*387f9dfdSAndroid Build Coastguard Worker #endif 149