1 /*
2 * Copyright (C) 2024 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 "ip_qos_monitor.h"
17 #include "wifi_logger.h"
18 #include "wifi_config_center.h"
19 #include "wifi_global_func.h"
20
21 static const int32_t MIN_DELTA_TCP_TX = 3;
22 static const int32_t QOS_TCP_TX_PKTS = 6;
23 static const int32_t QOS_TCP_RX_PKTS = 7;
24 static const int32_t QOS_MSG_FROM = 9;
25 static const int32_t MIN_PACKET_LEN = 7;
26 static const int32_t CMD_START_MONITOR = 10;
27 static const int32_t CMD_QUERY_PKTS = 15;
28
29 namespace OHOS {
30 namespace Wifi {
31 DEFINE_WIFILOG_LABEL("IpQosMonitor");
32
GetInstance()33 IpQosMonitor &IpQosMonitor::GetInstance()
34 {
35 static IpQosMonitor gIpQosMonitor;
36 return gIpQosMonitor;
37 }
38
StartMonitor(int32_t arg)39 void IpQosMonitor::StartMonitor(int32_t arg)
40 {
41 WIFI_LOGD("enter %{public}s", __FUNCTION__);
42 WifiNetLink::GetInstance().SendQoeCmd(CMD_START_MONITOR, arg);
43 }
44
QueryPackets(int32_t arg)45 void IpQosMonitor::QueryPackets(int32_t arg)
46 {
47 WIFI_LOGD("enter %{public}s", __FUNCTION__);
48 WifiNetLink::GetInstance().SendQoeCmd(CMD_QUERY_PKTS, arg);
49 }
50
HandleTcpReportMsgComplete(const std::vector<int64_t> & elems,int32_t cmd)51 void IpQosMonitor::HandleTcpReportMsgComplete(const std::vector<int64_t> &elems, int32_t cmd)
52 {
53 WIFI_LOGD("enter %{public}s", __FUNCTION__);
54 ParseTcpReportMsg(elems, cmd);
55 }
56
ParseTcpReportMsg(const std::vector<int64_t> & elems,int32_t cmd)57 void IpQosMonitor::ParseTcpReportMsg(const std::vector<int64_t> &elems, int32_t cmd)
58 {
59 if (elems.size() == 0) {
60 WIFI_LOGE("TcpReportMsg elems size is 0");
61 return;
62 }
63 if (cmd == CMD_QUERY_PKTS) {
64 HandleTcpPktsResp(elems);
65 }
66 }
67
HandleTcpPktsResp(const std::vector<int64_t> & elems)68 void IpQosMonitor::HandleTcpPktsResp(const std::vector<int64_t> &elems)
69 {
70 WIFI_LOGD("enter %{public}s", __FUNCTION__);
71 std::unique_lock<std::mutex> locker(txRxStatusMtx_);
72 bool internetGood = ParseNetworkInternetGood(elems);
73 if (internetGood) {
74 if (!lastTxRxGood_) {
75 WIFI_LOGI("%{public}s: set tx_rx_good true", __FUNCTION__);
76 lastTxRxGood_ = true;
77 }
78 mInternetFailedCounter = 0;
79 mInternetSelfCureAllowed = true;
80 mHttpDetectedAllowed = true;
81 return;
82 }
83
84 WifiLinkedInfo linkedInfo;
85 WifiConfigCenter::GetInstance().GetLinkedInfo(linkedInfo);
86 int32_t signalLevel = WifiSettings::GetInstance().GetSignalLevel(linkedInfo.rssi, linkedInfo.band, mInstId);
87 if (lastTxRxGood_) {
88 WIFI_LOGI("%{public}s: set tx_rx_good false", __FUNCTION__);
89 lastTxRxGood_ = false;
90 }
91 mInternetFailedCounter++;
92 WIFI_LOGI("%{public}s: mInternetFailedCounter = %{public}d", __FUNCTION__, mInternetFailedCounter);
93 if ((mInternetFailedCounter >= 1) && (linkedInfo.connState == ConnState::CONNECTED)) {
94 ISelfCureService *pSelfCureService = WifiServiceManager::GetInstance().GetSelfCureServiceInst(mInstId);
95 if (pSelfCureService == nullptr) {
96 WIFI_LOGE("%{public}s: pSelfCureService is null", __FUNCTION__);
97 return;
98 }
99 if (mHttpDetectedAllowed && signalLevel >= SIGNAL_LEVEL_2) {
100 WIFI_LOGI("%{public}s: start http detect", __FUNCTION__);
101 if (mNetWorkDetect == nullptr) {
102 mNetWorkDetect = sptr<NetStateObserver>(new NetStateObserver());
103 }
104 if (mNetWorkDetect == nullptr) {
105 WIFI_LOGE("%{public}s mNetWorkDetect is null", __func__);
106 return;
107 }
108 mNetWorkDetect->StartWifiDetection();
109 mHttpDetectedAllowed = false;
110 return;
111 }
112 }
113 }
114
AllowSelfCureNetwork(int32_t currentRssi)115 bool IpQosMonitor::AllowSelfCureNetwork(int32_t currentRssi)
116 {
117 ISelfCureService *pSelfCureService = WifiServiceManager::GetInstance().GetSelfCureServiceInst(mInstId);
118 if (pSelfCureService == nullptr) {
119 WIFI_LOGE("%{public}s: pSelfCureService is null.", __FUNCTION__);
120 return false;
121 }
122 if (mInternetSelfCureAllowed && currentRssi >= MIN_VAL_LEVEL_3_5 &&
123 (!pSelfCureService->IsSelfCureOnGoing())) {
124 return true;
125 }
126 return false;
127 }
128
ParseNetworkInternetGood(const std::vector<int64_t> & elems)129 bool IpQosMonitor::ParseNetworkInternetGood(const std::vector<int64_t> &elems)
130 {
131 WIFI_LOGD("enter %{public}s", __FUNCTION__);
132 bool queryResp = (elems[QOS_MSG_FROM] == 0);
133 int32_t packetsLength = static_cast<int32_t>(elems.size());
134 if ((queryResp) && (packetsLength > MIN_PACKET_LEN)) {
135 int64_t tcpTxPkts = elems[QOS_TCP_TX_PKTS];
136 int64_t tcpRxPkts = elems[QOS_TCP_RX_PKTS];
137 WIFI_LOGD("tcpTxPkts = %{public}" PRId64 ", tcpRxPkts = %{public}" PRId64, tcpTxPkts, tcpRxPkts);
138 if ((mLastTcpTxCounter == 0) && (mLastTcpRxCounter == 0)) {
139 mLastTcpTxCounter = tcpTxPkts;
140 mLastTcpRxCounter = tcpRxPkts;
141 WIFI_LOGI("mLastTcpTxCounter = %{public}" PRId64 ", mLastTcpRxCounter = %{public}" PRId64,
142 mLastTcpTxCounter, mLastTcpRxCounter);
143 return lastTxRxGood_;
144 }
145 int64_t deltaTcpTxPkts = tcpTxPkts - mLastTcpTxCounter;
146 int64_t deltaTcpRxPkts = tcpRxPkts - mLastTcpRxCounter;
147 WIFI_LOGI("deltaTcpTxPkts = %{public}" PRId64 ", deltaTcpRxPkts = %{public}" PRId64,
148 deltaTcpTxPkts, deltaTcpRxPkts);
149 mLastTcpTxCounter = tcpTxPkts;
150 mLastTcpRxCounter = tcpRxPkts;
151 if (deltaTcpRxPkts == 0) {
152 if (deltaTcpTxPkts < MIN_DELTA_TCP_TX) {
153 WIFI_LOGD("%{public}s deltaTcpRxPkts 0, deltaTcpTxPkts less 3, return last tx rx status %{public}d",
154 __FUNCTION__, lastTxRxGood_);
155 return lastTxRxGood_;
156 }
157 if (deltaTcpTxPkts >= MIN_DELTA_TCP_TX) {
158 WIFI_LOGI("%{public}s internetGood: false", __FUNCTION__);
159 return false;
160 }
161 }
162 }
163 return true;
164 }
165
GetCurrentTcpTxCounter()166 int64_t IpQosMonitor::GetCurrentTcpTxCounter()
167 {
168 return mLastTcpTxCounter;
169 }
170
GetCurrentTcpRxCounter()171 int64_t IpQosMonitor::GetCurrentTcpRxCounter()
172 {
173 return mLastTcpRxCounter;
174 }
175
ResetTxRxProperty()176 void IpQosMonitor::ResetTxRxProperty()
177 {
178 WIFI_LOGI("%{public}s: reset tx rx status", __FUNCTION__);
179 std::unique_lock<std::mutex> locker(txRxStatusMtx_);
180 lastTxRxGood_ = false;
181 mLastTcpTxCounter = 0;
182 mLastTcpRxCounter = 0;
183 }
184
GetTxRxStatus()185 bool IpQosMonitor::GetTxRxStatus()
186 {
187 std::unique_lock<std::mutex> locker(txRxStatusMtx_);
188 return lastTxRxGood_;
189 }
190
191 } // namespace Wifi
192 } // namespace OHOS
193