• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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