From a07b447e161bc5ce121399db044bb9f056e62cb3 Mon Sep 17 00:00:00 2001 From: chendejin Date: Wed, 12 Jun 2024 12:37:15 +0800 Subject: [PATCH 1/5] OpenThread: added Thread interface enabled support --- ...enericNetworkCommissioningThreadDriver.cpp | 37 +++++++++++++++++++ .../GenericNetworkCommissioningThreadDriver.h | 3 ++ ...nericThreadStackManagerImpl_OpenThread.hpp | 9 ++++- 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp b/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp index 0a961a9f8e4afa..af517afe62ca20 100644 --- a/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp +++ b/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp @@ -95,6 +95,12 @@ 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()) + { + // If backup is found, set InterfaceEnabled to default value (true). + ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Delete(kInterfaceEnabled)); + } + ChipLogProgress(NetworkProvisioning, "Reverting Thread operational dataset"); if (error == CHIP_NO_ERROR) @@ -166,6 +172,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 +195,31 @@ 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 && DeviceLayer::ThreadStackMgrImpl().IsThreadEnabled()) || + (enabled && DeviceLayer::ThreadStackMgrImpl().IsThreadProvisioned())) + { + ReturnErrorOnFailure(DeviceLayer::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) diff --git a/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.h b/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.h index 28dc8f176ddd1f..e98b9393818abe 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,6 +116,7 @@ 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); diff --git a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp index 2056699d77c8c0..563984fd1f973e 100644 --- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp +++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp @@ -1094,6 +1094,9 @@ CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::DoInit(otInstanc CHIP_ERROR err = CHIP_NO_ERROR; otError otErr = OT_ERROR_NONE; + // If InterfaceEnabled is false, do not start Thread + bool InterfaceEnabled = true; + // Arrange for OpenThread errors to be translated to text. RegisterOpenThreadErrorFormatter(); @@ -1131,8 +1134,12 @@ CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::DoInit(otInstanc memset(&mSrpClient, 0, sizeof(mSrpClient)); #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT +#ifndef _NO_NETWORK_COMMISSIONING_DRIVER_ + InterfaceEnabled = sGenericThreadDriver.GetEnabled(); +#endif + // If the Thread stack has been provisioned, but is not currently enabled, enable it now. - if (otThreadGetDeviceRole(mOTInst) == OT_DEVICE_ROLE_DISABLED && otDatasetIsCommissioned(otInst)) + if (InterfaceEnabled && otThreadGetDeviceRole(mOTInst) == OT_DEVICE_ROLE_DISABLED && otDatasetIsCommissioned(otInst)) { // Enable the Thread IPv6 interface. otErr = otIp6SetEnabled(otInst, true); From 4bda6637aa3f52a2e1cccde7bfaccf92b121ec57 Mon Sep 17 00:00:00 2001 From: chendejin Date: Fri, 14 Jun 2024 14:13:24 +0800 Subject: [PATCH 2/5] Added Thread autostart configuration and check for Thread interface --- src/include/platform/CHIPDeviceConfig.h | 9 ++++++++ ...enericNetworkCommissioningThreadDriver.cpp | 21 ++++++++++++++++--- .../GenericNetworkCommissioningThreadDriver.h | 1 + ...nericThreadStackManagerImpl_OpenThread.hpp | 11 +++------- 4 files changed, 31 insertions(+), 11 deletions(-) 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 af517afe62ca20..7c106b5e331ad0 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; } @@ -204,10 +206,9 @@ CHIP_ERROR GenericThreadDriver::SetEnabled(bool enabled) ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kInterfaceEnabled, &enabled, sizeof(enabled))); - if ((!enabled && DeviceLayer::ThreadStackMgrImpl().IsThreadEnabled()) || - (enabled && DeviceLayer::ThreadStackMgrImpl().IsThreadProvisioned())) + if ((!enabled && ThreadStackMgrImpl().IsThreadEnabled()) || (enabled && ThreadStackMgrImpl().IsThreadProvisioned())) { - ReturnErrorOnFailure(DeviceLayer::ThreadStackMgrImpl().SetThreadEnabled(enabled)); + ReturnErrorOnFailure(ThreadStackMgrImpl().SetThreadEnabled(enabled)); } return CHIP_NO_ERROR; } @@ -260,6 +261,20 @@ CHIP_ERROR GenericThreadDriver::BackupConfiguration() return KeyValueStoreMgr().Put(DefaultStorageKeyAllocator::FailSafeNetworkConfig().KeyName(), dataset.data(), dataset.size()); } +void GenericThreadDriver::CheckInterfaceEnabled() +{ + bool enabled = GetEnabled(); + ChipLogProgress(DeviceLayer, "OpenThread InterfaceEnabled: %s", enabled ? "true" : "false"); +#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 (enabled && 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 e98b9393818abe..7fd62159a36522 100644 --- a/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.h +++ b/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.h @@ -122,6 +122,7 @@ class GenericThreadDriver final : public ThreadDriver 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 563984fd1f973e..4e831f4ef678df 100644 --- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp +++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp @@ -1094,9 +1094,6 @@ CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::DoInit(otInstanc CHIP_ERROR err = CHIP_NO_ERROR; otError otErr = OT_ERROR_NONE; - // If InterfaceEnabled is false, do not start Thread - bool InterfaceEnabled = true; - // Arrange for OpenThread errors to be translated to text. RegisterOpenThreadErrorFormatter(); @@ -1134,12 +1131,9 @@ CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::DoInit(otInstanc memset(&mSrpClient, 0, sizeof(mSrpClient)); #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT -#ifndef _NO_NETWORK_COMMISSIONING_DRIVER_ - InterfaceEnabled = sGenericThreadDriver.GetEnabled(); -#endif - +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD_AUTOSTART // If the Thread stack has been provisioned, but is not currently enabled, enable it now. - if (InterfaceEnabled && otThreadGetDeviceRole(mOTInst) == OT_DEVICE_ROLE_DISABLED && otDatasetIsCommissioned(otInst)) + if (otThreadGetDeviceRole(mOTInst) == OT_DEVICE_ROLE_DISABLED && otDatasetIsCommissioned(otInst)) { // Enable the Thread IPv6 interface. otErr = otIp6SetEnabled(otInst, true); @@ -1150,6 +1144,7 @@ CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::DoInit(otInstanc ChipLogProgress(DeviceLayer, "OpenThread ifconfig up and thread start"); } +#endif initNetworkCommissioningThreadDriver(); From bd5ab1f24861b4b2a62207c00cfd3a034f1cbea8 Mon Sep 17 00:00:00 2001 From: cdj <45139296+DejinChen@users.noreply.github.com> Date: Mon, 24 Jun 2024 11:27:43 +0800 Subject: [PATCH 3/5] Update comments for RevertConfiguration --- .../OpenThread/GenericNetworkCommissioningThreadDriver.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp b/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp index 7c106b5e331ad0..60254f50d608de 100644 --- a/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp +++ b/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp @@ -99,7 +99,11 @@ CHIP_ERROR GenericThreadDriver::RevertConfiguration() if (!GetEnabled()) { - // If backup is found, set InterfaceEnabled to default value (true). + // 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)); } From 35ba199ad0571e1bb0f7b5d06277e91e7f36ddf9 Mon Sep 17 00:00:00 2001 From: cdj <45139296+DejinChen@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:09:26 +0800 Subject: [PATCH 4/5] Fix CI --- .../OpenThread/GenericNetworkCommissioningThreadDriver.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp b/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp index 60254f50d608de..cab17f5a59c292 100644 --- a/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp +++ b/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp @@ -268,7 +268,7 @@ CHIP_ERROR GenericThreadDriver::BackupConfiguration() void GenericThreadDriver::CheckInterfaceEnabled() { bool enabled = GetEnabled(); - ChipLogProgress(DeviceLayer, "OpenThread InterfaceEnabled: %s", enabled ? "true" : "false"); + ChipLogProgress(DeviceLayer, "OpenThread InterfaceEnabled: %d", enabled); #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 (enabled && ThreadStackMgrImpl().IsThreadProvisioned() && !ThreadStackMgrImpl().IsThreadEnabled()) From 3ef63fc375e56e6fb4dc21c411dac36bf4d1a141 Mon Sep 17 00:00:00 2001 From: cdj <45139296+DejinChen@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:22:59 +0800 Subject: [PATCH 5/5] Fix CI --- .../OpenThread/GenericNetworkCommissioningThreadDriver.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp b/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp index cab17f5a59c292..711ad4930f96d4 100644 --- a/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp +++ b/src/platform/OpenThread/GenericNetworkCommissioningThreadDriver.cpp @@ -267,11 +267,9 @@ CHIP_ERROR GenericThreadDriver::BackupConfiguration() void GenericThreadDriver::CheckInterfaceEnabled() { - bool enabled = GetEnabled(); - ChipLogProgress(DeviceLayer, "OpenThread InterfaceEnabled: %d", enabled); #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 (enabled && ThreadStackMgrImpl().IsThreadProvisioned() && !ThreadStackMgrImpl().IsThreadEnabled()) + if (GetEnabled() && ThreadStackMgrImpl().IsThreadProvisioned() && !ThreadStackMgrImpl().IsThreadEnabled()) { ReturnOnFailure(ThreadStackMgrImpl().SetThreadEnabled(true)); ChipLogProgress(DeviceLayer, "OpenThread ifconfig up and thread start");