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