From 720c834b82f63301f0aa6081f86e84a181a5ed64 Mon Sep 17 00:00:00 2001 From: cdj <45139296+DejinChen@users.noreply.github.com> Date: Thu, 27 Jun 2024 20:27:56 +0800 Subject: [PATCH] OpenThread: added Thread interface enabled support (#33860) * OpenThread: added Thread interface enabled support * Added Thread autostart configuration and check for Thread interface * Update comments for RevertConfiguration * Fix CI * Fix CI --- src/include/platform/CHIPDeviceConfig.h | 9 ++++ ...enericNetworkCommissioningThreadDriver.cpp | 54 +++++++++++++++++++ .../GenericNetworkCommissioningThreadDriver.h | 4 ++ ...nericThreadStackManagerImpl_OpenThread.hpp | 2 + 4 files changed, 69 insertions(+) diff --git a/src/include/platform/CHIPDeviceConfig.h b/src/include/platform/CHIPDeviceConfig.h index 785b47656dd5a3..49a94d75c23fcc 100644 --- a/src/include/platform/CHIPDeviceConfig.h +++ b/src/include/platform/CHIPDeviceConfig.h @@ -1101,6 +1101,15 @@ static_assert(CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MIN <= CHIP_DEVICE #define CHIP_DEVICE_CONFIG_ENABLE_THREAD_DNS_CLIENT 0 #endif +/** + * CHIP_DEVICE_CONFIG_ENABLE_THREAD_AUTOSTART + * + * Enable starting provisioned Thread network automatically after device power-up. + */ +#ifndef CHIP_DEVICE_CONFIG_ENABLE_THREAD_AUTOSTART +#define CHIP_DEVICE_CONFIG_ENABLE_THREAD_AUTOSTART 1 +#endif + // -------------------- Network Telemetry Configuration -------------------- /** diff --git a/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp b/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp index 0a961a9f8e4afa..711ad4930f96d4 100644 --- a/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp +++ b/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp @@ -54,6 +54,8 @@ CHIP_ERROR GenericThreadDriver::Init(Internal::BaseDriver::NetworkStatusChangeCa // must be restored on the boot. If there's no backup, the below function is a no-op. RevertConfiguration(); + CheckInterfaceEnabled(); + return CHIP_NO_ERROR; } @@ -95,6 +97,16 @@ CHIP_ERROR GenericThreadDriver::RevertConfiguration() // since the fail-safe was armed, so return with no error. ReturnErrorCodeIf(error == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND, CHIP_NO_ERROR); + if (!GetEnabled()) + { + // When reverting configuration, set InterfaceEnabled to default value (true). + // From the spec: + // If InterfaceEnabled is written to false on the same interface as that which is used to write the value, the Administrator + // could await the recovery of network configuration to prior safe values, before being able to communicate with the + // node again. + ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Delete(kInterfaceEnabled)); + } + ChipLogProgress(NetworkProvisioning, "Reverting Thread operational dataset"); if (error == CHIP_NO_ERROR) @@ -166,6 +178,12 @@ void GenericThreadDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * c { NetworkCommissioning::Status status = MatchesNetworkId(mStagingNetwork, networkId); + if (!GetEnabled()) + { + // Set InterfaceEnabled to default value (true). + ReturnOnFailure(PersistedStorage::KeyValueStoreMgr().Delete(kInterfaceEnabled)); + } + if (status == Status::kSuccess && BackupConfiguration() != CHIP_NO_ERROR) { status = Status::kUnknownError; @@ -183,6 +201,30 @@ void GenericThreadDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * c } } +CHIP_ERROR GenericThreadDriver::SetEnabled(bool enabled) +{ + if (enabled == GetEnabled()) + { + return CHIP_NO_ERROR; + } + + ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kInterfaceEnabled, &enabled, sizeof(enabled))); + + if ((!enabled && ThreadStackMgrImpl().IsThreadEnabled()) || (enabled && ThreadStackMgrImpl().IsThreadProvisioned())) + { + ReturnErrorOnFailure(ThreadStackMgrImpl().SetThreadEnabled(enabled)); + } + return CHIP_NO_ERROR; +} + +bool GenericThreadDriver::GetEnabled() +{ + bool value; + // InterfaceEnabled default value is true. + VerifyOrReturnValue(PersistedStorage::KeyValueStoreMgr().Get(kInterfaceEnabled, &value, sizeof(value)) == CHIP_NO_ERROR, true); + return value; +} + void GenericThreadDriver::ScanNetworks(ThreadDriver::ScanCallback * callback) { if (DeviceLayer::ThreadStackMgrImpl().StartThreadScan(callback) != CHIP_NO_ERROR) @@ -223,6 +265,18 @@ CHIP_ERROR GenericThreadDriver::BackupConfiguration() return KeyValueStoreMgr().Put(DefaultStorageKeyAllocator::FailSafeNetworkConfig().KeyName(), dataset.data(), dataset.size()); } +void GenericThreadDriver::CheckInterfaceEnabled() +{ +#if !CHIP_DEVICE_CONFIG_ENABLE_THREAD_AUTOSTART + // If the Thread interface is enabled and stack has been provisioned, but is not currently enabled, enable it now. + if (GetEnabled() && ThreadStackMgrImpl().IsThreadProvisioned() && !ThreadStackMgrImpl().IsThreadEnabled()) + { + ReturnOnFailure(ThreadStackMgrImpl().SetThreadEnabled(true)); + ChipLogProgress(DeviceLayer, "OpenThread ifconfig up and thread start"); + } +#endif +} + size_t GenericThreadDriver::ThreadNetworkIterator::Count() { return driver->mStagingNetwork.IsCommissioned() ? 1 : 0; diff --git a/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.h b/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.h index 28dc8f176ddd1f..7fd62159a36522 100644 --- a/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.h +++ b/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.h @@ -90,6 +90,8 @@ class GenericThreadDriver final : public ThreadDriver // BaseDriver NetworkIterator * GetNetworks() override { return new ThreadNetworkIterator(this); } CHIP_ERROR Init(Internal::BaseDriver::NetworkStatusChangeCallback * statusChangeCallback) override; + CHIP_ERROR SetEnabled(bool enabled) override; + bool GetEnabled() override; void Shutdown() override; // WirelessDriver @@ -114,11 +116,13 @@ class GenericThreadDriver final : public ThreadDriver void ScanNetworks(ThreadDriver::ScanCallback * callback) override; private: + static constexpr const char * kInterfaceEnabled = "g/gtd/en"; uint8_t scanNetworkTimeoutSeconds; uint8_t connectNetworkTimeout; static void OnThreadStateChangeHandler(const ChipDeviceEvent * event, intptr_t arg); Status MatchesNetworkId(const Thread::OperationalDataset & dataset, const ByteSpan & networkId) const; CHIP_ERROR BackupConfiguration(); + void CheckInterfaceEnabled(); ThreadNetworkIterator mThreadIterator = ThreadNetworkIterator(this); Thread::OperationalDataset mStagingNetwork = {}; diff --git a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp index 9079e5455db620..876cb54385efe6 100644 --- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp +++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp @@ -1131,6 +1131,7 @@ CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::DoInit(otInstanc memset(&mSrpClient, 0, sizeof(mSrpClient)); #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_AUTOSTART // If the Thread stack has been provisioned, but is not currently enabled, enable it now. if (otThreadGetDeviceRole(mOTInst) == OT_DEVICE_ROLE_DISABLED && otDatasetIsCommissioned(otInst)) { @@ -1143,6 +1144,7 @@ CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::DoInit(otInstanc ChipLogProgress(DeviceLayer, "OpenThread ifconfig up and thread start"); } +#endif initNetworkCommissioningThreadDriver();