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