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 #include <linux/version.h> 19*387f9dfdSAndroid Build Coastguard Worker 20*387f9dfdSAndroid Build Coastguard Worker #include "catch.hpp" 21*387f9dfdSAndroid Build Coastguard Worker 22*387f9dfdSAndroid Build Coastguard Worker TEST_CASE("test hash table", "[hash_table]") { 23*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"( 24*387f9dfdSAndroid Build Coastguard Worker BPF_TABLE("hash", int, int, myhash, 1024); 25*387f9dfdSAndroid Build Coastguard Worker BPF_TABLE("array", int, int, myarray, 1024); 26*387f9dfdSAndroid Build Coastguard Worker )"; 27*387f9dfdSAndroid Build Coastguard Worker 28*387f9dfdSAndroid Build Coastguard Worker ebpf::BPF bpf; 29*387f9dfdSAndroid Build Coastguard Worker ebpf::StatusTuple res(0); 30*387f9dfdSAndroid Build Coastguard Worker res = bpf.init(BPF_PROGRAM); 31*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 32*387f9dfdSAndroid Build Coastguard Worker 33*387f9dfdSAndroid Build Coastguard Worker ebpf::BPFHashTable<int, int> t = bpf.get_hash_table<int, int>("myhash"); 34*387f9dfdSAndroid Build Coastguard Worker 35*387f9dfdSAndroid Build Coastguard Worker SECTION("bad table type") { 36*387f9dfdSAndroid Build Coastguard Worker // try to get table of wrong type __anon99f2c8330102()37*387f9dfdSAndroid Build Coastguard Worker auto f1 = [&](){ 38*387f9dfdSAndroid Build Coastguard Worker bpf.get_hash_table<int, int>("myarray"); 39*387f9dfdSAndroid Build Coastguard Worker }; 40*387f9dfdSAndroid Build Coastguard Worker 41*387f9dfdSAndroid Build Coastguard Worker REQUIRE_THROWS(f1()); 42*387f9dfdSAndroid Build Coastguard Worker } 43*387f9dfdSAndroid Build Coastguard Worker 44*387f9dfdSAndroid Build Coastguard Worker SECTION("standard methods") { 45*387f9dfdSAndroid Build Coastguard Worker int k, v1, v2; 46*387f9dfdSAndroid Build Coastguard Worker k = 1; 47*387f9dfdSAndroid Build Coastguard Worker v1 = 42; 48*387f9dfdSAndroid Build Coastguard Worker // create new element 49*387f9dfdSAndroid Build Coastguard Worker res = t.update_value(k, v1); 50*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 51*387f9dfdSAndroid Build Coastguard Worker res = t.get_value(k, v2); 52*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 53*387f9dfdSAndroid Build Coastguard Worker REQUIRE(v2 == 42); 54*387f9dfdSAndroid Build Coastguard Worker 55*387f9dfdSAndroid Build Coastguard Worker // update existing element 56*387f9dfdSAndroid Build Coastguard Worker v1 = 69; 57*387f9dfdSAndroid Build Coastguard Worker res = t.update_value(k, v1); 58*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 59*387f9dfdSAndroid Build Coastguard Worker res = t.get_value(k, v2); 60*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 61*387f9dfdSAndroid Build Coastguard Worker REQUIRE(v2 == 69); 62*387f9dfdSAndroid Build Coastguard Worker 63*387f9dfdSAndroid Build Coastguard Worker // remove existing element 64*387f9dfdSAndroid Build Coastguard Worker res = t.remove_value(k); 65*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 66*387f9dfdSAndroid Build Coastguard Worker 67*387f9dfdSAndroid Build Coastguard Worker // remove non existing element 68*387f9dfdSAndroid Build Coastguard Worker res = t.remove_value(k); 69*387f9dfdSAndroid Build Coastguard Worker REQUIRE(!res.ok()); 70*387f9dfdSAndroid Build Coastguard Worker 71*387f9dfdSAndroid Build Coastguard Worker // get non existing element 72*387f9dfdSAndroid Build Coastguard Worker res = t.get_value(k, v2); 73*387f9dfdSAndroid Build Coastguard Worker REQUIRE(!res.ok()); 74*387f9dfdSAndroid Build Coastguard Worker } 75*387f9dfdSAndroid Build Coastguard Worker 76*387f9dfdSAndroid Build Coastguard Worker SECTION("walk table") { 77*387f9dfdSAndroid Build Coastguard Worker for (int i = 1; i <= 10; i++) { 78*387f9dfdSAndroid Build Coastguard Worker res = t.update_value(i * 3, i); 79*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 80*387f9dfdSAndroid Build Coastguard Worker } 81*387f9dfdSAndroid Build Coastguard Worker auto offline = t.get_table_offline(); 82*387f9dfdSAndroid Build Coastguard Worker REQUIRE(offline.size() == 10); 83*387f9dfdSAndroid Build Coastguard Worker for (const auto &pair : offline) { 84*387f9dfdSAndroid Build Coastguard Worker REQUIRE(pair.first % 3 == 0); 85*387f9dfdSAndroid Build Coastguard Worker REQUIRE(pair.first / 3 == pair.second); 86*387f9dfdSAndroid Build Coastguard Worker } 87*387f9dfdSAndroid Build Coastguard Worker 88*387f9dfdSAndroid Build Coastguard Worker // clear table 89*387f9dfdSAndroid Build Coastguard Worker t.clear_table_non_atomic(); 90*387f9dfdSAndroid Build Coastguard Worker REQUIRE(t.get_table_offline().size() == 0); 91*387f9dfdSAndroid Build Coastguard Worker } 92*387f9dfdSAndroid Build Coastguard Worker } 93*387f9dfdSAndroid Build Coastguard Worker 94*387f9dfdSAndroid Build Coastguard Worker #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) 95*387f9dfdSAndroid Build Coastguard Worker TEST_CASE("percpu hash table", "[percpu_hash_table]") { 96*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"( 97*387f9dfdSAndroid Build Coastguard Worker BPF_PERCPU_HASH(myhash, int, u64, 128); 98*387f9dfdSAndroid Build Coastguard Worker BPF_PERCPU_ARRAY(myarray, u64, 64); 99*387f9dfdSAndroid Build Coastguard Worker )"; 100*387f9dfdSAndroid Build Coastguard Worker 101*387f9dfdSAndroid Build Coastguard Worker ebpf::BPF bpf; 102*387f9dfdSAndroid Build Coastguard Worker ebpf::StatusTuple res(0); 103*387f9dfdSAndroid Build Coastguard Worker res = bpf.init(BPF_PROGRAM); 104*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 105*387f9dfdSAndroid Build Coastguard Worker 106*387f9dfdSAndroid Build Coastguard Worker ebpf::BPFPercpuHashTable<int, uint64_t> t = 107*387f9dfdSAndroid Build Coastguard Worker bpf.get_percpu_hash_table<int, uint64_t>("myhash"); 108*387f9dfdSAndroid Build Coastguard Worker size_t ncpus = ebpf::BPFTable::get_possible_cpu_count(); 109*387f9dfdSAndroid Build Coastguard Worker 110*387f9dfdSAndroid Build Coastguard Worker SECTION("bad table type") { 111*387f9dfdSAndroid Build Coastguard Worker // try to get table of wrong type __anon99f2c8330202()112*387f9dfdSAndroid Build Coastguard Worker auto f1 = [&](){ 113*387f9dfdSAndroid Build Coastguard Worker bpf.get_percpu_hash_table<int, uint64_t>("myarray"); 114*387f9dfdSAndroid Build Coastguard Worker }; 115*387f9dfdSAndroid Build Coastguard Worker 116*387f9dfdSAndroid Build Coastguard Worker REQUIRE_THROWS(f1()); 117*387f9dfdSAndroid Build Coastguard Worker } 118*387f9dfdSAndroid Build Coastguard Worker 119*387f9dfdSAndroid Build Coastguard Worker SECTION("standard methods") { 120*387f9dfdSAndroid Build Coastguard Worker int k; 121*387f9dfdSAndroid Build Coastguard Worker std::vector<uint64_t> v1(ncpus); 122*387f9dfdSAndroid Build Coastguard Worker std::vector<uint64_t> v2; 123*387f9dfdSAndroid Build Coastguard Worker 124*387f9dfdSAndroid Build Coastguard Worker for (size_t j = 0; j < ncpus; j++) { 125*387f9dfdSAndroid Build Coastguard Worker v1[j] = 42 * j; 126*387f9dfdSAndroid Build Coastguard Worker } 127*387f9dfdSAndroid Build Coastguard Worker 128*387f9dfdSAndroid Build Coastguard Worker k = 1; 129*387f9dfdSAndroid Build Coastguard Worker 130*387f9dfdSAndroid Build Coastguard Worker // create new element 131*387f9dfdSAndroid Build Coastguard Worker res = t.update_value(k, v1); 132*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 133*387f9dfdSAndroid Build Coastguard Worker res = t.get_value(k, v2); 134*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 135*387f9dfdSAndroid Build Coastguard Worker for (size_t j = 0; j < ncpus; j++) { 136*387f9dfdSAndroid Build Coastguard Worker REQUIRE(v2.at(j) == 42 * j); 137*387f9dfdSAndroid Build Coastguard Worker } 138*387f9dfdSAndroid Build Coastguard Worker 139*387f9dfdSAndroid Build Coastguard Worker // update existing element 140*387f9dfdSAndroid Build Coastguard Worker for (size_t j = 0; j < ncpus; j++) { 141*387f9dfdSAndroid Build Coastguard Worker v1[j] = 69 * j; 142*387f9dfdSAndroid Build Coastguard Worker } 143*387f9dfdSAndroid Build Coastguard Worker res = t.update_value(k, v1); 144*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 145*387f9dfdSAndroid Build Coastguard Worker res = t.get_value(k, v2); 146*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 147*387f9dfdSAndroid Build Coastguard Worker for (size_t j = 0; j < ncpus; j++) { 148*387f9dfdSAndroid Build Coastguard Worker REQUIRE(v2.at(j) == 69 * j); 149*387f9dfdSAndroid Build Coastguard Worker } 150*387f9dfdSAndroid Build Coastguard Worker 151*387f9dfdSAndroid Build Coastguard Worker // remove existing element 152*387f9dfdSAndroid Build Coastguard Worker res = t.remove_value(k); 153*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 154*387f9dfdSAndroid Build Coastguard Worker 155*387f9dfdSAndroid Build Coastguard Worker // remove non existing element 156*387f9dfdSAndroid Build Coastguard Worker res = t.remove_value(k); 157*387f9dfdSAndroid Build Coastguard Worker REQUIRE(!res.ok()); 158*387f9dfdSAndroid Build Coastguard Worker 159*387f9dfdSAndroid Build Coastguard Worker // get non existing element 160*387f9dfdSAndroid Build Coastguard Worker res = t.get_value(k, v2); 161*387f9dfdSAndroid Build Coastguard Worker REQUIRE(!res.ok()); 162*387f9dfdSAndroid Build Coastguard Worker } 163*387f9dfdSAndroid Build Coastguard Worker 164*387f9dfdSAndroid Build Coastguard Worker SECTION("walk table") { 165*387f9dfdSAndroid Build Coastguard Worker std::vector<uint64_t> v(ncpus); 166*387f9dfdSAndroid Build Coastguard Worker 167*387f9dfdSAndroid Build Coastguard Worker for (int k = 3; k <= 30; k+=3) { 168*387f9dfdSAndroid Build Coastguard Worker for (size_t cpu = 0; cpu < ncpus; cpu++) { 169*387f9dfdSAndroid Build Coastguard Worker v[cpu] = k * cpu; 170*387f9dfdSAndroid Build Coastguard Worker } 171*387f9dfdSAndroid Build Coastguard Worker res = t.update_value(k, v); 172*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 173*387f9dfdSAndroid Build Coastguard Worker } 174*387f9dfdSAndroid Build Coastguard Worker 175*387f9dfdSAndroid Build Coastguard Worker // get whole table 176*387f9dfdSAndroid Build Coastguard Worker auto offline = t.get_table_offline(); 177*387f9dfdSAndroid Build Coastguard Worker REQUIRE(offline.size() == 10); 178*387f9dfdSAndroid Build Coastguard Worker for (int i = 0; i < 10; i++) { 179*387f9dfdSAndroid Build Coastguard Worker // check the key 180*387f9dfdSAndroid Build Coastguard Worker REQUIRE(offline.at(i).first % 3 == 0); 181*387f9dfdSAndroid Build Coastguard Worker 182*387f9dfdSAndroid Build Coastguard Worker // check value 183*387f9dfdSAndroid Build Coastguard Worker for (size_t cpu = 0; cpu < ncpus; cpu++) { 184*387f9dfdSAndroid Build Coastguard Worker REQUIRE(offline.at(i).second.at(cpu) == cpu * offline.at(i).first); 185*387f9dfdSAndroid Build Coastguard Worker } 186*387f9dfdSAndroid Build Coastguard Worker } 187*387f9dfdSAndroid Build Coastguard Worker 188*387f9dfdSAndroid Build Coastguard Worker // clear table 189*387f9dfdSAndroid Build Coastguard Worker t.clear_table_non_atomic(); 190*387f9dfdSAndroid Build Coastguard Worker REQUIRE(t.get_table_offline().size() == 0); 191*387f9dfdSAndroid Build Coastguard Worker } 192*387f9dfdSAndroid Build Coastguard Worker } 193*387f9dfdSAndroid Build Coastguard Worker #endif 194