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 26namespace OHOS::NetManagerStandard { 27namespace { 28constexpr const char *CELLULAR_IFACE = "rmnet0"; 29constexpr const char *WIFI_IFACE = "wlan0"; 30} 31int32_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 53int32_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 79int32_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 94int32_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 142int32_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 179int32_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 201int32_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 221int32_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