1 /*
2 * Copyright (c) 2022 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 "netsys_bpf_stats.h"
17
18 #include <sys/resource.h>
19
20 #include <linux/bpf.h>
21 #include "securec.h"
22
23 #include "netnative_log_wrapper.h"
24
25 namespace OHOS {
26 namespace NetManagerStandard {
27 static constexpr const char *IFACE_STATS_MAP_PATH = "/sys/fs/bpf/netsys_iface_stats_map";
28 static constexpr const char *IFACE_INDEX_NAME_MAP_PATH = "/sys/fs/bpf/netsys_iface_name_map";
29 static constexpr const char *APP_UID_STATS_MAP_PATH = "/sys/fs/bpf/netsys_app_uid_stats_map";
30
31 NetsysBpfStats::NetsysBpfStats() = default;
32 NetsysBpfStats::~NetsysBpfStats() = default;
33
IsStatsValueValid(StatsValue value)34 bool NetsysBpfStats::IsStatsValueValid(StatsValue value)
35 {
36 return (value.rxBytes >= 0 && value.rxPackets >= 0 && value.txBytes >= 0 && value.txPackets >= 0);
37 }
38
CastResult(const NetStatsResultCode & code)39 int64_t NetsysBpfStats::CastResult(const NetStatsResultCode &code)
40 {
41 if (static_cast<int64_t>(code) < 0) {
42 NETNATIVE_LOGE("Error at bpf reader, code %{public}d, errno: %{public}d, err: %{public}s",
43 static_cast<int32_t>(code), errno, strerror(errno));
44 }
45 // The return value mains the stats data if any error the stats this time read no stats data.
46 return 0;
47 }
48
GetTotalStats(StatsType statsType)49 int64_t NetsysBpfStats::GetTotalStats(StatsType statsType)
50 {
51 NetsysBpfMap<uint32_t, StatsValue> ifaceStatsMap(IFACE_STATS_MAP_PATH, BPF_F_RDONLY);
52 if (!ifaceStatsMap.IsValid()) {
53 return CastResult(NetStatsResultCode::ERR_INVALID_IFACE_STATS_MAP);
54 }
55 return NetsysBpfStats::BpfGetTotalStats(statsType, ifaceStatsMap);
56 }
57
BpfGetTotalStats(StatsType statsType,const NetsysBpfMap<uint32_t,StatsValue> & ifaceStatsMap)58 int64_t NetsysBpfStats::BpfGetTotalStats(StatsType statsType, const NetsysBpfMap<uint32_t, StatsValue> &ifaceStatsMap)
59 {
60 StatsValue totalStats = {0};
61 uint32_t lookupKey, nextKey;
62 lookupKey = -1;
63 while (ifaceStatsMap.GetNextKeyFromStatsMap(lookupKey, nextKey) == 0) {
64 lookupKey = nextKey;
65 StatsValue statsValue = ifaceStatsMap.ReadValueFromMap(lookupKey);
66 if (!IsStatsValueValid(statsValue)) {
67 return CastResult(NetStatsResultCode::ERR_INVALID_STATS_VALUE);
68 }
69 totalStats += statsValue;
70 }
71 switch (statsType) {
72 case StatsType::STATS_TYPE_RX_BYTES:
73 return totalStats.rxBytes;
74 case StatsType::STATS_TYPE_RX_PACKETS:
75 return totalStats.rxPackets;
76 case StatsType::STATS_TYPE_TX_BYTES:
77 return totalStats.txBytes;
78 case StatsType::STATS_TYPE_TX_PACKETS:
79 return totalStats.txPackets;
80 default:
81 break;
82 }
83 return CastResult(NetStatsResultCode::ERR_INVALID_STATS_TYPE);
84 }
85
BpfGetUidStats(StatsType statsType,uint32_t uid,const NetsysBpfMap<uint32_t,StatsValue> & appUidStatsMap)86 int64_t NetsysBpfStats::BpfGetUidStats(StatsType statsType, uint32_t uid,
87 const NetsysBpfMap<uint32_t, StatsValue> &appUidStatsMap)
88 {
89 StatsValue uidStats = {0};
90 StatsValue statsValue = appUidStatsMap.ReadValueFromMap(uid);
91 if (!IsStatsValueValid(statsValue)) {
92 return CastResult(NetStatsResultCode::ERR_INVALID_STATS_VALUE);
93 }
94 uidStats += statsValue;
95 switch (statsType) {
96 case StatsType::STATS_TYPE_RX_BYTES:
97 return uidStats.rxBytes;
98 case StatsType::STATS_TYPE_RX_PACKETS:
99 return uidStats.rxPackets;
100 case StatsType::STATS_TYPE_TX_BYTES:
101 return uidStats.txBytes;
102 case StatsType::STATS_TYPE_TX_PACKETS:
103 return uidStats.txPackets;
104 default:
105 break;
106 }
107 return CastResult(NetStatsResultCode::ERR_INVALID_STATS_TYPE);
108 }
109
GetUidStats(StatsType type,uint32_t uid)110 int64_t NetsysBpfStats::GetUidStats(StatsType type, uint32_t uid)
111 {
112 NetsysBpfMap<uint32_t, StatsValue> appUidStatsMap(APP_UID_STATS_MAP_PATH, BPF_F_RDONLY);
113 if (!appUidStatsMap.IsValid()) {
114 return CastResult(NetStatsResultCode::ERR_INVALID_UID_STATS_MAP);
115 }
116 return BpfGetUidStats(type, uid, appUidStatsMap);
117 }
118
BpfGetIfaceStats(const StatsType statsType,const std::string & interfaceName,const NetsysBpfMap<uint32_t,IfaceName> & ifaceNameMap,const NetsysBpfMap<uint32_t,StatsValue> & ifaceStatsMap)119 int64_t NetsysBpfStats::BpfGetIfaceStats(const StatsType statsType, const std::string &interfaceName,
120 const NetsysBpfMap<uint32_t, IfaceName> &ifaceNameMap,
121 const NetsysBpfMap<uint32_t, StatsValue> &ifaceStatsMap)
122 {
123 StatsValue ifaceStats = {0};
124 std::string ifName;
125 const auto executeIfaceStats = [&interfaceName, &ifaceNameMap, &ifaceStats, &ifName,
126 this](const uint32_t key,
127 const NetsysBpfMap<uint32_t, StatsValue> &ifaceStatsMap) -> void {
128 if (GetIfaceName(ifaceNameMap, key, ifName)) {
129 NETNATIVE_LOGE("Get iface name failed");
130 return;
131 }
132 if (ifName == interfaceName) {
133 StatsValue statsValue = ifaceStatsMap.ReadValueFromMap(key);
134 if (!IsStatsValueValid(statsValue)) {
135 NETNATIVE_LOGE("Error key is %{public}u", key);
136 return;
137 }
138 ifaceStats += statsValue;
139 }
140 };
141 ifaceStatsMap.Iterate(executeIfaceStats);
142 switch (statsType) {
143 case StatsType::STATS_TYPE_RX_BYTES:
144 return ifaceStats.rxBytes;
145 case StatsType::STATS_TYPE_RX_PACKETS:
146 return ifaceStats.rxPackets;
147 case StatsType::STATS_TYPE_TX_BYTES:
148 return ifaceStats.txBytes;
149 case StatsType::STATS_TYPE_TX_PACKETS:
150 return ifaceStats.txPackets;
151 default:
152 break;
153 }
154 return CastResult(NetStatsResultCode::ERR_INVALID_STATS_TYPE);
155 }
156
GetIfaceStats(const StatsType statsType,const std::string & interfaceName)157 int64_t NetsysBpfStats::GetIfaceStats(const StatsType statsType, const std::string &interfaceName)
158 {
159 NetsysBpfMap<uint32_t, IfaceName> ifaceNameMap(IFACE_INDEX_NAME_MAP_PATH, BPF_F_RDONLY);
160 if (!ifaceNameMap.IsValid()) {
161 return CastResult(NetStatsResultCode::ERR_INVALID_IFACE_NAME_MAP);
162 }
163 NetsysBpfMap<uint32_t, StatsValue> ifaceStatsMap(IFACE_STATS_MAP_PATH, BPF_F_RDONLY);
164 if (!ifaceStatsMap.IsValid()) {
165 return CastResult(NetStatsResultCode::ERR_INVALID_IFACE_STATS_MAP);
166 }
167 return BpfGetIfaceStats(statsType, interfaceName, ifaceNameMap, ifaceStatsMap);
168 }
169
GetIfaceName(const NetsysBpfMap<uint32_t,IfaceName> & ifaceNameMap,uint32_t ifaceIndex,std::string & ifName)170 bool NetsysBpfStats::GetIfaceName(const NetsysBpfMap<uint32_t, IfaceName> &ifaceNameMap, uint32_t ifaceIndex,
171 std::string &ifName)
172 {
173 IfaceName ifaceName = ifaceNameMap.ReadValueFromMap(ifaceIndex);
174 ifName = ifaceName.name;
175 return ifName.empty();
176 }
177 } // namespace NetManagerStandard
178 } // namespace OHOS
179