1 /* 2 * Copyright (c) 2023 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 CONNECTIVITY_EXT_BPF_MAPPER_H 17 #define CONNECTIVITY_EXT_BPF_MAPPER_H 18 19 #include <cerrno> 20 #include <linux/bpf.h> 21 #include <linux/unistd.h> 22 #include <cstdint> 23 #include <fcntl.h> 24 #include <sys/stat.h> 25 #include <string> 26 #include <unistd.h> 27 #include <functional> 28 #include <linux/bpf.h> 29 #include <linux/if_ether.h> 30 #include <linux/unistd.h> 31 #include <memory> 32 #include <string> 33 #include <sys/stat.h> 34 #include <unistd.h> 35 #include <vector> 36 37 #include "net_manager_constants.h" 38 #include "netnative_log_wrapper.h" 39 #include "securec.h" 40 41 namespace OHOS::NetManagerStandard { 42 template <class Key, class Value> class BpfMapperImplement { 43 public: 44 BpfMapperImplement<Key, Value>() = default; 45 GetFirstKey(const int32_t mapFd,Key & key)46 static int32_t GetFirstKey(const int32_t mapFd, Key &key) 47 { 48 bpf_attr bpfAttr{}; 49 if (memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)) != EOK) { 50 return NETMANAGER_ERROR; 51 } 52 bpfAttr.map_fd = BpfFdToU32(mapFd); 53 bpfAttr.key = 0; 54 bpfAttr.next_key = BpfMapKeyToU64(key); 55 return BpfSyscall(BPF_MAP_GET_NEXT_KEY, bpfAttr); 56 } 57 58 /** 59 * Get the Next Key From Map 60 * 61 * @param mapFd map fd 62 * @param key the key of Bpf Map 63 * @param next_key the key of Bpf Map 64 * @return int32_t return next key 65 */ GetNextKey(const int32_t mapFd,const Key & key,Key & nextKey)66 static int32_t GetNextKey(const int32_t mapFd, const Key &key, Key &nextKey) 67 { 68 bpf_attr bpfAttr{}; 69 if (memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)) != EOK) { 70 return NETMANAGER_ERROR; 71 } 72 bpfAttr.map_fd = BpfFdToU32(mapFd); 73 bpfAttr.key = BpfMapKeyToU64(key); 74 bpfAttr.next_key = BpfMapKeyToU64(nextKey); 75 return BpfSyscall(BPF_MAP_GET_NEXT_KEY, bpfAttr); 76 } 77 78 /** 79 * Bpf Syscall 80 * 81 * @param cmd which command need to execute 82 * @param attr union consists of various anonymous structures 83 * @return int32_t return the result of executing the command 84 */ BpfSyscall(int32_t cmd,const bpf_attr & attr)85 static int32_t BpfSyscall(int32_t cmd, const bpf_attr &attr) 86 { 87 return static_cast<int32_t>(syscall(__NR_bpf, cmd, &attr, sizeof(attr))); 88 } 89 90 /** 91 * Write Value To Bpf Map 92 * 93 * @param mapFd map fd 94 * @param key the key of Bpf Map 95 * @param value the value of Bpf Map 96 * @param flags map flag 97 * @return int32_t 0:write success -1:failure 98 */ UpdateElem(const int32_t mapFd,const Key & key,const Value & value,uint64_t flags)99 static int32_t UpdateElem(const int32_t mapFd, const Key &key, const Value &value, uint64_t flags) 100 { 101 bpf_attr bpfAttr{}; 102 if (memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)) != EOK) { 103 return NETMANAGER_ERROR; 104 } 105 bpfAttr.map_fd = BpfFdToU32(mapFd); 106 bpfAttr.key = BpfMapKeyToU64(key); 107 bpfAttr.value = BpfMapValueToU64(value); 108 bpfAttr.flags = flags; 109 return BpfSyscall(BPF_MAP_UPDATE_ELEM, bpfAttr); 110 } 111 112 /** 113 * LookUp Elem From Map 114 * 115 * @param mapFd map fd 116 * @param key the key of Bpf Map 117 * @param value the value of Bpf Map 118 * @return int32_t 0:find success -1:failure 119 */ LookUpElem(const int32_t mapFd,const Key & key,const Value & value)120 static int32_t LookUpElem(const int32_t mapFd, const Key &key, const Value &value) 121 { 122 bpf_attr bpfAttr{}; 123 if (memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)) != EOK) { 124 return NETMANAGER_ERROR; 125 } 126 bpfAttr.map_fd = BpfFdToU32(mapFd); 127 bpfAttr.key = BpfMapKeyToU64(key); 128 bpfAttr.value = BpfMapValueToU64(value); 129 return BpfSyscall(BPF_MAP_LOOKUP_ELEM, bpfAttr); 130 } 131 132 /** 133 * Delete Elem From Map 134 * 135 * @param mapFd map fd 136 * @param key the key of Bpf Map 137 * @return int32_t 0:delete success -1:failure 138 */ DeleteElem(const int32_t mapFd,const Key & key)139 static int32_t DeleteElem(const int32_t mapFd, const Key &key) 140 { 141 bpf_attr bpfAttr{}; 142 if (memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)) != EOK) { 143 return NETMANAGER_ERROR; 144 } 145 bpfAttr.map_fd = BpfFdToU32(mapFd); 146 bpfAttr.key = BpfMapKeyToU64(key); 147 return BpfSyscall(BPF_MAP_DELETE_ELEM, bpfAttr); 148 } 149 150 /** 151 * Get Bpf Object By PathName 152 * 153 * @param pathName bpf map path 154 * @param fileFlags file flags 155 * @return int32_t return map file descriptor 156 */ BpfObjGet(const std::string & pathName,uint32_t fileFlags)157 static int32_t BpfObjGet(const std::string &pathName, uint32_t fileFlags) 158 { 159 bpf_attr bpfAttr{}; 160 if (memset_s(&bpfAttr, sizeof(bpfAttr), 0, sizeof(bpfAttr)) != EOK) { 161 return NETMANAGER_ERROR; 162 } 163 bpfAttr.pathname = BpfMapPathNameToU64(pathName); 164 bpfAttr.file_flags = fileFlags; 165 return BpfSyscall(BPF_OBJ_GET, bpfAttr); 166 } 167 168 /** 169 * Get the Map Fd 170 * 171 * @param pathName bpf map path 172 * @param objFlags obj flags 173 * @return int32_t return map file descriptor 174 */ GetMap(const std::string & pathName,uint32_t objFlags)175 static int32_t GetMap(const std::string &pathName, uint32_t objFlags) 176 { 177 return BpfObjGet(pathName, objFlags); 178 } 179 180 private: BpfFdToU32(const int32_t mapFd)181 static uint32_t BpfFdToU32(const int32_t mapFd) 182 { 183 return static_cast<uint32_t>(mapFd); 184 } 185 BpfMapPathNameToU64(const std::string & pathName)186 static uint64_t BpfMapPathNameToU64(const std::string &pathName) 187 { 188 return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(pathName.c_str())); 189 } 190 BpfMapKeyToU64(const Key & key)191 static uint64_t BpfMapKeyToU64(const Key &key) 192 { 193 return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&key)); 194 } 195 BpfMapValueToU64(const Value & value)196 static uint64_t BpfMapValueToU64(const Value &value) 197 { 198 return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&value)); 199 } 200 }; 201 202 template <class Key, class Value> class BpfMapper { 203 public: 204 BpfMapper<Key, Value>() = default; ~BpfMapper()205 ~BpfMapper<Key, Value>() 206 { 207 if (mapFd_ != NETMANAGER_ERROR) { 208 close(mapFd_); 209 mapFd_ = NETMANAGER_ERROR; 210 } 211 } 212 BpfMapper<Key, Value>(const std::string &pathName, uint32_t flags) 213 { 214 mapFd_ = NETMANAGER_ERROR; 215 int32_t mapFd = BpfMapperImplement<Key, Value>::GetMap(pathName, flags); 216 if (mapFd >= 0) { 217 mapFd_ = mapFd; 218 } 219 } 220 221 /** 222 * Is has map fd 223 * 224 * @return bool true:has map fd false:not have 225 */ IsValid()226 [[nodiscard]] bool IsValid() const 227 { 228 return mapFd_ >= 0; 229 } 230 231 /** 232 * Read Value From Map 233 * 234 * @param key the key of map 235 * @return Value value corresponding to key 236 */ Read(const Key & key,Value & val)237 [[nodiscard]] int32_t Read(const Key &key, Value &val) const 238 { 239 Value value{}; 240 if (BpfMapperImplement<Key, Value>::LookUpElem(mapFd_, key, value) < 0) { 241 return NETMANAGER_ERROR; 242 } 243 val = value; 244 return 0; 245 } 246 247 /** 248 * WriteValue 249 * 250 * @param key the key want to write 251 * @param value the value want to write 252 * @param flags map flag 253 * @return int32_t 0 if OK 254 */ Write(const Key & key,const Value & value,uint64_t flags)255 [[nodiscard]] int32_t Write(const Key &key, const Value &value, uint64_t flags) const 256 { 257 return BpfMapperImplement<Key, Value>::UpdateElem(mapFd_, key, value, flags); 258 } 259 260 /** 261 * Get all keys 262 * 263 * @return key of list 264 */ GetAllKeys()265 [[nodiscard]] std::vector<Key> GetAllKeys() const 266 { 267 Key key{}; 268 if (BpfMapperImplement<Key, Value>::GetFirstKey(mapFd_, key) < 0) { 269 return {}; 270 } 271 std::vector<Key> keys; 272 keys.emplace_back(key); 273 274 Key nextKey{}; 275 while (BpfMapperImplement<Key, Value>::GetNextKey(mapFd_, key, nextKey) >= 0) { 276 key = nextKey; 277 keys.emplace_back(key); 278 } 279 return keys; 280 } 281 Clear(const std::vector<Key> & keys)282 [[nodiscard]] int32_t Clear(const std::vector<Key> &keys) const 283 { 284 for (const auto &k : keys) { 285 if (Delete(k) < NETSYS_SUCCESS) { 286 return NETMANAGER_ERROR; 287 } 288 } 289 return 0; 290 } 291 292 /** 293 * DeleteEntryFromMap 294 * 295 * @param deleteKey the key need to delete 296 * @return int32_t 0 if OK 297 */ Delete(const Key & deleteKey)298 [[nodiscard]] int32_t Delete(const Key &deleteKey) const 299 { 300 return BpfMapperImplement<Key, Value>::DeleteElem(mapFd_, deleteKey); 301 } 302 303 private: 304 int32_t mapFd_ = NETMANAGER_ERROR; 305 }; 306 } // namespace OHOS::NetManagerStandard 307 #endif /* CONNECTIVITY_EXT_BPF_MAPPER_H */ 308