Skip to content

Commit

Permalink
[nrfconnect] Implemented WiFiNetworkDiagnostics events generation
Browse files Browse the repository at this point in the history
* Added generation of optional events from WiFiNetworkDiagnostics
cluster.
* Improved handler methods to validate the input data size
  • Loading branch information
kkasperczyk-no committed Apr 16, 2024
1 parent 3c7c9b1 commit 5b788dc
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 11 deletions.
109 changes: 103 additions & 6 deletions src/platform/nrfconnect/wifi/WiFiManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <crypto/RandUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/CHIPDeviceLayer.h>
#include <platform/DiagnosticDataProvider.h>
#include <platform/Zephyr/InetUtils.h>

#include <zephyr/kernel.h>
Expand Down Expand Up @@ -151,7 +152,7 @@ void WiFiManager::WifiMgmtEventHandler(net_mgmt_event_callback * cb, uint32_t mg
Platform::UniquePtr<uint8_t> eventData(new uint8_t[cb->info_length]);
VerifyOrReturn(eventData);
memcpy(eventData.get(), cb->info, cb->info_length);
sEventHandlerMap[mgmtEvent](std::move(eventData));
sEventHandlerMap[mgmtEvent](std::move(eventData), cb->info_length);
}
}

Expand Down Expand Up @@ -292,8 +293,11 @@ CHIP_ERROR WiFiManager::GetNetworkStatistics(NetworkStatistics & stats) const
return CHIP_NO_ERROR;
}

void WiFiManager::ScanResultHandler(Platform::UniquePtr<uint8_t> data)
void WiFiManager::ScanResultHandler(Platform::UniquePtr<uint8_t> data, size_t length)
{
// Validate that input data size matches the expected one.
VerifyOrReturn(length == sizeof(wifi_scan_result));

// Contrary to other handlers, offload accumulating of the scan results from the CHIP thread to the caller's thread
const wifi_scan_result * scanResult = reinterpret_cast<const wifi_scan_result *>(data.get());

Expand Down Expand Up @@ -337,8 +341,11 @@ void WiFiManager::ScanResultHandler(Platform::UniquePtr<uint8_t> data)
}
}

void WiFiManager::ScanDoneHandler(Platform::UniquePtr<uint8_t> data)
void WiFiManager::ScanDoneHandler(Platform::UniquePtr<uint8_t> data, size_t length)
{
// Validate that input data size matches the expected one.
VerifyOrReturn(length == sizeof(wifi_status));

CHIP_ERROR err = SystemLayer().ScheduleLambda([capturedData = data.get()] {
Platform::UniquePtr<uint8_t> safePtr(capturedData);
uint8_t * rawData = safePtr.get();
Expand Down Expand Up @@ -416,8 +423,13 @@ void WiFiManager::SendRouterSolicitation(System::Layer * layer, void * param)
}
}

void WiFiManager::ConnectHandler(Platform::UniquePtr<uint8_t> data)
void WiFiManager::ConnectHandler(Platform::UniquePtr<uint8_t> data, size_t length)
{
using app::Clusters::WiFiNetworkDiagnostics::AssociationFailureCauseEnum;

// Validate that input data size matches the expected one.
VerifyOrReturn(length == sizeof(wifi_status));

CHIP_ERROR err = SystemLayer().ScheduleLambda([capturedData = data.get()] {
Platform::UniquePtr<uint8_t> safePtr(capturedData);
uint8_t * rawData = safePtr.get();
Expand All @@ -432,6 +444,32 @@ void WiFiManager::ConnectHandler(Platform::UniquePtr<uint8_t> data)
{
Instance().mHandling.mOnConnectionDone(connStatus);
}

WiFiDiagnosticsDelegate * delegate = GetDiagnosticDataProvider().GetWiFiDiagnosticsDelegate();
if (delegate)
{
uint16_t reason = Instance().GetLastDisconnectReason();
uint8_t associationFailureCause;

switch (connStatus)
{
case WIFI_STATUS_CONN_WRONG_PASSWORD:
associationFailureCause = to_underlying(AssociationFailureCauseEnum::kAuthenticationFailed);
break;
case WIFI_STATUS_CONN_FAIL:
case WIFI_STATUS_CONN_TIMEOUT:
associationFailureCause = to_underlying(AssociationFailureCauseEnum::kAssociationFailed);
break;
case WIFI_STATUS_CONN_AP_NOT_FOUND:
associationFailureCause = to_underlying(AssociationFailureCauseEnum::kSsidNotFound);
break;
default:
associationFailureCause = to_underlying(AssociationFailureCauseEnum::kUnknown);
break;
}

delegate->OnAssociationFailureDetected(associationFailureCause, reason);
}
}
else // The connection has been established successfully.
{
Expand All @@ -457,6 +495,13 @@ void WiFiManager::ConnectHandler(Platform::UniquePtr<uint8_t> data)
{
ChipLogError(DeviceLayer, "Cannot post event [error: %s]", ErrorStr(error));
}

WiFiDiagnosticsDelegate * delegate = GetDiagnosticDataProvider().GetWiFiDiagnosticsDelegate();
if (delegate)
{
delegate->OnConnectionStatusChanged(
to_underlying(app::Clusters::WiFiNetworkDiagnostics::ConnectionStatusEnum::kConnected));
}
}
// cleanup the provisioning data as it is configured per each connect request
Instance().ClearStationProvisioningData();
Expand All @@ -469,13 +514,55 @@ void WiFiManager::ConnectHandler(Platform::UniquePtr<uint8_t> data)
}
}

void WiFiManager::DisconnectHandler(Platform::UniquePtr<uint8_t>)
void WiFiManager::DisconnectHandler(Platform::UniquePtr<uint8_t> data, size_t length)
{
SystemLayer().ScheduleLambda([] {
// Validate that input data size matches the expected one.
VerifyOrReturn(length == sizeof(wifi_status));

CHIP_ERROR err = SystemLayer().ScheduleLambda([capturedData = data.get()] {
Platform::UniquePtr<uint8_t> safePtr(capturedData);
uint8_t * rawData = safePtr.get();
const wifi_status * status = reinterpret_cast<const wifi_status *>(rawData);
uint16_t reason;

switch (status->disconn_reason)
{
case WIFI_REASON_DISCONN_UNSPECIFIED:
reason = WLAN_REASON_UNSPECIFIED;
break;
case WIFI_REASON_DISCONN_USER_REQUEST:
reason = WLAN_REASON_DEAUTH_LEAVING;
break;
case WIFI_REASON_DISCONN_AP_LEAVING:
reason = WLAN_REASON_DEAUTH_LEAVING;
break;
case WIFI_REASON_DISCONN_INACTIVITY:
reason = WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY;
break;
default:
reason = WLAN_REASON_UNSPECIFIED;
break;
}
Instance().SetLastDisconnectReason(reason);

ChipLogProgress(DeviceLayer, "WiFi station disconnected");
Instance().mWiFiState = WIFI_STATE_DISCONNECTED;
Instance().PostConnectivityStatusChange(kConnectivity_Lost);

WiFiDiagnosticsDelegate * delegate = GetDiagnosticDataProvider().GetWiFiDiagnosticsDelegate();
if (delegate)
{
delegate->OnConnectionStatusChanged(
to_underlying(app::Clusters::WiFiNetworkDiagnostics::ConnectionStatusEnum::kNotConnected));
delegate->OnDisconnectionDetected(reason);
}
});

if (CHIP_NO_ERROR == err)
{
// the ownership has been transferred to the worker thread - release the buffer
data.release();
}
}

void WiFiManager::IPv6AddressChangeHandler(const void * data)
Expand Down Expand Up @@ -586,5 +673,15 @@ CHIP_ERROR WiFiManager::SetLowPowerMode(bool onoff)
return CHIP_NO_ERROR;
}

void WiFiManager::SetLastDisconnectReason(uint16_t reason)
{
mLastDisconnectedReason = reason;
}

uint16_t WiFiManager::GetLastDisconnectReason()
{
return mLastDisconnectedReason;
}

} // namespace DeviceLayer
} // namespace chip
13 changes: 8 additions & 5 deletions src/platform/nrfconnect/wifi/WiFiManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,11 @@ class WiFiManager
CHIP_ERROR GetNetworkStatistics(NetworkStatistics & stats) const;
void AbortConnectionRecovery();
CHIP_ERROR SetLowPowerMode(bool onoff);
void SetLastDisconnectReason(uint16_t reason);
uint16_t GetLastDisconnectReason();

private:
using NetEventHandler = void (*)(Platform::UniquePtr<uint8_t>);
using NetEventHandler = void (*)(Platform::UniquePtr<uint8_t>, size_t);

struct ConnectionParams
{
Expand All @@ -197,10 +199,10 @@ class WiFiManager
// Event handling
static void WifiMgmtEventHandler(net_mgmt_event_callback * cb, uint32_t mgmtEvent, net_if * iface);
static void IPv6MgmtEventHandler(net_mgmt_event_callback * cb, uint32_t mgmtEvent, net_if * iface);
static void ScanResultHandler(Platform::UniquePtr<uint8_t> data);
static void ScanDoneHandler(Platform::UniquePtr<uint8_t> data);
static void ConnectHandler(Platform::UniquePtr<uint8_t> data);
static void DisconnectHandler(Platform::UniquePtr<uint8_t> data);
static void ScanResultHandler(Platform::UniquePtr<uint8_t> data, size_t length);
static void ScanDoneHandler(Platform::UniquePtr<uint8_t> data, size_t length);
static void ConnectHandler(Platform::UniquePtr<uint8_t> data, size_t length);
static void DisconnectHandler(Platform::UniquePtr<uint8_t> data, size_t length);
static void PostConnectivityStatusChange(ConnectivityChange changeType);
static void SendRouterSolicitation(System::Layer * layer, void * param);
static void IPv6AddressChangeHandler(const void * data);
Expand Down Expand Up @@ -234,6 +236,7 @@ class WiFiManager
uint32_t mConnectionRecoveryCounter{ 0 };
uint32_t mConnectionRecoveryTimeMs{ kConnectionRecoveryMinIntervalMs };
bool mApplicationDisconnectRequested{ false };
uint16_t mLastDisconnectedReason = WLAN_REASON_UNSPECIFIED;

static const Map<wifi_iface_state, StationStatus, 10> sStatusMap;
static const Map<uint32_t, NetEventHandler, 5> sEventHandlerMap;
Expand Down

0 comments on commit 5b788dc

Please sign in to comment.