From 82778094a739a4c05b3dd322fb2f4a4f241579de Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Thu, 11 Nov 2021 13:32:13 -0800 Subject: [PATCH] [linux]: Implement the optional attributes for WiFi diagnostic cluster (#11616) * [linux]: Implement the optional attributes for WiFi diagnostic cluster * Address the review comments --- examples/platform/linux/Options.h | 2 +- .../wifi_network_diagnostics_server.cpp | 24 ++++ src/include/platform/ConnectivityManager.h | 6 + .../GenericConnectivityManagerImpl_NoWiFi.h | 7 ++ .../GenericConnectivityManagerImpl_WiFi.h | 7 ++ .../Linux/ConnectivityManagerImpl.cpp | 113 ++++++++++++++++-- src/platform/Linux/ConnectivityManagerImpl.h | 4 + 7 files changed, 152 insertions(+), 11 deletions(-) diff --git a/examples/platform/linux/Options.h b/examples/platform/linux/Options.h index e347f0297d53df..2f1ee87627aed0 100644 --- a/examples/platform/linux/Options.h +++ b/examples/platform/linux/Options.h @@ -33,7 +33,7 @@ struct LinuxDeviceOptions { chip::SetupPayload payload; uint32_t mBleDevice = 0; - bool mWiFi = false; + bool mWiFi = true; bool mThread = false; uint32_t securedDevicePort = CHIP_PORT; uint32_t securedCommissionerPort = CHIP_PORT + 2; diff --git a/src/app/clusters/wifi_network_diagnostics_server/wifi_network_diagnostics_server.cpp b/src/app/clusters/wifi_network_diagnostics_server/wifi_network_diagnostics_server.cpp index fa237a5f26489a..4372f621992d6d 100644 --- a/src/app/clusters/wifi_network_diagnostics_server/wifi_network_diagnostics_server.cpp +++ b/src/app/clusters/wifi_network_diagnostics_server/wifi_network_diagnostics_server.cpp @@ -33,6 +33,7 @@ using namespace chip::app::Clusters; using namespace chip::app::Clusters::WiFiNetworkDiagnostics; using namespace chip::app::Clusters::WiFiNetworkDiagnostics::Attributes; using chip::DeviceLayer::ConnectivityManager; +using chip::DeviceLayer::ConnectivityMgr; namespace { @@ -47,6 +48,8 @@ class WiFiDiagosticsAttrAccess : public AttributeAccessInterface private: template CHIP_ERROR ReadIfSupported(CHIP_ERROR (ConnectivityManager::*getter)(T &), AttributeValueEncoder & aEncoder); + + CHIP_ERROR ReadWiFiBssId(AttributeValueEncoder & aEncoder); }; template @@ -67,6 +70,24 @@ CHIP_ERROR WiFiDiagosticsAttrAccess::ReadIfSupported(CHIP_ERROR (ConnectivityMan return aEncoder.Encode(data); } +CHIP_ERROR WiFiDiagosticsAttrAccess::ReadWiFiBssId(AttributeValueEncoder & aEncoder) +{ + // TODO: Use Nullable after we get darwin converted over to the new APIs. + Bssid::TypeInfo::Type bssid; + + if (ConnectivityMgr().GetWiFiBssId(bssid) == CHIP_NO_ERROR) + { + ChipLogProgress(Zcl, "Node is currently connected to Wi-Fi network with BSSID:"); + ChipLogByteSpan(Zcl, bssid); + } + else + { + ChipLogProgress(Zcl, "Node is not currently connected."); + } + + return aEncoder.Encode(bssid); +} + WiFiDiagosticsAttrAccess gAttrAccess; CHIP_ERROR WiFiDiagosticsAttrAccess::Read(const ConcreteAttributePath & aPath, AttributeValueEncoder & aEncoder) @@ -79,6 +100,9 @@ CHIP_ERROR WiFiDiagosticsAttrAccess::Read(const ConcreteAttributePath & aPath, A switch (aPath.mAttributeId) { + case Bssid::Id: { + return ReadWiFiBssId(aEncoder); + } case Attributes::SecurityType::Id: { return ReadIfSupported(&ConnectivityManager::GetWiFiSecurityType, aEncoder); } diff --git a/src/include/platform/ConnectivityManager.h b/src/include/platform/ConnectivityManager.h index 88ce7bd11159d3..1a999ed72054f8 100644 --- a/src/include/platform/ConnectivityManager.h +++ b/src/include/platform/ConnectivityManager.h @@ -248,6 +248,7 @@ class ConnectivityManager CHIP_ERROR ResetEthNetworkDiagnosticsCounts(); // WiFi network diagnostics methods + CHIP_ERROR GetWiFiBssId(ByteSpan & value); CHIP_ERROR GetWiFiSecurityType(uint8_t & securityType); CHIP_ERROR GetWiFiVersion(uint8_t & wiFiVersion); CHIP_ERROR GetWiFiChannelNumber(uint16_t & channelNumber); @@ -520,6 +521,11 @@ inline CHIP_ERROR ConnectivityManager::ResetEthNetworkDiagnosticsCounts() return static_cast(this)->_ResetEthNetworkDiagnosticsCounts(); } +inline CHIP_ERROR ConnectivityManager::GetWiFiBssId(ByteSpan & value) +{ + return static_cast(this)->_GetWiFiBssId(value); +} + inline CHIP_ERROR ConnectivityManager::GetWiFiSecurityType(uint8_t & securityType) { return static_cast(this)->_GetWiFiSecurityType(securityType); diff --git a/src/include/platform/internal/GenericConnectivityManagerImpl_NoWiFi.h b/src/include/platform/internal/GenericConnectivityManagerImpl_NoWiFi.h index 9e583ed6ef552d..9bb5dca21a33a0 100644 --- a/src/include/platform/internal/GenericConnectivityManagerImpl_NoWiFi.h +++ b/src/include/platform/internal/GenericConnectivityManagerImpl_NoWiFi.h @@ -71,6 +71,7 @@ class GenericConnectivityManagerImpl_NoWiFi System::Clock::Timeout _GetWiFiAPIdleTimeout(void); void _SetWiFiAPIdleTimeout(System::Clock::Timeout val); CHIP_ERROR _GetAndLogWifiStatsCounters(void); + CHIP_ERROR _GetWiFiBssId(ByteSpan & value); CHIP_ERROR _GetWiFiSecurityType(uint8_t & securityType); CHIP_ERROR _GetWiFiVersion(uint8_t & wiFiVersion); CHIP_ERROR _GetWiFiChannelNumber(uint16_t & channelNumber); @@ -234,6 +235,12 @@ inline const char * GenericConnectivityManagerImpl_NoWiFi::_WiFiAPSta return NULL; } +template +inline CHIP_ERROR GenericConnectivityManagerImpl_NoWiFi::_GetWiFiBssId(ByteSpan & value) +{ + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + template inline CHIP_ERROR GenericConnectivityManagerImpl_NoWiFi::_GetWiFiSecurityType(uint8_t & securityType) { diff --git a/src/include/platform/internal/GenericConnectivityManagerImpl_WiFi.h b/src/include/platform/internal/GenericConnectivityManagerImpl_WiFi.h index a79e79628ae0c4..74fb0de64259d6 100644 --- a/src/include/platform/internal/GenericConnectivityManagerImpl_WiFi.h +++ b/src/include/platform/internal/GenericConnectivityManagerImpl_WiFi.h @@ -73,6 +73,7 @@ class GenericConnectivityManagerImpl_WiFi System::Clock::Timeout _GetWiFiAPIdleTimeout(); void _SetWiFiAPIdleTimeout(System::Clock::Timeout val); CHIP_ERROR _GetAndLogWifiStatsCounters(); + CHIP_ERROR _GetWiFiBssId(ByteSpan & value); CHIP_ERROR _GetWiFiSecurityType(uint8_t & securityType); CHIP_ERROR _GetWiFiVersion(uint8_t & wiFiVersion); CHIP_ERROR _GetWiFiChannelNumber(uint16_t & channelNumber); @@ -194,6 +195,12 @@ template inline void GenericConnectivityManagerImpl_WiFi::_OnWiFiStationProvisionChange() {} +template +inline CHIP_ERROR GenericConnectivityManagerImpl_WiFi::_GetWiFiBssId(ByteSpan & value) +{ + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; +} + template inline CHIP_ERROR GenericConnectivityManagerImpl_WiFi::_GetWiFiSecurityType(uint8_t & securityType) { diff --git a/src/platform/Linux/ConnectivityManagerImpl.cpp b/src/platform/Linux/ConnectivityManagerImpl.cpp index 2a0da89c490a32..2a822b3d117897 100644 --- a/src/platform/Linux/ConnectivityManagerImpl.cpp +++ b/src/platform/Linux/ConnectivityManagerImpl.cpp @@ -91,8 +91,7 @@ CHIP_ERROR GetEthernetStatsCount(EthernetStatsCountType type, uint64_t & count) { struct ifaddrs * ifa = nullptr; - /* Walk through linked list, maintaining head pointer so we - can free list later */ + // 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) == InterfaceType::EMBER_ZCL_INTERFACE_TYPE_ETHERNET) @@ -156,8 +155,7 @@ CHIP_ERROR GetWiFiStatsCount(WiFiStatsCountType type, uint64_t & count) { struct ifaddrs * ifa = nullptr; - /* Walk through linked list, maintaining head pointer so we - can free list later */ + // 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) == InterfaceType::EMBER_ZCL_INTERFACE_TYPE_WI_FI) @@ -433,6 +431,104 @@ CHIP_ERROR ConnectivityManagerImpl::_SetWiFiAPMode(WiFiAPMode val) return err; } +CHIP_ERROR ConnectivityManagerImpl::_GetWiFiBssId(ByteSpan & value) +{ + CHIP_ERROR err = CHIP_ERROR_READ_FAILED; + struct ifaddrs * ifaddr = nullptr; + + // On Linux simulation, we don't have the DBus API to get the BSSID of connected AP. Use mac address + // of local WiFi network card instead. + if (getifaddrs(&ifaddr) == -1) + { + ChipLogError(DeviceLayer, "Failed to get network interfaces"); + } + else + { + // Walk through linked list, maintaining head pointer so we can free list later. + for (struct ifaddrs * ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) + { + if (ConnectivityUtils::GetInterfaceConnectionType(ifa->ifa_name) == InterfaceType::EMBER_ZCL_INTERFACE_TYPE_WI_FI) + { + if (ConnectivityUtils::GetInterfaceHardwareAddrs(ifa->ifa_name, mWiFiMacAddress, kMaxHardwareAddrSize) != + CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Failed to get WiFi network hardware address"); + } + else + { + // Set 48-bit IEEE MAC Address + value = ByteSpan(mWiFiMacAddress, 6); + err = CHIP_NO_ERROR; + break; + } + } + } + + freeifaddrs(ifaddr); + } + + return err; +} + +CHIP_ERROR ConnectivityManagerImpl::_GetWiFiSecurityType(uint8_t & securityType) +{ + const gchar * mode = nullptr; + + std::lock_guard lock(mWpaSupplicantMutex); + + if (mWpaSupplicant.state != GDBusWpaSupplicant::WPA_INTERFACE_CONNECTED) + { + ChipLogError(DeviceLayer, "wpa_supplicant: _GetWiFiSecurityType: interface proxy not connected"); + return CHIP_ERROR_INCORRECT_STATE; + } + + mode = wpa_fi_w1_wpa_supplicant1_interface_get_current_auth_mode(mWpaSupplicant.iface); + ChipLogProgress(DeviceLayer, "wpa_supplicant: current Wi-Fi security type: %s", mode); + + if (strncmp(mode, "WPA-PSK", 7) == 0) + { + securityType = EMBER_ZCL_SECURITY_TYPE_WPA; + } + else if (strncmp(mode, "WPA2-PSK", 8) == 0) + { + securityType = EMBER_ZCL_SECURITY_TYPE_WPA2; + } + else if (strncmp(mode, "WPA2-EAP", 8) == 0) + { + securityType = EMBER_ZCL_SECURITY_TYPE_WPA2; + } + else if (strncmp(mode, "WPA3-PSK", 8) == 0) + { + securityType = EMBER_ZCL_SECURITY_TYPE_WPA3; + } + else if (strncmp(mode, "WEP", 3) == 0) + { + securityType = EMBER_ZCL_SECURITY_TYPE_WEP; + } + else if (strncmp(mode, "NONE", 4) == 0) + { + securityType = EMBER_ZCL_SECURITY_TYPE_NONE; + } + else if (strncmp(mode, "WPA-NONE", 8) == 0) + { + securityType = EMBER_ZCL_SECURITY_TYPE_NONE; + } + else + { + securityType = EMBER_ZCL_SECURITY_TYPE_UNSPECIFIED; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR ConnectivityManagerImpl::_GetWiFiVersion(uint8_t & wiFiVersion) +{ + // We don't have driect API to get the WiFi version yet, retrun 802.11n on Linux simulation. + wiFiVersion = EMBER_ZCL_WI_FI_VERSION_TYPE_802__11N; + + return CHIP_NO_ERROR; +} + void ConnectivityManagerImpl::_DemandStartWiFiAP() { if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision) @@ -1105,8 +1201,7 @@ CHIP_ERROR ConnectivityManagerImpl::_GetNetworkInterfaces(NetworkInterface ** ne { NetworkInterface * head = nullptr; - /* Walk through linked list, maintaining head pointer so we - can free list later */ + // Walk through linked list, maintaining head pointer so we can free list later. for (struct ifaddrs * ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) { if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_PACKET) @@ -1250,8 +1345,7 @@ CHIP_ERROR ConnectivityManagerImpl::ResetEthernetStatsCount() { struct ifaddrs * ifa = nullptr; - /* Walk through linked list, maintaining head pointer so we - can free list later */ + // 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) == InterfaceType::EMBER_ZCL_INTERFACE_TYPE_ETHERNET) @@ -1421,8 +1515,7 @@ CHIP_ERROR ConnectivityManagerImpl::ResetWiFiStatsCount() { struct ifaddrs * ifa = nullptr; - /* Walk through linked list, maintaining head pointer so we - can free list later */ + // 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) == InterfaceType::EMBER_ZCL_INTERFACE_TYPE_WI_FI) diff --git a/src/platform/Linux/ConnectivityManagerImpl.h b/src/platform/Linux/ConnectivityManagerImpl.h index 8f7706b425a7e9..2f26ece65ff5bd 100644 --- a/src/platform/Linux/ConnectivityManagerImpl.h +++ b/src/platform/Linux/ConnectivityManagerImpl.h @@ -136,6 +136,9 @@ class ConnectivityManagerImpl final : public ConnectivityManager, WiFiAPMode _GetWiFiAPMode(); CHIP_ERROR _SetWiFiAPMode(WiFiAPMode val); + CHIP_ERROR _GetWiFiBssId(ByteSpan & value); + CHIP_ERROR _GetWiFiSecurityType(uint8_t & securityType); + CHIP_ERROR _GetWiFiVersion(uint8_t & wiFiVersion); bool _IsWiFiAPActive(); bool _IsWiFiAPApplicationControlled(); void _DemandStartWiFiAP(); @@ -220,6 +223,7 @@ class ConnectivityManagerImpl final : public ConnectivityManager, System::Clock::Timestamp mLastAPDemandTime; System::Clock::Timeout mWiFiStationReconnectInterval; System::Clock::Timeout mWiFiAPIdleTimeout; + uint8_t mWiFiMacAddress[kMaxHardwareAddrSize]; #endif #if CHIP_DEVICE_CONFIG_ENABLE_WIFI