1*387f9dfdSAndroid Build Coastguard Worker /* 2*387f9dfdSAndroid Build Coastguard Worker * Copyright (c) 2019 Kinvolk GmbH 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 <linux/version.h> 18*387f9dfdSAndroid Build Coastguard Worker #include <unistd.h> 19*387f9dfdSAndroid Build Coastguard Worker #include <string> 20*387f9dfdSAndroid Build Coastguard Worker #include <sys/mount.h> 21*387f9dfdSAndroid Build Coastguard Worker 22*387f9dfdSAndroid Build Coastguard Worker #include "BPF.h" 23*387f9dfdSAndroid Build Coastguard Worker #include "catch.hpp" 24*387f9dfdSAndroid Build Coastguard Worker 25*387f9dfdSAndroid Build Coastguard Worker #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) 26*387f9dfdSAndroid Build Coastguard Worker TEST_CASE("test pinned table", "[pinned_table]") { 27*387f9dfdSAndroid Build Coastguard Worker bool mounted = false; 28*387f9dfdSAndroid Build Coastguard Worker if (system("mount | grep /sys/fs/bpf")) { 29*387f9dfdSAndroid Build Coastguard Worker REQUIRE(system("mkdir -p /sys/fs/bpf") == 0); 30*387f9dfdSAndroid Build Coastguard Worker REQUIRE(system("mount -o nosuid,nodev,noexec,mode=700 -t bpf bpf /sys/fs/bpf") == 0); 31*387f9dfdSAndroid Build Coastguard Worker mounted = true; 32*387f9dfdSAndroid Build Coastguard Worker } 33*387f9dfdSAndroid Build Coastguard Worker // prepare test by pinning table to bpffs 34*387f9dfdSAndroid Build Coastguard Worker { 35*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"( 36*387f9dfdSAndroid Build Coastguard Worker BPF_TABLE("hash", u64, u64, ids, 1024); 37*387f9dfdSAndroid Build Coastguard Worker )"; 38*387f9dfdSAndroid Build Coastguard Worker 39*387f9dfdSAndroid Build Coastguard Worker ebpf::BPF bpf; 40*387f9dfdSAndroid Build Coastguard Worker ebpf::StatusTuple res(0); 41*387f9dfdSAndroid Build Coastguard Worker res = bpf.init(BPF_PROGRAM); 42*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 43*387f9dfdSAndroid Build Coastguard Worker 44*387f9dfdSAndroid Build Coastguard Worker REQUIRE(bpf_obj_pin(bpf.get_hash_table<int, int>("ids").get_fd(), "/sys/fs/bpf/test_pinned_table") == 0); 45*387f9dfdSAndroid Build Coastguard Worker } 46*387f9dfdSAndroid Build Coastguard Worker 47*387f9dfdSAndroid Build Coastguard Worker // test table access 48*387f9dfdSAndroid Build Coastguard Worker { 49*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"( 50*387f9dfdSAndroid Build Coastguard Worker BPF_TABLE_PINNED("hash", u64, u64, ids, 0, "/sys/fs/bpf/test_pinned_table", BPF_F_NO_PREALLOC); 51*387f9dfdSAndroid Build Coastguard Worker )"; 52*387f9dfdSAndroid Build Coastguard Worker 53*387f9dfdSAndroid Build Coastguard Worker ebpf::BPF bpf; 54*387f9dfdSAndroid Build Coastguard Worker ebpf::StatusTuple res(0); 55*387f9dfdSAndroid Build Coastguard Worker res = bpf.init(BPF_PROGRAM); 56*387f9dfdSAndroid Build Coastguard Worker unlink("/sys/fs/bpf/test_pinned_table"); // can delete table here already 57*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 58*387f9dfdSAndroid Build Coastguard Worker 59*387f9dfdSAndroid Build Coastguard Worker auto t = bpf.get_hash_table<int, int>("ids"); 60*387f9dfdSAndroid Build Coastguard Worker int key, value; 61*387f9dfdSAndroid Build Coastguard Worker 62*387f9dfdSAndroid Build Coastguard Worker // write element 63*387f9dfdSAndroid Build Coastguard Worker key = 0x08; 64*387f9dfdSAndroid Build Coastguard Worker value = 0x43; 65*387f9dfdSAndroid Build Coastguard Worker res = t.update_value(key, value); 66*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 67*387f9dfdSAndroid Build Coastguard Worker REQUIRE(t[key] == value); 68*387f9dfdSAndroid Build Coastguard Worker } 69*387f9dfdSAndroid Build Coastguard Worker 70*387f9dfdSAndroid Build Coastguard Worker // test create if not exist 71*387f9dfdSAndroid Build Coastguard Worker { 72*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"( 73*387f9dfdSAndroid Build Coastguard Worker BPF_TABLE_PINNED("hash", u64, u64, ids, 1024, "/sys/fs/bpf/test_pinned_table"); 74*387f9dfdSAndroid Build Coastguard Worker )"; 75*387f9dfdSAndroid Build Coastguard Worker 76*387f9dfdSAndroid Build Coastguard Worker ebpf::BPF bpf; 77*387f9dfdSAndroid Build Coastguard Worker ebpf::StatusTuple res(0); 78*387f9dfdSAndroid Build Coastguard Worker res = bpf.init(BPF_PROGRAM); 79*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 80*387f9dfdSAndroid Build Coastguard Worker unlink("/sys/fs/bpf/test_pinned_table"); 81*387f9dfdSAndroid Build Coastguard Worker } 82*387f9dfdSAndroid Build Coastguard Worker 83*387f9dfdSAndroid Build Coastguard Worker if (mounted) { 84*387f9dfdSAndroid Build Coastguard Worker REQUIRE(umount("/sys/fs/bpf") == 0); 85*387f9dfdSAndroid Build Coastguard Worker } 86*387f9dfdSAndroid Build Coastguard Worker } 87*387f9dfdSAndroid Build Coastguard Worker #endif 88*387f9dfdSAndroid Build Coastguard Worker 89*387f9dfdSAndroid Build Coastguard Worker #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) 90*387f9dfdSAndroid Build Coastguard Worker TEST_CASE("test pinned sk_storage table", "[pinned_sk_storage_table]") { 91*387f9dfdSAndroid Build Coastguard Worker bool mounted = false; 92*387f9dfdSAndroid Build Coastguard Worker if (system("mount | grep /sys/fs/bpf")) { 93*387f9dfdSAndroid Build Coastguard Worker REQUIRE(system("mkdir -p /sys/fs/bpf") == 0); 94*387f9dfdSAndroid Build Coastguard Worker REQUIRE(system("mount -o nosuid,nodev,noexec,mode=700 -t bpf bpf /sys/fs/bpf") == 0); 95*387f9dfdSAndroid Build Coastguard Worker mounted = true; 96*387f9dfdSAndroid Build Coastguard Worker } 97*387f9dfdSAndroid Build Coastguard Worker // prepare test by pinning table to bpffs 98*387f9dfdSAndroid Build Coastguard Worker { 99*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"( 100*387f9dfdSAndroid Build Coastguard Worker BPF_SK_STORAGE(sk_stg, __u64); 101*387f9dfdSAndroid Build Coastguard Worker int test(struct __sk_buff *skb) { return 0; } 102*387f9dfdSAndroid Build Coastguard Worker )"; 103*387f9dfdSAndroid Build Coastguard Worker 104*387f9dfdSAndroid Build Coastguard Worker ebpf::BPF bpf; 105*387f9dfdSAndroid Build Coastguard Worker ebpf::StatusTuple res(0); 106*387f9dfdSAndroid Build Coastguard Worker res = bpf.init(BPF_PROGRAM); 107*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 108*387f9dfdSAndroid Build Coastguard Worker 109*387f9dfdSAndroid Build Coastguard Worker REQUIRE(bpf_obj_pin(bpf.get_sk_storage_table<unsigned long long>("sk_stg").get_fd(), "/sys/fs/bpf/test_pinned_table") == 0); 110*387f9dfdSAndroid Build Coastguard Worker } 111*387f9dfdSAndroid Build Coastguard Worker 112*387f9dfdSAndroid Build Coastguard Worker // exercise <pinned_map>.sk_storage_get(). 113*387f9dfdSAndroid Build Coastguard Worker { 114*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"( 115*387f9dfdSAndroid Build Coastguard Worker BPF_TABLE_PINNED("sk_storage", __u32, __u64, sk_stg, 0, "/sys/fs/bpf/test_pinned_table"); 116*387f9dfdSAndroid Build Coastguard Worker int test(struct __sk_buff *skb) { 117*387f9dfdSAndroid Build Coastguard Worker struct bpf_sock *sk; 118*387f9dfdSAndroid Build Coastguard Worker __u64 *val; 119*387f9dfdSAndroid Build Coastguard Worker 120*387f9dfdSAndroid Build Coastguard Worker sk = skb->sk; 121*387f9dfdSAndroid Build Coastguard Worker if (!sk) 122*387f9dfdSAndroid Build Coastguard Worker return 0; 123*387f9dfdSAndroid Build Coastguard Worker sk = bpf_sk_fullsock(sk); 124*387f9dfdSAndroid Build Coastguard Worker if (!sk) 125*387f9dfdSAndroid Build Coastguard Worker return 0; 126*387f9dfdSAndroid Build Coastguard Worker 127*387f9dfdSAndroid Build Coastguard Worker val = sk_stg.sk_storage_get(sk, NULL, BPF_SK_STORAGE_GET_F_CREATE); 128*387f9dfdSAndroid Build Coastguard Worker if (!val) 129*387f9dfdSAndroid Build Coastguard Worker return 0; 130*387f9dfdSAndroid Build Coastguard Worker 131*387f9dfdSAndroid Build Coastguard Worker return 1; 132*387f9dfdSAndroid Build Coastguard Worker } 133*387f9dfdSAndroid Build Coastguard Worker )"; 134*387f9dfdSAndroid Build Coastguard Worker 135*387f9dfdSAndroid Build Coastguard Worker ebpf::BPF bpf; 136*387f9dfdSAndroid Build Coastguard Worker ebpf::StatusTuple res(0); 137*387f9dfdSAndroid Build Coastguard Worker res = bpf.init(BPF_PROGRAM); 138*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 139*387f9dfdSAndroid Build Coastguard Worker int prog_fd; 140*387f9dfdSAndroid Build Coastguard Worker res = bpf.load_func("test", BPF_PROG_TYPE_CGROUP_SKB, prog_fd); 141*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok()); 142*387f9dfdSAndroid Build Coastguard Worker } 143*387f9dfdSAndroid Build Coastguard Worker 144*387f9dfdSAndroid Build Coastguard Worker unlink("/sys/fs/bpf/test_pinned_table"); 145*387f9dfdSAndroid Build Coastguard Worker if (mounted) { 146*387f9dfdSAndroid Build Coastguard Worker REQUIRE(umount("/sys/fs/bpf") == 0); 147*387f9dfdSAndroid Build Coastguard Worker } 148*387f9dfdSAndroid Build Coastguard Worker } 149*387f9dfdSAndroid Build Coastguard Worker #endif 150