From 3d70836cb9b4d4770b08e6f77a9aaa2cfd58e828 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Fri, 1 Oct 2021 15:58:27 -0700 Subject: [PATCH] Implement the ResetEthNetworkDiagnosticsCounts method in ConnectivityManager (#10122) * Implement the ResetEthNetworkDiagnosticsCounts method for the zcl command * Address the review comments --- .../ethernet_network_diagnostics_server.cpp | 7 +- src/include/platform/ConnectivityManager.h | 6 ++ .../internal/GenericConnectivityManagerImpl.h | 7 ++ .../Linux/ConnectivityManagerImpl.cpp | 100 +++++++++++++++++- src/platform/Linux/ConnectivityManagerImpl.h | 9 ++ src/platform/Linux/ConnectivityUtils.cpp | 19 ++-- 6 files changed, 134 insertions(+), 14 deletions(-) diff --git a/src/app/clusters/ethernet_network_diagnostics_server/ethernet_network_diagnostics_server.cpp b/src/app/clusters/ethernet_network_diagnostics_server/ethernet_network_diagnostics_server.cpp index 5c258eacb8a2f8..8b943526779bdc 100644 --- a/src/app/clusters/ethernet_network_diagnostics_server/ethernet_network_diagnostics_server.cpp +++ b/src/app/clusters/ethernet_network_diagnostics_server/ethernet_network_diagnostics_server.cpp @@ -102,7 +102,12 @@ CHIP_ERROR EthernetDiagosticsAttrAccess::ReadIfSupported(CHIP_ERROR (Connectivit bool emberAfEthernetNetworkDiagnosticsClusterResetCountsCallback(EndpointId endpoint, app::CommandHandler * commandObj) { - EmberAfStatus status = EthernetNetworkDiagnostics::Attributes::PacketRxCount::Set(endpoint, 0); + EmberAfStatus status = EMBER_ZCL_STATUS_SUCCESS; + + VerifyOrExit(DeviceLayer::ConnectivityMgr().ResetEthNetworkDiagnosticsCounts() == CHIP_NO_ERROR, + status = EMBER_ZCL_STATUS_FAILURE); + + status = EthernetNetworkDiagnostics::Attributes::PacketRxCount::Set(endpoint, 0); VerifyOrExit(status == EMBER_ZCL_STATUS_SUCCESS, ChipLogError(Zcl, "Failed to reset PacketRxCount attribute")); status = EthernetNetworkDiagnostics::Attributes::PacketTxCount::Set(endpoint, 0); diff --git a/src/include/platform/ConnectivityManager.h b/src/include/platform/ConnectivityManager.h index 49bae75c692f1d..85cb27091f89a6 100644 --- a/src/include/platform/ConnectivityManager.h +++ b/src/include/platform/ConnectivityManager.h @@ -173,6 +173,7 @@ class ConnectivityManager CHIP_ERROR GetEthTxErrCount(uint64_t & txErrCount); CHIP_ERROR GetEthCollisionCount(uint64_t & collisionCount); CHIP_ERROR GetEthOverrunCount(uint64_t & overrunCount); + CHIP_ERROR ResetEthNetworkDiagnosticsCounts(); // WiFi network diagnostics methods CHIP_ERROR GetWiFiSecurityType(uint8_t & securityType); @@ -410,6 +411,11 @@ inline CHIP_ERROR ConnectivityManager::GetEthOverrunCount(uint64_t & overrunCoun return static_cast(this)->_GetEthOverrunCount(overrunCount); } +inline CHIP_ERROR ConnectivityManager::ResetEthNetworkDiagnosticsCounts() +{ + return static_cast(this)->_ResetEthNetworkDiagnosticsCounts(); +} + inline CHIP_ERROR ConnectivityManager::GetWiFiSecurityType(uint8_t & securityType) { return static_cast(this)->_GetWiFiSecurityType(securityType); diff --git a/src/include/platform/internal/GenericConnectivityManagerImpl.h b/src/include/platform/internal/GenericConnectivityManagerImpl.h index 044d83857eb2e6..0639d48b2d1c00 100644 --- a/src/include/platform/internal/GenericConnectivityManagerImpl.h +++ b/src/include/platform/internal/GenericConnectivityManagerImpl.h @@ -52,6 +52,7 @@ class GenericConnectivityManagerImpl CHIP_ERROR _GetEthTxErrCount(uint64_t & txErrCount); CHIP_ERROR _GetEthCollisionCount(uint64_t & collisionCount); CHIP_ERROR _GetEthOverrunCount(uint64_t & overrunCount); + CHIP_ERROR _ResetEthNetworkDiagnosticsCounts(); private: ImplClass * Impl() { return static_cast(this); } @@ -107,6 +108,12 @@ inline CHIP_ERROR GenericConnectivityManagerImpl::_GetEthOverrunCount return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; } +template +inline CHIP_ERROR GenericConnectivityManagerImpl::_ResetEthNetworkDiagnosticsCounts() +{ + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + } // namespace Internal } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/Linux/ConnectivityManagerImpl.cpp b/src/platform/Linux/ConnectivityManagerImpl.cpp index d182090ea7c699..2495f1cfeffe14 100644 --- a/src/platform/Linux/ConnectivityManagerImpl.cpp +++ b/src/platform/Linux/ConnectivityManagerImpl.cpp @@ -223,6 +223,11 @@ CHIP_ERROR ConnectivityManagerImpl::_Init() mWiFiStationMode = kWiFiStationMode_Disabled; mWiFiStationReconnectIntervalMS = CHIP_DEVICE_CONFIG_WIFI_STATION_RECONNECT_INTERVAL; + if (ResetEthernetStatsCount() != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Failed to reset Ethernet statistic counts"); + } + // Initialize the generic base classes that require it. #if CHIP_DEVICE_CONFIG_ENABLE_THREAD GenericConnectivityManagerImpl_Thread::_Init(); @@ -1012,27 +1017,112 @@ CHIP_ERROR ConnectivityManagerImpl::ProvisionWiFiNetwork(const char * ssid, cons CHIP_ERROR ConnectivityManagerImpl::_GetEthPacketRxCount(uint64_t & packetRxCount) { - return GetEthernetStatsCount(EthernetStatsCountType::kEthPacketRxCount, packetRxCount); + uint64_t count; + + ReturnErrorOnFailure(GetEthernetStatsCount(EthernetStatsCountType::kEthPacketRxCount, count)); + VerifyOrReturnError(count >= mEthPacketRxCount, CHIP_ERROR_INVALID_INTEGER_VALUE); + + packetRxCount = count - mEthPacketRxCount; + + return CHIP_NO_ERROR; } CHIP_ERROR ConnectivityManagerImpl::_GetEthPacketTxCount(uint64_t & packetTxCount) { - return GetEthernetStatsCount(EthernetStatsCountType::kEthPacketTxCount, packetTxCount); + uint64_t count; + + ReturnErrorOnFailure(GetEthernetStatsCount(EthernetStatsCountType::kEthPacketTxCount, count)); + VerifyOrReturnError(count >= mEthPacketTxCount, CHIP_ERROR_INVALID_INTEGER_VALUE); + + packetTxCount = count - mEthPacketTxCount; + + return CHIP_NO_ERROR; } CHIP_ERROR ConnectivityManagerImpl::_GetEthTxErrCount(uint64_t & txErrCount) { - return GetEthernetStatsCount(EthernetStatsCountType::kEthTxErrCount, txErrCount); + uint64_t count; + + ReturnErrorOnFailure(GetEthernetStatsCount(EthernetStatsCountType::kEthTxErrCount, count)); + VerifyOrReturnError(count >= mEthTxErrCount, CHIP_ERROR_INVALID_INTEGER_VALUE); + + txErrCount = count - mEthTxErrCount; + + return CHIP_NO_ERROR; } CHIP_ERROR ConnectivityManagerImpl::_GetEthCollisionCount(uint64_t & collisionCount) { - return GetEthernetStatsCount(EthernetStatsCountType::kEthCollisionCount, collisionCount); + uint64_t count; + + ReturnErrorOnFailure(GetEthernetStatsCount(EthernetStatsCountType::kEthCollisionCount, count)); + VerifyOrReturnError(count >= mEthCollisionCount, CHIP_ERROR_INVALID_INTEGER_VALUE); + + collisionCount = count - mEthCollisionCount; + + return CHIP_NO_ERROR; } CHIP_ERROR ConnectivityManagerImpl::_GetEthOverrunCount(uint64_t & overrunCount) { - return GetEthernetStatsCount(EthernetStatsCountType::kEthOverrunCount, overrunCount); + uint64_t count; + + ReturnErrorOnFailure(GetEthernetStatsCount(EthernetStatsCountType::kEthOverrunCount, count)); + VerifyOrReturnError(count >= mEthOverrunCount, CHIP_ERROR_INVALID_INTEGER_VALUE); + + overrunCount = count - mEthOverrunCount; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR ConnectivityManagerImpl::_ResetEthNetworkDiagnosticsCounts() +{ + return ResetEthernetStatsCount(); +} + +CHIP_ERROR ConnectivityManagerImpl::ResetEthernetStatsCount() +{ + CHIP_ERROR ret = CHIP_ERROR_READ_FAILED; + struct ifaddrs * ifaddr = nullptr; + + if (getifaddrs(&ifaddr) == -1) + { + ChipLogError(DeviceLayer, "Failed to get network interfaces"); + } + else + { + struct ifaddrs * ifa = nullptr; + + /* Walk through linked list, maintaining head pointer so we + can free list later */ + for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) + { + if (ConnectivityUtils::GetInterfaceConnectionType(ifa->ifa_name) == ConnectionType::kConnectionEthernet) + { + ChipLogProgress(DeviceLayer, "Found the primary Ethernet interface:%s", ifa->ifa_name); + break; + } + } + + if (ifa != nullptr) + { + if (ifa->ifa_addr->sa_family == AF_PACKET && ifa->ifa_data != nullptr) + { + struct rtnl_link_stats * stats = (struct rtnl_link_stats *) ifa->ifa_data; + + mEthPacketRxCount = stats->rx_packets; + mEthPacketTxCount = stats->tx_packets; + mEthTxErrCount = stats->tx_errors; + mEthCollisionCount = stats->collisions; + mEthOverrunCount = stats->rx_over_errors; + ret = CHIP_NO_ERROR; + } + } + + freeifaddrs(ifaddr); + } + + return ret; } #if CHIP_DEVICE_CONFIG_ENABLE_WIFI diff --git a/src/platform/Linux/ConnectivityManagerImpl.h b/src/platform/Linux/ConnectivityManagerImpl.h index 0081d07f1fcb85..406cc26c89c1d2 100644 --- a/src/platform/Linux/ConnectivityManagerImpl.h +++ b/src/platform/Linux/ConnectivityManagerImpl.h @@ -155,6 +155,7 @@ class ConnectivityManagerImpl final : public ConnectivityManager, CHIP_ERROR _GetEthTxErrCount(uint64_t & txErrCount); CHIP_ERROR _GetEthCollisionCount(uint64_t & collisionCount); CHIP_ERROR _GetEthOverrunCount(uint64_t & overrunCount); + CHIP_ERROR _ResetEthNetworkDiagnosticsCounts(); #if CHIP_DEVICE_CONFIG_ENABLE_WIFI CHIP_ERROR _GetWiFiChannelNumber(uint16_t & channelNumber); @@ -171,6 +172,8 @@ class ConnectivityManagerImpl final : public ConnectivityManager, // ==================== ConnectivityManager Private Methods ==================== + CHIP_ERROR ResetEthernetStatsCount(); + #if CHIP_DEVICE_CONFIG_ENABLE_WPA void DriveAPState(); CHIP_ERROR ConfigureWiFiAP(); @@ -187,6 +190,12 @@ class ConnectivityManagerImpl final : public ConnectivityManager, // ===== Private members reserved for use by this class only. + uint64_t mEthPacketRxCount = 0; + uint64_t mEthPacketTxCount = 0; + uint64_t mEthTxErrCount = 0; + uint64_t mEthCollisionCount = 0; + uint64_t mEthOverrunCount = 0; + #if CHIP_DEVICE_CONFIG_ENABLE_WPA ConnectivityManager::WiFiStationMode mWiFiStationMode; ConnectivityManager::WiFiAPMode mWiFiAPMode; diff --git a/src/platform/Linux/ConnectivityUtils.cpp b/src/platform/Linux/ConnectivityUtils.cpp index 118ad90907bc4e..dba135bbac5c5c 100644 --- a/src/platform/Linux/ConnectivityUtils.cpp +++ b/src/platform/Linux/ConnectivityUtils.cpp @@ -257,14 +257,17 @@ ConnectionType ConnectivityUtils::GetInterfaceConnectionType(const char * ifname return ConnectionType::kConnectionWiFi; // Test ethtool for CONNECTION_ETHERNET - struct ethtool_cmd ecmd = {}; - ecmd.cmd = ETHTOOL_GSET; - struct ifreq ifr = {}; - ifr.ifr_data = reinterpret_cast(&ecmd); - strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); - - if (ioctl(sock, SIOCETHTOOL, &ifr) != -1) - return ConnectionType::kConnectionEthernet; + if ((strncmp(ifname, "en", 2) == 0) || (strncmp(ifname, "eth", 3) == 0)) + { + struct ethtool_cmd ecmd = {}; + ecmd.cmd = ETHTOOL_GSET; + struct ifreq ifr = {}; + ifr.ifr_data = reinterpret_cast(&ecmd); + strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); + + if (ioctl(sock, SIOCETHTOOL, &ifr) != -1) + return ConnectionType::kConnectionEthernet; + } return ConnectionType::kConnectionUnknown; }