diff --git a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_common/wifi_netlink.cpp b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_common/wifi_netlink.cpp index 4aabed120c3facd130f1b3353df90ffcacaff7ac..3cb50f127a02eb055ac363ba7587f7e1c8882f07 100644 --- a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_common/wifi_netlink.cpp +++ b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_common/wifi_netlink.cpp @@ -42,11 +42,13 @@ static const int32_t QOS_MSG_FROM = 9; enum WifiKnlMsgType { NETLINK_WIFIPRO_START_MONITOR = 0, NETLINK_WIFIPRO_GET_MSG, + NETLINK_WIFIPRO_GET_IPV6_MSG = 9, }; enum CmdWord { CMD_START_MONITOR = 10, CMD_QUERY_PKTS = 15, + CMD_QUERY_IPV6_PKTS = 24, MSG_REPORT_IPQOS = 100, }; @@ -129,6 +131,11 @@ int32_t WifiNetLink::ProcessQueryTcp(int32_t sockFd) return SendCmdKernel(sockFd, NETLINK_WIFIPRO_GET_MSG, 0); } +int32_t WifiNetLink::ProcessQueryIpv6Tcp(int32_t sockFd) +{ + return SendCmdKernel(sockFd, NETLINK_WIFIPRO_GET_IPV6_MSG, 0); +} + int32_t WifiNetLink::SendQoeCmd(int32_t cmd, int32_t arg) { int32_t sockFd = -1; @@ -149,6 +156,10 @@ int32_t WifiNetLink::SendQoeCmd(int32_t cmd, int32_t arg) sendResult = ProcessQueryTcp(sockFd); isNeedReport = true; break; + case CMD_QUERY_IPV6_PKTS: + sendResult = ProcessQueryIpv6Tcp(sockFd); + isNeedReport = true; + break; default: break; } @@ -199,7 +210,8 @@ int32_t WifiNetLink::ProcessReportMsg(int32_t sockFd, int32_t cmd) mWifiNetLinkCallbacks.OnTcpReportMsgComplete(elems, cmd, mInstId); return 0; } else { - WIFI_LOGI("Received invalid message info.hdr.nlmsg_type = %{public}d", info.hdr.nlmsg_type); + const char* type = (cmd == CMD_QUERY_IPV6_PKTS) ? "IPv6" : "IPv4"; + WIFI_LOGI("Received invalid %{public}s message info.hdr.nlmsg_type = %{public}d", type, info.hdr.nlmsg_type); return -1; } } diff --git a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_common/wifi_netlink.h b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_common/wifi_netlink.h index 4b059a23888d6b7298e48c8fbeab60eb4e5b56cc..08430a9f85ae5351f298317e0ff7bcdbbc400af3 100644 --- a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_common/wifi_netlink.h +++ b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_common/wifi_netlink.h @@ -37,6 +37,7 @@ public: int32_t SendCmdKernel(int32_t sockFd, int32_t cmd, int32_t flag); int32_t StartMonitor(int32_t sockFd); int32_t ProcessQueryTcp(int32_t sockFd); + int32_t ProcessQueryIpv6Tcp(int32_t sockFd); int32_t SendQoeCmd(int32_t cmd, int32_t arg = 0); int32_t ProcessReportMsg(int32_t sockFd, int32_t cmd); private: diff --git a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/ip_qos_monitor.cpp b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/ip_qos_monitor.cpp index d389ac1688c71b09593c649fdcc484ba9c304428..53316e12a27ce0b27991e6de0cbb1c7214d95acb 100644 --- a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/ip_qos_monitor.cpp +++ b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/ip_qos_monitor.cpp @@ -22,9 +22,12 @@ static const int32_t MIN_DELTA_TCP_TX = 3; static const int32_t QOS_TCP_TX_PKTS = 6; static const int32_t QOS_TCP_RX_PKTS = 7; static const int32_t QOS_MSG_FROM = 9; -static const int32_t MIN_PACKET_LEN = 7; +static const int32_t QOS_IPV6_MSG_FROM = 5; +static const int32_t MIN_PACKET_LEN = 9; static const int32_t CMD_START_MONITOR = 10; static const int32_t CMD_QUERY_PKTS = 15; +static const int32_t CMD_QUERY_IPV6_PKTS = 24; +static const int32_t IPV6_FAILURE_THRESHOLD = 3; namespace OHOS { namespace Wifi { @@ -39,6 +42,13 @@ IpQosMonitor &IpQosMonitor::GetInstance() void IpQosMonitor::StartMonitor(int32_t arg) { WIFI_LOGD("enter %{public}s", __FUNCTION__); + + // Reset IPv6 failed counter when starting monitor, indicating a new connection + if (mIpv6FailedCounter > 0) { + WIFI_LOGI("StartMonitor: reset IPv6 failed counter from %{public}d to 0", mIpv6FailedCounter); + mIpv6FailedCounter = 0; + } + WifiNetLink::GetInstance().SendQoeCmd(CMD_START_MONITOR, arg); } @@ -48,6 +58,12 @@ void IpQosMonitor::QueryPackets(int32_t arg) WifiNetLink::GetInstance().SendQoeCmd(CMD_QUERY_PKTS, arg); } +void IpQosMonitor::QueryIpv6Packets(int32_t arg) +{ + WIFI_LOGD("enter %{public}s", __FUNCTION__); + WifiNetLink::GetInstance().SendQoeCmd(CMD_QUERY_IPV6_PKTS, arg); +} + void IpQosMonitor::HandleTcpReportMsgComplete(const std::vector &elems, int32_t cmd) { WIFI_LOGD("enter %{public}s", __FUNCTION__); @@ -62,6 +78,8 @@ void IpQosMonitor::ParseTcpReportMsg(const std::vector &elems, int32_t } if (cmd == CMD_QUERY_PKTS) { HandleTcpPktsResp(elems); + } else if (cmd == CMD_QUERY_IPV6_PKTS) { + HandleIpv6TcpPktsResp(elems); } } @@ -112,6 +130,46 @@ void IpQosMonitor::HandleTcpPktsResp(const std::vector &elems) } } +void IpQosMonitor::HandleIpv6TcpPktsResp(const std::vector &elems) +{ + WIFI_LOGD("enter %{public}s", __FUNCTION__); + bool ipv6InternetGood = ParseIpv6NetworkInternetGood(elems); + if (ipv6InternetGood) { + mIpv6FailedCounter = 0; + WIFI_LOGD("IPv6 connection is good, reset failed counter"); + return; + } + + mIpv6FailedCounter++; + WIFI_LOGI("%{public}s: IPv6 mIpv6FailedCounter = %{public}d", __FUNCTION__, mIpv6FailedCounter); + + // Check WiFi connection state, only handle IPv6 failure when connected + WifiLinkedInfo linkedInfo; + WifiConfigCenter::GetInstance().GetLinkedInfo(linkedInfo); + if (linkedInfo.connState != ConnState::CONNECTED) { + WIFI_LOGD("WiFi not connected, ignore IPv6 failure"); + return; + } + + // Notify SelfCure service when IPv6 fails 3 times consecutively + if (mIpv6FailedCounter >= IPV6_FAILURE_THRESHOLD) { + ISelfCureService *pSelfCureService = WifiServiceManager::GetInstance().GetSelfCureServiceInst(mInstId); + if (pSelfCureService == nullptr) { + WIFI_LOGE("%{public}s: pSelfCureService is null", __FUNCTION__); + return; + } + + // Notify SelfCure service about IPv6 connection failure to trigger IPv6 disable mechanism + ErrCode result = pSelfCureService->NotifyIpv6FailureDetected(); + if (result == WIFI_OPT_SUCCESS) { + WIFI_LOGI("%{public}s: IPv6 failure notified to SelfCure successfully after %{public}d failures", + __FUNCTION__, mIpv6FailedCounter); + } else { + WIFI_LOGE("%{public}s: Failed to notify IPv6 failure to SelfCure", __FUNCTION__); + } + } +} + bool IpQosMonitor::AllowSelfCureNetwork(int32_t currentRssi) { ISelfCureService *pSelfCureService = WifiServiceManager::GetInstance().GetSelfCureServiceInst(mInstId); @@ -129,9 +187,15 @@ bool IpQosMonitor::AllowSelfCureNetwork(int32_t currentRssi) bool IpQosMonitor::ParseNetworkInternetGood(const std::vector &elems) { WIFI_LOGD("enter %{public}s", __FUNCTION__); - bool queryResp = (elems[QOS_MSG_FROM] == 0); int32_t packetsLength = static_cast(elems.size()); - if ((queryResp) && (packetsLength > MIN_PACKET_LEN)) { + // Check if array length is sufficient to access required indices + if (packetsLength <= QOS_MSG_FROM) { + WIFI_LOGE("elems length %{public}d is too short, expected > %{public}d", packetsLength, QOS_MSG_FROM); + return true; + } + + bool queryResp = (elems[QOS_MSG_FROM] == 0); + if (queryResp) { int64_t tcpTxPkts = elems[QOS_TCP_TX_PKTS]; int64_t tcpRxPkts = elems[QOS_TCP_RX_PKTS]; WIFI_LOGD("tcpTxPkts = %{public}" PRId64 ", tcpRxPkts = %{public}" PRId64, tcpTxPkts, tcpRxPkts); @@ -144,6 +208,15 @@ bool IpQosMonitor::ParseNetworkInternetGood(const std::vector &elems) } int64_t deltaTcpTxPkts = tcpTxPkts - mLastTcpTxCounter; int64_t deltaTcpRxPkts = tcpRxPkts - mLastTcpRxCounter; + + // Handle integer overflow wraparound + if (deltaTcpTxPkts < 0 || deltaTcpRxPkts < 0) { + WIFI_LOGW("TCP counter overflow detected, reset counters"); + mLastTcpTxCounter = tcpTxPkts; + mLastTcpRxCounter = tcpRxPkts; + return true; // Return true on overflow to avoid false negative + } + WIFI_LOGI("deltaTcpTxPkts = %{public}" PRId64 ", deltaTcpRxPkts = %{public}" PRId64, deltaTcpTxPkts, deltaTcpRxPkts); mLastTcpTxCounter = tcpTxPkts; @@ -163,6 +236,64 @@ bool IpQosMonitor::ParseNetworkInternetGood(const std::vector &elems) return true; } +bool IpQosMonitor::ParseIpv6NetworkInternetGood(const std::vector &elems) +{ + WIFI_LOGD("enter %{public}s", __FUNCTION__); + + // First check elems length + int32_t packetsLength = static_cast(elems.size()); + if (packetsLength <= MIN_PACKET_LEN) { + WIFI_LOGE("IPv6 elems length %{public}d is too short, expected > %{public}d", packetsLength, MIN_PACKET_LEN); + return true; // Return true when length is insufficient to avoid false negative + } + + // Check if this is an IPv6 query response, elems[QOS_MSG_FROM] should equal QOS_IPV6_MSG_FROM(5) + bool queryResp = (elems[QOS_MSG_FROM] == QOS_IPV6_MSG_FROM); + if (!queryResp) { + WIFI_LOGD("IPv6 not a query response, msgFrom = %{public}" PRId64 ", expected = %{public}d", + elems[QOS_MSG_FROM], QOS_IPV6_MSG_FROM); + return true; // Return true when not IPv6 query response + } + + int64_t tcpTxPkts = elems[QOS_TCP_TX_PKTS]; + int64_t tcpRxPkts = elems[QOS_TCP_RX_PKTS]; + WIFI_LOGD("IPv6 tcpTxPkts = %{public}" PRId64 ", tcpRxPkts = %{public}" PRId64, tcpTxPkts, tcpRxPkts); + + if ((mLastIpv6TcpTxCounter == 0) || (mLastIpv6TcpRxCounter == 0)) { + mLastIpv6TcpTxCounter = tcpTxPkts; + mLastIpv6TcpRxCounter = tcpRxPkts; + WIFI_LOGI("IPv6 mLastTcpTxCounter = %{public}" PRId64 ", mLastTcpRxCounter = %{public}" PRId64, + mLastIpv6TcpTxCounter, mLastIpv6TcpRxCounter); + return true; + } + + int64_t deltaTcpTxPkts = tcpTxPkts - mLastIpv6TcpTxCounter; + int64_t deltaTcpRxPkts = tcpRxPkts - mLastIpv6TcpRxCounter; + + // Handle integer overflow wraparound + if (deltaTcpTxPkts < 0 || deltaTcpRxPkts < 0) { + WIFI_LOGW("IPv6 TCP counter overflow detected, reset counters"); + mLastIpv6TcpTxCounter = tcpTxPkts; + mLastIpv6TcpRxCounter = tcpRxPkts; + return true; // Return true on overflow to avoid false negative + } + + WIFI_LOGI("IPv6 deltaTcpTxPkts = %{public}" PRId64 ", deltaTcpRxPkts = %{public}" PRId64, + deltaTcpTxPkts, deltaTcpRxPkts); + + mLastIpv6TcpTxCounter = tcpTxPkts; + mLastIpv6TcpRxCounter = tcpRxPkts; + + if (deltaTcpRxPkts == 0) { + if (deltaTcpTxPkts >= MIN_DELTA_TCP_TX) { + WIFI_LOGI("%{public}s IPv6 internetGood: false", __FUNCTION__); + return false; + } + } + + return true; +} + int64_t IpQosMonitor::GetCurrentTcpTxCounter() { return mLastTcpTxCounter; @@ -188,5 +319,19 @@ bool IpQosMonitor::GetTxRxStatus() return lastTxRxGood_; } +int64_t IpQosMonitor::GetCurrentIpv6TcpTxCounter() +{ + return mLastIpv6TcpTxCounter; +} + +int64_t IpQosMonitor::GetCurrentIpv6TcpRxCounter() +{ + return mLastIpv6TcpRxCounter; +} + +int32_t IpQosMonitor::GetIpv6FailedCounter() +{ + return mIpv6FailedCounter; +} } // namespace Wifi } // namespace OHOS diff --git a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/ip_qos_monitor.h b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/ip_qos_monitor.h index 493113295dd34f4d2f7fb7324bfd6bc14c6dbc80..e11ae87b0230297efcb80ac5d3e322b5846596fb 100644 --- a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/ip_qos_monitor.h +++ b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/ip_qos_monitor.h @@ -28,14 +28,20 @@ public: static IpQosMonitor &GetInstance(); void StartMonitor(int32_t arg = 0); void QueryPackets(int32_t arg = 0); + void QueryIpv6Packets(int32_t arg = 0); void HandleTcpReportMsgComplete(const std::vector &elems, int32_t cmd); void ParseTcpReportMsg(const std::vector &elems, int32_t cmd); void HandleTcpPktsResp(const std::vector &elems); + void HandleIpv6TcpPktsResp(const std::vector &elems); bool ParseNetworkInternetGood(const std::vector &elems); + bool ParseIpv6NetworkInternetGood(const std::vector &elems); int64_t GetCurrentTcpTxCounter(); int64_t GetCurrentTcpRxCounter(); void ResetTxRxProperty(); bool GetTxRxStatus(); + int64_t GetCurrentIpv6TcpTxCounter(); + int64_t GetCurrentIpv6TcpRxCounter(); + int32_t GetIpv6FailedCounter(); private: bool AllowSelfCureNetwork(int32_t currentRssi); int32_t mInstId = 0; @@ -43,7 +49,10 @@ private: bool mHttpDetectedAllowed = true; int64_t mLastTcpTxCounter = 0; int64_t mLastTcpRxCounter = 0; + int64_t mLastIpv6TcpTxCounter = 0; + int64_t mLastIpv6TcpRxCounter = 0; int32_t mInternetFailedCounter = 0; + int32_t mIpv6FailedCounter = 0; sptr mNetWorkDetect; bool lastTxRxGood_ = false; std::mutex txRxStatusMtx_; diff --git a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/iself_cure_service.h b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/iself_cure_service.h index e4d68a933b58d339961a71df8a2463ed72c8d5e1..46d774453a71d38f97a8ded9b084006ca0622419 100644 --- a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/iself_cure_service.h +++ b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/iself_cure_service.h @@ -92,6 +92,12 @@ public: * @return bool - true: have done selfcure or no need to do, false: selfcure not finish */ virtual bool IsWifiSelfcureDone() = 0; + /** + * @Description Notify IPv6 connection failure detected + * + * @return ErrCode - success: WIFI_OPT_SUCCESS, failed: WIFI_OPT_FAILED + */ + virtual ErrCode NotifyIpv6FailureDetected() = 0; }; } // namespace Wifi } // namespace OHOS diff --git a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_interface.cpp b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_interface.cpp index 23095c4ca9332bd896d80b7b558c0a6ff9ce08e9..24bc0faf826f10dbc927cbc2256f80a0f7ca6147 100644 --- a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_interface.cpp +++ b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_interface.cpp @@ -189,5 +189,17 @@ void SelfCureInterface::DealRssiLevelChanged(int rssi, int instId) } pSelfCureService->HandleRssiLevelChanged(rssi); } + +ErrCode SelfCureInterface::NotifyIpv6FailureDetected() +{ + WIFI_LOGD("Enter SelfCureInterface::NotifyIpv6FailureDetected"); + std::lock_guard lock(mutex); + if (pSelfCureService == nullptr) { + WIFI_LOGE("pSelfCureService is null"); + return WIFI_OPT_FAILED; + } + bool ret = pSelfCureService->NotifyIpv6FailureDetected(); + return ret ? WIFI_OPT_SUCCESS : WIFI_OPT_FAILED; +} } // namespace Wifi } // namespace OHOS diff --git a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_interface.h b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_interface.h index 2ce8820b25c494078374c12ea90571a6a6ef0703..600d7535dd361ff97eb6bf6d3fe6479a72226816 100644 --- a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_interface.h +++ b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_interface.h @@ -126,6 +126,13 @@ public: * @return bool - true: have done selfcure or no need to do, false: selfcure not finish */ bool IsWifiSelfcureDone() override; + + /** + * @Description Notify IPv6 connection failure detected + * + * @return ErrCode - success: WIFI_OPT_SUCCESS, failed: WIFI_OPT_FAILED + */ + ErrCode NotifyIpv6FailureDetected() override; private: std::mutex mutex; std::vector mSelfCureCallback; diff --git a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_service.cpp b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_service.cpp index e512a77fec68c09659200b2262a36a36d5a233d1..ec2bd5fbbd4e437e28e566b75c73220e7b1cd572 100644 --- a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_service.cpp +++ b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_service.cpp @@ -223,5 +223,33 @@ void SelfCureService::P2pEnhanceStateChange(const std::string &ifName, int32_t s WifiConfigCenter::GetInstance().SetP2pEnhanceState(p2pEnhanceState); } } + +bool SelfCureService::NotifyIpv6FailureDetected() +{ + WIFI_LOGI("Enter NotifyIpv6FailureDetected"); + // Check WiFi connection state, only handle IPv6 failure when connected + WifiLinkedInfo linkedInfo; + WifiConfigCenter::GetInstance().GetLinkedInfo(linkedInfo); + if (linkedInfo.connState != ConnState::CONNECTED) { + WIFI_LOGI("WiFi not connected, ignore IPv6 failure"); + return false; + } + + // Check if the system supports IPv6 self-cure functionality + if (!SelfCureUtils::GetInstance().IsIpv6SelfCureSupported()) { + WIFI_LOGI("IPv6 self-cure not supported, ignore IPv6 failure"); + return false; + } + + // Disable IPv6 to avoid potential connection issues + bool result = SelfCureUtils::GetInstance().DisableIpv6(); + if (result) { + WIFI_LOGI("IPv6 disabled successfully due to connection failure"); + return true; + } else { + WIFI_LOGE("Failed to disable IPv6"); + } + return false; +} } //namespace Wifi } //namespace OHOS \ No newline at end of file diff --git a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_service.h b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_service.h index ad7f8e1de949f21c2a03022b3541f3de68604de2..9dfdd8527f19111874fc8d4097ef48ed97a6ea85 100644 --- a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_service.h +++ b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_service.h @@ -43,6 +43,7 @@ public: void StopSelfCureWifi(int32_t status); bool CheckSelfCureWifiResult(int event); bool IsWifiSelfcureDone(); + bool NotifyIpv6FailureDetected(); private: void RegisterP2pEnhanceCallback(); void P2pEnhanceStateChange(const std::string &ifName, int32_t state, int32_t frequency); diff --git a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_state_machine.cpp b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_state_machine.cpp index 842f2e8a131662205911ce53ee0f75a7cf6f2735..009410cea2e7691a0c1af0b1947e4fd7525e06dc 100644 --- a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_state_machine.cpp +++ b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_state_machine.cpp @@ -594,6 +594,7 @@ void SelfCureStateMachine::ConnectedMonitorState::HandleTcpQualityQuery(Internal pSelfCureStateMachine_->StopTimer(CMD_INTERNET_STATUS_DETECT_INTERVAL); if (WifiConfigCenter::GetInstance().GetScreenState() != MODE_STATE_CLOSE) { IpQosMonitor::GetInstance().QueryPackets(); + IpQosMonitor::GetInstance().QueryIpv6Packets(); } pSelfCureStateMachine_->MessageExecutedLater(CMD_INTERNET_STATUS_DETECT_INTERVAL, INTERNET_STATUS_DETECT_INTERVAL_MS); diff --git a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_utils.cpp b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_utils.cpp index 14bd421f45d152659b67f43abef01e6b5174f39b..dc4e7c64a452b1ee40066933ee2c60094b1b9d7e 100644 --- a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_utils.cpp +++ b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_utils.cpp @@ -24,6 +24,8 @@ #include "wifi_config_center.h" #include "wifi_country_code_manager.h" #include "wifi_sta_hal_interface.h" +#include +#include namespace OHOS { namespace Wifi { @@ -558,5 +560,32 @@ void SelfCureUtils::ReportNoInternetChrEvent() } WriteWifiAccessIntFailedHiSysEvent(1, networkFailReason, resetState, selfcureHistory); } + +bool SelfCureUtils::IsIpv6SelfCureSupported() +{ + // Check if the system supports IPv6 self-cure functionality + // This can be configured based on system capabilities or policies + return true; +} + +bool SelfCureUtils::DisableIpv6() +{ + WIFI_LOGI("Attempting to disable IPv6"); + std::string ifName = WifiConfigCenter::GetInstance().GetStaIfaceName(); + // write sys event + std::string selfcureHistory = GetSelfCureHistory(); + int resetState = (WifiConfigCenter::GetInstance().GetWifiSelfcureResetEntered() ? 1 : 0); + WriteWifiAccessIntFailedHiSysEvent(1, NetworkFailReason::IPV6_STATE_UNREACHABLE, resetState, selfcureHistory); + // Use NetManagerStandard API to disable IPv6 on WiFi interface + int result = NetManagerStandard::NetsysController::GetInstance().SetEnableIpv6(ifName, 0); + if (result == 0) { + WIFI_LOGI("IPv6 disabled successfully on interface %{public}s", ifName.c_str()); + return true; + } else { + WIFI_LOGE("Failed to disable IPv6 on interface %{public}s, result: %{public}d", ifName.c_str(), result); + return false; + } +} + } // namespace Wifi } // namespace OHOS \ No newline at end of file diff --git a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_utils.h b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_utils.h index f97bb54dfd67ed2f9ab81dbef0d4ca0e04f3171b..493f304fa2f0bbe098cdc1684cfe8d9ba127693d 100644 --- a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_utils.h +++ b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_self_cure/self_cure_utils.h @@ -53,6 +53,8 @@ public: bool IsIpConflictDetect(); std::string GetSelfCureHistory(); void ReportNoInternetChrEvent(); + bool IsIpv6SelfCureSupported(); + bool DisableIpv6(); private: class SelfCureDnsResultCallback : public NetManagerStandard::NetsysDnsReportCallback { public: diff --git a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_sta/sta_define.h b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_sta/sta_define.h index b946fb8a9cf56163e8d34c17538947f43b246382..bc4ff4a4b0a8cbc271a5d976acb04be69eb4fe9e 100644 --- a/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_sta/sta_define.h +++ b/wifi/services/wifi_standard/wifi_framework/wifi_manage/wifi_sta/sta_define.h @@ -123,6 +123,7 @@ enum NetworkFailReason { DNS_STATE_WORKING, DNS_STATE_UNREACHABLE, IP_STATE_CONFLICT, + IPV6_STATE_UNREACHABLE, }; typedef enum EnumNetWorkState { diff --git a/wifi/test/wifi_standard/wifi_framework/wifi_manage/unittest/common/wifi_netlink_test.cpp b/wifi/test/wifi_standard/wifi_framework/wifi_manage/unittest/common/wifi_netlink_test.cpp index f209dfcc5a1dcdb1e81a78167e3c5636d05134fa..24d363d3a1bd6ff9ad7d7cef0baa135394cd63b2 100644 --- a/wifi/test/wifi_standard/wifi_framework/wifi_manage/unittest/common/wifi_netlink_test.cpp +++ b/wifi/test/wifi_standard/wifi_framework/wifi_manage/unittest/common/wifi_netlink_test.cpp @@ -93,4 +93,19 @@ HWTEST_F(WifiNetLinkTest, SendQoeCmdTest001, TestSize.Level1) int32_t arg = 456; WifiNetLink::GetInstance().SendQoeCmd(cmd, arg); EXPECT_NE(WifiNetLink::GetInstance().SendQoeCmd(cmd, arg), -1); +} + +HWTEST_F(WifiNetLinkTest, TestProcessQueryIpv6Tcp, TestSize.Level1) +{ + int32_t sockFd = 123; + WifiNetLink::GetInstance().ProcessQueryIpv6Tcp(sockFd); + EXPECT_EQ(WifiNetLink::GetInstance().ProcessQueryIpv6Tcp(sockFd), -1); +} + +HWTEST_F(WifiNetLinkTest, SendIpv6QoeCmdTest, TestSize.Level1) +{ + int32_t cmd = 24; // CMD_QUERY_IPV6_PKTS + int32_t arg = 0; + WifiNetLink::GetInstance().SendQoeCmd(cmd, arg); + EXPECT_EQ(WifiNetLink::GetInstance().SendQoeCmd(cmd, arg), -1); } \ No newline at end of file diff --git a/wifi/test/wifi_standard/wifi_framework/wifi_manage/wifi_sta/ip_qos_monitor_test.cpp b/wifi/test/wifi_standard/wifi_framework/wifi_manage/wifi_sta/ip_qos_monitor_test.cpp index d801f0db2b331f91915899f695d2bb00f3c557d0..443bd88a24a50bca92b5205fcf9dbcd000aecfc2 100644 --- a/wifi/test/wifi_standard/wifi_framework/wifi_manage/wifi_sta/ip_qos_monitor_test.cpp +++ b/wifi/test/wifi_standard/wifi_framework/wifi_manage/wifi_sta/ip_qos_monitor_test.cpp @@ -124,4 +124,173 @@ HWTEST_F(IpQosMonitorTest, TestParseNetworkInternetGood, TestSize.Level1) { std::vector elems = {1, 2, 3, 1, 2, 3, 1, 2, 0, 1}; EXPECT_TRUE(IpQosMonitor::GetInstance().ParseNetworkInternetGood(elems)); +} + +HWTEST_F(IpQosMonitorTest, TestQueryIpv6Packets, TestSize.Level1) +{ + int32_t arg = 0; + using namespace std::placeholders; + WifiNetLinkCallbacks mWifiNetLinkCallbacks; + mWifiNetLinkCallbacks.OnTcpReportMsgComplete = + std::bind(&IpQosMonitorTest::OnTcpReportMsgCompleteTest, this, _1, _2, _3); + WifiNetLink::GetInstance().InitWifiNetLink(mWifiNetLinkCallbacks); + IpQosMonitor::GetInstance().QueryIpv6Packets(arg); + EXPECT_FALSE(g_errLog.find("service is null")!=std::string::npos); +} + +HWTEST_F(IpQosMonitorTest, TestHandleIpv6TcpPktsResp, TestSize.Level1) +{ + // Test IPv6 network good case + std::vector elems = {1, 2, 3, 1, 2, 3, 10, 5, 0, 5}; // elems[9] = QOS_IPV6_MSG_FROM = 5 + WifiLinkedInfo wifiLinkedInfo; + wifiLinkedInfo.connState = ConnState::CONNECTED; + EXPECT_CALL(WifiConfigCenter::GetInstance(), GetLinkedInfo(_, _)) + .WillRepeatedly(DoAll(SetArgReferee<0>(wifiLinkedInfo), Return(0))); + + IpQosMonitor::GetInstance().HandleIpv6TcpPktsResp(elems); + EXPECT_EQ(IpQosMonitor::GetInstance().GetIpv6FailedCounter(), 0); +} + +HWTEST_F(IpQosMonitorTest, TestHandleIpv6TcpPktsRespFailure, TestSize.Level1) +{ + // Test IPv6 failure case - TX packets but no RX packets + std::vector elems = {1, 2, 3, 1, 2, 3, 15, 5, 0, 5}; // TX=15, RX=5, MSG_FROM=5 + WifiLinkedInfo wifiLinkedInfo; + wifiLinkedInfo.connState = ConnState::CONNECTED; + EXPECT_CALL(WifiConfigCenter::GetInstance(), GetLinkedInfo(_, _)) + .WillRepeatedly(DoAll(SetArgReferee<0>(wifiLinkedInfo), Return(0))); + + // First call to set initial counters + IpQosMonitor::GetInstance().HandleIpv6TcpPktsResp(elems); + + // Second call with same RX but more TX packets (failure condition) + elems[6] = 20; // Increase TX packets + IpQosMonitor::GetInstance().HandleIpv6TcpPktsResp(elems); + + EXPECT_GT(IpQosMonitor::GetInstance().GetIpv6FailedCounter(), 0); +} + +HWTEST_F(IpQosMonitorTest, TestHandleIpv6TcpPktsRespDisconnected, TestSize.Level1) +{ + // Test IPv6 failure when WiFi is disconnected + std::vector elems = {1, 2, 3, 1, 2, 3, 15, 5, 0, 5}; + WifiLinkedInfo wifiLinkedInfo; + wifiLinkedInfo.connState = ConnState::DISCONNECTED; + EXPECT_CALL(WifiConfigCenter::GetInstance(), GetLinkedInfo(_, _)) + .WillRepeatedly(DoAll(SetArgReferee<0>(wifiLinkedInfo), Return(0))); + + int32_t initialFailedCount = IpQosMonitor::GetInstance().GetIpv6FailedCounter(); + IpQosMonitor::GetInstance().HandleIpv6TcpPktsResp(elems); + + // Should not increment failure counter when disconnected + EXPECT_EQ(IpQosMonitor::GetInstance().GetIpv6FailedCounter(), initialFailedCount); +} + +HWTEST_F(IpQosMonitorTest, TestParseIpv6NetworkInternetGood, TestSize.Level1) +{ + // Test normal IPv6 response + std::vector elems = {1, 2, 3, 1, 2, 3, 10, 8, 0, 5}; // QOS_IPV6_MSG_FROM = 5 + EXPECT_TRUE(IpQosMonitor::GetInstance().ParseIpv6NetworkInternetGood(elems)); +} + +HWTEST_F(IpQosMonitorTest, TestParseIpv6NetworkInternetGoodShortLength, TestSize.Level1) +{ + // Test with insufficient length + std::vector elems = {1, 2, 3}; // Length <= MIN_PACKET_LEN + EXPECT_TRUE(IpQosMonitor::GetInstance().ParseIpv6NetworkInternetGood(elems)); +} + +HWTEST_F(IpQosMonitorTest, TestParseIpv6NetworkInternetGoodWrongMsgFrom, TestSize.Level1) +{ + // Test with wrong MSG_FROM (not IPv6 response) + std::vector elems = {1, 2, 3, 1, 2, 3, 10, 8, 0, 0}; // MSG_FROM = 0 (IPv4) + EXPECT_TRUE(IpQosMonitor::GetInstance().ParseIpv6NetworkInternetGood(elems)); +} + +HWTEST_F(IpQosMonitorTest, TestParseIpv6NetworkInternetGoodFailure, TestSize.Level1) +{ + // Test IPv6 failure detection - TX > 3 but RX = 0 + std::vector elems = {1, 2, 3, 1, 2, 3, 15, 8, 0, 5}; // TX=15, RX=8, MSG_FROM=5 + + // First call to initialize counters + IpQosMonitor::GetInstance().ParseIpv6NetworkInternetGood(elems); + + // Second call with no RX increase but TX increase >= 3 + elems[6] = 20; // TX increases to 20, delta = 5 >= 3 + // RX stays same, delta = 0 + EXPECT_FALSE(IpQosMonitor::GetInstance().ParseIpv6NetworkInternetGood(elems)); +} + +HWTEST_F(IpQosMonitorTest, TestParseIpv6NetworkInternetGoodOverflow, TestSize.Level1) +{ + // Test counter overflow handling + std::vector elems = {1, 2, 3, 1, 2, 3, 100, 50, 0, 5}; + + // Set initial large values + IpQosMonitor::GetInstance().ParseIpv6NetworkInternetGood(elems); + + // Simulate overflow with smaller values + elems[6] = 10; // TX counter wrapped around + elems[7] = 5; // RX counter wrapped around + + // Should return true on overflow detection + EXPECT_TRUE(IpQosMonitor::GetInstance().ParseIpv6NetworkInternetGood(elems)); +} + +HWTEST_F(IpQosMonitorTest, TestGetCurrentIpv6Counters, TestSize.Level1) +{ + // Test IPv6 counter getters + std::vector elems = {1, 2, 3, 1, 2, 3, 25, 15, 0, 5}; + IpQosMonitor::GetInstance().ParseIpv6NetworkInternetGood(elems); + + EXPECT_EQ(IpQosMonitor::GetInstance().GetCurrentIpv6TcpTxCounter(), 25); + EXPECT_EQ(IpQosMonitor::GetInstance().GetCurrentIpv6TcpRxCounter(), 15); +} + +HWTEST_F(IpQosMonitorTest, TestGetIpv6FailedCounter, TestSize.Level1) +{ + // Test IPv6 failed counter getter + int32_t initialCount = IpQosMonitor::GetInstance().GetIpv6FailedCounter(); + EXPECT_GE(initialCount, 0); +} + +HWTEST_F(IpQosMonitorTest, TestParseTcpReportMsgWithIpv6Cmd, TestSize.Level1) +{ + // Test ParseTcpReportMsg with IPv6 command + std::vector elems = {1, 2, 3, 1, 2, 3, 10, 8, 0, 5}; + int32_t cmd = 24; // CMD_QUERY_IPV6_PKTS + + WifiLinkedInfo wifiLinkedInfo; + wifiLinkedInfo.connState = ConnState::CONNECTED; + EXPECT_CALL(WifiConfigCenter::GetInstance(), GetLinkedInfo(_, _)) + .WillRepeatedly(DoAll(SetArgReferee<0>(wifiLinkedInfo), Return(0))); + + IpQosMonitor::GetInstance().ParseTcpReportMsg(elems, cmd); + EXPECT_FALSE(g_errLog.find("service is null")!=std::string::npos); +} + +HWTEST_F(IpQosMonitorTest, TestStartMonitorResetsIpv6Counter, TestSize.Level1) +{ + // Test that StartMonitor resets IPv6 failed counter + + // First simulate some IPv6 failures to increment counter + std::vector elems = {1, 2, 3, 1, 2, 3, 15, 8, 0, 5}; + WifiLinkedInfo wifiLinkedInfo; + wifiLinkedInfo.connState = ConnState::CONNECTED; + EXPECT_CALL(WifiConfigCenter::GetInstance(), GetLinkedInfo(_, _)) + .WillRepeatedly(DoAll(SetArgReferee<0>(wifiLinkedInfo), Return(0))); + + // Initialize and cause failure + IpQosMonitor::GetInstance().HandleIpv6TcpPktsResp(elems); + elems[6] = 20; // Increase TX to cause failure + IpQosMonitor::GetInstance().HandleIpv6TcpPktsResp(elems); + + // Verify counter is incremented + EXPECT_GT(IpQosMonitor::GetInstance().GetIpv6FailedCounter(), 0); + + // Call StartMonitor to reset + IpQosMonitor::GetInstance().StartMonitor(0); + + // Verify counter is reset to 0 + EXPECT_EQ(IpQosMonitor::GetInstance().GetIpv6FailedCounter(), 0); } \ No newline at end of file diff --git a/wifi/test/wifi_standard/wifi_framework/wifi_manage/wifi_sta/self_cure_interface_test.cpp b/wifi/test/wifi_standard/wifi_framework/wifi_manage/wifi_sta/self_cure_interface_test.cpp index c9a67ee5b0eca1fda884cd98e08b5bb13bab8ac0..3f2a2f7aa092c2a1c3d68431895d7aba12eda518 100644 --- a/wifi/test/wifi_standard/wifi_framework/wifi_manage/wifi_sta/self_cure_interface_test.cpp +++ b/wifi/test/wifi_standard/wifi_framework/wifi_manage/wifi_sta/self_cure_interface_test.cpp @@ -184,6 +184,16 @@ HWTEST_F(SelfCureInterfaceTest, DealDhcpOfferReportTest, TestSize.Level1) EXPECT_FALSE(g_errLog.find("service is null") != std::string::npos); } +HWTEST_F(SelfCureInterfaceTest, NotifyIpv6FailureDetectedTest, TestSize.Level1) +{ + // Test IPv6 failure notification interface + EXPECT_EQ(WIFI_OPT_SUCCESS, pSelfCureInterface->NotifyIpv6FailureDetected()); + + // Test with null service + pSelfCureInterface->pSelfCureService = nullptr; + EXPECT_EQ(WIFI_OPT_FAILED, pSelfCureInterface->NotifyIpv6FailureDetected()); +} + } // namespace Wifi } // namespace OHOS \ No newline at end of file diff --git a/wifi/test/wifi_standard/wifi_framework/wifi_manage/wifi_sta/self_cure_service_test.cpp b/wifi/test/wifi_standard/wifi_framework/wifi_manage/wifi_sta/self_cure_service_test.cpp index 108e7d14d98d9c7de388f0a62892af076d87d9c5..19631e977777fb75becb91e8e2008c1349336481 100644 --- a/wifi/test/wifi_standard/wifi_framework/wifi_manage/wifi_sta/self_cure_service_test.cpp +++ b/wifi/test/wifi_standard/wifi_framework/wifi_manage/wifi_sta/self_cure_service_test.cpp @@ -188,6 +188,14 @@ HWTEST_F(SelfCureServiceTest, NotifyInternetFailureDetectedTest, TestSize.Level1 EXPECT_FALSE(g_errLog.find("service is null") != std::string::npos); } +HWTEST_F(SelfCureServiceTest, NotifyIpv6FailureDetectedTest, TestSize.Level1) +{ + // Test IPv6 failure detection notification + bool result = pSelfCureService->NotifyIpv6FailureDetected(); + EXPECT_EQ(result, true); + EXPECT_FALSE(g_errLog.find("service is null") != std::string::npos); +} + HWTEST_F(SelfCureServiceTest, IsSelfCureOnGoingTest, TestSize.Level1) { EXPECT_EQ(pSelfCureService->IsSelfCureOnGoing(), false); diff --git a/wifi/test/wifi_standard/wifi_framework/wifi_manage/wifi_sta/self_cure_utils_test.cpp b/wifi/test/wifi_standard/wifi_framework/wifi_manage/wifi_sta/self_cure_utils_test.cpp index c6457c3315e6cb11a928fa190732af0988c09b2b..0edc247d44a7c64cca9d38fd04fc2b3380356a23 100644 --- a/wifi/test/wifi_standard/wifi_framework/wifi_manage/wifi_sta/self_cure_utils_test.cpp +++ b/wifi/test/wifi_standard/wifi_framework/wifi_manage/wifi_sta/self_cure_utils_test.cpp @@ -101,5 +101,21 @@ HWTEST_F(SelfCureUtilsTest, ReportNoInternetChrEventTest001, TestSize.Level1) EXPECT_CALL(WifiConfigCenter::GetInstance(), GetWifiSelfcureResetEntered()).WillRepeatedly(Return(0)); SelfCureUtils::GetInstance().ReportNoInternetChrEvent(); } + +HWTEST_F(SelfCureUtilsTest, IsIpv6SelfCureSupportedTest, TestSize.Level1) +{ + // Test IPv6 self-cure support check + EXPECT_TRUE(SelfCureUtils::GetInstance().IsIpv6SelfCureSupported()); +} + +HWTEST_F(SelfCureUtilsTest, DisableIpv6Test, TestSize.Level1) +{ + // Test IPv6 disable functionality + // Note: This test may fail in environments without proper network setup + // but validates the method can be called without crashing + bool result = SelfCureUtils::GetInstance().DisableIpv6(); + // We expect either success or failure, not a crash + EXPECT_TRUE(result == true || result == false); +} } } \ No newline at end of file