• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #include "network_plugin.h"
16 #include "buffer_splitter.h"
17 #include "securec.h"
18 
19 #include <string>
20 
21 namespace {
22 constexpr size_t READ_BUFFER_SIZE = 1024 * 16;
23 const std::string DEFAULT_NET_PATH("/proc/net/xt_qtaguid/stats");
24 } // namespace
25 
NetworkPlugin()26 NetworkPlugin::NetworkPlugin()
27     : buffer_(new (std::nothrow) uint8_t[READ_BUFFER_SIZE]), fp_(nullptr, nullptr)
28 {
29     pidUid_.clear();
30 }
31 
Start(const uint8_t * configData,uint32_t configSize)32 int NetworkPlugin::Start(const uint8_t* configData, uint32_t configSize)
33 {
34     CHECK_NOTNULL(buffer_, -1, "%s:NetworkPlugin, buffer_ is null", __func__);
35 
36     if (protoConfig_.ParseFromArray(configData, configSize) <= 0) {
37         HILOG_ERROR(LOG_CORE, "%s:NetworkPlugin, parseFromArray failed!", __func__);
38         return -1;
39     }
40 
41     for (int i = 0; i < protoConfig_.pid().size(); i++) {
42         int32_t pid = protoConfig_.pid(i);
43         pidUid_.emplace(pid, GetUid(pid));
44     }
45 
46     HILOG_INFO(LOG_CORE, "%s:NetworkPlugin, start success!", __func__);
47 
48     return 0;
49 }
50 
Report(uint8_t * data,uint32_t dataSize)51 int NetworkPlugin::Report(uint8_t* data, uint32_t dataSize)
52 {
53     NetworkDatas dataProto;
54     std::string file = GetRateNodePath();
55     if (protoConfig_.test_file() != "") {
56         file = protoConfig_.test_file();
57     }
58 
59     char realPath[PATH_MAX + 1] = {0};
60     if ((file.length() >= PATH_MAX) || (realpath(file.c_str(), realPath) == nullptr)) {
61         HILOG_ERROR(LOG_CORE, "%s:path is invalid: %s, errno=%d", __func__, file.c_str(), errno);
62         return -1;
63     }
64     fp_ = std::unique_ptr<FILE, int (*)(FILE*)>(fopen(realPath, "r"), fclose);
65     CHECK_NOTNULL(fp_, -1, "%s:NetworkPlugin, open(%s) Failed, errno(%d)", __func__, file.c_str(), errno);
66 
67     if (protoConfig_.pid().size() > 0) {
68         for (int i = 0; i < protoConfig_.pid().size(); i++) {
69             auto* info = dataProto.add_networkinfo();
70             int32_t pid = protoConfig_.pid(i);
71             NetworkCell dataCell = {0};
72             ReadTxRxBytes(pid, dataCell);
73             // set proto
74             for (auto& it : dataCell.details) {
75                 NetworkDetails* data = info->add_details();
76                 data->set_tx_bytes(it.tx);
77                 data->set_rx_bytes(it.rx);
78                 data->set_type(it.type);
79             }
80             info->set_pid(pid);
81             info->set_tx_bytes(dataCell.tx);
82             info->set_rx_bytes(dataCell.rx);
83             info->set_tv_sec(dataCell.ts.tv_sec);
84             info->set_tv_nsec(dataCell.ts.tv_nsec);
85         }
86     } else if (protoConfig_.test_file() != "") { // test data
87         NetSystemData systemData = {};
88         ReadSystemTxRxBytes(systemData);
89         static int randNum = 0;
90         randNum++;
91         auto* systemInfo = dataProto.mutable_network_system_info();
92         for (auto& it : systemData.details) {
93             NetworkSystemDetails* data = systemInfo->add_details();
94             data->set_rx_bytes(it.rxBytes + randNum * RX_BYTES_INDEX);
95             data->set_rx_packets(it.rxPackets + randNum * RX_PACKETS_INDEX);
96             data->set_tx_bytes(it.txBytes + randNum * TX_BYTES_INDEX);
97             data->set_tx_packets(it.txPackets + randNum * TX_PACKETS_INDEX);
98             data->set_type(it.type);
99         }
100         systemInfo->set_tv_sec(systemData.ts.tv_sec);
101         systemInfo->set_tv_nsec(systemData.ts.tv_nsec);
102         systemInfo->set_rx_bytes(systemData.rxBytes + (randNum * RX_BYTES_INDEX * systemData.details.size()));
103         systemInfo->set_rx_packets(systemData.rxPackets + (randNum * RX_PACKETS_INDEX * systemData.details.size()));
104         systemInfo->set_tx_bytes(systemData.txBytes + (randNum * TX_BYTES_INDEX * systemData.details.size()));
105         systemInfo->set_tx_packets(systemData.txPackets + (randNum * TX_PACKETS_INDEX * systemData.details.size()));
106     } else { // real data
107         NetSystemData systemData = {};
108         ReadSystemTxRxBytes(systemData);
109         auto* systemInfo = dataProto.mutable_network_system_info();
110         for (auto& it : systemData.details) {
111             NetworkSystemDetails* data = systemInfo->add_details();
112             data->set_rx_bytes(it.rxBytes);
113             data->set_rx_packets(it.rxPackets);
114             data->set_tx_bytes(it.txBytes);
115             data->set_tx_packets(it.txPackets);
116             data->set_type(it.type);
117         }
118         systemInfo->set_tv_sec(systemData.ts.tv_sec);
119         systemInfo->set_tv_nsec(systemData.ts.tv_nsec);
120         systemInfo->set_rx_bytes(systemData.rxBytes);
121         systemInfo->set_rx_packets(systemData.rxPackets);
122         systemInfo->set_tx_bytes(systemData.txBytes);
123         systemInfo->set_tx_packets(systemData.txPackets);
124     }
125 
126     uint32_t length = dataProto.ByteSizeLong();
127     if (length > dataSize) {
128         return -length;
129     }
130     if (dataProto.SerializeToArray(data, length) > 0) {
131         return length;
132     }
133     return 0;
134 }
135 
Stop()136 int NetworkPlugin::Stop()
137 {
138     buffer_ = nullptr;
139     fp_ = nullptr;
140     pidUid_.clear();
141 
142     HILOG_INFO(LOG_CORE, "%s:NetworkPlugin, stop success!", __func__);
143     return 0;
144 }
145 
GetRateNodePath()146 std::string NetworkPlugin::GetRateNodePath()
147 {
148     std::string name = "";
149 
150     if (!fileForTest_.empty()) {
151         name = fileForTest_ + DEFAULT_NET_PATH;
152         return name;
153     }
154     if (access(DEFAULT_NET_PATH.c_str(), F_OK) == 0) {
155         name = DEFAULT_NET_PATH;
156     }
157     return name;
158 }
159 
GetUid(int32_t pid)160 int32_t NetworkPlugin::GetUid(int32_t pid)
161 {
162     if (pid <= 0) {
163         HILOG_ERROR(LOG_CORE, "%s:NetworkPlugin, check param fail, pid less than 0!", __func__);
164         return -1;
165     }
166 
167     char* end = nullptr;
168     std::string path = std::string("/proc/") + std::to_string(pid) + std::string("/status");
169     if (!fileForTest_.empty()) {
170         path = fileForTest_ + std::string("/proc/") + std::to_string(pid) + std::string("/status");
171     }
172     std::ifstream input(path, std::ios::in);
173     if (input.fail()) {
174         const int bufSize = 256;
175         char buf[bufSize] = { 0 };
176         strerror_r(errno, buf, bufSize);
177         HILOG_ERROR(LOG_CORE, "%s:NetworkPlugin, open %s failed, errno(%s)", __func__, path.c_str(), buf);
178         return -1;
179     }
180     do {
181         if (!input.good()) {
182             return -1;
183         }
184         std::string line;
185         getline(input, line);
186         if (!strncmp(line.c_str(), "Uid:", strlen("Uid:"))) {
187             std::string str = line.substr(strlen("Uid:\t"));
188             HILOG_INFO(LOG_CORE, "%s:NetworkPlugin, line(%s), str(%s)", __func__, line.c_str(), str.c_str());
189             return strtol(str.c_str(), &end, DEC_BASE);
190         }
191     } while (!input.eof());
192     input.close();
193 
194     return -1;
195 }
196 
ReadTxRxBytes(int32_t pid,NetworkCell & cell)197 bool NetworkPlugin::ReadTxRxBytes(int32_t pid, NetworkCell &cell)
198 {
199     int32_t uid = pidUid_.at(pid);
200     CHECK_NOTNULL(fp_.get(), false, "%s:NetworkPlugin, fp_ is null", __func__);
201     int ret = fseek(fp_.get(), 0, SEEK_SET);
202     CHECK_TRUE(ret == 0, false, "%s:NetworkPlugin, fseek failed, error(%d)!", __func__, errno);
203     size_t rsize = static_cast<size_t>(fread(buffer_.get(), sizeof(char), READ_BUFFER_SIZE - 1, fp_.get()));
204     buffer_.get()[rsize] = '\0';
205     CHECK_TRUE(rsize >= 0, false, "%s:NetworkPlugin, read failed, errno(%d)", __func__, errno);
206     char* end = nullptr;
207     BufferSplitter totalbuffer((const char*)buffer_.get(), rsize + 1);
208     do {
209         int index = 0;
210         NetDetails cache = {0};
211         char tmp[TX_BYTES_INDEX + 1] = {0};
212         while (totalbuffer.NextWord(' ')) {
213             index++;
214             if (totalbuffer.CurWord() == nullptr) {
215                 continue;
216             }
217             if (index == IFACE_INDEX && !strncmp(totalbuffer.CurWord(), "lo", strlen("lo"))) {
218                 break;
219             }
220             if (index == IFACE_INDEX &&
221                 strncpy_s(tmp, sizeof(tmp), totalbuffer.CurWord(), totalbuffer.CurWordSize()) == EOK) {
222                 cache.type = tmp;
223             }
224             uint64_t value = static_cast<uint64_t>(strtoull(totalbuffer.CurWord(), &end, DEC_BASE));
225             CHECK_TRUE(value >= 0, false, "%s:NetworkPlugin, strtoull value failed", __func__);
226             if ((index == UID_INDEX) && (uid != static_cast<int32_t>(value))) {
227                 break;
228             }
229             if (index == RX_BYTES_INDEX) {
230                 uint64_t rxBytes = value;
231                 cache.rx = rxBytes;
232                 cell.rx += rxBytes;
233             }
234             if (index == TX_BYTES_INDEX) {
235                 uint64_t txBytes = value;
236                 cache.tx = txBytes;
237                 cell.tx += txBytes;
238                 AddNetDetails(cell, cache);
239             }
240         }
241     } while (totalbuffer.NextLine());
242 
243     clock_gettime(CLOCK_REALTIME, &cell.ts);
244 
245     return true;
246 }
247 
AddNetDetails(NetworkCell & cell,NetDetails & data)248 void NetworkPlugin::AddNetDetails(NetworkCell& cell, NetDetails& data)
249 {
250     bool finded = false;
251 
252     // 处理重复数据
253     for (auto it = cell.details.begin(); it != cell.details.end(); it++) {
254         if (it->type == data.type) {
255             it->tx += data.tx;
256             it->rx += data.rx;
257             finded = true;
258         }
259     }
260 
261     if (!finded) {
262         cell.details.push_back(data);
263     }
264 }
265 
ReadSystemTxRxBytes(NetSystemData & systemData)266 bool NetworkPlugin::ReadSystemTxRxBytes(NetSystemData &systemData)
267 {
268     CHECK_NOTNULL(fp_.get(), false, "%s:NetworkPlugin, fp_ is null", __func__);
269     int ret = fseek(fp_.get(), 0, SEEK_SET);
270     CHECK_TRUE(ret == 0, false, "%s:NetworkPlugin, fseek failed, error(%d)!", __func__, errno);
271     size_t rsize = static_cast<size_t>(fread(buffer_.get(), sizeof(char), READ_BUFFER_SIZE - 1, fp_.get()));
272     buffer_.get()[rsize] = '\0';
273     CHECK_TRUE(rsize >= 0, false, "%s:NetworkPlugin, read failed, errno(%d)", __func__, errno);
274     char* end = nullptr;
275     BufferSplitter totalbuffer((const char*)buffer_.get(), rsize + 1);
276     do {
277         int index = 0;
278         NetSystemDetails systemCache = {};
279         char tmp[TX_BYTES_INDEX + 1] = "";
280         while (totalbuffer.NextWord(' ')) {
281             index++;
282             if (totalbuffer.CurWord() == nullptr) {
283                 continue;
284             }
285             if (index == IFACE_INDEX && !strncmp(totalbuffer.CurWord(), "lo", strlen("lo"))) {
286                 break;
287             }
288             if (index == IFACE_INDEX &&
289                 strncpy_s(tmp, sizeof(tmp), totalbuffer.CurWord(), totalbuffer.CurWordSize()) == EOK) {
290                 systemCache.type = tmp;
291             }
292             if (strcmp(systemCache.type.c_str(), "iface") == 0) {
293                 break;
294             }
295             uint64_t value = static_cast<uint64_t>(strtoull(totalbuffer.CurWord(), &end, DEC_BASE));
296             CHECK_TRUE(value >= 0, false, "%s:NetworkPlugin, strtoull value failed", __func__);
297             if (index == RX_BYTES_INDEX) {
298                 uint64_t rxBytes = value;
299                 systemCache.rxBytes = rxBytes;
300                 systemData.rxBytes += rxBytes;
301             } else if (index == RX_PACKETS_INDEX) {
302                 uint64_t rxPackets = value;
303                 systemCache.rxPackets = rxPackets;
304                 systemData.rxPackets += rxPackets;
305             } else if (index == TX_BYTES_INDEX) {
306                 uint64_t txBytes = value;
307                 systemCache.txBytes = txBytes;
308                 systemData.txBytes += txBytes;
309             } else if (index == TX_PACKETS_INDEX) {
310                 uint64_t txPackets = value;
311                 systemCache.txPackets = txPackets;
312                 systemData.txPackets += txPackets;
313                 AddNetSystemDetails(systemData, systemCache);
314             }
315         }
316     } while (totalbuffer.NextLine());
317 
318     clock_gettime(CLOCK_REALTIME, &systemData.ts);
319 
320     return true;
321 }
322 
AddNetSystemDetails(NetSystemData & systemData,NetSystemDetails & data)323 void NetworkPlugin::AddNetSystemDetails(NetSystemData& systemData, NetSystemDetails& data)
324 {
325     bool finded = false;
326 
327     // 处理重复数据
328     for (auto it = systemData.details.begin(); it != systemData.details.end(); it++) {
329         if (it->type == data.type) {
330             it->rxBytes += data.rxBytes;
331             it->rxPackets += data.rxPackets;
332             it->txBytes += data.txBytes;
333             it->txPackets += data.txPackets;
334             finded = true;
335         }
336     }
337 
338     if (!finded) {
339         systemData.details.push_back(data);
340     }
341 }
342