1 /* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef OHOS_NETMANAGERSTANDARD_BPFWRAPPER_H 17 #define OHOS_NETMANAGERSTANDARD_BPFWRAPPER_H 18 19 #include <cerrno> 20 #include <linux/bpf.h> 21 #include <linux/unistd.h> 22 #include <stdint.h> 23 #include <string> 24 #include <unistd.h> 25 26 #include "netnative_log_wrapper.h" 27 #include "securec.h" 28 29 namespace OHOS { 30 namespace NetManagerStandard { 31 static constexpr int IFNAMESIZE = 16; 32 static constexpr int INVALID = -1; 33 34 struct StatsValue { 35 uint64_t rxPackets; 36 uint64_t rxBytes; 37 uint64_t txPackets; 38 uint64_t txBytes; 39 40 StatsValue &operator+=(const StatsValue &other) 41 { 42 rxPackets += other.rxPackets; 43 rxBytes += other.rxBytes; 44 txPackets += other.txPackets; 45 txBytes += other.txBytes; 46 return *this; 47 } 48 }; 49 50 typedef struct { 51 std::string name; 52 } IfaceName; 53 54 template <class Key, class Value> class BpfWrappers { 55 public: 56 BpfWrappers<Key, Value>() = default; 57 58 /** 59 * Bpf Syscall 60 * 61 * @param cmd which command need to execute 62 * @param attr union consists of various anonymous structures 63 * @return int return the result of executing the command 64 */ BpfSyscall(int cmd,const bpf_attr & attr)65 static inline int BpfSyscall(int cmd, const bpf_attr &attr) 66 { 67 int result = syscall(__NR_bpf, cmd, &attr, sizeof(attr)); 68 NETNATIVE_LOGI("cmd = %{public}d,result = %{public}d", cmd, result); 69 if (result < 0) { 70 NETNATIVE_LOGE("BpfSyscall: errno = %{public}d,failed : %{public}s", errno, strerror(errno)); 71 result = -errno; 72 } 73 return result; 74 } 75 76 /** 77 * Create A Bpf Map but for test only 78 * 79 * @param mapType map type 80 * @param keySize key size in bytes 81 * @param valueSize value size in bytes 82 * @param maxEntries maximum number of elements 83 * @param mapFlags map flag 84 * @return int return a map file descriptor 85 */ CreateMap(bpf_map_type mapType,uint32_t keySize,uint32_t valueSize,uint32_t maxEntries,uint32_t mapFlags)86 static int CreateMap(bpf_map_type mapType, uint32_t keySize, uint32_t valueSize, uint32_t maxEntries, 87 uint32_t mapFlags) 88 { 89 bpf_attr bpfAttr; 90 (void)memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)); 91 bpfAttr.map_type = mapType; 92 bpfAttr.key_size = keySize; 93 bpfAttr.value_size = valueSize; 94 bpfAttr.max_entries = maxEntries; 95 bpfAttr.map_flags = mapFlags; 96 return BpfSyscall(BPF_MAP_CREATE, bpfAttr); 97 } 98 99 /** 100 * Write Value To Bpf Map 101 * 102 * @param mapFd map fd 103 * @param key the key of Bpf Map 104 * @param value the value of Bpf Map 105 * @param flags map flag 106 * @return int true:write success false:failure 107 */ WriteValueToMap(const int mapFd,const Key & key,const Value & value,uint64_t flags)108 static int WriteValueToMap(const int mapFd, const Key &key, const Value &value, uint64_t flags) 109 { 110 bpf_attr bpfAttr; 111 (void)memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)); 112 bpfAttr.map_fd = BpfFdToU32(mapFd); 113 bpfAttr.key = BpfMapKeyToU64(key); 114 bpfAttr.value = BpfMapValueToU64(value); 115 bpfAttr.flags = flags; 116 return BpfSyscall(BPF_MAP_UPDATE_ELEM, bpfAttr); 117 } 118 119 /** 120 * LookUp Elem From Map 121 * 122 * @param mapFd map fd 123 * @param key the key of Bpf Map 124 * @param value the value of Bpf Map 125 * @return int true:find success false:failure 126 */ LookUpElem(const int mapFd,const Key & key,const Value & value)127 static int LookUpElem(const int mapFd, const Key &key, const Value &value) 128 { 129 bpf_attr bpfAttr; 130 (void)memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)); 131 bpfAttr.map_fd = BpfFdToU32(mapFd); 132 bpfAttr.key = BpfMapKeyToU64(key); 133 bpfAttr.value = BpfMapValueToU64(value); 134 return BpfSyscall(BPF_MAP_LOOKUP_ELEM, bpfAttr); 135 } 136 137 /** 138 * Delete Elem From Map 139 * 140 * @param mapFd map fd 141 * @param key the key of Bpf Map 142 * @return int true:delete success false:failure 143 */ DeleteElem(const int mapFd,const Key & key)144 static int DeleteElem(const int mapFd, const Key &key) 145 { 146 bpf_attr bpfAttr; 147 (void)memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)); 148 bpfAttr.map_fd = BpfFdToU32(mapFd); 149 bpfAttr.key = BpfMapKeyToU64(key); 150 return BpfSyscall(BPF_MAP_DELETE_ELEM, bpfAttr); 151 } 152 153 /** 154 * Get the Next Key From Map 155 * 156 * @param mapFd map fd 157 * @param key the key of Bpf Map 158 * @param next_key the key of Bpf Map 159 * @return int return next key 160 */ GetNextKey(const int mapFd,const Key & key,Key & next_key)161 static int GetNextKey(const int mapFd, const Key &key, Key &next_key) 162 { 163 bpf_attr bpfAttr; 164 (void)memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)); 165 bpfAttr.map_fd = BpfFdToU32(mapFd); 166 bpfAttr.key = BpfMapKeyToU64(key); 167 bpfAttr.next_key = BpfMapKeyToU64(next_key); 168 return BpfSyscall(BPF_MAP_GET_NEXT_KEY, bpfAttr); 169 } 170 171 /** 172 * Get the First Key From Map 173 * 174 * @param mapFd map fd 175 * @param firstKey the first key of Bpf Map 176 * @return int return first key 177 */ GetFirstKey(const int mapFd,Key & key)178 static int GetFirstKey(const int mapFd, Key &key) 179 { 180 return GetNextKey(mapFd, INVALID, key); 181 } 182 183 /** 184 * Attach Program To Map 185 * 186 * @param type bpf attach type 187 * @param progFd eBPF program to attach 188 * @param cgFd container object to attach to 189 * @return int true:attach success false:failure 190 */ AttachProgram(bpf_attach_type type,const int progFd,const int cgFd)191 static int AttachProgram(bpf_attach_type type, const int progFd, const int cgFd) 192 { 193 bpf_attr bpfAttr; 194 (void)memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)); 195 bpfAttr.target_fd = BpfFdToU32(cgFd); 196 bpfAttr.attach_bpf_fd = BpfFdToU32(progFd); 197 bpfAttr.attach_type = type; 198 return BpfSyscall(BPF_PROG_ATTACH, bpfAttr); 199 } 200 201 /** 202 * Detach Program From Map 203 * 204 * @param type bpf detach type 205 * @param cgFd container object to detach to 206 * @return int true:detach success false:failure 207 */ DetachProgram(bpf_attach_type type,const int cgFd)208 static int DetachProgram(bpf_attach_type type, const int cgFd) 209 { 210 bpf_attr bpfAttr; 211 (void)memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)); 212 bpfAttr.target_fd = BpfFdToU32(cgFd); 213 bpfAttr.attach_type = type; 214 return BpfSyscall(BPF_PROG_DETACH, bpfAttr); 215 } 216 217 /** 218 * Pin Bpf Object To File node 219 * 220 * @param pathName path the bpf map pinned 221 * @param bfdFd bfd fd 222 * @return int true:pin success false:failure 223 */ BpfObjPin(const std::string & pathName,int bfdFd)224 static int BpfObjPin(const std::string &pathName, int bfdFd) 225 { 226 bpf_attr bpfAttr; 227 (void)memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)); 228 bpfAttr.pathname = BpfMapPathNameToU64(pathName); 229 bpfAttr.bpf_fd = BpfFdToU32(bfdFd); 230 return BpfSyscall(BPF_OBJ_PIN, bpfAttr); 231 } 232 233 /** 234 * Get Bpf Object By PathName 235 * 236 * @param pathName bpf map path 237 * @param fileFlags file flags 238 * @return int return map file descriptor 239 */ BpfObjGet(const std::string & pathName,uint32_t fileFlags)240 static int BpfObjGet(const std::string &pathName, uint32_t fileFlags) 241 { 242 bpf_attr bpfAttr; 243 (void)memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)); 244 bpfAttr.pathname = BpfMapPathNameToU64(pathName); 245 bpfAttr.file_flags = fileFlags; 246 return BpfSyscall(BPF_OBJ_GET, bpfAttr); 247 } 248 249 /** 250 * Get the Map Fd 251 * 252 * @param pathName bpf map path 253 * @param objFlags obj flags 254 * @return int return map file descriptor 255 */ GetMap(const std::string & pathName,uint32_t objFlags)256 static int GetMap(const std::string &pathName, uint32_t objFlags) 257 { 258 return BpfObjGet(pathName, objFlags); 259 } 260 261 /** 262 * Get the Map Fd 263 * 264 * @param pathName bpf map path 265 * @return int return map file descriptor 266 */ GetRWMap(const std::string & pathName)267 static int GetRWMap(const std::string &pathName) 268 { 269 return GetMap(pathName, 0); 270 } 271 272 /** 273 * Get the Read—Only Map Fd 274 * 275 * @param pathName bpf map path 276 * @return int return map file descriptor 277 */ GetROMap(const std::string & pathName)278 static int GetROMap(const std::string &pathName) 279 { 280 return GetMap(pathName, BPF_F_RDONLY); 281 } 282 283 /** 284 * Get the Write—Only Map Fd 285 * 286 * @param pathName bpf map path 287 * @return int return map file descriptor 288 */ GetWOMap(const std::string & pathName)289 static int GetWOMap(const std::string &pathName) 290 { 291 return GetMap(pathName, BPF_F_WRONLY); 292 } 293 294 private: BpfFdToU32(const int mapFd)295 static inline __u32 BpfFdToU32(const int mapFd) 296 { 297 return static_cast<__u32>(mapFd); 298 } 299 BpfMapPathNameToU64(const std::string & pathName)300 static inline uint64_t BpfMapPathNameToU64(const std::string &pathName) 301 { 302 return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(pathName.c_str())); 303 } 304 BpfMapKeyToU64(const Key & key)305 static inline uint64_t BpfMapKeyToU64(const Key &key) 306 { 307 return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&key)); 308 } 309 BpfMapValueToU64(const Value & value)310 static inline uint64_t BpfMapValueToU64(const Value &value) 311 { 312 return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&value)); 313 } 314 }; 315 } // namespace NetManagerStandard 316 } // namespace OHOS 317 #endif // OHOS_NETMANAGERSTANDARD_BPFWRAPPER_H 318