1 /* 2 * Copyright (c) 2020 Facebook, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <linux/version.h> 18 #include <unistd.h> 19 #include <sys/types.h> 20 #include <sys/socket.h> 21 #include <string> 22 23 #include "BPF.h" 24 #include "catch.hpp" 25 26 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0) 27 28 // Prior to 5.15, the socket must be TCP established socket to be updatable. 29 // https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/commit/?id=0c48eefae712c2fd91480346a07a1a9cd0f9470b 30 #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 15, 0) 31 bool expected_update_result = false; 32 #else 33 bool expected_update_result = true; 34 #endif 35 36 TEST_CASE("test sock map", "[sockmap]") { 37 { 38 const std::string BPF_PROGRAM = R"( 39 BPF_SOCKMAP(sk_map1, 10); 40 BPF_SOCKMAP(sk_map2, 10); 41 int test(struct bpf_sock_ops *skops) 42 { 43 u32 key = 0, val = 0; 44 45 sk_map2.update(&key, &val); 46 sk_map2.delete(&key); 47 sk_map2.sock_map_update(skops, &key, 0); 48 49 return 0; 50 } 51 )"; 52 53 // make sure program is loaded successfully 54 ebpf::BPF bpf; 55 ebpf::StatusTuple res(0); 56 res = bpf.init(BPF_PROGRAM); 57 REQUIRE(res.ok()); 58 59 // create a udp socket so we can do some map operations. 60 int sockfd = socket(AF_INET, SOCK_DGRAM, 0); 61 REQUIRE(sockfd >= 0); 62 63 auto sk_map = bpf.get_sockmap_table("sk_map1"); 64 int key = 0, val = sockfd; 65 66 res = sk_map.remove_value(key); 67 REQUIRE(!res.ok()); 68 69 res = sk_map.update_value(key, val); 70 REQUIRE(res.ok() == expected_update_result); 71 } 72 } 73 74 TEST_CASE("test sock hash", "[sockhash]") { 75 { 76 const std::string BPF_PROGRAM = R"( 77 BPF_SOCKHASH(sk_hash1, u32, 10); 78 BPF_SOCKHASH(sk_hash2, u32, 10); 79 int test(struct bpf_sock_ops *skops) 80 { 81 u32 key = 0, val = 0; 82 struct sk_msg_buff *msg; 83 struct sk_buff *skb; 84 85 sk_hash2.update(&key, &val); 86 sk_hash2.delete(&key); 87 sk_hash2.sock_hash_update(skops, &key, 0); 88 sk_hash2.msg_redirect_hash(msg, &key, 0); 89 sk_hash2.sk_redirect_hash(skb, &key, 0); 90 91 return 0; 92 } 93 )"; 94 95 // make sure program is loaded successfully 96 ebpf::BPF bpf; 97 ebpf::StatusTuple res(0); 98 res = bpf.init(BPF_PROGRAM); 99 REQUIRE(res.ok()); 100 101 // create a udp socket so we can do some map operations. 102 int sockfd = socket(AF_INET, SOCK_DGRAM, 0); 103 REQUIRE(sockfd >= 0); 104 105 auto sk_hash = bpf.get_sockhash_table("sk_hash1"); 106 int key = 0, val = sockfd; 107 108 res = sk_hash.remove_value(key); 109 REQUIRE(!res.ok()); 110 111 res = sk_hash.update_value(key, val); 112 REQUIRE(res.ok() == expected_update_result); 113 } 114 } 115 116 #endif 117