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