Skip to content

Commit

Permalink
[linux]: Implement the optional attributes for WiFi diagnostic cluster (
Browse files Browse the repository at this point in the history
#11616)

* [linux]: Implement the optional attributes for WiFi diagnostic cluster

* Address the review comments
  • Loading branch information
yufengwangca authored and pull[bot] committed Aug 29, 2023
1 parent b06c52e commit 1446818
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 11 deletions.
2 changes: 1 addition & 1 deletion examples/platform/linux/Options.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -47,6 +48,8 @@ class WiFiDiagosticsAttrAccess : public AttributeAccessInterface
private:
template <typename T>
CHIP_ERROR ReadIfSupported(CHIP_ERROR (ConnectivityManager::*getter)(T &), AttributeValueEncoder & aEncoder);

CHIP_ERROR ReadWiFiBssId(AttributeValueEncoder & aEncoder);
};

template <typename T>
Expand All @@ -67,6 +70,24 @@ CHIP_ERROR WiFiDiagosticsAttrAccess::ReadIfSupported(CHIP_ERROR (ConnectivityMan
return aEncoder.Encode(data);
}

CHIP_ERROR WiFiDiagosticsAttrAccess::ReadWiFiBssId(AttributeValueEncoder & aEncoder)
{
// TODO: Use Nullable<ByteSpan> 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)
Expand All @@ -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);
}
Expand Down
6 changes: 6 additions & 0 deletions src/include/platform/ConnectivityManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -520,6 +521,11 @@ inline CHIP_ERROR ConnectivityManager::ResetEthNetworkDiagnosticsCounts()
return static_cast<ImplClass *>(this)->_ResetEthNetworkDiagnosticsCounts();
}

inline CHIP_ERROR ConnectivityManager::GetWiFiBssId(ByteSpan & value)
{
return static_cast<ImplClass *>(this)->_GetWiFiBssId(value);
}

inline CHIP_ERROR ConnectivityManager::GetWiFiSecurityType(uint8_t & securityType)
{
return static_cast<ImplClass *>(this)->_GetWiFiSecurityType(securityType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -234,6 +235,12 @@ inline const char * GenericConnectivityManagerImpl_NoWiFi<ImplClass>::_WiFiAPSta
return NULL;
}

template <class ImplClass>
inline CHIP_ERROR GenericConnectivityManagerImpl_NoWiFi<ImplClass>::_GetWiFiBssId(ByteSpan & value)
{
return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
}

template <class ImplClass>
inline CHIP_ERROR GenericConnectivityManagerImpl_NoWiFi<ImplClass>::_GetWiFiSecurityType(uint8_t & securityType)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -194,6 +195,12 @@ template <class ImplClass>
inline void GenericConnectivityManagerImpl_WiFi<ImplClass>::_OnWiFiStationProvisionChange()
{}

template <class ImplClass>
inline CHIP_ERROR GenericConnectivityManagerImpl_WiFi<ImplClass>::_GetWiFiBssId(ByteSpan & value)
{
return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
}

template <class ImplClass>
inline CHIP_ERROR GenericConnectivityManagerImpl_WiFi<ImplClass>::_GetWiFiSecurityType(uint8_t & securityType)
{
Expand Down
113 changes: 103 additions & 10 deletions src/platform/Linux/ConnectivityManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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<std::mutex> 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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 4 additions & 0 deletions src/platform/Linux/ConnectivityManagerImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 1446818

Please sign in to comment.