1 /*
2 * Copyright (C) 2021 The Android Open Source Project
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 <inttypes.h>
18 #include <linux/bpf.h>
19 #include <test/mock_bpf_helpers.h>
20 #include <map>
21 #include <unordered_map>
22 #include <vector>
23
24 struct ByteArrayHash {
operator ()ByteArrayHash25 std::size_t operator()(std::vector<uint8_t> const& bytes) const {
26 size_t result = 0;
27 for (size_t i = 0; i < bytes.size(); i++) {
28 result = (result * 31) ^ bytes[i];
29 }
30 return result;
31 }
32 };
33
34 typedef std::unordered_map<std::vector<uint8_t>, std::vector<uint8_t>, ByteArrayHash> byteArrayMap;
35
36 struct mock_bpf_map {
37 uint32_t type;
38 size_t key_size;
39 size_t value_size;
40
41 // Per-CPU hash map. Cross-CPU maps have just one key-value pair, the key being 0.
42 std::map<uint32_t, byteArrayMap> map;
43 };
44
45 static uint64_t gKtimeNs;
46 static uint32_t gSmpProcessorId;
47 static uint32_t gUid;
48 static uint32_t gPidTgid;
49
bpf_ktime_get_ns()50 uint64_t bpf_ktime_get_ns() {
51 return gKtimeNs;
52 }
53
mock_bpf_set_ktime_ns(uint64_t time_ns)54 void mock_bpf_set_ktime_ns(uint64_t time_ns) {
55 gKtimeNs = time_ns;
56 }
57
mock_bpf_set_smp_processor_id(uint32_t cpu)58 void mock_bpf_set_smp_processor_id(uint32_t cpu) {
59 gSmpProcessorId = cpu;
60 }
61
bpf_get_smp_processor_id()62 uint64_t bpf_get_smp_processor_id() {
63 return gSmpProcessorId;
64 }
65
mock_bpf_set_current_uid_gid(uint32_t uid)66 void mock_bpf_set_current_uid_gid(uint32_t uid) {
67 gUid = uid;
68 }
69
bpf_get_current_uid_gid()70 uint64_t bpf_get_current_uid_gid() {
71 return gUid;
72 }
73
mock_bpf_set_current_pid_tgid(uint64_t pid_tgid)74 void mock_bpf_set_current_pid_tgid(uint64_t pid_tgid) {
75 gPidTgid = pid_tgid;
76 }
77
bpf_get_current_pid_tgid()78 uint64_t bpf_get_current_pid_tgid() {
79 return gPidTgid;
80 }
81
mock_bpf_map_create(uint32_t key_size,uint32_t value_size,uint32_t type)82 mock_bpf_map_t mock_bpf_map_create(uint32_t key_size, uint32_t value_size, uint32_t type) {
83 mock_bpf_map* map = new mock_bpf_map();
84 map->type = type;
85 map->key_size = key_size;
86 map->value_size = value_size;
87 return map;
88 }
89
getCurrentMap(mock_bpf_map * map)90 static byteArrayMap& getCurrentMap(mock_bpf_map* map) {
91 if (map->type == BPF_MAP_TYPE_PERCPU_HASH || map->type == BPF_MAP_TYPE_PERCPU_ARRAY) {
92 return map->map[gSmpProcessorId];
93 } else {
94 return map->map[0];
95 }
96 }
97
mock_bpf_lookup_elem(mock_bpf_map_t mock_map,void * key)98 void* mock_bpf_lookup_elem(mock_bpf_map_t mock_map, void* key) {
99 mock_bpf_map* map = (mock_bpf_map*)mock_map;
100 std::vector<uint8_t> keyVector(map->key_size);
101 memcpy(keyVector.data(), key, map->key_size);
102 byteArrayMap& currentMap = getCurrentMap(map);
103 if (currentMap.find(keyVector) == currentMap.end()) {
104 return NULL;
105 }
106 return currentMap[keyVector].data();
107 }
108
mock_bpf_update_elem(mock_bpf_map_t mock_map,void * key,void * value,uint64_t flags)109 int mock_bpf_update_elem(mock_bpf_map_t mock_map, void* key, void* value, uint64_t flags) {
110 mock_bpf_map* map = (mock_bpf_map*)mock_map;
111 std::vector<uint8_t> keyVector(map->key_size);
112 memcpy(keyVector.data(), key, map->key_size);
113 std::vector<uint8_t> value_vector(map->value_size);
114 memcpy(value_vector.data(), value, map->value_size);
115
116 byteArrayMap& currentMap = getCurrentMap(map);
117 if (flags & BPF_EXIST) {
118 if (currentMap.find(keyVector) == currentMap.end()) {
119 return 0;
120 }
121 } else if (flags & BPF_NOEXIST) {
122 if (currentMap.find(keyVector) != currentMap.end()) {
123 return 0;
124 }
125 }
126 currentMap[keyVector] = value_vector;
127 return 1;
128 }
129
mock_bpf_delete_elem(mock_bpf_map_t mock_map,void * key)130 int mock_bpf_delete_elem(mock_bpf_map_t mock_map, void* key) {
131 mock_bpf_map* map = (mock_bpf_map*)mock_map;
132 std::vector<uint8_t> keyVector(map->key_size);
133 memcpy(keyVector.data(), key, map->key_size);
134
135 byteArrayMap& currentMap = getCurrentMap(map);
136 return currentMap.erase(keyVector);
137 }
138