1 /*
2 * Copyright (c) 2022-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 #include <net/if.h>
17 #include <vector>
18
19 #include "bpf_path.h"
20 #include "bpf_def.h"
21 #include "bpf_stats.h"
22 #include "securec.h"
23 #include "netnative_log_wrapper.h"
24 #include "net_stats_constants.h"
25
26 namespace OHOS::NetManagerStandard {
27 namespace {
28 constexpr const char *CELLULAR_IFACE = "rmnet0";
29 constexpr const char *WIFI_IFACE = "wlan0";
30 }
GetNumberFromStatsValue(uint64_t &stats, StatsType statsType, const stats_value &value)31 int32_t NetsysBpfStats::GetNumberFromStatsValue(uint64_t &stats, StatsType statsType, const stats_value &value)
32 {
33 switch (statsType) {
34 case StatsType::STATS_TYPE_RX_BYTES:
35 stats = value.rxBytes;
36 break;
37 case StatsType::STATS_TYPE_RX_PACKETS:
38 stats = value.rxPackets;
39 break;
40 case StatsType::STATS_TYPE_TX_BYTES:
41 stats = value.txBytes;
42 break;
43 case StatsType::STATS_TYPE_TX_PACKETS:
44 stats = value.txPackets;
45 break;
46 default:
47 NETNATIVE_LOGE("invalid StatsType type %{public}d", statsType);
48 return STATS_ERR_READ_BPF_FAIL;
49 }
50 return NETSYS_SUCCESS;
51 }
52
GetTotalStats(uint64_t &stats, StatsType statsType)53 int32_t NetsysBpfStats::GetTotalStats(uint64_t &stats, StatsType statsType)
54 {
55 stats = 0;
56 BpfMapper<iface_stats_key, iface_stats_value> ifaceStatsMap(IFACE_STATS_MAP_PATH, BPF_F_RDONLY);
57 if (!ifaceStatsMap.IsValid()) {
58 NETNATIVE_LOGE("ifaceStatsMap IsValid");
59 return STATS_ERR_INVALID_IFACE_NAME_MAP;
60 }
61
62 iface_stats_value totalStats = {0};
63 auto keys = ifaceStatsMap.GetAllKeys();
64 for (const auto &k : keys) {
65 iface_stats_value v = {0};
66 if (ifaceStatsMap.Read(k, v) < NETSYS_SUCCESS) {
67 NETNATIVE_LOGE("Read ifaceStatsMap err");
68 return STATS_ERR_READ_BPF_FAIL;
69 }
70 totalStats.rxPackets += v.rxPackets;
71 totalStats.rxBytes += v.rxBytes;
72 totalStats.txPackets += v.txPackets;
73 totalStats.txBytes += v.txBytes;
74 }
75
76 return GetNumberFromStatsValue(stats, statsType, totalStats);
77 }
78
GetUidStats(uint64_t &stats, StatsType statsType, uint32_t uid)79 int32_t NetsysBpfStats::GetUidStats(uint64_t &stats, StatsType statsType, uint32_t uid)
80 {
81 stats = 0;
82 BpfMapper<app_uid_stats_key, app_uid_stats_value> appUidStatsMap(APP_UID_STATS_MAP_PATH, BPF_F_RDONLY);
83 if (!appUidStatsMap.IsValid()) {
84 return STATS_ERR_INVALID_IFACE_NAME_MAP;
85 }
86
87 app_uid_stats_value uidStats = {0};
88 if (appUidStatsMap.Read(uid, uidStats) < 0) {
89 return STATS_ERR_READ_BPF_FAIL;
90 }
91 return GetNumberFromStatsValue(stats, statsType, uidStats);
92 }
93
GetAllSimStatsInfo(std::vector<OHOS::NetManagerStandard::NetStatsInfo> &stats)94 int32_t NetsysBpfStats::GetAllSimStatsInfo(std::vector<OHOS::NetManagerStandard::NetStatsInfo> &stats)
95 {
96 BpfMapper<stats_key, stats_value> uidSimStatsMap(APP_UID_SIM_STATS_MAP_PATH, BPF_F_RDONLY);
97 if (!uidSimStatsMap.IsValid()) {
98 return STATS_ERR_INVALID_IFACE_NAME_MAP;
99 }
100
101 stats.clear();
102 char if_name[IFNAME_SIZE] = {0};
103 auto keys = uidSimStatsMap.GetAllKeys();
104 for (const auto &k : keys) {
105 stats_value v = {};
106 if (uidSimStatsMap.Read(k, v) < 0) {
107 NETNATIVE_LOGE("Read uid_sim_map err");
108 return STATS_ERR_READ_BPF_FAIL;
109 }
110
111 NetStatsInfo tempStats;
112 tempStats.uid_ = k.uId;
113 if (memset_s(if_name, sizeof(if_name), 0, sizeof(if_name)) != EOK) {
114 return STATS_ERR_READ_BPF_FAIL;
115 }
116
117 char *pName = if_indextoname(k.ifIndex, if_name);
118 if (pName != nullptr) {
119 tempStats.iface_ = pName;
120 }
121 if (k.ifType == IFACE_TYPE_WIFI) {
122 tempStats.iface_ = WIFI_IFACE;
123 } else if (k.ifType == IFACE_TYPE_CELLULAR) {
124 tempStats.iface_ = CELLULAR_IFACE;
125 }
126 tempStats.rxBytes_ = v.rxBytes;
127 tempStats.txBytes_ = v.txBytes;
128 tempStats.rxPackets_ = v.rxPackets;
129 tempStats.txPackets_ = v.txPackets;
130 auto findRet = std::find_if(stats.begin(), stats.end(),
131 [&tempStats](const NetStatsInfo &info) { return info.Equals(tempStats); });
132 if (findRet == stats.end()) {
133 stats.push_back(std::move(tempStats));
134 } else {
135 *findRet += tempStats;
136 }
137 }
138
139 return NETSYS_SUCCESS;
140 }
141
GetAllStatsInfo(std::vector<OHOS::NetManagerStandard::NetStatsInfo> &stats)142 int32_t NetsysBpfStats::GetAllStatsInfo(std::vector<OHOS::NetManagerStandard::NetStatsInfo> &stats)
143 {
144 BpfMapper<stats_key, stats_value> uidIfaceStatsMap(APP_UID_IF_STATS_MAP_PATH, BPF_F_RDONLY);
145 if (!uidIfaceStatsMap.IsValid()) {
146 return STATS_ERR_INVALID_IFACE_NAME_MAP;
147 }
148
149 stats.clear();
150 char if_name[IFNAME_SIZE] = {0};
151 auto keys = uidIfaceStatsMap.GetAllKeys();
152 for (const auto &k : keys) {
153 stats_value v = {};
154 if (uidIfaceStatsMap.Read(k, v) < 0) {
155 NETNATIVE_LOGE("Read ifaceStatsMap err");
156 return STATS_ERR_READ_BPF_FAIL;
157 }
158
159 NetStatsInfo tempStats;
160 tempStats.uid_ = k.uId;
161 if (memset_s(if_name, sizeof(if_name), 0, sizeof(if_name)) != EOK) {
162 return STATS_ERR_READ_BPF_FAIL;
163 }
164
165 char *pName = if_indextoname(k.ifIndex, if_name);
166 if (pName != nullptr) {
167 tempStats.iface_ = pName;
168 }
169 tempStats.rxBytes_ = v.rxBytes;
170 tempStats.txBytes_ = v.txBytes;
171 tempStats.rxPackets_ = v.rxPackets;
172 tempStats.txPackets_ = v.txPackets;
173 stats.emplace_back(std::move(tempStats));
174 }
175
176 return NETSYS_SUCCESS;
177 }
178
DeleteStatsInfo(const std::string &path, uint32_t uid)179 int32_t NetsysBpfStats::DeleteStatsInfo(const std::string &path, uint32_t uid)
180 {
181 if (path != APP_UID_IF_STATS_MAP_PATH && path != APP_UID_SIM_STATS_MAP_PATH) {
182 NETNATIVE_LOGI("DeleteStatsInfo invalid path");
183 return NETSYS_SUCCESS;
184 }
185 BpfMapper<stats_key, stats_value> uidStatsMap(path, BPF_ANY);
186 if (!uidStatsMap.IsValid()) {
187 return STATS_ERR_INVALID_IFACE_NAME_MAP;
188 }
189 auto keys = uidStatsMap.GetAllKeys();
190 for (const auto &k : keys) {
191 if (k.uId == uid) {
192 if (uidStatsMap.Delete(k) < 0) {
193 NETNATIVE_LOGE("Delete uidStatsMap err");
194 return STATS_ERR_WRITE_BPF_FAIL;
195 }
196 }
197 }
198 return NETSYS_SUCCESS;
199 }
200
GetIfaceStats(uint64_t &stats, const StatsType statsType, const std::string &interfaceName)201 int32_t NetsysBpfStats::GetIfaceStats(uint64_t &stats, const StatsType statsType, const std::string &interfaceName)
202 {
203 stats = 0;
204 BpfMapper<iface_stats_key, iface_stats_value> ifaceStatsMap(IFACE_STATS_MAP_PATH, BPF_F_RDONLY);
205 if (!ifaceStatsMap.IsValid()) {
206 return STATS_ERR_INVALID_IFACE_NAME_MAP;
207 }
208
209 auto ifIndex = if_nametoindex(interfaceName.c_str());
210 if (ifIndex <= 0) {
211 return STATS_ERR_GET_IFACE_NAME_FAILED;
212 }
213
214 iface_stats_value ifaceStats = {0};
215 if (ifaceStatsMap.Read(ifIndex, ifaceStats) < 0) {
216 return STATS_ERR_READ_BPF_FAIL;
217 }
218 return GetNumberFromStatsValue(stats, statsType, ifaceStats);
219 }
220
GetCookieStats(uint64_t &stats, StatsType statsType, uint64_t cookie)221 int32_t NetsysBpfStats::GetCookieStats(uint64_t &stats, StatsType statsType, uint64_t cookie)
222 {
223 NETNATIVE_LOGI("GetCookieStats start");
224 stats = 0;
225 BpfMapper<socket_cookie_stats_key, app_cookie_stats_value> appUidCookieStatsMap(APP_COOKIE_STATS_MAP_PATH,
226 BPF_F_RDONLY);
227 if (!appUidCookieStatsMap.IsValid()) {
228 NETNATIVE_LOGE("GetCookieStats appUidCookieStatsMap is valid");
229 return NETMANAGER_ERR_INTERNAL;
230 }
231
232 app_cookie_stats_value cookieStats = {0};
233 if (appUidCookieStatsMap.Read(cookie, cookieStats) < 0) {
234 NETNATIVE_LOGE("GetCookieStats appUidCookieStatsMap read error");
235 return NETMANAGER_ERR_INTERNAL;
236 }
237
238 int32_t res = GetNumberFromStatsValue(stats, statsType, cookieStats);
239 if (res == STATS_ERR_READ_BPF_FAIL) {
240 NETNATIVE_LOGE("GetCookieStats GetNumberFromStatsValue error");
241 return NETMANAGER_ERR_INTERNAL;
242 }
243 return NETSYS_SUCCESS;
244 }
245 } // namespace OHOS::NetManagerStandard
246