From 2b50fd7abd4fba98594b4ccbf113fca4628cfb02 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Wed, 12 Jun 2024 17:53:38 +0800 Subject: [PATCH 01/46] Add Thread Border Router Management cluster server implementation and ESP32 delegate --- config/esp32/components/chip/CMakeLists.txt | 6 + .../thread-br-delegate.h | 76 ++++ .../thread-br-mgmt-server.cpp | 385 ++++++++++++++++++ .../thread-br-mgmt-server.h | 85 ++++ src/app/common/templates/config-data.yaml | 1 + .../zcl/zcl-with-test-extensions.json | 8 + src/app/zap-templates/zcl/zcl.json | 8 + src/platform/ESP32/BUILD.gn | 7 + .../ESP32/ESP32ThreadBorderRouterDelegate.cpp | 244 +++++++++++ .../ESP32/ESP32ThreadBorderRouterDelegate.h | 93 +++++ .../zap-generated/attributes/Accessors.cpp | 327 --------------- .../zap-generated/attributes/Accessors.h | 41 -- .../app-common/zap-generated/callback.h | 24 -- 13 files changed, 913 insertions(+), 392 deletions(-) create mode 100644 src/app/clusters/thread-border-router-management-server/thread-br-delegate.h create mode 100644 src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp create mode 100644 src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h create mode 100644 src/platform/ESP32/ESP32ThreadBorderRouterDelegate.cpp create mode 100644 src/platform/ESP32/ESP32ThreadBorderRouterDelegate.h diff --git a/config/esp32/components/chip/CMakeLists.txt b/config/esp32/components/chip/CMakeLists.txt index d0c1fc4463f442..6a001deccbc862 100644 --- a/config/esp32/components/chip/CMakeLists.txt +++ b/config/esp32/components/chip/CMakeLists.txt @@ -234,6 +234,12 @@ else() chip_gn_arg_append("chip_openthread_ftd" "false") endif() +if (CONFIG_OPENTHREAD_BORDER_ROUTER) + chip_gn_arg_append("chip_enable_thread_border_router" "true") +else() + chip_gn_arg_append("chip_enable_thread_border_router" "false") +endif() + if (CONFIG_ENABLE_OTA_REQUESTOR) chip_gn_arg_append("chip_enable_ota_requestor" "true") endif() diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h new file mode 100644 index 00000000000000..0c54464e95a534 --- /dev/null +++ b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h @@ -0,0 +1,76 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace ThreadBorderRouterManagement { + +constexpr size_t kBorderRouterNameMaxLength = 63; +constexpr size_t kBorderAgentIdLength = 16; + +class Delegate +{ +public: + Delegate() = default; + virtual ~Delegate() = default; + + class ActivateDatasetCallback + { + public: + virtual void OnActivateDatasetComplete(CHIP_ERROR error) = 0; + }; + + virtual CHIP_ERROR Init() = 0; + + virtual CHIP_ERROR GetPanChangeSupported(bool & panChangeSupported) = 0; + + virtual CHIP_ERROR GetBorderRouterName(MutableCharSpan & borderRouterName) = 0; + + virtual CHIP_ERROR GetBorderAgentId(MutableByteSpan & borderAgentId) = 0; + + virtual CHIP_ERROR GetThreadVersion(uint16_t & threadVersion) = 0; + + virtual CHIP_ERROR GetInterfaceEnabled(bool & interfaceEnabled) = 0; + + virtual CHIP_ERROR GetActiveDataset(chip::Thread::OperationalDataset & activeDataset) = 0; + + virtual CHIP_ERROR GetPendingDataset(chip::Thread::OperationalDataset & pendingDataset) = 0; + + virtual CHIP_ERROR SetActiveDataset(const chip::Thread::OperationalDataset & activeDataset, + ActivateDatasetCallback * callback) = 0; + + virtual CHIP_ERROR RevertActiveDataset() = 0; + + virtual CHIP_ERROR SetPendingDataset(const chip::Thread::OperationalDataset & pendingDataset) = 0; +}; + +} // namespace ThreadBorderRouterManagement +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp new file mode 100644 index 00000000000000..a050a9f5d2b751 --- /dev/null +++ b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp @@ -0,0 +1,385 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "thread-br-mgmt-server.h" + +#include "app-common/zap-generated/cluster-objects.h" +#include "app-common/zap-generated/ids/Attributes.h" +#include "app-common/zap-generated/ids/Clusters.h" +#include "app-common/zap-generated/ids/Commands.h" +#include "app/AttributeAccessInterfaceRegistry.h" +#include "app/AttributeValueEncoder.h" +#include "app/CommandHandler.h" +#include "app/CommandHandlerInterface.h" +#include "app/InteractionModelEngine.h" +#include "app/clusters/general-commissioning-server/general-commissioning-server.h" +#include "app/data-model/Nullable.h" +#include "app/server/Server.h" +#include "lib/core/CHIPError.h" +#include "lib/support/CodeUtils.h" +#include "lib/support/Span.h" +#include "lib/support/ThreadOperationalDataset.h" +#include "platform/CHIPDeviceEvent.h" +#include "platform/PlatformManager.h" +#include "protocols/interaction_model/StatusCode.h" + +namespace chip { +namespace app { +namespace Clusters { +namespace ThreadBorderRouterManagement { + +using Protocols::InteractionModel::Status; + +static bool CheckOverCASESession(CommandHandlerInterface::HandlerContext & ctx) +{ + chip::Messaging::ExchangeContext * exchangeCtx = ctx.mCommandHandler.GetExchangeContext(); + if (!exchangeCtx || !exchangeCtx->HasSessionHandle() || !exchangeCtx->GetSessionHandle()->IsSecureSession() || + exchangeCtx->GetSessionHandle()->AsSecureSession()->GetSecureSessionType() != Transport::SecureSession::Type::kCASE) + { + ChipLogError(Zcl, "This command MUST be over a valid CASE session"); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::UnsupportedAccess); + return false; + } + return true; +} + +static bool CheckFailSafeArmed(CommandHandlerInterface::HandlerContext & ctx) +{ + auto & failSafeContext = chip::Server::GetInstance().GetFailSafeContext(); + if (failSafeContext.IsFailSafeArmed(ctx.mCommandHandler.GetAccessingFabricIndex())) + { + return true; + } + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::FailsafeRequired); + return false; +} + +static bool CheckDelegate(CommandHandlerInterface::HandlerContext & ctx, Delegate * delegate) +{ + if (!delegate) + { + ChipLogError(Zcl, "Thread Border Router Management server not initialized"); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::InvalidInState); + } + return delegate; +} + +void ServerInstance::HandleGetActiveDatasetRequest(HandlerContext & ctx, + const Commands::GetActiveDatasetRequest::DecodableType & req) +{ + VerifyOrReturn(CheckOverCASESession(ctx)); + VerifyOrReturn(CheckDelegate(ctx, mDelegate)); + + Commands::DatasetResponse::Type response; + Thread::OperationalDataset activeDataset; + CHIP_ERROR err = mDelegate->GetActiveDataset(activeDataset); + if (err == CHIP_ERROR_NOT_FOUND) + { + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); + } + else if (err != CHIP_NO_ERROR) + { + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); + } + ReturnOnFailure(err); + response.dataset = activeDataset.AsByteSpan(); + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); +} + +void ServerInstance::HandleGetPendingDatasetRequest(HandlerContext & ctx, + const Commands::GetPendingDatasetRequest::DecodableType & req) +{ + VerifyOrReturn(CheckOverCASESession(ctx)); + VerifyOrReturn(CheckDelegate(ctx, mDelegate)); + + Commands::DatasetResponse::Type response; + Thread::OperationalDataset pendingDataset; + CHIP_ERROR err = mDelegate->GetPendingDataset(pendingDataset); + if (err == CHIP_ERROR_NOT_FOUND) + { + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); + } + else if (err != CHIP_NO_ERROR) + { + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); + } + ReturnOnFailure(err); + response.dataset = pendingDataset.AsByteSpan(); + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); +} + +void ServerInstance::HandleSetActiveDatasetRequest(HandlerContext & ctx, + const Commands::SetActiveDatasetRequest::DecodableType & req) +{ + VerifyOrReturn(CheckFailSafeArmed(ctx)); + VerifyOrReturn(CheckDelegate(ctx, mDelegate)); + if (mAsyncCommandHandle.Get() != nullptr) + { + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Busy); + ctx.SetCommandHandled(); + return; + } + + Thread::OperationalDataset activeDataset; + Thread::OperationalDataset currentActiveDataset; + uint64_t currentActiveDatasetTimestamp; + if (activeDataset.Init(req.activeDataset) != CHIP_NO_ERROR) + { + // If any of the parameters in the ActiveDataset is invalid, the command SHALL fail with a status code + // of INVALID_COMMAND. + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); + return; + } + + if (mDelegate->GetActiveDataset(currentActiveDataset) == CHIP_NO_ERROR && + currentActiveDataset.GetActiveTimestamp(currentActiveDatasetTimestamp) == CHIP_NO_ERROR) + { + // If this command is invoked when the ActiveDatasetTimestamp attribute is not null, the command SHALL + // fail with a status code of INVALID_IN_STATE. + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidInState); + return; + } + + mPath = ctx.mRequestPath; + mAsyncCommandHandle = CommandHandler::Handle(&ctx.mCommandHandler); + ctx.mCommandHandler.FlushAcksRightAwayOnSlowCommand(); + mBreadcrumb = req.breadcrumb; + CHIP_ERROR err = CHIP_NO_ERROR; + if ((err = mDelegate->SetActiveDataset(activeDataset, this)) != CHIP_NO_ERROR) + { + OnActivateDatasetComplete(err); + } +} + +void ServerInstance::HandleSetPendingDatasetRequest(HandlerContext & ctx, + const Commands::SetPendingDatasetRequest::DecodableType & req) +{ + VerifyOrReturn(CheckDelegate(ctx, mDelegate)); + bool panChangeSupported; + if (mDelegate->GetPanChangeSupported(panChangeSupported) != CHIP_NO_ERROR || !panChangeSupported) + { + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::UnsupportedCommand); + return; + } + Thread::OperationalDataset pendingDataset; + if (pendingDataset.Init(req.pendingDataset) != CHIP_NO_ERROR) + { + // If any of the parameters in the PendingDataset is invalid, the command SHALL fail with a status code + // of INVALID_COMMAND. + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); + return; + } + if (mDelegate->SetPendingDataset(pendingDataset) != CHIP_NO_ERROR) + { + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::Failure); + } + else + { + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::Success); + } +} + +void ServerInstance::InvokeCommand(HandlerContext & ctx) +{ + switch (ctx.mRequestPath.mCommandId) + { + case Commands::GetActiveDatasetRequest::Id: + HandleCommand( + ctx, [this](HandlerContext & ctx, const auto & req) { HandleGetActiveDatasetRequest(ctx, req); }); + break; + case Commands::GetPendingDatasetRequest::Id: + HandleCommand( + ctx, [this](HandlerContext & ctx, const auto & req) { HandleGetPendingDatasetRequest(ctx, req); }); + break; + case Commands::SetActiveDatasetRequest::Id: + HandleCommand( + ctx, [this](HandlerContext & ctx, const auto & req) { HandleSetActiveDatasetRequest(ctx, req); }); + break; + case Commands::SetPendingDatasetRequest::Id: + HandleCommand( + ctx, [this](HandlerContext & ctx, const auto & req) { HandleSetPendingDatasetRequest(ctx, req); }); + break; + default: + break; + } +} + +CHIP_ERROR ServerInstance::ReadFeatureMap(AttributeValueEncoder & aEncoder) +{ + BitFlags featureMap; + bool panChangeSupported; + ReturnErrorOnFailure(mDelegate->GetPanChangeSupported(panChangeSupported)); + if (panChangeSupported) + { + featureMap.Set(Feature::kPANChange); + } + return aEncoder.Encode(featureMap); +} + +CHIP_ERROR ServerInstance::ReadBorderRouterName(AttributeValueEncoder & aEncoder) +{ + char borderRouterName[kBorderRouterNameMaxLength]; + MutableCharSpan borderRouterNameSpan(borderRouterName); + ReturnErrorOnFailure(mDelegate->GetBorderRouterName(borderRouterNameSpan)); + return aEncoder.Encode(chip::CharSpan(borderRouterName, borderRouterNameSpan.size())); +} + +CHIP_ERROR ServerInstance::ReadBorderAgentID(AttributeValueEncoder & aEncoder) +{ + uint8_t borderAgentId[kBorderAgentIdLength]; + MutableByteSpan borderAgentIdSpan(borderAgentId); + ReturnErrorOnFailure(mDelegate->GetBorderAgentId(borderAgentIdSpan)); + return aEncoder.Encode(chip::ByteSpan(borderAgentId)); +} + +CHIP_ERROR ServerInstance::ReadThreadVersion(AttributeValueEncoder & aEncoder) +{ + uint16_t threadVersion; + ReturnErrorOnFailure(mDelegate->GetThreadVersion(threadVersion)); + return aEncoder.Encode(threadVersion); +} + +CHIP_ERROR ServerInstance::ReadInterfaceEnabled(AttributeValueEncoder & aEncoder) +{ + bool interfaceEnabled; + ReturnErrorOnFailure(mDelegate->GetInterfaceEnabled(interfaceEnabled)); + return aEncoder.Encode(interfaceEnabled); +} + +CHIP_ERROR ServerInstance::ReadActiveDatasetTimestamp(AttributeValueEncoder & aEncoder) +{ + Thread::OperationalDataset activeDataset; + uint64_t activeDatasetTimestamp; + if (mDelegate->GetActiveDataset(activeDataset) == CHIP_NO_ERROR && + activeDataset.GetActiveTimestamp(activeDatasetTimestamp) == CHIP_NO_ERROR) + { + return aEncoder.Encode(DataModel::MakeNullable(activeDatasetTimestamp)); + } + return aEncoder.Encode(DataModel::Nullable()); +} + +CHIP_ERROR ServerInstance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) +{ + if (aPath.mClusterId != ThreadBorderRouterManagement::Id) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + if (!mDelegate) + { + ChipLogError(Zcl, "Thread Border Router Management server not initialized"); + return CHIP_ERROR_UNINITIALIZED; + } + CHIP_ERROR status = CHIP_NO_ERROR; + switch (aPath.mAttributeId) + { + case Globals::Attributes::FeatureMap::Id: + status = ReadFeatureMap(aEncoder); + break; + case Attributes::BorderRouterName::Id: + status = ReadBorderRouterName(aEncoder); + break; + case Attributes::BorderAgentID::Id: + status = ReadBorderAgentID(aEncoder); + break; + case Attributes::ThreadVersion::Id: + status = ReadThreadVersion(aEncoder); + break; + case Attributes::InterfaceEnabled::Id: + status = ReadInterfaceEnabled(aEncoder); + break; + case Attributes::ActiveDatasetTimestamp::Id: + status = ReadActiveDatasetTimestamp(aEncoder); + break; + default: + break; + } + return status; +} + +void ServerInstance::CommitSavedBreadcrumb() +{ + if (mBreadcrumb.HasValue()) + { + GeneralCommissioning::SetBreadcrumb(mBreadcrumb.Value()); + } + mBreadcrumb.ClearValue(); +} + +void ServerInstance::OnActivateDatasetComplete(CHIP_ERROR error) +{ + auto commandHandleRef = std::move(mAsyncCommandHandle); + auto commandHandle = commandHandleRef.Get(); + if (commandHandle == nullptr) + { + return; + } + if (error == CHIP_NO_ERROR) + { + // The successful completion of the activation process SHALL disarm the fail-safe timer. + auto & failSafeContext = chip::Server::GetInstance().GetFailSafeContext(); + failSafeContext.DisarmFailSafe(); + CommitSavedBreadcrumb(); + } + else + { + ChipLogError(Zcl, "Failed on activating the active dataset for Thread BR: %" CHIP_ERROR_FORMAT, error.Format()); + } + commandHandle->AddStatus(mPath, error == CHIP_NO_ERROR ? Status::Success : Status::Failure); +} + +void ServerInstance::OnFailSafeTimerExpired() +{ + auto commandHandleRef = std::move(mAsyncCommandHandle); + auto commandHandle = commandHandleRef.Get(); + if (commandHandle == nullptr) + { + return; + } + if (mDelegate) + { + mDelegate->RevertActiveDataset(); + } + commandHandle->AddStatus(mPath, Status::Timeout); +} + +void ServerInstance::OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg) +{ + ServerInstance * _this = reinterpret_cast(arg); + if (event->Type == DeviceLayer::DeviceEventType::kFailSafeTimerExpired) + { + _this->OnFailSafeTimerExpired(); + } +} + +CHIP_ERROR ServerInstance::Init() +{ + ReturnErrorCodeIf(!mDelegate, CHIP_ERROR_INVALID_ARGUMENT); + ReturnErrorOnFailure(InteractionModelEngine::GetInstance()->RegisterCommandHandler(this)); + VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE); + ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler, reinterpret_cast(this))); + return mDelegate->Init(); +} + +} // namespace ThreadBorderRouterManagement +} // namespace Clusters +} // namespace app +} // namespace chip + +void MatterThreadBorderRouterManagementPluginServerInitCallback() +{ + // Nothing to do, the server init routine will be done in Instance::Init() +} diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h new file mode 100644 index 00000000000000..0338f411e73dd4 --- /dev/null +++ b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h @@ -0,0 +1,85 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "thread-br-delegate.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace ThreadBorderRouterManagement { + +class ServerInstance : public CommandHandlerInterface, public AttributeAccessInterface, public Delegate::ActivateDatasetCallback +{ +public: + ServerInstance(EndpointId endpointId, Delegate * delegate) : + CommandHandlerInterface(Optional(endpointId), Id), + AttributeAccessInterface(Optional(endpointId), Id), mDelegate(delegate) + {} + virtual ~ServerInstance() = default; + + CHIP_ERROR Init(); + + // CommandHanlerInterface + void InvokeCommand(HandlerContext & ctx) override; + + // AttributeAccessInterface + CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; + + // ActivateDatasetCallbackInterface + void OnActivateDatasetComplete(CHIP_ERROR error) override; + +private: + // Command Handlers + void HandleGetActiveDatasetRequest(HandlerContext & ctx, const Commands::GetActiveDatasetRequest::DecodableType & req); + void HandleGetPendingDatasetRequest(HandlerContext & ctx, const Commands::GetPendingDatasetRequest::DecodableType & req); + void HandleSetActiveDatasetRequest(HandlerContext & ctx, const Commands::SetActiveDatasetRequest::DecodableType & req); + void HandleSetPendingDatasetRequest(HandlerContext & ctx, const Commands::SetPendingDatasetRequest::DecodableType & req); + + // Attribute Read handler + CHIP_ERROR ReadFeatureMap(AttributeValueEncoder & aEncoder); + CHIP_ERROR ReadBorderRouterName(AttributeValueEncoder & aEncoder); + CHIP_ERROR ReadBorderAgentID(AttributeValueEncoder & aEncoder); + CHIP_ERROR ReadThreadVersion(AttributeValueEncoder & aEncoder); + CHIP_ERROR ReadInterfaceEnabled(AttributeValueEncoder & aEncoder); + CHIP_ERROR ReadActiveDatasetTimestamp(AttributeValueEncoder & aEncoder); + + static void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg); + void OnFailSafeTimerExpired(); + void CommitSavedBreadcrumb(); + + Delegate * mDelegate; + app::CommandHandler::Handle mAsyncCommandHandle; + ConcreteCommandPath mPath = ConcreteCommandPath(0, 0, 0); + Optional mBreadcrumb; +}; + +} // namespace ThreadBorderRouterManagement +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/common/templates/config-data.yaml b/src/app/common/templates/config-data.yaml index 83d1b682153ed7..432a7a5593e209 100644 --- a/src/app/common/templates/config-data.yaml +++ b/src/app/common/templates/config-data.yaml @@ -41,6 +41,7 @@ CommandHandlerInterfaceOnlyClusters: - Electrical Power Measurement - Electrical Energy Measurement - Wi-Fi Network Management + - Thread Border Router Management # We need a more configurable way of deciding which clusters have which init functions.... # See https://github.com/project-chip/connectedhomeip/issues/4369 diff --git a/src/app/zap-templates/zcl/zcl-with-test-extensions.json b/src/app/zap-templates/zcl/zcl-with-test-extensions.json index c6b39c837a1e00..fed647bf301ab7 100644 --- a/src/app/zap-templates/zcl/zcl-with-test-extensions.json +++ b/src/app/zap-templates/zcl/zcl-with-test-extensions.json @@ -298,6 +298,14 @@ "general_error_boolean", "cluster_error_boolean" ], + "Thread Border Router Management": [ + "BorderRouterName", + "BorderAgentID", + "ThreadVersion", + "InterfaceEnabled", + "ActiveDatasetTimestamp", + "FeatureMap" + ], "Thread Network Diagnostics": [ "Channel", "RoutingRole", diff --git a/src/app/zap-templates/zcl/zcl.json b/src/app/zap-templates/zcl/zcl.json index 18afa7eacc2f8a..5e7a529f2ae35a 100644 --- a/src/app/zap-templates/zcl/zcl.json +++ b/src/app/zap-templates/zcl/zcl.json @@ -296,6 +296,14 @@ "general_error_boolean", "cluster_error_boolean" ], + "Thread Border Router Management": [ + "BorderRouterName", + "BorderAgentID", + "ThreadVersion", + "InterfaceEnabled", + "ActiveDatasetTimestamp", + "FeatureMap" + ], "Thread Network Diagnostics": [ "Channel", "RoutingRole", diff --git a/src/platform/ESP32/BUILD.gn b/src/platform/ESP32/BUILD.gn index e835896fb59092..ef48c291ceca31 100644 --- a/src/platform/ESP32/BUILD.gn +++ b/src/platform/ESP32/BUILD.gn @@ -33,6 +33,7 @@ declare_args() { chip_use_esp32_ecdsa_peripheral = false chip_enable_ethernet = false chip_enable_route_hook = false + chip_enable_thread_border_router = false } defines = [ @@ -172,6 +173,12 @@ static_library("ESP32") { "../OpenThread/OpenThreadDnssdImpl.h", ] } + if (chip_enable_thread_border_router) { + sources += [ + "ESP32ThreadBorderRouterDelegate.cpp", + "ESP32ThreadBorderRouterDelegate.h", + ] + } configs -= [ "${chip_root}/build/config/compiler:warnings_default" ] } diff --git a/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.cpp b/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.cpp new file mode 100644 index 00000000000000..1a1c6c573cfae8 --- /dev/null +++ b/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.cpp @@ -0,0 +1,244 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ESP32ThreadBorderRouterDelegate.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { + +namespace ThreadBorderRouterManagement { + +class ScopedThreadLock +{ +public: + ScopedThreadLock() { DeviceLayer::ThreadStackMgr().LockThreadStack(); } + ~ScopedThreadLock() { DeviceLayer::ThreadStackMgr().UnlockThreadStack(); } +}; + +CHIP_ERROR ESP32ThreadBorderRouterDelegate::Init() +{ + mCallback = nullptr; + ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler, reinterpret_cast(this))); + ReturnErrorOnFailure(RevertActiveDataset()); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ESP32ThreadBorderRouterDelegate::GetBorderAgentId(MutableByteSpan & borderAgentIdSpan) +{ + otBorderAgentId borderAgentId; + if (borderAgentIdSpan.size() < sizeof(borderAgentId.mId)) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + ScopedThreadLock threadLock; + otError err = otBorderAgentGetId(esp_openthread_get_instance(), &borderAgentId); + if (err == OT_ERROR_NONE) + { + memcpy(borderAgentIdSpan.data(), borderAgentId.mId, sizeof(borderAgentId.mId)); + borderAgentIdSpan.reduce_size(sizeof(borderAgentId.mId)); + return CHIP_NO_ERROR; + } + return CHIP_ERROR_INTERNAL; +} + +CHIP_ERROR ESP32ThreadBorderRouterDelegate::GetThreadVersion(uint16_t & threadVersion) +{ + threadVersion = otThreadGetVersion(); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ESP32ThreadBorderRouterDelegate::GetInterfaceEnabled(bool & interfaceEnabled) +{ + ScopedThreadLock threadLock; + interfaceEnabled = otIp6IsEnabled(esp_openthread_get_instance()); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ESP32ThreadBorderRouterDelegate::GetActiveDataset(chip::Thread::OperationalDataset & activeDataset) +{ + ScopedThreadLock threadLock; + otOperationalDatasetTlvs datasetTlvs; + if (GetThreadEnabled()) + { + otError otErr = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &datasetTlvs); + if (otErr == OT_ERROR_NONE) + { + return activeDataset.Init(ByteSpan(datasetTlvs.mTlvs, datasetTlvs.mLength)); + } + } + return CHIP_ERROR_NOT_FOUND; +} + +CHIP_ERROR ESP32ThreadBorderRouterDelegate::GetPendingDataset(chip::Thread::OperationalDataset & pendingDataset) +{ + ScopedThreadLock threadLock; + otOperationalDatasetTlvs datasetTlvs; + otError otErr = otDatasetGetPendingTlvs(esp_openthread_get_instance(), &datasetTlvs); + if (otErr == OT_ERROR_NONE) + { + return pendingDataset.Init(ByteSpan(datasetTlvs.mTlvs, datasetTlvs.mLength)); + } + return CHIP_ERROR_NOT_FOUND; +} + +CHIP_ERROR ESP32ThreadBorderRouterDelegate::SetActiveDataset(const chip::Thread::OperationalDataset & activeDataset, + ActivateDatasetCallback * callback) +{ + VerifyOrReturnError(callback, CHIP_ERROR_INVALID_ARGUMENT); + otOperationalDatasetTlvs datasetTlvs; + memcpy(datasetTlvs.mTlvs, activeDataset.AsByteSpan().data(), activeDataset.AsByteSpan().size()); + datasetTlvs.mLength = activeDataset.AsByteSpan().size(); + + ScopedThreadLock threadLock; + // Save the previous thread state and dataset for reverting + bool threadIsEnabled = GetThreadEnabled(); + ReturnErrorOnFailure(DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(kFailsafeThreadEnabledKey, threadIsEnabled)); + if (threadIsEnabled) + { + otOperationalDatasetTlvs stagingDataset; + ReturnErrorCodeIf(otDatasetGetActiveTlvs(esp_openthread_get_instance(), &stagingDataset) != OT_ERROR_NONE, + CHIP_ERROR_INTERNAL); + if (activeDataset.AsByteSpan().data_equal(ByteSpan(stagingDataset.mTlvs, stagingDataset.mLength))) + { + callback->OnActivateDatasetComplete(CHIP_NO_ERROR); + return CHIP_NO_ERROR; + } + ReturnErrorOnFailure(DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(kFailsafeThreadDatasetTlvsKey, + stagingDataset.mTlvs, stagingDataset.mLength)); + } + SetThreadEnabled(false); + ReturnErrorCodeIf(otDatasetSetActiveTlvs(esp_openthread_get_instance(), &datasetTlvs) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); + SetThreadEnabled(true); + mCallback = callback; + return CHIP_NO_ERROR; +} + +void ESP32ThreadBorderRouterDelegate::OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg) +{ + ESP32ThreadBorderRouterDelegate * delegate = reinterpret_cast(arg); + if (delegate && delegate->mCallback) + { + if (event->Type == DeviceLayer::DeviceEventType::kThreadConnectivityChange && + event->ThreadConnectivityChange.Result == DeviceLayer::kConnectivity_Established) + { + delegate->mCallback->OnActivateDatasetComplete(CHIP_NO_ERROR); + // Delete Failsafe Keys after activating dataset is completed + DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(kFailsafeThreadDatasetTlvsKey); + DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(kFailsafeThreadEnabledKey); + delegate->mCallback = nullptr; + } + } +} + +CHIP_ERROR ESP32ThreadBorderRouterDelegate::RevertActiveDataset() +{ + bool threadIsEnabled = false; + CHIP_ERROR err = DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(kFailsafeThreadEnabledKey, &threadIsEnabled); + if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) + { + return CHIP_NO_ERROR; + } + ReturnErrorOnFailure(err); + + ScopedThreadLock threadLock; + if (threadIsEnabled) + { + otOperationalDatasetTlvs stagingDataset; + size_t datasetTlvslen = 0; + err = DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(kFailsafeThreadDatasetTlvsKey, stagingDataset.mTlvs, + sizeof(stagingDataset.mTlvs), &datasetTlvslen); + if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) + { + return CHIP_NO_ERROR; + } + ReturnErrorOnFailure(err); + stagingDataset.mLength = datasetTlvslen; + ReturnErrorOnFailure(SetThreadEnabled(false)); + ReturnErrorCodeIf(otDatasetSetActiveTlvs(esp_openthread_get_instance(), &stagingDataset) != OT_ERROR_NONE, + CHIP_ERROR_INTERNAL); + } + ReturnErrorOnFailure(SetThreadEnabled(threadIsEnabled)); + // Delete Failsafe Keys after reverting. + DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(kFailsafeThreadDatasetTlvsKey); + DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(kFailsafeThreadEnabledKey); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ESP32ThreadBorderRouterDelegate::SetPendingDataset(const chip::Thread::OperationalDataset & pendingDataset) +{ + ScopedThreadLock threadLock; + otOperationalDatasetTlvs datasetTlvs; + memcpy(datasetTlvs.mTlvs, pendingDataset.AsByteSpan().data(), pendingDataset.AsByteSpan().size()); + datasetTlvs.mLength = pendingDataset.AsByteSpan().size(); + ReturnErrorCodeIf(otDatasetSetPendingTlvs(esp_openthread_get_instance(), &datasetTlvs) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ESP32ThreadBorderRouterDelegate::SetThreadEnabled(bool enabled) +{ + otInstance * instance = esp_openthread_get_instance(); + bool isEnabled = (otThreadGetDeviceRole(instance) != OT_DEVICE_ROLE_DISABLED); + bool isIp6Enabled = otIp6IsEnabled(instance); + if (enabled && !isIp6Enabled) + { + ReturnErrorCodeIf(otIp6SetEnabled(instance, enabled) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); + } + if (enabled != isEnabled) + { + ReturnErrorCodeIf(otThreadSetEnabled(instance, enabled) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); + } + if (!enabled && isIp6Enabled) + { + ReturnErrorCodeIf(otIp6SetEnabled(instance, enabled) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); + } + return CHIP_NO_ERROR; +} + +bool ESP32ThreadBorderRouterDelegate::GetThreadEnabled() +{ + otInstance * instance = esp_openthread_get_instance(); + return otIp6IsEnabled(instance) && (otThreadGetDeviceRole(instance) != OT_DEVICE_ROLE_DISABLED); +} + +} // namespace ThreadBorderRouterManagement +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.h b/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.h new file mode 100644 index 00000000000000..d0dc952f616b73 --- /dev/null +++ b/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.h @@ -0,0 +1,93 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "openthread/dataset.h" +#include +#include +#include +#include +#include +#include + +using chip::MutableByteSpan; +using chip::MutableCharSpan; +using chip::Span; + +namespace chip { +namespace app { +namespace Clusters { + +namespace ThreadBorderRouterManagement { + +class ESP32ThreadBorderRouterDelegate : public Delegate +{ +public: + static constexpr char kThreadBorderRourterName[] = "Espressif-ThreadBR"; + static constexpr char kFailsafeThreadDatasetTlvsKey[] = "g/fs/td"; + static constexpr char kFailsafeThreadEnabledKey[] = "g/fs/te"; + + ESP32ThreadBorderRouterDelegate() = default; + ~ESP32ThreadBorderRouterDelegate() = default; + + CHIP_ERROR Init() override; + + CHIP_ERROR GetPanChangeSupported(bool & panChangeSupported) override + { + panChangeSupported = true; + return CHIP_NO_ERROR; + } + + CHIP_ERROR GetBorderRouterName(MutableCharSpan & borderRouterName) override + { + if (borderRouterName.size() < strlen(kThreadBorderRourterName)) + { + return CHIP_ERROR_NO_MEMORY; + } + strcpy(borderRouterName.data(), kThreadBorderRourterName); + borderRouterName.reduce_size(strlen(kThreadBorderRourterName)); + return CHIP_NO_ERROR; + } + + CHIP_ERROR GetBorderAgentId(MutableByteSpan & borderAgentId) override; + + CHIP_ERROR GetThreadVersion(uint16_t & threadVersion) override; + + CHIP_ERROR GetInterfaceEnabled(bool & interfaceEnabled) override; + + CHIP_ERROR GetActiveDataset(chip::Thread::OperationalDataset & activeDataset) override; + + CHIP_ERROR GetPendingDataset(chip::Thread::OperationalDataset & pendingDataset) override; + + CHIP_ERROR SetActiveDataset(const chip::Thread::OperationalDataset & activeDataset, ActivateDatasetCallback *callback) override; + + CHIP_ERROR RevertActiveDataset() override; + + CHIP_ERROR SetPendingDataset(const chip::Thread::OperationalDataset & pendingDataset) override; + + static void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg); + +private: + CHIP_ERROR SetThreadEnabled(bool enabled); + bool GetThreadEnabled(); + ActivateDatasetCallback * mCallback = nullptr; +}; +} // namespace ThreadBorderRouterManagement +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp index 5ea642c2490387..1a2bb6bed15103 100644 --- a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp @@ -35381,333 +35381,6 @@ Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t valu namespace ThreadBorderRouterManagement { namespace Attributes { -namespace BorderRouterName { - -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, chip::MutableCharSpan & value) -{ - uint8_t zclString[63 + 1]; - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, zclString, sizeof(zclString)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - size_t length = emberAfStringLength(zclString); - if (length == NumericAttributeTraits::kNullValue) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - - VerifyOrReturnError(value.size() == 63, Protocols::InteractionModel::Status::InvalidDataType); - memcpy(value.data(), &zclString[1], 63); - value.reduce_size(length); - return status; -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, chip::CharSpan value, MarkAttributeDirty markDirty) -{ - - static_assert(63 < NumericAttributeTraits::kNullValue, "value.size() might be too big"); - VerifyOrReturnError(value.size() <= 63, Protocols::InteractionModel::Status::ConstraintError); - uint8_t zclString[63 + 1]; - auto length = static_cast(value.size()); - Encoding::Put8(zclString, length); - memcpy(&zclString[1], value.data(), value.size()); - return emberAfWriteAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, zclString, - ZCL_CHAR_STRING_ATTRIBUTE_TYPE, markDirty); -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, chip::CharSpan value) -{ - - static_assert(63 < NumericAttributeTraits::kNullValue, "value.size() might be too big"); - VerifyOrReturnError(value.size() <= 63, Protocols::InteractionModel::Status::ConstraintError); - uint8_t zclString[63 + 1]; - auto length = static_cast(value.size()); - Encoding::Put8(zclString, length); - memcpy(&zclString[1], value.data(), value.size()); - return emberAfWriteAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, zclString, - ZCL_CHAR_STRING_ATTRIBUTE_TYPE); -} - -} // namespace BorderRouterName - -namespace BorderAgentID { - -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, chip::MutableByteSpan & value) -{ - uint8_t zclString[254 + 1]; - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, zclString, sizeof(zclString)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - size_t length = emberAfStringLength(zclString); - if (length == NumericAttributeTraits::kNullValue) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - - VerifyOrReturnError(value.size() == 254, Protocols::InteractionModel::Status::InvalidDataType); - memcpy(value.data(), &zclString[1], 254); - value.reduce_size(length); - return status; -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, chip::ByteSpan value, MarkAttributeDirty markDirty) -{ - - static_assert(254 < NumericAttributeTraits::kNullValue, "value.size() might be too big"); - VerifyOrReturnError(value.size() <= 254, Protocols::InteractionModel::Status::ConstraintError); - uint8_t zclString[254 + 1]; - auto length = static_cast(value.size()); - Encoding::Put8(zclString, length); - memcpy(&zclString[1], value.data(), value.size()); - return emberAfWriteAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, zclString, - ZCL_OCTET_STRING_ATTRIBUTE_TYPE, markDirty); -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, chip::ByteSpan value) -{ - - static_assert(254 < NumericAttributeTraits::kNullValue, "value.size() might be too big"); - VerifyOrReturnError(value.size() <= 254, Protocols::InteractionModel::Status::ConstraintError); - uint8_t zclString[254 + 1]; - auto length = static_cast(value.size()); - Encoding::Put8(zclString, length); - memcpy(&zclString[1], value.data(), value.size()); - return emberAfWriteAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, zclString, - ZCL_OCTET_STRING_ATTRIBUTE_TYPE); -} - -} // namespace BorderAgentID - -namespace ThreadVersion { - -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, uint16_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, writable, ZCL_INT16U_ATTRIBUTE_TYPE, - markDirty); -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, writable, ZCL_INT16U_ATTRIBUTE_TYPE); -} - -} // namespace ThreadVersion - -namespace InterfaceEnabled { - -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, bool * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, bool value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, writable, ZCL_BOOLEAN_ATTRIBUTE_TYPE, - markDirty); -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, bool value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, writable, ZCL_BOOLEAN_ATTRIBUTE_TYPE); -} - -} // namespace InterfaceEnabled - -namespace ActiveDatasetTimestamp { - -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, DataModel::Nullable & value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (Traits::IsNullValue(temp)) - { - value.SetNull(); - } - else - { - value.SetNonNull() = Traits::StorageToWorking(temp); - } - return status; -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint64_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ true, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, writable, ZCL_INT64U_ATTRIBUTE_TYPE, - markDirty); -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint64_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ true, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, writable, ZCL_INT64U_ATTRIBUTE_TYPE); -} - -Protocols::InteractionModel::Status SetNull(chip::EndpointId endpoint, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType value; - Traits::SetNull(value); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(value); - return emberAfWriteAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, writable, ZCL_INT64U_ATTRIBUTE_TYPE, - markDirty); -} - -Protocols::InteractionModel::Status SetNull(chip::EndpointId endpoint) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType value; - Traits::SetNull(value); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(value); - return emberAfWriteAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, writable, ZCL_INT64U_ATTRIBUTE_TYPE); -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, const chip::app::DataModel::Nullable & value, - MarkAttributeDirty markDirty) -{ - if (value.IsNull()) - { - return SetNull(endpoint, markDirty); - } - - return Set(endpoint, value.Value(), markDirty); -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, const chip::app::DataModel::Nullable & value) -{ - if (value.IsNull()) - { - return SetNull(endpoint); - } - - return Set(endpoint, value.Value()); -} - -} // namespace ActiveDatasetTimestamp - -namespace FeatureMap { - -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, uint32_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint32_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, writable, ZCL_BITMAP32_ATTRIBUTE_TYPE, - markDirty); -} - -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint32_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::ThreadBorderRouterManagement::Id, Id, writable, ZCL_BITMAP32_ATTRIBUTE_TYPE); -} - -} // namespace FeatureMap - namespace ClusterRevision { Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, uint16_t * value) diff --git a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h index 2e9f20115c2738..4895a188ce8a05 100644 --- a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h +++ b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h @@ -5450,47 +5450,6 @@ Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t valu namespace ThreadBorderRouterManagement { namespace Attributes { -namespace BorderRouterName { -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, chip::MutableCharSpan & value); // char_string -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, chip::CharSpan value); -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, chip::CharSpan value, MarkAttributeDirty markDirty); -} // namespace BorderRouterName - -namespace BorderAgentID { -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, chip::MutableByteSpan & value); // octet_string -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, chip::ByteSpan value); -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, chip::ByteSpan value, MarkAttributeDirty markDirty); -} // namespace BorderAgentID - -namespace ThreadVersion { -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, uint16_t * value); // int16u -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t value); -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty); -} // namespace ThreadVersion - -namespace InterfaceEnabled { -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, bool * value); // boolean -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, bool value); -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, bool value, MarkAttributeDirty markDirty); -} // namespace InterfaceEnabled - -namespace ActiveDatasetTimestamp { -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, DataModel::Nullable & value); // int64u -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint64_t value); -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint64_t value, MarkAttributeDirty markDirty); -Protocols::InteractionModel::Status SetNull(chip::EndpointId endpoint); -Protocols::InteractionModel::Status SetNull(chip::EndpointId endpoint, MarkAttributeDirty markDirty); -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, const chip::app::DataModel::Nullable & value); -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, const chip::app::DataModel::Nullable & value, - MarkAttributeDirty markDirty); -} // namespace ActiveDatasetTimestamp - -namespace FeatureMap { -Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, uint32_t * value); // bitmap32 -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint32_t value); -Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint32_t value, MarkAttributeDirty markDirty); -} // namespace FeatureMap - namespace ClusterRevision { Protocols::InteractionModel::Status Get(chip::EndpointId endpoint, uint16_t * value); // int16u Protocols::InteractionModel::Status Set(chip::EndpointId endpoint, uint16_t value); diff --git a/zzz_generated/app-common/app-common/zap-generated/callback.h b/zzz_generated/app-common/app-common/zap-generated/callback.h index 7be9f882fd37ef..b549abaaf6cbfc 100644 --- a/zzz_generated/app-common/app-common/zap-generated/callback.h +++ b/zzz_generated/app-common/app-common/zap-generated/callback.h @@ -6399,30 +6399,6 @@ bool emberAfColorControlClusterMoveColorTemperatureCallback( bool emberAfColorControlClusterStepColorTemperatureCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::ColorControl::Commands::StepColorTemperature::DecodableType & commandData); -/** - * @brief Thread Border Router Management Cluster GetActiveDatasetRequest Command callback (from client) - */ -bool emberAfThreadBorderRouterManagementClusterGetActiveDatasetRequestCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::ThreadBorderRouterManagement::Commands::GetActiveDatasetRequest::DecodableType & commandData); -/** - * @brief Thread Border Router Management Cluster GetPendingDatasetRequest Command callback (from client) - */ -bool emberAfThreadBorderRouterManagementClusterGetPendingDatasetRequestCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::ThreadBorderRouterManagement::Commands::GetPendingDatasetRequest::DecodableType & commandData); -/** - * @brief Thread Border Router Management Cluster SetActiveDatasetRequest Command callback (from client) - */ -bool emberAfThreadBorderRouterManagementClusterSetActiveDatasetRequestCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::ThreadBorderRouterManagement::Commands::SetActiveDatasetRequest::DecodableType & commandData); -/** - * @brief Thread Border Router Management Cluster SetPendingDatasetRequest Command callback (from client) - */ -bool emberAfThreadBorderRouterManagementClusterSetPendingDatasetRequestCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::ThreadBorderRouterManagement::Commands::SetPendingDatasetRequest::DecodableType & commandData); /** * @brief Thread Network Directory Cluster AddNetwork Command callback (from client) */ From 38ef19a330a9af58016fc0f5c1330cc653df045f Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Wed, 12 Jun 2024 11:09:04 +0000 Subject: [PATCH 02/46] Restyled by clang-format --- .../thread-br-mgmt-server.cpp | 2 +- src/platform/ESP32/ESP32ThreadBorderRouterDelegate.h | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp index a050a9f5d2b751..e927623d0db850 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp +++ b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp @@ -157,7 +157,7 @@ void ServerInstance::HandleSetActiveDatasetRequest(HandlerContext & ctx, mPath = ctx.mRequestPath; mAsyncCommandHandle = CommandHandler::Handle(&ctx.mCommandHandler); ctx.mCommandHandler.FlushAcksRightAwayOnSlowCommand(); - mBreadcrumb = req.breadcrumb; + mBreadcrumb = req.breadcrumb; CHIP_ERROR err = CHIP_NO_ERROR; if ((err = mDelegate->SetActiveDataset(activeDataset, this)) != CHIP_NO_ERROR) { diff --git a/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.h b/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.h index d0dc952f616b73..e869bfd2e16a0e 100644 --- a/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.h +++ b/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.h @@ -38,9 +38,9 @@ namespace ThreadBorderRouterManagement { class ESP32ThreadBorderRouterDelegate : public Delegate { public: - static constexpr char kThreadBorderRourterName[] = "Espressif-ThreadBR"; + static constexpr char kThreadBorderRourterName[] = "Espressif-ThreadBR"; static constexpr char kFailsafeThreadDatasetTlvsKey[] = "g/fs/td"; - static constexpr char kFailsafeThreadEnabledKey[] = "g/fs/te"; + static constexpr char kFailsafeThreadEnabledKey[] = "g/fs/te"; ESP32ThreadBorderRouterDelegate() = default; ~ESP32ThreadBorderRouterDelegate() = default; @@ -74,7 +74,8 @@ class ESP32ThreadBorderRouterDelegate : public Delegate CHIP_ERROR GetPendingDataset(chip::Thread::OperationalDataset & pendingDataset) override; - CHIP_ERROR SetActiveDataset(const chip::Thread::OperationalDataset & activeDataset, ActivateDatasetCallback *callback) override; + CHIP_ERROR SetActiveDataset(const chip::Thread::OperationalDataset & activeDataset, + ActivateDatasetCallback * callback) override; CHIP_ERROR RevertActiveDataset() override; From a0349ca0e5e679a94825db0f144a5d724fa8a1c9 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Thu, 13 Jun 2024 16:15:27 +0800 Subject: [PATCH 03/46] Fix compile error for external platform and mark thread-br-management cluster provisional --- examples/platform/esp32/external_platform/ESP32_custom/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/platform/esp32/external_platform/ESP32_custom/BUILD.gn b/examples/platform/esp32/external_platform/ESP32_custom/BUILD.gn index d8d2f92b542ac7..93b00ef8f81617 100644 --- a/examples/platform/esp32/external_platform/ESP32_custom/BUILD.gn +++ b/examples/platform/esp32/external_platform/ESP32_custom/BUILD.gn @@ -29,6 +29,7 @@ declare_args() { chip_bt_bluedroid_enabled = true chip_max_discovered_ip_addresses = 5 chip_enable_route_hook = false + chip_enable_thread_border_router = false } buildconfig_header("custom_buildconfig") { From 3550ee426792ff1e2231ca17b73e981710a944c1 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Thu, 13 Jun 2024 17:17:46 +0800 Subject: [PATCH 04/46] remove the topology request and response command and fix the id of activedatasettimestamp --- .../data_model/controller-clusters.zap | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/src/controller/data_model/controller-clusters.zap b/src/controller/data_model/controller-clusters.zap index abba3d15cd18ca..eebde797075997 100644 --- a/src/controller/data_model/controller-clusters.zap +++ b/src/controller/data_model/controller-clusters.zap @@ -1181,6 +1181,90 @@ } ] }, + { + "name": "Thread Border Router Management", + "code": 1106, + "mfgCode": null, + "define": "THREAD_BORDER_ROUTER_MANAGEMENT_CLUSTER", + "side": "client", + "enabled": 1, + "commands": [ + { + "name": "GetActiveDatasetRequest", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "GetPendingDatasetRequest", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "DatasetResponse", + "code": 3, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "SetActiveDatasetRequest", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "SetPendingDatasetRequest", + "code": 5, + "mfgCode": null, + "source": "client", + "isIncoming": 0, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "client", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "client", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "2", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, { "name": "Thread Network Diagnostics", "code": 53, From 6421343bff7fc27a7c6461133779f90e13e44e05 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Fri, 14 Jun 2024 14:24:13 +0800 Subject: [PATCH 05/46] review changes --- .../thread-br-delegate.h | 17 ++-- .../thread-br-mgmt-server.cpp | 93 +++++++------------ .../thread-br-mgmt-server.h | 11 ++- .../ESP32/ESP32ThreadBorderRouterDelegate.cpp | 29 +++--- .../ESP32/ESP32ThreadBorderRouterDelegate.h | 13 +-- 5 files changed, 67 insertions(+), 96 deletions(-) diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h index 0c54464e95a534..cd56cf827648c3 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h @@ -46,6 +46,12 @@ class Delegate virtual void OnActivateDatasetComplete(CHIP_ERROR error) = 0; }; + enum class DatasetType : uint8_t + { + kActive, + kPending, + }; + virtual CHIP_ERROR Init() = 0; virtual CHIP_ERROR GetPanChangeSupported(bool & panChangeSupported) = 0; @@ -58,16 +64,15 @@ class Delegate virtual CHIP_ERROR GetInterfaceEnabled(bool & interfaceEnabled) = 0; - virtual CHIP_ERROR GetActiveDataset(chip::Thread::OperationalDataset & activeDataset) = 0; - - virtual CHIP_ERROR GetPendingDataset(chip::Thread::OperationalDataset & pendingDataset) = 0; + virtual CHIP_ERROR GetDataset(Thread::OperationalDataset & dataset, DatasetType type) = 0; - virtual CHIP_ERROR SetActiveDataset(const chip::Thread::OperationalDataset & activeDataset, - ActivateDatasetCallback * callback) = 0; + virtual CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, ActivateDatasetCallback * callback) = 0; + // The Thread BR should be able to revert the active dataset set by SetActiveDataset(), and restore + // the previous status of Thread BR. virtual CHIP_ERROR RevertActiveDataset() = 0; - virtual CHIP_ERROR SetPendingDataset(const chip::Thread::OperationalDataset & pendingDataset) = 0; + virtual CHIP_ERROR SetPendingDataset(const Thread::OperationalDataset & pendingDataset) = 0; }; } // namespace ThreadBorderRouterManagement diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp index e927623d0db850..258b603e7bc471 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp +++ b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp @@ -26,6 +26,7 @@ #include "app/CommandHandler.h" #include "app/CommandHandlerInterface.h" #include "app/InteractionModelEngine.h" +#include "app/MessageDef/StatusIB.h" #include "app/clusters/general-commissioning-server/general-commissioning-server.h" #include "app/data-model/Nullable.h" #include "app/server/Server.h" @@ -46,12 +47,12 @@ using Protocols::InteractionModel::Status; static bool CheckOverCASESession(CommandHandlerInterface::HandlerContext & ctx) { - chip::Messaging::ExchangeContext * exchangeCtx = ctx.mCommandHandler.GetExchangeContext(); + Messaging::ExchangeContext * exchangeCtx = ctx.mCommandHandler.GetExchangeContext(); if (!exchangeCtx || !exchangeCtx->HasSessionHandle() || !exchangeCtx->GetSessionHandle()->IsSecureSession() || exchangeCtx->GetSessionHandle()->AsSecureSession()->GetSecureSessionType() != Transport::SecureSession::Type::kCASE) { ChipLogError(Zcl, "This command MUST be over a valid CASE session"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::UnsupportedAccess); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::UnsupportedAccess); return false; } return true; @@ -59,12 +60,12 @@ static bool CheckOverCASESession(CommandHandlerInterface::HandlerContext & ctx) static bool CheckFailSafeArmed(CommandHandlerInterface::HandlerContext & ctx) { - auto & failSafeContext = chip::Server::GetInstance().GetFailSafeContext(); + auto & failSafeContext = Server::GetInstance().GetFailSafeContext(); if (failSafeContext.IsFailSafeArmed(ctx.mCommandHandler.GetAccessingFabricIndex())) { return true; } - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::FailsafeRequired); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::FailsafeRequired); return false; } @@ -73,64 +74,42 @@ static bool CheckDelegate(CommandHandlerInterface::HandlerContext & ctx, Delegat if (!delegate) { ChipLogError(Zcl, "Thread Border Router Management server not initialized"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::InvalidInState); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidInState); } return delegate; } -void ServerInstance::HandleGetActiveDatasetRequest(HandlerContext & ctx, - const Commands::GetActiveDatasetRequest::DecodableType & req) -{ - VerifyOrReturn(CheckOverCASESession(ctx)); - VerifyOrReturn(CheckDelegate(ctx, mDelegate)); - - Commands::DatasetResponse::Type response; - Thread::OperationalDataset activeDataset; - CHIP_ERROR err = mDelegate->GetActiveDataset(activeDataset); - if (err == CHIP_ERROR_NOT_FOUND) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); - } - else if (err != CHIP_NO_ERROR) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); - } - ReturnOnFailure(err); - response.dataset = activeDataset.AsByteSpan(); - ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); -} - -void ServerInstance::HandleGetPendingDatasetRequest(HandlerContext & ctx, - const Commands::GetPendingDatasetRequest::DecodableType & req) +void ServerInstance::HandleGetDatasetRequest(HandlerContext & ctx, Delegate::DatasetType type) { VerifyOrReturn(CheckOverCASESession(ctx)); VerifyOrReturn(CheckDelegate(ctx, mDelegate)); Commands::DatasetResponse::Type response; - Thread::OperationalDataset pendingDataset; - CHIP_ERROR err = mDelegate->GetPendingDataset(pendingDataset); - if (err == CHIP_ERROR_NOT_FOUND) + Thread::OperationalDataset dataset; + CHIP_ERROR err = mDelegate->GetDataset(dataset, type); + if (err != CHIP_NO_ERROR) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::NotFound); - } - else if (err != CHIP_NO_ERROR) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, StatusIB(err).mStatus); + return; } - ReturnOnFailure(err); - response.dataset = pendingDataset.AsByteSpan(); + response.dataset = dataset.AsByteSpan(); ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); } void ServerInstance::HandleSetActiveDatasetRequest(HandlerContext & ctx, const Commands::SetActiveDatasetRequest::DecodableType & req) { + // The SetActiveDatasetRequest command SHALL be FailSafeArmed. Upon receiving this command, the Thread BR will set its + // active dataset. If the dataset is set successfully, OnActivateDatasetComplete will be called with CHIP_NO_ERROR, prompting + // the Thread BR to respond with a success status and disarm the FailSafe timer. If an error occurs while setting the active + // dataset, the Thread BR should respond with a failure status. In this case, when the FailSafe timer expires, the active + // dataset set by this command will be reverted. If the FailSafe timer expires before the Thread BR responds, the Thread BR will + // respond with a timeout status and the active dataset should also be reverted. VerifyOrReturn(CheckFailSafeArmed(ctx)); VerifyOrReturn(CheckDelegate(ctx, mDelegate)); if (mAsyncCommandHandle.Get() != nullptr) { ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Busy); - ctx.SetCommandHandled(); return; } @@ -145,7 +124,7 @@ void ServerInstance::HandleSetActiveDatasetRequest(HandlerContext & ctx, return; } - if (mDelegate->GetActiveDataset(currentActiveDataset) == CHIP_NO_ERROR && + if (mDelegate->GetDataset(currentActiveDataset, Delegate::DatasetType::kActive) == CHIP_NO_ERROR && currentActiveDataset.GetActiveTimestamp(currentActiveDatasetTimestamp) == CHIP_NO_ERROR) { // If this command is invoked when the ActiveDatasetTimestamp attribute is not null, the command SHALL @@ -172,7 +151,7 @@ void ServerInstance::HandleSetPendingDatasetRequest(HandlerContext & ctx, bool panChangeSupported; if (mDelegate->GetPanChangeSupported(panChangeSupported) != CHIP_NO_ERROR || !panChangeSupported) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::UnsupportedCommand); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::UnsupportedCommand); return; } Thread::OperationalDataset pendingDataset; @@ -183,14 +162,8 @@ void ServerInstance::HandleSetPendingDatasetRequest(HandlerContext & ctx, ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); return; } - if (mDelegate->SetPendingDataset(pendingDataset) != CHIP_NO_ERROR) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::Failure); - } - else - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::Success); - } + CHIP_ERROR err = mDelegate->SetPendingDataset(pendingDataset); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, StatusIB(err).mStatus); } void ServerInstance::InvokeCommand(HandlerContext & ctx) @@ -235,7 +208,7 @@ CHIP_ERROR ServerInstance::ReadBorderRouterName(AttributeValueEncoder & aEncoder char borderRouterName[kBorderRouterNameMaxLength]; MutableCharSpan borderRouterNameSpan(borderRouterName); ReturnErrorOnFailure(mDelegate->GetBorderRouterName(borderRouterNameSpan)); - return aEncoder.Encode(chip::CharSpan(borderRouterName, borderRouterNameSpan.size())); + return aEncoder.Encode(borderRouterNameSpan); } CHIP_ERROR ServerInstance::ReadBorderAgentID(AttributeValueEncoder & aEncoder) @@ -243,7 +216,7 @@ CHIP_ERROR ServerInstance::ReadBorderAgentID(AttributeValueEncoder & aEncoder) uint8_t borderAgentId[kBorderAgentIdLength]; MutableByteSpan borderAgentIdSpan(borderAgentId); ReturnErrorOnFailure(mDelegate->GetBorderAgentId(borderAgentIdSpan)); - return aEncoder.Encode(chip::ByteSpan(borderAgentId)); + return aEncoder.Encode(borderAgentIdSpan); } CHIP_ERROR ServerInstance::ReadThreadVersion(AttributeValueEncoder & aEncoder) @@ -264,12 +237,12 @@ CHIP_ERROR ServerInstance::ReadActiveDatasetTimestamp(AttributeValueEncoder & aE { Thread::OperationalDataset activeDataset; uint64_t activeDatasetTimestamp; - if (mDelegate->GetActiveDataset(activeDataset) == CHIP_NO_ERROR && + if (mDelegate->GetDataset(activeDataset, Delegate::DatasetType::kActive) == CHIP_NO_ERROR && activeDataset.GetActiveTimestamp(activeDatasetTimestamp) == CHIP_NO_ERROR) { return aEncoder.Encode(DataModel::MakeNullable(activeDatasetTimestamp)); } - return aEncoder.Encode(DataModel::Nullable()); + return aEncoder.EncodeNull(); } CHIP_ERROR ServerInstance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) @@ -330,7 +303,7 @@ void ServerInstance::OnActivateDatasetComplete(CHIP_ERROR error) if (error == CHIP_NO_ERROR) { // The successful completion of the activation process SHALL disarm the fail-safe timer. - auto & failSafeContext = chip::Server::GetInstance().GetFailSafeContext(); + auto & failSafeContext = Server::GetInstance().GetFailSafeContext(); failSafeContext.DisarmFailSafe(); CommitSavedBreadcrumb(); } @@ -338,21 +311,21 @@ void ServerInstance::OnActivateDatasetComplete(CHIP_ERROR error) { ChipLogError(Zcl, "Failed on activating the active dataset for Thread BR: %" CHIP_ERROR_FORMAT, error.Format()); } - commandHandle->AddStatus(mPath, error == CHIP_NO_ERROR ? Status::Success : Status::Failure); + commandHandle->AddStatus(mPath, StatusIB(error).mStatus); } void ServerInstance::OnFailSafeTimerExpired() { + if (mDelegate) + { + mDelegate->RevertActiveDataset(); + } auto commandHandleRef = std::move(mAsyncCommandHandle); auto commandHandle = commandHandleRef.Get(); if (commandHandle == nullptr) { return; } - if (mDelegate) - { - mDelegate->RevertActiveDataset(); - } commandHandle->AddStatus(mPath, Status::Timeout); } diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h index 0338f411e73dd4..d947afe1c97216 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h @@ -56,10 +56,17 @@ class ServerInstance : public CommandHandlerInterface, public AttributeAccessInt private: // Command Handlers - void HandleGetActiveDatasetRequest(HandlerContext & ctx, const Commands::GetActiveDatasetRequest::DecodableType & req); - void HandleGetPendingDatasetRequest(HandlerContext & ctx, const Commands::GetPendingDatasetRequest::DecodableType & req); + void HandleGetActiveDatasetRequest(HandlerContext & ctx, const Commands::GetActiveDatasetRequest::DecodableType & req) + { + HandleGetDatasetRequest(ctx, Delegate::DatasetType::kActive); + } + void HandleGetPendingDatasetRequest(HandlerContext & ctx, const Commands::GetPendingDatasetRequest::DecodableType & req) + { + HandleGetDatasetRequest(ctx, Delegate::DatasetType::kPending); + } void HandleSetActiveDatasetRequest(HandlerContext & ctx, const Commands::SetActiveDatasetRequest::DecodableType & req); void HandleSetPendingDatasetRequest(HandlerContext & ctx, const Commands::SetPendingDatasetRequest::DecodableType & req); + void HandleGetDatasetRequest(HandlerContext & ctx, Delegate::DatasetType type); // Attribute Read handler CHIP_ERROR ReadFeatureMap(AttributeValueEncoder & aEncoder); diff --git a/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.cpp b/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.cpp index 1a1c6c573cfae8..2bc6f3dde35408 100644 --- a/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.cpp +++ b/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.cpp @@ -92,34 +92,27 @@ CHIP_ERROR ESP32ThreadBorderRouterDelegate::GetInterfaceEnabled(bool & interface return CHIP_NO_ERROR; } -CHIP_ERROR ESP32ThreadBorderRouterDelegate::GetActiveDataset(chip::Thread::OperationalDataset & activeDataset) +CHIP_ERROR ESP32ThreadBorderRouterDelegate::GetDataset(Thread::OperationalDataset & dataset, DatasetType type) { ScopedThreadLock threadLock; + otError otErr = OT_ERROR_NONE; otOperationalDatasetTlvs datasetTlvs; - if (GetThreadEnabled()) + if (type == DatasetType::kActive) { - otError otErr = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &datasetTlvs); - if (otErr == OT_ERROR_NONE) - { - return activeDataset.Init(ByteSpan(datasetTlvs.mTlvs, datasetTlvs.mLength)); - } + otErr = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &datasetTlvs); + } + else + { + otErr = otDatasetGetPendingTlvs(esp_openthread_get_instance(), &datasetTlvs); } - return CHIP_ERROR_NOT_FOUND; -} - -CHIP_ERROR ESP32ThreadBorderRouterDelegate::GetPendingDataset(chip::Thread::OperationalDataset & pendingDataset) -{ - ScopedThreadLock threadLock; - otOperationalDatasetTlvs datasetTlvs; - otError otErr = otDatasetGetPendingTlvs(esp_openthread_get_instance(), &datasetTlvs); if (otErr == OT_ERROR_NONE) { - return pendingDataset.Init(ByteSpan(datasetTlvs.mTlvs, datasetTlvs.mLength)); + return dataset.Init(ByteSpan(datasetTlvs.mTlvs, datasetTlvs.mLength)); } return CHIP_ERROR_NOT_FOUND; } -CHIP_ERROR ESP32ThreadBorderRouterDelegate::SetActiveDataset(const chip::Thread::OperationalDataset & activeDataset, +CHIP_ERROR ESP32ThreadBorderRouterDelegate::SetActiveDataset(const Thread::OperationalDataset & activeDataset, ActivateDatasetCallback * callback) { VerifyOrReturnError(callback, CHIP_ERROR_INVALID_ARGUMENT); @@ -202,7 +195,7 @@ CHIP_ERROR ESP32ThreadBorderRouterDelegate::RevertActiveDataset() return CHIP_NO_ERROR; } -CHIP_ERROR ESP32ThreadBorderRouterDelegate::SetPendingDataset(const chip::Thread::OperationalDataset & pendingDataset) +CHIP_ERROR ESP32ThreadBorderRouterDelegate::SetPendingDataset(const Thread::OperationalDataset & pendingDataset) { ScopedThreadLock threadLock; otOperationalDatasetTlvs datasetTlvs; diff --git a/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.h b/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.h index e869bfd2e16a0e..1fb9f78b76840d 100644 --- a/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.h +++ b/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.h @@ -25,10 +25,6 @@ #include #include -using chip::MutableByteSpan; -using chip::MutableCharSpan; -using chip::Span; - namespace chip { namespace app { namespace Clusters { @@ -70,16 +66,13 @@ class ESP32ThreadBorderRouterDelegate : public Delegate CHIP_ERROR GetInterfaceEnabled(bool & interfaceEnabled) override; - CHIP_ERROR GetActiveDataset(chip::Thread::OperationalDataset & activeDataset) override; - - CHIP_ERROR GetPendingDataset(chip::Thread::OperationalDataset & pendingDataset) override; + CHIP_ERROR GetDataset(Thread::OperationalDataset & dataset, DatasetType type) override; - CHIP_ERROR SetActiveDataset(const chip::Thread::OperationalDataset & activeDataset, - ActivateDatasetCallback * callback) override; + CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, ActivateDatasetCallback * callback) override; CHIP_ERROR RevertActiveDataset() override; - CHIP_ERROR SetPendingDataset(const chip::Thread::OperationalDataset & pendingDataset) override; + CHIP_ERROR SetPendingDataset(const Thread::OperationalDataset & pendingDataset) override; static void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg); From 5ad4655f91b6ab6eac7d2408a3d890ec8d5ed799 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Tue, 18 Jun 2024 12:17:26 +0800 Subject: [PATCH 06/46] move the border router delegate to generic directory --- config/esp32/components/chip/CMakeLists.txt | 4 +- src/platform/ESP32/BUILD.gn | 7 +- .../GenericThreadBorderRouterDelegate.cpp} | 76 +++++++++++-------- .../GenericThreadBorderRouterDelegate.h} | 8 +- 4 files changed, 54 insertions(+), 41 deletions(-) rename src/platform/{ESP32/ESP32ThreadBorderRouterDelegate.cpp => OpenThread/GenericThreadBorderRouterDelegate.cpp} (66%) rename src/platform/{ESP32/ESP32ThreadBorderRouterDelegate.h => OpenThread/GenericThreadBorderRouterDelegate.h} (92%) diff --git a/config/esp32/components/chip/CMakeLists.txt b/config/esp32/components/chip/CMakeLists.txt index 6a001deccbc862..c6ab08e74506ff 100644 --- a/config/esp32/components/chip/CMakeLists.txt +++ b/config/esp32/components/chip/CMakeLists.txt @@ -235,9 +235,9 @@ else() endif() if (CONFIG_OPENTHREAD_BORDER_ROUTER) - chip_gn_arg_append("chip_enable_thread_border_router" "true") + chip_gn_arg_append("chip_openthread_border_router" "true") else() - chip_gn_arg_append("chip_enable_thread_border_router" "false") + chip_gn_arg_append("chip_openthread_border_router" "false") endif() if (CONFIG_ENABLE_OTA_REQUESTOR) diff --git a/src/platform/ESP32/BUILD.gn b/src/platform/ESP32/BUILD.gn index ef48c291ceca31..587388e3f969be 100644 --- a/src/platform/ESP32/BUILD.gn +++ b/src/platform/ESP32/BUILD.gn @@ -33,7 +33,6 @@ declare_args() { chip_use_esp32_ecdsa_peripheral = false chip_enable_ethernet = false chip_enable_route_hook = false - chip_enable_thread_border_router = false } defines = [ @@ -173,10 +172,10 @@ static_library("ESP32") { "../OpenThread/OpenThreadDnssdImpl.h", ] } - if (chip_enable_thread_border_router) { + if (chip_openthread_border_router) { sources += [ - "ESP32ThreadBorderRouterDelegate.cpp", - "ESP32ThreadBorderRouterDelegate.h", + "../OpenThread/GenericThreadBorderRouterDelegate.cpp", + "../OpenThread/GenericThreadBorderRouterDelegate.h", ] } configs -= [ "${chip_root}/build/config/compiler:warnings_default" ] diff --git a/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.cpp b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp similarity index 66% rename from src/platform/ESP32/ESP32ThreadBorderRouterDelegate.cpp rename to src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp index 2bc6f3dde35408..e05e90b1b2ad3f 100644 --- a/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.cpp +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp @@ -15,9 +15,8 @@ * limitations under the License. */ -#include "ESP32ThreadBorderRouterDelegate.h" +#include "GenericThreadBorderRouterDelegate.h" -#include #include #include #include @@ -53,7 +52,7 @@ class ScopedThreadLock ~ScopedThreadLock() { DeviceLayer::ThreadStackMgr().UnlockThreadStack(); } }; -CHIP_ERROR ESP32ThreadBorderRouterDelegate::Init() +CHIP_ERROR GenericThreadBorderRouterDelegate::Init() { mCallback = nullptr; ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler, reinterpret_cast(this))); @@ -61,15 +60,17 @@ CHIP_ERROR ESP32ThreadBorderRouterDelegate::Init() return CHIP_NO_ERROR; } -CHIP_ERROR ESP32ThreadBorderRouterDelegate::GetBorderAgentId(MutableByteSpan & borderAgentIdSpan) +CHIP_ERROR GenericThreadBorderRouterDelegate::GetBorderAgentId(MutableByteSpan & borderAgentIdSpan) { + otInstance *otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); + VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); otBorderAgentId borderAgentId; if (borderAgentIdSpan.size() < sizeof(borderAgentId.mId)) { return CHIP_ERROR_INVALID_ARGUMENT; } ScopedThreadLock threadLock; - otError err = otBorderAgentGetId(esp_openthread_get_instance(), &borderAgentId); + otError err = otBorderAgentGetId(otInst, &borderAgentId); if (err == OT_ERROR_NONE) { memcpy(borderAgentIdSpan.data(), borderAgentId.mId, sizeof(borderAgentId.mId)); @@ -79,31 +80,36 @@ CHIP_ERROR ESP32ThreadBorderRouterDelegate::GetBorderAgentId(MutableByteSpan & b return CHIP_ERROR_INTERNAL; } -CHIP_ERROR ESP32ThreadBorderRouterDelegate::GetThreadVersion(uint16_t & threadVersion) +CHIP_ERROR GenericThreadBorderRouterDelegate::GetThreadVersion(uint16_t & threadVersion) { threadVersion = otThreadGetVersion(); return CHIP_NO_ERROR; } -CHIP_ERROR ESP32ThreadBorderRouterDelegate::GetInterfaceEnabled(bool & interfaceEnabled) +CHIP_ERROR GenericThreadBorderRouterDelegate::GetInterfaceEnabled(bool & interfaceEnabled) { + otInstance *otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); + VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); ScopedThreadLock threadLock; - interfaceEnabled = otIp6IsEnabled(esp_openthread_get_instance()); + interfaceEnabled = otIp6IsEnabled(otInst); return CHIP_NO_ERROR; } -CHIP_ERROR ESP32ThreadBorderRouterDelegate::GetDataset(Thread::OperationalDataset & dataset, DatasetType type) +CHIP_ERROR GenericThreadBorderRouterDelegate::GetDataset(Thread::OperationalDataset & dataset, DatasetType type) { + otInstance *otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); + VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); + ScopedThreadLock threadLock; otError otErr = OT_ERROR_NONE; otOperationalDatasetTlvs datasetTlvs; if (type == DatasetType::kActive) { - otErr = otDatasetGetActiveTlvs(esp_openthread_get_instance(), &datasetTlvs); + otErr = otDatasetGetActiveTlvs(otInst, &datasetTlvs); } else { - otErr = otDatasetGetPendingTlvs(esp_openthread_get_instance(), &datasetTlvs); + otErr = otDatasetGetPendingTlvs(otInst, &datasetTlvs); } if (otErr == OT_ERROR_NONE) { @@ -112,9 +118,12 @@ CHIP_ERROR ESP32ThreadBorderRouterDelegate::GetDataset(Thread::OperationalDatase return CHIP_ERROR_NOT_FOUND; } -CHIP_ERROR ESP32ThreadBorderRouterDelegate::SetActiveDataset(const Thread::OperationalDataset & activeDataset, +CHIP_ERROR GenericThreadBorderRouterDelegate::SetActiveDataset(const Thread::OperationalDataset & activeDataset, ActivateDatasetCallback * callback) { + otInstance *otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); + VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(callback, CHIP_ERROR_INVALID_ARGUMENT); otOperationalDatasetTlvs datasetTlvs; memcpy(datasetTlvs.mTlvs, activeDataset.AsByteSpan().data(), activeDataset.AsByteSpan().size()); @@ -127,7 +136,7 @@ CHIP_ERROR ESP32ThreadBorderRouterDelegate::SetActiveDataset(const Thread::Opera if (threadIsEnabled) { otOperationalDatasetTlvs stagingDataset; - ReturnErrorCodeIf(otDatasetGetActiveTlvs(esp_openthread_get_instance(), &stagingDataset) != OT_ERROR_NONE, + ReturnErrorCodeIf(otDatasetGetActiveTlvs(otInst, &stagingDataset) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); if (activeDataset.AsByteSpan().data_equal(ByteSpan(stagingDataset.mTlvs, stagingDataset.mLength))) { @@ -138,15 +147,15 @@ CHIP_ERROR ESP32ThreadBorderRouterDelegate::SetActiveDataset(const Thread::Opera stagingDataset.mTlvs, stagingDataset.mLength)); } SetThreadEnabled(false); - ReturnErrorCodeIf(otDatasetSetActiveTlvs(esp_openthread_get_instance(), &datasetTlvs) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); + ReturnErrorCodeIf(otDatasetSetActiveTlvs(otInst, &datasetTlvs) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); SetThreadEnabled(true); mCallback = callback; return CHIP_NO_ERROR; } -void ESP32ThreadBorderRouterDelegate::OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg) +void GenericThreadBorderRouterDelegate::OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg) { - ESP32ThreadBorderRouterDelegate * delegate = reinterpret_cast(arg); + GenericThreadBorderRouterDelegate * delegate = reinterpret_cast(arg); if (delegate && delegate->mCallback) { if (event->Type == DeviceLayer::DeviceEventType::kThreadConnectivityChange && @@ -161,8 +170,11 @@ void ESP32ThreadBorderRouterDelegate::OnPlatformEventHandler(const DeviceLayer:: } } -CHIP_ERROR ESP32ThreadBorderRouterDelegate::RevertActiveDataset() +CHIP_ERROR GenericThreadBorderRouterDelegate::RevertActiveDataset() { + otInstance *otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); + VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); + bool threadIsEnabled = false; CHIP_ERROR err = DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(kFailsafeThreadEnabledKey, &threadIsEnabled); if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) @@ -185,7 +197,7 @@ CHIP_ERROR ESP32ThreadBorderRouterDelegate::RevertActiveDataset() ReturnErrorOnFailure(err); stagingDataset.mLength = datasetTlvslen; ReturnErrorOnFailure(SetThreadEnabled(false)); - ReturnErrorCodeIf(otDatasetSetActiveTlvs(esp_openthread_get_instance(), &stagingDataset) != OT_ERROR_NONE, + ReturnErrorCodeIf(otDatasetSetActiveTlvs(otInst, &stagingDataset) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); } ReturnErrorOnFailure(SetThreadEnabled(threadIsEnabled)); @@ -195,40 +207,44 @@ CHIP_ERROR ESP32ThreadBorderRouterDelegate::RevertActiveDataset() return CHIP_NO_ERROR; } -CHIP_ERROR ESP32ThreadBorderRouterDelegate::SetPendingDataset(const Thread::OperationalDataset & pendingDataset) +CHIP_ERROR GenericThreadBorderRouterDelegate::SetPendingDataset(const Thread::OperationalDataset & pendingDataset) { + otInstance *otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); + VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); + ScopedThreadLock threadLock; otOperationalDatasetTlvs datasetTlvs; memcpy(datasetTlvs.mTlvs, pendingDataset.AsByteSpan().data(), pendingDataset.AsByteSpan().size()); datasetTlvs.mLength = pendingDataset.AsByteSpan().size(); - ReturnErrorCodeIf(otDatasetSetPendingTlvs(esp_openthread_get_instance(), &datasetTlvs) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); + ReturnErrorCodeIf(otDatasetSetPendingTlvs(otInst, &datasetTlvs) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); return CHIP_NO_ERROR; } -CHIP_ERROR ESP32ThreadBorderRouterDelegate::SetThreadEnabled(bool enabled) +CHIP_ERROR GenericThreadBorderRouterDelegate::SetThreadEnabled(bool enabled) { - otInstance * instance = esp_openthread_get_instance(); - bool isEnabled = (otThreadGetDeviceRole(instance) != OT_DEVICE_ROLE_DISABLED); - bool isIp6Enabled = otIp6IsEnabled(instance); + otInstance *otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); + VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); + bool isEnabled = (otThreadGetDeviceRole(otInst) != OT_DEVICE_ROLE_DISABLED); + bool isIp6Enabled = otIp6IsEnabled(otInst); if (enabled && !isIp6Enabled) { - ReturnErrorCodeIf(otIp6SetEnabled(instance, enabled) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); + ReturnErrorCodeIf(otIp6SetEnabled(otInst, enabled) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); } if (enabled != isEnabled) { - ReturnErrorCodeIf(otThreadSetEnabled(instance, enabled) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); + ReturnErrorCodeIf(otThreadSetEnabled(otInst, enabled) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); } if (!enabled && isIp6Enabled) { - ReturnErrorCodeIf(otIp6SetEnabled(instance, enabled) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); + ReturnErrorCodeIf(otIp6SetEnabled(otInst, enabled) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); } return CHIP_NO_ERROR; } -bool ESP32ThreadBorderRouterDelegate::GetThreadEnabled() +bool GenericThreadBorderRouterDelegate::GetThreadEnabled() { - otInstance * instance = esp_openthread_get_instance(); - return otIp6IsEnabled(instance) && (otThreadGetDeviceRole(instance) != OT_DEVICE_ROLE_DISABLED); + otInstance *otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); + return otInst && otIp6IsEnabled(otInst) && (otThreadGetDeviceRole(otInst) != OT_DEVICE_ROLE_DISABLED); } } // namespace ThreadBorderRouterManagement diff --git a/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.h b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h similarity index 92% rename from src/platform/ESP32/ESP32ThreadBorderRouterDelegate.h rename to src/platform/OpenThread/GenericThreadBorderRouterDelegate.h index 1fb9f78b76840d..84f3eeead7a819 100644 --- a/src/platform/ESP32/ESP32ThreadBorderRouterDelegate.h +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h @@ -17,13 +17,11 @@ #pragma once -#include "openthread/dataset.h" #include #include #include #include #include -#include namespace chip { namespace app { @@ -31,15 +29,15 @@ namespace Clusters { namespace ThreadBorderRouterManagement { -class ESP32ThreadBorderRouterDelegate : public Delegate +class GenericThreadBorderRouterDelegate : public Delegate { public: static constexpr char kThreadBorderRourterName[] = "Espressif-ThreadBR"; static constexpr char kFailsafeThreadDatasetTlvsKey[] = "g/fs/td"; static constexpr char kFailsafeThreadEnabledKey[] = "g/fs/te"; - ESP32ThreadBorderRouterDelegate() = default; - ~ESP32ThreadBorderRouterDelegate() = default; + GenericThreadBorderRouterDelegate() = default; + ~GenericThreadBorderRouterDelegate() = default; CHIP_ERROR Init() override; From c8f1e9f24299094b9197a87a95d9e39256ea4056 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Tue, 18 Jun 2024 12:48:37 +0000 Subject: [PATCH 07/46] Restyled by clang-format --- .../GenericThreadBorderRouterDelegate.cpp | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp index e05e90b1b2ad3f..c2e1368d23c0dd 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp @@ -62,7 +62,7 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::Init() CHIP_ERROR GenericThreadBorderRouterDelegate::GetBorderAgentId(MutableByteSpan & borderAgentIdSpan) { - otInstance *otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); + otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); otBorderAgentId borderAgentId; if (borderAgentIdSpan.size() < sizeof(borderAgentId.mId)) @@ -88,7 +88,7 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::GetThreadVersion(uint16_t & thread CHIP_ERROR GenericThreadBorderRouterDelegate::GetInterfaceEnabled(bool & interfaceEnabled) { - otInstance *otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); + otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); ScopedThreadLock threadLock; interfaceEnabled = otIp6IsEnabled(otInst); @@ -97,7 +97,7 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::GetInterfaceEnabled(bool & interfa CHIP_ERROR GenericThreadBorderRouterDelegate::GetDataset(Thread::OperationalDataset & dataset, DatasetType type) { - otInstance *otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); + otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); ScopedThreadLock threadLock; @@ -119,9 +119,9 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::GetDataset(Thread::OperationalData } CHIP_ERROR GenericThreadBorderRouterDelegate::SetActiveDataset(const Thread::OperationalDataset & activeDataset, - ActivateDatasetCallback * callback) + ActivateDatasetCallback * callback) { - otInstance *otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); + otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); VerifyOrReturnError(callback, CHIP_ERROR_INVALID_ARGUMENT); @@ -136,8 +136,7 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::SetActiveDataset(const Thread::Ope if (threadIsEnabled) { otOperationalDatasetTlvs stagingDataset; - ReturnErrorCodeIf(otDatasetGetActiveTlvs(otInst, &stagingDataset) != OT_ERROR_NONE, - CHIP_ERROR_INTERNAL); + ReturnErrorCodeIf(otDatasetGetActiveTlvs(otInst, &stagingDataset) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); if (activeDataset.AsByteSpan().data_equal(ByteSpan(stagingDataset.mTlvs, stagingDataset.mLength))) { callback->OnActivateDatasetComplete(CHIP_NO_ERROR); @@ -172,7 +171,7 @@ void GenericThreadBorderRouterDelegate::OnPlatformEventHandler(const DeviceLayer CHIP_ERROR GenericThreadBorderRouterDelegate::RevertActiveDataset() { - otInstance *otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); + otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); bool threadIsEnabled = false; @@ -197,8 +196,7 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::RevertActiveDataset() ReturnErrorOnFailure(err); stagingDataset.mLength = datasetTlvslen; ReturnErrorOnFailure(SetThreadEnabled(false)); - ReturnErrorCodeIf(otDatasetSetActiveTlvs(otInst, &stagingDataset) != OT_ERROR_NONE, - CHIP_ERROR_INTERNAL); + ReturnErrorCodeIf(otDatasetSetActiveTlvs(otInst, &stagingDataset) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); } ReturnErrorOnFailure(SetThreadEnabled(threadIsEnabled)); // Delete Failsafe Keys after reverting. @@ -209,7 +207,7 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::RevertActiveDataset() CHIP_ERROR GenericThreadBorderRouterDelegate::SetPendingDataset(const Thread::OperationalDataset & pendingDataset) { - otInstance *otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); + otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); ScopedThreadLock threadLock; @@ -222,10 +220,10 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::SetPendingDataset(const Thread::Op CHIP_ERROR GenericThreadBorderRouterDelegate::SetThreadEnabled(bool enabled) { - otInstance *otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); + otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); - bool isEnabled = (otThreadGetDeviceRole(otInst) != OT_DEVICE_ROLE_DISABLED); - bool isIp6Enabled = otIp6IsEnabled(otInst); + bool isEnabled = (otThreadGetDeviceRole(otInst) != OT_DEVICE_ROLE_DISABLED); + bool isIp6Enabled = otIp6IsEnabled(otInst); if (enabled && !isIp6Enabled) { ReturnErrorCodeIf(otIp6SetEnabled(otInst, enabled) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); @@ -243,7 +241,7 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::SetThreadEnabled(bool enabled) bool GenericThreadBorderRouterDelegate::GetThreadEnabled() { - otInstance *otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); + otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); return otInst && otIp6IsEnabled(otInst) && (otThreadGetDeviceRole(otInst) != OT_DEVICE_ROLE_DISABLED); } From ea5aff623499ca2c47304811c973237e62f7d57f Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Thu, 20 Jun 2024 19:11:05 +0800 Subject: [PATCH 08/46] remove the duplicate thread br management cluster in controller zap --- .../data_model/controller-clusters.zap | 86 +------------------ 1 file changed, 1 insertion(+), 85 deletions(-) diff --git a/src/controller/data_model/controller-clusters.zap b/src/controller/data_model/controller-clusters.zap index eebde797075997..b716c9ddd28d0c 100644 --- a/src/controller/data_model/controller-clusters.zap +++ b/src/controller/data_model/controller-clusters.zap @@ -1181,90 +1181,6 @@ } ] }, - { - "name": "Thread Border Router Management", - "code": 1106, - "mfgCode": null, - "define": "THREAD_BORDER_ROUTER_MANAGEMENT_CLUSTER", - "side": "client", - "enabled": 1, - "commands": [ - { - "name": "GetActiveDatasetRequest", - "code": 0, - "mfgCode": null, - "source": "client", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "GetPendingDatasetRequest", - "code": 1, - "mfgCode": null, - "source": "client", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "DatasetResponse", - "code": 3, - "mfgCode": null, - "source": "server", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "SetActiveDatasetRequest", - "code": 4, - "mfgCode": null, - "source": "client", - "isIncoming": 0, - "isEnabled": 1 - }, - { - "name": "SetPendingDatasetRequest", - "code": 5, - "mfgCode": null, - "source": "client", - "isIncoming": 0, - "isEnabled": 1 - } - ], - "attributes": [ - { - "name": "FeatureMap", - "code": 65532, - "mfgCode": null, - "side": "client", - "type": "bitmap32", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "0", - "reportable": 1, - "minInterval": 1, - "maxInterval": 65534, - "reportableChange": 0 - }, - { - "name": "ClusterRevision", - "code": 65533, - "mfgCode": null, - "side": "client", - "type": "int16u", - "included": 1, - "storageOption": "RAM", - "singleton": 0, - "bounded": 0, - "defaultValue": "2", - "reportable": 1, - "minInterval": 0, - "maxInterval": 65344, - "reportableChange": 0 - } - ] - }, { "name": "Thread Network Diagnostics", "code": 53, @@ -5888,4 +5804,4 @@ "parentEndpointIdentifier": null } ] -} \ No newline at end of file +} From 280a619c3850e2a70566cb6a2798d715c7254900 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Fri, 21 Jun 2024 10:40:46 +0800 Subject: [PATCH 09/46] Ensure that the Get dataset response failure status matches the spec --- .../thread-br-mgmt-server.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp index 258b603e7bc471..fe5c1b10672333 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp +++ b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp @@ -89,7 +89,8 @@ void ServerInstance::HandleGetDatasetRequest(HandlerContext & ctx, Delegate::Dat CHIP_ERROR err = mDelegate->GetDataset(dataset, type); if (err != CHIP_NO_ERROR) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, StatusIB(err).mStatus); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, + err == CHIP_IM_GLOBAL_STATUS(NotFound) ? StatusIB(err).mStatus : Status::Failure); return; } response.dataset = dataset.AsByteSpan(); From 656fe2cb3718e31b56c063f5dde992d8357e52fe Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Mon, 24 Jun 2024 19:57:51 +0800 Subject: [PATCH 10/46] add the document for ActivateDatasetCallback --- .../thread-br-delegate.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h index cd56cf827648c3..f490c6c99c3d9e 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h @@ -43,6 +43,9 @@ class Delegate class ActivateDatasetCallback { public: + // If the dataset is set successfully, OnActivateDatasetComplete should be called with CHIP_NO_ERROR when the + // Border Router is attached to the Thread network. + // If an error occurs while setting the active dataset, this callback should be called with the error. virtual void OnActivateDatasetComplete(CHIP_ERROR error) = 0; }; From 3c2e3adb9cba443a6a901dedf2a9c5f9a9fb1a9c Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Tue, 25 Jun 2024 11:34:48 +0800 Subject: [PATCH 11/46] Update GenericThreadBorderRouterDelegate and add the function description for thread-br-delegate --- .../thread-br-delegate.h | 8 +- .../GenericThreadBorderRouterDelegate.cpp | 122 ++++++------------ .../GenericThreadBorderRouterDelegate.h | 7 +- 3 files changed, 52 insertions(+), 85 deletions(-) diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h index f490c6c99c3d9e..33ba9d1fe00bfe 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h @@ -69,10 +69,14 @@ class Delegate virtual CHIP_ERROR GetDataset(Thread::OperationalDataset & dataset, DatasetType type) = 0; + // The Delegate implement should back up the old active dataset at the begining of function if no backup already exists. virtual CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, ActivateDatasetCallback * callback) = 0; - // The Thread BR should be able to revert the active dataset set by SetActiveDataset(), and restore - // the previous status of Thread BR. + // The Delegate implement should remove the backup active dataset in this function. + virtual CHIP_ERROR CommitActiveDataset() = 0; + + // The Delegate implement should restore the backup active dataset in this function. + // Once RevertActiveDataset is called the ActivateDatasetCallback of previous SetActiveDataset should never be called. virtual CHIP_ERROR RevertActiveDataset() = 0; virtual CHIP_ERROR SetPendingDataset(const Thread::OperationalDataset & pendingDataset) = 0; diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp index c2e1368d23c0dd..a6663c0662c8ef 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp @@ -121,35 +121,16 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::GetDataset(Thread::OperationalData CHIP_ERROR GenericThreadBorderRouterDelegate::SetActiveDataset(const Thread::OperationalDataset & activeDataset, ActivateDatasetCallback * callback) { - otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); - VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); - - VerifyOrReturnError(callback, CHIP_ERROR_INVALID_ARGUMENT); - otOperationalDatasetTlvs datasetTlvs; - memcpy(datasetTlvs.mTlvs, activeDataset.AsByteSpan().data(), activeDataset.AsByteSpan().size()); - datasetTlvs.mLength = activeDataset.AsByteSpan().size(); - - ScopedThreadLock threadLock; - // Save the previous thread state and dataset for reverting - bool threadIsEnabled = GetThreadEnabled(); - ReturnErrorOnFailure(DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(kFailsafeThreadEnabledKey, threadIsEnabled)); - if (threadIsEnabled) + CHIP_ERROR err = BackupActiveDataset(); + if (err == CHIP_NO_ERROR) { - otOperationalDatasetTlvs stagingDataset; - ReturnErrorCodeIf(otDatasetGetActiveTlvs(otInst, &stagingDataset) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); - if (activeDataset.AsByteSpan().data_equal(ByteSpan(stagingDataset.mTlvs, stagingDataset.mLength))) - { - callback->OnActivateDatasetComplete(CHIP_NO_ERROR); - return CHIP_NO_ERROR; - } - ReturnErrorOnFailure(DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(kFailsafeThreadDatasetTlvsKey, - stagingDataset.mTlvs, stagingDataset.mLength)); + err = DeviceLayer::ThreadStackMgrImpl().AttachToThreadNetwork(activeDataset, nullptr); } - SetThreadEnabled(false); - ReturnErrorCodeIf(otDatasetSetActiveTlvs(otInst, &datasetTlvs) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); - SetThreadEnabled(true); - mCallback = callback; - return CHIP_NO_ERROR; + if (err == CHIP_NO_ERROR) + { + mCallback = callback; + } + return err; } void GenericThreadBorderRouterDelegate::OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg) @@ -163,45 +144,53 @@ void GenericThreadBorderRouterDelegate::OnPlatformEventHandler(const DeviceLayer delegate->mCallback->OnActivateDatasetComplete(CHIP_NO_ERROR); // Delete Failsafe Keys after activating dataset is completed DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(kFailsafeThreadDatasetTlvsKey); - DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(kFailsafeThreadEnabledKey); delegate->mCallback = nullptr; } } } -CHIP_ERROR GenericThreadBorderRouterDelegate::RevertActiveDataset() +CHIP_ERROR GenericThreadBorderRouterDelegate::BackupActiveDataset() { - otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); - VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); - - bool threadIsEnabled = false; - CHIP_ERROR err = DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(kFailsafeThreadEnabledKey, &threadIsEnabled); - if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) + // If active dataset is already backed up, return with no error + CHIP_ERROR err = DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(kFailsafeThreadDatasetTlvsKey, nullptr, 0); + if (err == CHIP_NO_ERROR || err == CHIP_ERROR_BUFFER_TOO_SMALL) { return CHIP_NO_ERROR; } - ReturnErrorOnFailure(err); + GetDataset(mStagingDataset, DatasetType::kActive); + ByteSpan dataset = mStagingDataset.AsByteSpan(); + return DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(kFailsafeThreadDatasetTlvsKey, dataset.data(), dataset.size()); +} - ScopedThreadLock threadLock; - if (threadIsEnabled) +CHIP_ERROR GenericThreadBorderRouterDelegate::CommitActiveDataset() +{ + // Delete Failsafe Key when committing. + DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(kFailsafeThreadDatasetTlvsKey); + return CHIP_NO_ERROR; +} + +CHIP_ERROR GenericThreadBorderRouterDelegate::RevertActiveDataset() +{ + // The FailSafe Timer is triggered and the previous command request should be handled, so reset the callback. + mCallback = nullptr; + uint8_t datasetBytes[Thread::kSizeOperationalDataset]; + size_t datasetLength; + CHIP_ERROR err = DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(kFailsafeThreadDatasetTlvsKey, datasetBytes, + sizeof(datasetBytes), &datasetLength); + // If no backup could be found, it means the active datset has not been modified since the fail-safe was armed, + // so return with no error. + ReturnErrorCodeIf(err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND, CHIP_NO_ERROR); + if (err == CHIP_NO_ERROR) { - otOperationalDatasetTlvs stagingDataset; - size_t datasetTlvslen = 0; - err = DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(kFailsafeThreadDatasetTlvsKey, stagingDataset.mTlvs, - sizeof(stagingDataset.mTlvs), &datasetTlvslen); - if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND) - { - return CHIP_NO_ERROR; - } - ReturnErrorOnFailure(err); - stagingDataset.mLength = datasetTlvslen; - ReturnErrorOnFailure(SetThreadEnabled(false)); - ReturnErrorCodeIf(otDatasetSetActiveTlvs(otInst, &stagingDataset) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); + err = mStagingDataset.Init(ByteSpan(datasetBytes, datasetLength)); + } + if (err == CHIP_NO_ERROR) + { + err = DeviceLayer::ThreadStackMgrImpl().AttachToThreadNetwork(mStagingDataset, nullptr); } - ReturnErrorOnFailure(SetThreadEnabled(threadIsEnabled)); - // Delete Failsafe Keys after reverting. + + // Always delete the backup, regardless if it can be successfully restored. DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(kFailsafeThreadDatasetTlvsKey); - DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(kFailsafeThreadEnabledKey); return CHIP_NO_ERROR; } @@ -218,33 +207,6 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::SetPendingDataset(const Thread::Op return CHIP_NO_ERROR; } -CHIP_ERROR GenericThreadBorderRouterDelegate::SetThreadEnabled(bool enabled) -{ - otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); - VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); - bool isEnabled = (otThreadGetDeviceRole(otInst) != OT_DEVICE_ROLE_DISABLED); - bool isIp6Enabled = otIp6IsEnabled(otInst); - if (enabled && !isIp6Enabled) - { - ReturnErrorCodeIf(otIp6SetEnabled(otInst, enabled) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); - } - if (enabled != isEnabled) - { - ReturnErrorCodeIf(otThreadSetEnabled(otInst, enabled) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); - } - if (!enabled && isIp6Enabled) - { - ReturnErrorCodeIf(otIp6SetEnabled(otInst, enabled) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); - } - return CHIP_NO_ERROR; -} - -bool GenericThreadBorderRouterDelegate::GetThreadEnabled() -{ - otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); - return otInst && otIp6IsEnabled(otInst) && (otThreadGetDeviceRole(otInst) != OT_DEVICE_ROLE_DISABLED); -} - } // namespace ThreadBorderRouterManagement } // namespace Clusters } // namespace app diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h index 84f3eeead7a819..b38f9ab021ee9b 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h @@ -34,7 +34,6 @@ class GenericThreadBorderRouterDelegate : public Delegate public: static constexpr char kThreadBorderRourterName[] = "Espressif-ThreadBR"; static constexpr char kFailsafeThreadDatasetTlvsKey[] = "g/fs/td"; - static constexpr char kFailsafeThreadEnabledKey[] = "g/fs/te"; GenericThreadBorderRouterDelegate() = default; ~GenericThreadBorderRouterDelegate() = default; @@ -70,14 +69,16 @@ class GenericThreadBorderRouterDelegate : public Delegate CHIP_ERROR RevertActiveDataset() override; + CHIP_ERROR CommitActiveDataset() override; + CHIP_ERROR SetPendingDataset(const Thread::OperationalDataset & pendingDataset) override; static void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg); private: - CHIP_ERROR SetThreadEnabled(bool enabled); - bool GetThreadEnabled(); + CHIP_ERROR BackupActiveDataset(); ActivateDatasetCallback * mCallback = nullptr; + Thread::OperationalDataset mStagingDataset = {}; }; } // namespace ThreadBorderRouterManagement } // namespace Clusters From 9e4bc2502ae53e0c8d0507646ad4e3960cae47b4 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Tue, 25 Jun 2024 04:18:56 +0000 Subject: [PATCH 12/46] Restyled by clang-format --- src/platform/OpenThread/GenericThreadBorderRouterDelegate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h index b38f9ab021ee9b..5331b11d88ce01 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h @@ -77,7 +77,7 @@ class GenericThreadBorderRouterDelegate : public Delegate private: CHIP_ERROR BackupActiveDataset(); - ActivateDatasetCallback * mCallback = nullptr; + ActivateDatasetCallback * mCallback = nullptr; Thread::OperationalDataset mStagingDataset = {}; }; } // namespace ThreadBorderRouterManagement From b0cca2503216a5479bb4c4a8852b633875e0977c Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Wed, 26 Jun 2024 14:08:30 +0800 Subject: [PATCH 13/46] Add unit test --- .../thread-br-delegate.h | 2 + .../thread-br-mgmt-server.cpp | 267 ++++++++++-------- .../thread-br-mgmt-server.h | 28 +- src/app/tests/BUILD.gn | 15 + ...estThreadBorderRouterManagementCluster.cpp | 242 ++++++++++++++++ .../data_model/controller-clusters.zap | 2 +- 6 files changed, 421 insertions(+), 135 deletions(-) create mode 100644 src/app/tests/TestThreadBorderRouterManagementCluster.cpp diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h index 33ba9d1fe00bfe..efc20625680625 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h @@ -43,6 +43,8 @@ class Delegate class ActivateDatasetCallback { public: + ActivateDatasetCallback() = default; + virtual ~ActivateDatasetCallback() = default; // If the dataset is set successfully, OnActivateDatasetComplete should be called with CHIP_NO_ERROR when the // Border Router is attached to the Thread network. // If an error occurs while setting the active dataset, this callback should be called with the error. diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp index fe5c1b10672333..b85d59f726717a 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp +++ b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp @@ -45,60 +45,37 @@ namespace ThreadBorderRouterManagement { using Protocols::InteractionModel::Status; -static bool CheckOverCASESession(CommandHandlerInterface::HandlerContext & ctx) +static bool IsOverCASESession(CommandHandlerInterface::HandlerContext & ctx) { Messaging::ExchangeContext * exchangeCtx = ctx.mCommandHandler.GetExchangeContext(); - if (!exchangeCtx || !exchangeCtx->HasSessionHandle() || !exchangeCtx->GetSessionHandle()->IsSecureSession() || - exchangeCtx->GetSessionHandle()->AsSecureSession()->GetSecureSessionType() != Transport::SecureSession::Type::kCASE) - { - ChipLogError(Zcl, "This command MUST be over a valid CASE session"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::UnsupportedAccess); - return false; - } - return true; + return exchangeCtx && exchangeCtx->HasSessionHandle() && exchangeCtx->GetSessionHandle()->IsSecureSession() && + exchangeCtx->GetSessionHandle()->AsSecureSession()->GetSecureSessionType() == Transport::SecureSession::Type::kCASE; } -static bool CheckFailSafeArmed(CommandHandlerInterface::HandlerContext & ctx) +static bool IsFailSafeArmed(CommandHandlerInterface::HandlerContext & ctx) { auto & failSafeContext = Server::GetInstance().GetFailSafeContext(); - if (failSafeContext.IsFailSafeArmed(ctx.mCommandHandler.GetAccessingFabricIndex())) - { - return true; - } - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::FailsafeRequired); - return false; + return failSafeContext.IsFailSafeArmed(ctx.mCommandHandler.GetAccessingFabricIndex()); } -static bool CheckDelegate(CommandHandlerInterface::HandlerContext & ctx, Delegate * delegate) +Status ServerInstance::HandleGetDatasetRequest(bool isOverCASESession, Delegate::DatasetType type, + Thread::OperationalDataset & dataset) { - if (!delegate) + if (!isOverCASESession) { - ChipLogError(Zcl, "Thread Border Router Management server not initialized"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidInState); + return Status::UnsupportedAccess; } - return delegate; -} - -void ServerInstance::HandleGetDatasetRequest(HandlerContext & ctx, Delegate::DatasetType type) -{ - VerifyOrReturn(CheckOverCASESession(ctx)); - VerifyOrReturn(CheckDelegate(ctx, mDelegate)); - Commands::DatasetResponse::Type response; - Thread::OperationalDataset dataset; CHIP_ERROR err = mDelegate->GetDataset(dataset, type); if (err != CHIP_NO_ERROR) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, - err == CHIP_IM_GLOBAL_STATUS(NotFound) ? StatusIB(err).mStatus : Status::Failure); - return; + return err == CHIP_IM_GLOBAL_STATUS(NotFound) ? StatusIB(err).mStatus : Status::Failure; } - response.dataset = dataset.AsByteSpan(); - ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + return Status::Success; } -void ServerInstance::HandleSetActiveDatasetRequest(HandlerContext & ctx, - const Commands::SetActiveDatasetRequest::DecodableType & req) +Status ServerInstance::HandleSetActiveDatasetRequest(bool failSafeArmed, + const Commands::SetActiveDatasetRequest::DecodableType & req) { // The SetActiveDatasetRequest command SHALL be FailSafeArmed. Upon receiving this command, the Thread BR will set its // active dataset. If the dataset is set successfully, OnActivateDatasetComplete will be called with CHIP_NO_ERROR, prompting @@ -106,144 +83,153 @@ void ServerInstance::HandleSetActiveDatasetRequest(HandlerContext & ctx, // dataset, the Thread BR should respond with a failure status. In this case, when the FailSafe timer expires, the active // dataset set by this command will be reverted. If the FailSafe timer expires before the Thread BR responds, the Thread BR will // respond with a timeout status and the active dataset should also be reverted. - VerifyOrReturn(CheckFailSafeArmed(ctx)); - VerifyOrReturn(CheckDelegate(ctx, mDelegate)); - if (mAsyncCommandHandle.Get() != nullptr) - { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Busy); - return; - } + ReturnErrorCodeIf(!failSafeArmed, Status::FailsafeRequired); + ReturnErrorCodeIf(!mDelegate, Status::InvalidInState); Thread::OperationalDataset activeDataset; Thread::OperationalDataset currentActiveDataset; uint64_t currentActiveDatasetTimestamp; - if (activeDataset.Init(req.activeDataset) != CHIP_NO_ERROR) - { - // If any of the parameters in the ActiveDataset is invalid, the command SHALL fail with a status code - // of INVALID_COMMAND. - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); - return; - } + // If any of the parameters in the ActiveDataset is invalid, the command SHALL fail with a status code + // of INVALID_COMMAND. + ReturnErrorCodeIf(activeDataset.Init(req.activeDataset) != CHIP_NO_ERROR, Status::InvalidCommand); + // If this command is invoked when the ActiveDatasetTimestamp attribute is not null, the command SHALL + // fail with a status code of INVALID_IN_STATE. if (mDelegate->GetDataset(currentActiveDataset, Delegate::DatasetType::kActive) == CHIP_NO_ERROR && currentActiveDataset.GetActiveTimestamp(currentActiveDatasetTimestamp) == CHIP_NO_ERROR) { - // If this command is invoked when the ActiveDatasetTimestamp attribute is not null, the command SHALL - // fail with a status code of INVALID_IN_STATE. - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidInState); - return; + return Status::InvalidInState; } - mPath = ctx.mRequestPath; - mAsyncCommandHandle = CommandHandler::Handle(&ctx.mCommandHandler); - ctx.mCommandHandler.FlushAcksRightAwayOnSlowCommand(); mBreadcrumb = req.breadcrumb; - CHIP_ERROR err = CHIP_NO_ERROR; - if ((err = mDelegate->SetActiveDataset(activeDataset, this)) != CHIP_NO_ERROR) - { - OnActivateDatasetComplete(err); - } + CHIP_ERROR err = mDelegate->SetActiveDataset(activeDataset, this); + return StatusIB(err).mStatus; } -void ServerInstance::HandleSetPendingDatasetRequest(HandlerContext & ctx, - const Commands::SetPendingDatasetRequest::DecodableType & req) +Status ServerInstance::HandleSetPendingDatasetRequest(const Commands::SetPendingDatasetRequest::DecodableType & req) { - VerifyOrReturn(CheckDelegate(ctx, mDelegate)); + ReturnErrorCodeIf(!mDelegate, Status::InvalidInState); bool panChangeSupported; if (mDelegate->GetPanChangeSupported(panChangeSupported) != CHIP_NO_ERROR || !panChangeSupported) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::UnsupportedCommand); - return; + return Status::UnsupportedCommand; } Thread::OperationalDataset pendingDataset; - if (pendingDataset.Init(req.pendingDataset) != CHIP_NO_ERROR) + // If any of the parameters in the PendingDataset is invalid, the command SHALL fail with a status code + // of INVALID_COMMAND. + ReturnErrorCodeIf(pendingDataset.Init(req.pendingDataset) != CHIP_NO_ERROR, Status::InvalidCommand); + CHIP_ERROR err = mDelegate->SetPendingDataset(pendingDataset); + return StatusIB(err).mStatus; +} + +void AddDatasetResponse(CommandHandlerInterface::HandlerContext & ctx, Status status, Thread::OperationalDataset & dataset) +{ + if (status != Status::Success) { - // If any of the parameters in the PendingDataset is invalid, the command SHALL fail with a status code - // of INVALID_COMMAND. - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::InvalidCommand); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); return; } - CHIP_ERROR err = mDelegate->SetPendingDataset(pendingDataset); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, StatusIB(err).mStatus); + Commands::DatasetResponse::Type response; + response.dataset = dataset.AsByteSpan(); + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); } -void ServerInstance::InvokeCommand(HandlerContext & ctx) +void ServerInstance::InvokeCommand(HandlerContext & ctxt) { - switch (ctx.mRequestPath.mCommandId) + switch (ctxt.mRequestPath.mCommandId) { case Commands::GetActiveDatasetRequest::Id: - HandleCommand( - ctx, [this](HandlerContext & ctx, const auto & req) { HandleGetActiveDatasetRequest(ctx, req); }); + HandleCommand(ctxt, [this](HandlerContext & ctx, const auto & req) { + Thread::OperationalDataset dataset; + Status status = HandleGetActiveDatasetRequest(IsOverCASESession(ctx), dataset); + AddDatasetResponse(ctx, status, dataset); + }); break; case Commands::GetPendingDatasetRequest::Id: - HandleCommand( - ctx, [this](HandlerContext & ctx, const auto & req) { HandleGetPendingDatasetRequest(ctx, req); }); + HandleCommand(ctxt, [this](HandlerContext & ctx, const auto & req) { + Thread::OperationalDataset dataset; + Status status = HandleGetPendingDatasetRequest(IsOverCASESession(ctx), dataset); + AddDatasetResponse(ctx, status, dataset); + }); break; case Commands::SetActiveDatasetRequest::Id: - HandleCommand( - ctx, [this](HandlerContext & ctx, const auto & req) { HandleSetActiveDatasetRequest(ctx, req); }); + HandleCommand(ctxt, [this](HandlerContext & ctx, const auto & req) { + if (!mAsyncCommandHandle.Get()) + { + mPath = ctx.mRequestPath; + mAsyncCommandHandle = CommandHandler::Handle(&ctx.mCommandHandler); + ctx.mCommandHandler.FlushAcksRightAwayOnSlowCommand(); + Status status = HandleSetActiveDatasetRequest(IsFailSafeArmed(ctx), req); + if (status != Status::Success) + { + OnActivateDatasetComplete(ChipError(ChipError::SdkPart::kIMGlobalStatus, to_underlying(status))); + } + } + else + { + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Busy); + } + }); break; case Commands::SetPendingDatasetRequest::Id: - HandleCommand( - ctx, [this](HandlerContext & ctx, const auto & req) { HandleSetPendingDatasetRequest(ctx, req); }); + HandleCommand(ctxt, [this](HandlerContext & ctx, const auto & req) { + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, HandleSetPendingDatasetRequest(req)); + }); break; default: break; } } -CHIP_ERROR ServerInstance::ReadFeatureMap(AttributeValueEncoder & aEncoder) +CHIP_ERROR ServerInstance::ReadFeatureMap(BitFlags & featureMap) { - BitFlags featureMap; bool panChangeSupported; ReturnErrorOnFailure(mDelegate->GetPanChangeSupported(panChangeSupported)); if (panChangeSupported) { featureMap.Set(Feature::kPANChange); } - return aEncoder.Encode(featureMap); + return CHIP_NO_ERROR; } -CHIP_ERROR ServerInstance::ReadBorderRouterName(AttributeValueEncoder & aEncoder) +CHIP_ERROR ServerInstance::ReadBorderRouterName(MutableCharSpan & borderRouterName) { - char borderRouterName[kBorderRouterNameMaxLength]; - MutableCharSpan borderRouterNameSpan(borderRouterName); - ReturnErrorOnFailure(mDelegate->GetBorderRouterName(borderRouterNameSpan)); - return aEncoder.Encode(borderRouterNameSpan); + ReturnErrorOnFailure(mDelegate->GetBorderRouterName(borderRouterName)); + ReturnErrorCodeIf(borderRouterName.size() > kBorderRouterNameMaxLength, CHIP_IM_GLOBAL_STATUS(ConstraintError)); + return CHIP_NO_ERROR; } -CHIP_ERROR ServerInstance::ReadBorderAgentID(AttributeValueEncoder & aEncoder) +CHIP_ERROR ServerInstance::ReadBorderAgentID(MutableByteSpan & borderAgentId) { - uint8_t borderAgentId[kBorderAgentIdLength]; - MutableByteSpan borderAgentIdSpan(borderAgentId); - ReturnErrorOnFailure(mDelegate->GetBorderAgentId(borderAgentIdSpan)); - return aEncoder.Encode(borderAgentIdSpan); + ReturnErrorOnFailure(mDelegate->GetBorderAgentId(borderAgentId)); + ReturnErrorCodeIf(borderAgentId.size() != kBorderAgentIdLength, CHIP_IM_GLOBAL_STATUS(ConstraintError)); + return CHIP_NO_ERROR; } -CHIP_ERROR ServerInstance::ReadThreadVersion(AttributeValueEncoder & aEncoder) +CHIP_ERROR ServerInstance::ReadThreadVersion(uint16_t & threadVersion) { - uint16_t threadVersion; - ReturnErrorOnFailure(mDelegate->GetThreadVersion(threadVersion)); - return aEncoder.Encode(threadVersion); + return mDelegate->GetThreadVersion(threadVersion); } -CHIP_ERROR ServerInstance::ReadInterfaceEnabled(AttributeValueEncoder & aEncoder) +CHIP_ERROR ServerInstance::ReadInterfaceEnabled(bool & interfaceEnabled) { - bool interfaceEnabled; - ReturnErrorOnFailure(mDelegate->GetInterfaceEnabled(interfaceEnabled)); - return aEncoder.Encode(interfaceEnabled); + return mDelegate->GetInterfaceEnabled(interfaceEnabled); } -CHIP_ERROR ServerInstance::ReadActiveDatasetTimestamp(AttributeValueEncoder & aEncoder) +CHIP_ERROR ServerInstance::ReadActiveDatasetTimestamp(Optional & activeDatasetTimestamp) { + uint64_t activeDatasetTimestampValue; Thread::OperationalDataset activeDataset; - uint64_t activeDatasetTimestamp; if (mDelegate->GetDataset(activeDataset, Delegate::DatasetType::kActive) == CHIP_NO_ERROR && - activeDataset.GetActiveTimestamp(activeDatasetTimestamp) == CHIP_NO_ERROR) + activeDataset.GetActiveTimestamp(activeDatasetTimestampValue) == CHIP_NO_ERROR) { - return aEncoder.Encode(DataModel::MakeNullable(activeDatasetTimestamp)); + activeDatasetTimestamp.SetValue(activeDatasetTimestampValue); } - return aEncoder.EncodeNull(); + else + { + activeDatasetTimestamp.ClearValue(); + } + return CHIP_NO_ERROR; } CHIP_ERROR ServerInstance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) @@ -260,24 +246,63 @@ CHIP_ERROR ServerInstance::Read(const ConcreteReadAttributePath & aPath, Attribu CHIP_ERROR status = CHIP_NO_ERROR; switch (aPath.mAttributeId) { - case Globals::Attributes::FeatureMap::Id: - status = ReadFeatureMap(aEncoder); + case Globals::Attributes::FeatureMap::Id: { + BitFlags featureMap; + status = ReadFeatureMap(featureMap); + if (status == CHIP_NO_ERROR) + { + status = aEncoder.Encode(featureMap); + } break; - case Attributes::BorderRouterName::Id: - status = ReadBorderRouterName(aEncoder); + } + case Attributes::BorderRouterName::Id: { + char borderRouterNameBuf[kBorderRouterNameMaxLength + 1]; + MutableCharSpan borderRouterName(borderRouterNameBuf); + status = ReadBorderRouterName(borderRouterName); + if (status == CHIP_NO_ERROR) + { + status = aEncoder.Encode(borderRouterName); + } break; - case Attributes::BorderAgentID::Id: - status = ReadBorderAgentID(aEncoder); + } + case Attributes::BorderAgentID::Id: { + uint8_t borderAgentIDBuf[kBorderAgentIdLength]; + MutableByteSpan borderAgentID(borderAgentIDBuf); + status = ReadBorderAgentID(borderAgentID); + if (status == CHIP_NO_ERROR) + { + status = aEncoder.Encode(borderAgentID); + } break; - case Attributes::ThreadVersion::Id: - status = ReadThreadVersion(aEncoder); + } + case Attributes::ThreadVersion::Id: { + uint16_t threadVersion; + status = ReadThreadVersion(threadVersion); + if (status == CHIP_NO_ERROR) + { + status = aEncoder.Encode(threadVersion); + } break; - case Attributes::InterfaceEnabled::Id: - status = ReadInterfaceEnabled(aEncoder); + } + case Attributes::InterfaceEnabled::Id: { + bool interfaceEnabled; + status = ReadInterfaceEnabled(interfaceEnabled); + if (status == CHIP_NO_ERROR) + { + status = aEncoder.Encode(interfaceEnabled); + } break; - case Attributes::ActiveDatasetTimestamp::Id: - status = ReadActiveDatasetTimestamp(aEncoder); + } + case Attributes::ActiveDatasetTimestamp::Id: { + Optional activeDatasetTimestamp; + status = ReadActiveDatasetTimestamp(activeDatasetTimestamp); + if (status == CHIP_NO_ERROR) + { + status = activeDatasetTimestamp.HasValue() ? aEncoder.Encode(DataModel::MakeNullable(activeDatasetTimestamp.Value())) + : aEncoder.EncodeNull(); + } break; + } default: break; } diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h index d947afe1c97216..fac58385b4214b 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h @@ -37,6 +37,7 @@ namespace ThreadBorderRouterManagement { class ServerInstance : public CommandHandlerInterface, public AttributeAccessInterface, public Delegate::ActivateDatasetCallback { public: + using Status = Protocols::InteractionModel::Status; ServerInstance(EndpointId endpointId, Delegate * delegate) : CommandHandlerInterface(Optional(endpointId), Id), AttributeAccessInterface(Optional(endpointId), Id), mDelegate(delegate) @@ -55,26 +56,27 @@ class ServerInstance : public CommandHandlerInterface, public AttributeAccessInt void OnActivateDatasetComplete(CHIP_ERROR error) override; private: + friend class TestThreadBorderRouterManagementCluster; // Command Handlers - void HandleGetActiveDatasetRequest(HandlerContext & ctx, const Commands::GetActiveDatasetRequest::DecodableType & req) + Status HandleGetActiveDatasetRequest(bool isOverCASESession, Thread::OperationalDataset & dataset) { - HandleGetDatasetRequest(ctx, Delegate::DatasetType::kActive); + return HandleGetDatasetRequest(isOverCASESession, Delegate::DatasetType::kActive, dataset); } - void HandleGetPendingDatasetRequest(HandlerContext & ctx, const Commands::GetPendingDatasetRequest::DecodableType & req) + Status HandleGetPendingDatasetRequest(bool isOverCASESession, Thread::OperationalDataset & dataset) { - HandleGetDatasetRequest(ctx, Delegate::DatasetType::kPending); + return HandleGetDatasetRequest(isOverCASESession, Delegate::DatasetType::kPending, dataset); } - void HandleSetActiveDatasetRequest(HandlerContext & ctx, const Commands::SetActiveDatasetRequest::DecodableType & req); - void HandleSetPendingDatasetRequest(HandlerContext & ctx, const Commands::SetPendingDatasetRequest::DecodableType & req); - void HandleGetDatasetRequest(HandlerContext & ctx, Delegate::DatasetType type); + Status HandleSetActiveDatasetRequest(bool failSafeArmed, const Commands::SetActiveDatasetRequest::DecodableType & req); + Status HandleSetPendingDatasetRequest(const Commands::SetPendingDatasetRequest::DecodableType & req); + Status HandleGetDatasetRequest(bool isOverCASESession, Delegate::DatasetType type, Thread::OperationalDataset & dataset); // Attribute Read handler - CHIP_ERROR ReadFeatureMap(AttributeValueEncoder & aEncoder); - CHIP_ERROR ReadBorderRouterName(AttributeValueEncoder & aEncoder); - CHIP_ERROR ReadBorderAgentID(AttributeValueEncoder & aEncoder); - CHIP_ERROR ReadThreadVersion(AttributeValueEncoder & aEncoder); - CHIP_ERROR ReadInterfaceEnabled(AttributeValueEncoder & aEncoder); - CHIP_ERROR ReadActiveDatasetTimestamp(AttributeValueEncoder & aEncoder); + CHIP_ERROR ReadFeatureMap(BitFlags & feature); + CHIP_ERROR ReadBorderRouterName(MutableCharSpan & borderRouterName); + CHIP_ERROR ReadBorderAgentID(MutableByteSpan & borderAgentId); + CHIP_ERROR ReadThreadVersion(uint16_t & threadVersion); + CHIP_ERROR ReadInterfaceEnabled(bool & interfaceEnable); + CHIP_ERROR ReadActiveDatasetTimestamp(Optional & activeDatasetTimestamp); static void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg); void OnFailSafeTimerExpired(); diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn index c1826884923af4..988620bde20d4f 100644 --- a/src/app/tests/BUILD.gn +++ b/src/app/tests/BUILD.gn @@ -123,6 +123,19 @@ source_set("operational-state-test-srcs") { ] } +source_set("thread-border-router-management-test-srcs") { + sources = [ "${chip_root}/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp" ] + + deps = [ "${chip_root}/src/app/server"] + + public_deps = [ + "${chip_root}/src/app", + "${chip_root}/src/app/common:cluster-objects", + "${chip_root}/src/app/util/mock:mock_ember", + "${chip_root}/src/lib/core", + ] +} + source_set("app-test-stubs") { sources = [ "test-ember-api.cpp", @@ -176,6 +189,7 @@ chip_test_suite("tests") { "TestStatusIB.cpp", "TestStatusResponseMessage.cpp", "TestTestEventTriggerDelegate.cpp", + "TestThreadBorderRouterManagementCluster.cpp", "TestTimeSyncDataProvider.cpp", "TestTimedHandler.cpp", "TestWriteInteraction.cpp", @@ -189,6 +203,7 @@ chip_test_suite("tests") { ":operational-state-test-srcs", ":ota-requestor-test-srcs", ":power-cluster-test-srcs", + ":thread-border-router-management-test-srcs", ":time-sync-data-provider-test-srcs", "${chip_root}/src/app", "${chip_root}/src/app/common:cluster-objects", diff --git a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp new file mode 100644 index 00000000000000..b446dc05f3298b --- /dev/null +++ b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp @@ -0,0 +1,242 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { + +namespace GeneralCommissioning { +// Mock function +void SetBreadcrumb(Attributes::Breadcrumb::TypeInfo::Type breadcrumb) {} +} // namespace GeneralCommissioning + +namespace ThreadBorderRouterManagement { + +class TestDelegate : public Delegate +{ +public: + TestDelegate() = default; + ~TestDelegate() = default; + + CHIP_ERROR Init() override { return CHIP_NO_ERROR; } + + CHIP_ERROR GetPanChangeSupported(bool & panChangeSupported) override + { + panChangeSupported = mPanChangeSupported; + return CHIP_NO_ERROR; + } + + CHIP_ERROR GetBorderRouterName(MutableCharSpan & borderRouterName) override + { + size_t nameIndex = mUseInvalidBorderRouterName ? 1 : 0; + if (borderRouterName.size() > strlen(kTestName[nameIndex])) + { + memcpy(borderRouterName.data(), kTestName[nameIndex], strlen(kTestName[nameIndex])); + borderRouterName.reduce_size(strlen(kTestName[nameIndex])); + return CHIP_NO_ERROR; + } + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + + CHIP_ERROR GetBorderAgentId(MutableByteSpan & borderAgentId) override + { + if (borderAgentId.size() >= mTestBorderAgentIdLen) + { + memcpy(borderAgentId.data(), kTestBorderAgentId, mTestBorderAgentIdLen); + borderAgentId.reduce_size(mTestBorderAgentIdLen); + return CHIP_NO_ERROR; + } + return CHIP_ERROR_BUFFER_TOO_SMALL; + } + + CHIP_ERROR GetThreadVersion(uint16_t & threadVersion) override + { + threadVersion = kTestThreadVersion; + return CHIP_NO_ERROR; + } + + CHIP_ERROR GetInterfaceEnabled(bool & interfaceEnabled) override + { + interfaceEnabled = mInterfaceEnabled; + return CHIP_NO_ERROR; + } + + CHIP_ERROR GetDataset(Thread::OperationalDataset & dataset, DatasetType type) override + { + if (type == DatasetType::kActive && mActiveDatasetLen) + { + dataset.Init(ByteSpan(mActiveDataset, mActiveDatasetLen)); + return CHIP_NO_ERROR; + } + else if (type == DatasetType::kPending && mPendingDatasetLen) + { + dataset.Init(ByteSpan(mPendingDataset, mPendingDatasetLen)); + return CHIP_NO_ERROR; + } + return CHIP_IM_GLOBAL_STATUS(NotFound); + } + + CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, ActivateDatasetCallback * callback) override + { + memcpy(mActiveDataset, activeDataset.AsByteSpan().data(), activeDataset.AsByteSpan().size()); + mActiveDatasetLen = activeDataset.AsByteSpan().size(); + mInterfaceEnabled = true; + return CHIP_NO_ERROR; + } + + CHIP_ERROR CommitActiveDataset() override { return CHIP_NO_ERROR; } + + CHIP_ERROR RevertActiveDataset() override { return CHIP_NO_ERROR; } + + CHIP_ERROR SetPendingDataset(const Thread::OperationalDataset & pendingDataset) override + { + memcpy(mPendingDataset, pendingDataset.AsByteSpan().data(), pendingDataset.AsByteSpan().size()); + mPendingDatasetLen = pendingDataset.AsByteSpan().size(); + return CHIP_NO_ERROR; + } + + bool mPanChangeSupported = true; + const char * kTestName[2] = { "TestName", "TestNameLength64________________________________________________" }; + const uint8_t kTestBorderAgentId[kBorderAgentIdLength] = { 0x0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }; + const uint16_t kTestThreadVersion = 4; + uint8_t mActiveDataset[Thread::kSizeOperationalDataset]; + size_t mActiveDatasetLen = 0; + uint8_t mPendingDataset[Thread::kSizeOperationalDataset]; + size_t mPendingDatasetLen = 0; + bool mUseInvalidBorderRouterName = true; + size_t mTestBorderAgentIdLen = kBorderAgentIdLength - 1; + bool mInterfaceEnabled = false; +}; + +constexpr chip::EndpointId sTestEndpointId = 1; +static TestDelegate * sTestDelegatePtr = nullptr; +static ServerInstance * sTestSeverInstancePtr = nullptr; + +class TestThreadBorderRouterManagementCluster : public ::testing::Test +{ +public: + static void SetUpTestSuite() + { + sTestDelegatePtr = new ThreadBorderRouterManagement::TestDelegate(); + ASSERT_TRUE(sTestDelegatePtr); + sTestSeverInstancePtr = new ThreadBorderRouterManagement::ServerInstance(sTestEndpointId, sTestDelegatePtr); + ASSERT_TRUE(sTestSeverInstancePtr); + } + + static void TearDownTestSuite() + { + delete sTestDelegatePtr; + delete sTestSeverInstancePtr; + } + + void TestAttributeRead(); + void TestCommandHandle(); +}; + +// Test ReadXX functions in ThreadBorderRouterManagement ServerInstance +TEST_F_FROM_FIXTURE(TestThreadBorderRouterManagementCluster, TestAttributeRead) +{ + BitFlags featureMap; + EXPECT_EQ(sTestSeverInstancePtr->ReadFeatureMap(featureMap), CHIP_NO_ERROR); + EXPECT_TRUE(featureMap.Has(Feature::kPANChange)); + sTestDelegatePtr->mPanChangeSupported = false; + featureMap.ClearAll(); + EXPECT_EQ(sTestSeverInstancePtr->ReadFeatureMap(featureMap), CHIP_NO_ERROR); + EXPECT_FALSE(featureMap.Has(Feature::kPANChange)); + char borderRouterName[kBorderRouterNameMaxLength + 10]; + MutableCharSpan nameSpan = MutableCharSpan(borderRouterName); + EXPECT_EQ(sTestSeverInstancePtr->ReadBorderRouterName(nameSpan), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + nameSpan = MutableCharSpan(borderRouterName); + sTestDelegatePtr->mUseInvalidBorderRouterName = false; + EXPECT_EQ(sTestSeverInstancePtr->ReadBorderRouterName(nameSpan), CHIP_NO_ERROR); + EXPECT_TRUE(nameSpan.data_equal(CharSpan("TestName", strlen("TestName")))); + uint8_t borderAgentId[kBorderAgentIdLength]; + MutableByteSpan agentIdSpan = MutableByteSpan(borderAgentId); + EXPECT_EQ(sTestSeverInstancePtr->ReadBorderAgentID(agentIdSpan), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + agentIdSpan = MutableByteSpan(borderAgentId); + sTestDelegatePtr->mTestBorderAgentIdLen = kBorderAgentIdLength; + EXPECT_EQ(sTestSeverInstancePtr->ReadBorderAgentID(agentIdSpan), CHIP_NO_ERROR); + EXPECT_TRUE(agentIdSpan.data_equal(ByteSpan(sTestDelegatePtr->kTestBorderAgentId))); + uint16_t threadVersion; + EXPECT_EQ(sTestSeverInstancePtr->ReadThreadVersion(threadVersion), CHIP_NO_ERROR); + EXPECT_EQ(threadVersion, sTestDelegatePtr->kTestThreadVersion); + bool interfaceEnabled; + EXPECT_EQ(sTestSeverInstancePtr->ReadInterfaceEnabled(interfaceEnabled), CHIP_NO_ERROR); + EXPECT_FALSE(interfaceEnabled); + Optional timestamp; + EXPECT_EQ(sTestSeverInstancePtr->ReadActiveDatasetTimestamp(timestamp), CHIP_NO_ERROR); + EXPECT_FALSE(timestamp.HasValue()); +} + +TEST_F_FROM_FIXTURE(TestThreadBorderRouterManagementCluster, TestCommandHandle) +{ + Thread::OperationalDataset dataset; + using DatasetType = Delegate::DatasetType; + using Status = Protocols::InteractionModel::Status; + EXPECT_EQ(sTestSeverInstancePtr->HandleGetDatasetRequest(false, DatasetType::kActive, dataset), Status::UnsupportedAccess); + EXPECT_EQ(sTestSeverInstancePtr->HandleGetDatasetRequest(false, DatasetType::kPending, dataset), Status::UnsupportedAccess); + EXPECT_EQ(sTestSeverInstancePtr->HandleGetDatasetRequest(true, DatasetType::kActive, dataset), Status::NotFound); + EXPECT_EQ(sTestSeverInstancePtr->HandleGetDatasetRequest(true, DatasetType::kPending, dataset), Status::NotFound); + ThreadBorderRouterManagement::Commands::SetActiveDatasetRequest::DecodableType req1; + uint8_t invalidDataset[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }; + uint8_t validDataset[] = { 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0b, 0x35, 0x06, + 0x00, 0x04, 0x00, 0x1f, 0xff, 0xe0, 0x02, 0x08, 0xde, 0xaa, 0x00, 0xbe, 0xef, 0x00, 0xca, 0xef, 0x07, + 0x08, 0xfd, 0xde, 0xad, 0x00, 0xbe, 0xef, 0x00, 0x00, 0x05, 0x10, 0xb7, 0x28, 0x08, 0x04, 0x85, 0xcf, + 0xc5, 0x25, 0x7f, 0x68, 0x4c, 0x54, 0x9d, 0x6a, 0x57, 0x5e, 0x03, 0x0a, 0x4f, 0x70, 0x65, 0x6e, 0x54, + 0x68, 0x72, 0x65, 0x61, 0x64, 0x01, 0x02, 0xc1, 0x15, 0x04, 0x10, 0xcb, 0x13, 0x47, 0xeb, 0x0c, 0xd4, + 0xb3, 0x5c, 0xd1, 0x42, 0xda, 0x5e, 0x6d, 0xf1, 0x8b, 0x88, 0x0c, 0x04, 0x02, 0xa0, 0xf7, 0xf8 }; + req1.activeDataset = ByteSpan(invalidDataset); + EXPECT_EQ(sTestSeverInstancePtr->HandleSetActiveDatasetRequest(false, req1), Status::FailsafeRequired); + EXPECT_EQ(sTestSeverInstancePtr->HandleSetActiveDatasetRequest(true, req1), Status::InvalidCommand); + req1.activeDataset = ByteSpan(validDataset); + EXPECT_EQ(sTestSeverInstancePtr->HandleSetActiveDatasetRequest(true, req1), Status::Success); + EXPECT_EQ(sTestSeverInstancePtr->HandleGetDatasetRequest(true, DatasetType::kActive, dataset), Status::Success); + EXPECT_TRUE(dataset.AsByteSpan().data_equal(ByteSpan(validDataset))); + bool interfaceEnabled; + EXPECT_EQ(sTestSeverInstancePtr->ReadInterfaceEnabled(interfaceEnabled), CHIP_NO_ERROR); + EXPECT_TRUE(interfaceEnabled); + EXPECT_EQ(sTestSeverInstancePtr->HandleSetActiveDatasetRequest(true, req1), Status::InvalidInState); + Commands::SetPendingDatasetRequest::DecodableType req2; + req2.pendingDataset = ByteSpan(validDataset); + EXPECT_EQ(sTestSeverInstancePtr->HandleSetPendingDatasetRequest(req2), Status::UnsupportedCommand); + sTestDelegatePtr->mPanChangeSupported = true; + req2.pendingDataset = ByteSpan(invalidDataset); + EXPECT_EQ(sTestSeverInstancePtr->HandleSetPendingDatasetRequest(req2), Status::InvalidCommand); + req2.pendingDataset = ByteSpan(validDataset); + EXPECT_EQ(sTestSeverInstancePtr->HandleSetPendingDatasetRequest(req2), Status::Success); + EXPECT_EQ(sTestSeverInstancePtr->HandleGetDatasetRequest(true, DatasetType::kPending, dataset), Status::Success); + EXPECT_TRUE(dataset.AsByteSpan().data_equal(ByteSpan(validDataset))); +} + +} // namespace ThreadBorderRouterManagement +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/controller/data_model/controller-clusters.zap b/src/controller/data_model/controller-clusters.zap index b716c9ddd28d0c..abba3d15cd18ca 100644 --- a/src/controller/data_model/controller-clusters.zap +++ b/src/controller/data_model/controller-clusters.zap @@ -5804,4 +5804,4 @@ "parentEndpointIdentifier": null } ] -} +} \ No newline at end of file From 2f8e888ca05499a3e26cb1e0bf693f506084e125 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Wed, 26 Jun 2024 11:22:51 +0000 Subject: [PATCH 14/46] Restyled by clang-format --- src/app/tests/TestThreadBorderRouterManagementCluster.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp index b446dc05f3298b..04472a3b50c085 100644 --- a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp +++ b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp @@ -130,10 +130,10 @@ class TestDelegate : public Delegate uint8_t mActiveDataset[Thread::kSizeOperationalDataset]; size_t mActiveDatasetLen = 0; uint8_t mPendingDataset[Thread::kSizeOperationalDataset]; - size_t mPendingDatasetLen = 0; - bool mUseInvalidBorderRouterName = true; - size_t mTestBorderAgentIdLen = kBorderAgentIdLength - 1; - bool mInterfaceEnabled = false; + size_t mPendingDatasetLen = 0; + bool mUseInvalidBorderRouterName = true; + size_t mTestBorderAgentIdLen = kBorderAgentIdLength - 1; + bool mInterfaceEnabled = false; }; constexpr chip::EndpointId sTestEndpointId = 1; From 8911398ad7804f0f18f3b04dece15db5a62a4e6c Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Wed, 26 Jun 2024 11:22:51 +0000 Subject: [PATCH 15/46] Restyled by gn --- src/app/tests/BUILD.gn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn index 988620bde20d4f..2405695272bed7 100644 --- a/src/app/tests/BUILD.gn +++ b/src/app/tests/BUILD.gn @@ -126,7 +126,7 @@ source_set("operational-state-test-srcs") { source_set("thread-border-router-management-test-srcs") { sources = [ "${chip_root}/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp" ] - deps = [ "${chip_root}/src/app/server"] + deps = [ "${chip_root}/src/app/server" ] public_deps = [ "${chip_root}/src/app", From 349d3d92e74ba05abb6d851a9f84b605a7519a39 Mon Sep 17 00:00:00 2001 From: Wang Qixiang <43193572+wqx6@users.noreply.github.com> Date: Thu, 27 Jun 2024 10:49:22 +0800 Subject: [PATCH 16/46] Update src/app/clusters/thread-border-router-management-server/thread-br-delegate.h Co-authored-by: Boris Zbarsky --- .../thread-border-router-management-server/thread-br-delegate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h index efc20625680625..5a257c9c97e995 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h @@ -71,7 +71,7 @@ class Delegate virtual CHIP_ERROR GetDataset(Thread::OperationalDataset & dataset, DatasetType type) = 0; - // The Delegate implement should back up the old active dataset at the begining of function if no backup already exists. + // The Delegate implementation should back up the old active dataset at the beginning of function if no backup already exists. virtual CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, ActivateDatasetCallback * callback) = 0; // The Delegate implement should remove the backup active dataset in this function. From 1309bf6e67add8c8debb5bcdaf5e328fbccb73e4 Mon Sep 17 00:00:00 2001 From: Wang Qixiang <43193572+wqx6@users.noreply.github.com> Date: Thu, 27 Jun 2024 10:49:32 +0800 Subject: [PATCH 17/46] Update src/app/clusters/thread-border-router-management-server/thread-br-delegate.h Co-authored-by: Boris Zbarsky --- .../thread-border-router-management-server/thread-br-delegate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h index 5a257c9c97e995..3f90bad6658d98 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h @@ -74,7 +74,7 @@ class Delegate // The Delegate implementation should back up the old active dataset at the beginning of function if no backup already exists. virtual CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, ActivateDatasetCallback * callback) = 0; - // The Delegate implement should remove the backup active dataset in this function. + // The Delegate implementation should remove the backup active dataset in this function. virtual CHIP_ERROR CommitActiveDataset() = 0; // The Delegate implement should restore the backup active dataset in this function. From d2a332bc48c12c3db0c31467d64f7ac584ec476f Mon Sep 17 00:00:00 2001 From: Wang Qixiang <43193572+wqx6@users.noreply.github.com> Date: Thu, 27 Jun 2024 10:49:41 +0800 Subject: [PATCH 18/46] Update src/app/clusters/thread-border-router-management-server/thread-br-delegate.h Co-authored-by: Boris Zbarsky --- .../thread-border-router-management-server/thread-br-delegate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h index 3f90bad6658d98..3fd11eeb9b9cad 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h @@ -77,7 +77,7 @@ class Delegate // The Delegate implementation should remove the backup active dataset in this function. virtual CHIP_ERROR CommitActiveDataset() = 0; - // The Delegate implement should restore the backup active dataset in this function. + // The Delegate implementation should restore the backup active dataset in this function. // Once RevertActiveDataset is called the ActivateDatasetCallback of previous SetActiveDataset should never be called. virtual CHIP_ERROR RevertActiveDataset() = 0; From f03cc4b3bf6280d1aedce9c1933aa1b77b53096f Mon Sep 17 00:00:00 2001 From: Wang Qixiang <43193572+wqx6@users.noreply.github.com> Date: Thu, 27 Jun 2024 10:49:50 +0800 Subject: [PATCH 19/46] Update src/app/clusters/thread-border-router-management-server/thread-br-delegate.h Co-authored-by: Boris Zbarsky --- .../thread-br-delegate.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h index 3fd11eeb9b9cad..2d474f9d362d70 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h @@ -78,7 +78,9 @@ class Delegate virtual CHIP_ERROR CommitActiveDataset() = 0; // The Delegate implementation should restore the backup active dataset in this function. - // Once RevertActiveDataset is called the ActivateDatasetCallback of previous SetActiveDataset should never be called. + // If RevertActiveDataset is called before the ActivateDatasetCallback that would result from a + // previous SetActiveDataset, the delegate must ensure that the ActivateDatasetCallback + // for that previous SetActiveDataset call will not happen. virtual CHIP_ERROR RevertActiveDataset() = 0; virtual CHIP_ERROR SetPendingDataset(const Thread::OperationalDataset & pendingDataset) = 0; From 5becd0a821daee9e6d58faa79220f613d5e91259 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Thu, 27 Jun 2024 11:15:32 +0800 Subject: [PATCH 20/46] add logic of no callbacks for an activate-before-revert happening after the revert --- .../thread-br-delegate.h | 9 ++++----- .../thread-br-mgmt-server.cpp | 20 ++++++++++++++++--- .../thread-br-mgmt-server.h | 3 ++- src/app/tests/BUILD.gn | 3 +-- ...estThreadBorderRouterManagementCluster.cpp | 3 ++- .../GenericThreadBorderRouterDelegate.cpp | 7 ++++--- .../GenericThreadBorderRouterDelegate.h | 4 +++- 7 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h index 2d474f9d362d70..968ded553262be 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h @@ -48,7 +48,7 @@ class Delegate // If the dataset is set successfully, OnActivateDatasetComplete should be called with CHIP_NO_ERROR when the // Border Router is attached to the Thread network. // If an error occurs while setting the active dataset, this callback should be called with the error. - virtual void OnActivateDatasetComplete(CHIP_ERROR error) = 0; + virtual void OnActivateDatasetComplete(uint32_t randomNumber, CHIP_ERROR error) = 0; }; enum class DatasetType : uint8_t @@ -72,15 +72,14 @@ class Delegate virtual CHIP_ERROR GetDataset(Thread::OperationalDataset & dataset, DatasetType type) = 0; // The Delegate implementation should back up the old active dataset at the beginning of function if no backup already exists. - virtual CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, ActivateDatasetCallback * callback) = 0; + // The Delegate implementation should store the random number and pass it to OnActivateDatasetComplete. + virtual CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t randomNum, + ActivateDatasetCallback * callback) = 0; // The Delegate implementation should remove the backup active dataset in this function. virtual CHIP_ERROR CommitActiveDataset() = 0; // The Delegate implementation should restore the backup active dataset in this function. - // If RevertActiveDataset is called before the ActivateDatasetCallback that would result from a - // previous SetActiveDataset, the delegate must ensure that the ActivateDatasetCallback - // for that previous SetActiveDataset call will not happen. virtual CHIP_ERROR RevertActiveDataset() = 0; virtual CHIP_ERROR SetPendingDataset(const Thread::OperationalDataset & pendingDataset) = 0; diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp index b85d59f726717a..82834af4f7e9da 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp +++ b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp @@ -30,6 +30,7 @@ #include "app/clusters/general-commissioning-server/general-commissioning-server.h" #include "app/data-model/Nullable.h" #include "app/server/Server.h" +#include "crypto/RandUtils.h" #include "lib/core/CHIPError.h" #include "lib/support/CodeUtils.h" #include "lib/support/Span.h" @@ -102,7 +103,12 @@ Status ServerInstance::HandleSetActiveDatasetRequest(bool failSafeArmed, } mBreadcrumb = req.breadcrumb; - CHIP_ERROR err = mDelegate->SetActiveDataset(activeDataset, this); + mRandomNumber = Crypto::GetRandU32(); + CHIP_ERROR err = mDelegate->SetActiveDataset(activeDataset, mRandomNumber, this); + if (err != CHIP_NO_ERROR) + { + mRandomNumber = 0; + } return StatusIB(err).mStatus; } @@ -162,7 +168,7 @@ void ServerInstance::InvokeCommand(HandlerContext & ctxt) Status status = HandleSetActiveDatasetRequest(IsFailSafeArmed(ctx), req); if (status != Status::Success) { - OnActivateDatasetComplete(ChipError(ChipError::SdkPart::kIMGlobalStatus, to_underlying(status))); + OnActivateDatasetComplete(mRandomNumber, ChipError(ChipError::SdkPart::kIMGlobalStatus, to_underlying(status))); } } else @@ -318,7 +324,7 @@ void ServerInstance::CommitSavedBreadcrumb() mBreadcrumb.ClearValue(); } -void ServerInstance::OnActivateDatasetComplete(CHIP_ERROR error) +void ServerInstance::OnActivateDatasetComplete(uint32_t randomNumber, CHIP_ERROR error) { auto commandHandleRef = std::move(mAsyncCommandHandle); auto commandHandle = commandHandleRef.Get(); @@ -326,6 +332,12 @@ void ServerInstance::OnActivateDatasetComplete(CHIP_ERROR error) { return; } + if (mRandomNumber != randomNumber) + { + // Previous SetActiveDatasetRequest was handled. + return; + } + mRandomNumber = 0; if (error == CHIP_NO_ERROR) { // The successful completion of the activation process SHALL disarm the fail-safe timer. @@ -352,6 +364,8 @@ void ServerInstance::OnFailSafeTimerExpired() { return; } + // Reset the RandomNumeber so that the OnActivateDatasetComplete will not handle the previous SetActiveDatasetRequest command. + mRandomNumber = 0; commandHandle->AddStatus(mPath, Status::Timeout); } diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h index fac58385b4214b..3dad445d029524 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h @@ -53,7 +53,7 @@ class ServerInstance : public CommandHandlerInterface, public AttributeAccessInt CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; // ActivateDatasetCallbackInterface - void OnActivateDatasetComplete(CHIP_ERROR error) override; + void OnActivateDatasetComplete(uint32_t randomNum, CHIP_ERROR error) override; private: friend class TestThreadBorderRouterManagementCluster; @@ -86,6 +86,7 @@ class ServerInstance : public CommandHandlerInterface, public AttributeAccessInt app::CommandHandler::Handle mAsyncCommandHandle; ConcreteCommandPath mPath = ConcreteCommandPath(0, 0, 0); Optional mBreadcrumb; + uint32_t mRandomNumber; }; } // namespace ThreadBorderRouterManagement diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn index 2405695272bed7..6484715319dc27 100644 --- a/src/app/tests/BUILD.gn +++ b/src/app/tests/BUILD.gn @@ -126,11 +126,10 @@ source_set("operational-state-test-srcs") { source_set("thread-border-router-management-test-srcs") { sources = [ "${chip_root}/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp" ] - deps = [ "${chip_root}/src/app/server" ] - public_deps = [ "${chip_root}/src/app", "${chip_root}/src/app/common:cluster-objects", + "${chip_root}/src/app/server", "${chip_root}/src/app/util/mock:mock_ember", "${chip_root}/src/lib/core", ] diff --git a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp index 04472a3b50c085..c62fd6fd89fcd8 100644 --- a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp +++ b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp @@ -103,7 +103,8 @@ class TestDelegate : public Delegate return CHIP_IM_GLOBAL_STATUS(NotFound); } - CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, ActivateDatasetCallback * callback) override + CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t randomNumber, + ActivateDatasetCallback * callback) override { memcpy(mActiveDataset, activeDataset.AsByteSpan().data(), activeDataset.AsByteSpan().size()); mActiveDatasetLen = activeDataset.AsByteSpan().size(); diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp index a6663c0662c8ef..0d2fb1326230f0 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp @@ -119,7 +119,7 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::GetDataset(Thread::OperationalData } CHIP_ERROR GenericThreadBorderRouterDelegate::SetActiveDataset(const Thread::OperationalDataset & activeDataset, - ActivateDatasetCallback * callback) + uint32_t randomNumber, ActivateDatasetCallback * callback) { CHIP_ERROR err = BackupActiveDataset(); if (err == CHIP_NO_ERROR) @@ -128,7 +128,8 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::SetActiveDataset(const Thread::Ope } if (err == CHIP_NO_ERROR) { - mCallback = callback; + mRandomNumber = randomNumber; + mCallback = callback; } return err; } @@ -141,7 +142,7 @@ void GenericThreadBorderRouterDelegate::OnPlatformEventHandler(const DeviceLayer if (event->Type == DeviceLayer::DeviceEventType::kThreadConnectivityChange && event->ThreadConnectivityChange.Result == DeviceLayer::kConnectivity_Established) { - delegate->mCallback->OnActivateDatasetComplete(CHIP_NO_ERROR); + delegate->mCallback->OnActivateDatasetComplete(delegate->mRandomNumber, CHIP_NO_ERROR); // Delete Failsafe Keys after activating dataset is completed DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(kFailsafeThreadDatasetTlvsKey); delegate->mCallback = nullptr; diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h index 5331b11d88ce01..1a7de3bd4136ea 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h @@ -65,7 +65,8 @@ class GenericThreadBorderRouterDelegate : public Delegate CHIP_ERROR GetDataset(Thread::OperationalDataset & dataset, DatasetType type) override; - CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, ActivateDatasetCallback * callback) override; + CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t randomNumber, + ActivateDatasetCallback * callback) override; CHIP_ERROR RevertActiveDataset() override; @@ -79,6 +80,7 @@ class GenericThreadBorderRouterDelegate : public Delegate CHIP_ERROR BackupActiveDataset(); ActivateDatasetCallback * mCallback = nullptr; Thread::OperationalDataset mStagingDataset = {}; + uint32_t mRandomNumber; }; } // namespace ThreadBorderRouterManagement } // namespace Clusters From f92d9976b5be623241552dc0f854e0d39482247d Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Thu, 27 Jun 2024 18:44:44 +0800 Subject: [PATCH 21/46] fix clang tidy error --- src/app/tests/TestThreadBorderRouterManagementCluster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp index c62fd6fd89fcd8..48beb3812e7c86 100644 --- a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp +++ b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp @@ -95,7 +95,7 @@ class TestDelegate : public Delegate dataset.Init(ByteSpan(mActiveDataset, mActiveDatasetLen)); return CHIP_NO_ERROR; } - else if (type == DatasetType::kPending && mPendingDatasetLen) + if (type == DatasetType::kPending && mPendingDatasetLen) { dataset.Init(ByteSpan(mPendingDataset, mPendingDatasetLen)); return CHIP_NO_ERROR; From 479f08ea2c2f5bebfff1f2ba01d6afe41f522b57 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Mon, 1 Jul 2024 16:38:22 +0800 Subject: [PATCH 22/46] rename the delegate implementation class --- .../GenericThreadBorderRouterDelegate.cpp | 24 +++++++++---------- .../GenericThreadBorderRouterDelegate.h | 8 +++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp index 0d2fb1326230f0..a2ea7cb2e7c3c4 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp @@ -52,7 +52,7 @@ class ScopedThreadLock ~ScopedThreadLock() { DeviceLayer::ThreadStackMgr().UnlockThreadStack(); } }; -CHIP_ERROR GenericThreadBorderRouterDelegate::Init() +CHIP_ERROR GenericOpenThreadBorderRouterDelegate::Init() { mCallback = nullptr; ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler, reinterpret_cast(this))); @@ -60,7 +60,7 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::Init() return CHIP_NO_ERROR; } -CHIP_ERROR GenericThreadBorderRouterDelegate::GetBorderAgentId(MutableByteSpan & borderAgentIdSpan) +CHIP_ERROR GenericOpenThreadBorderRouterDelegate::GetBorderAgentId(MutableByteSpan & borderAgentIdSpan) { otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); @@ -80,13 +80,13 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::GetBorderAgentId(MutableByteSpan & return CHIP_ERROR_INTERNAL; } -CHIP_ERROR GenericThreadBorderRouterDelegate::GetThreadVersion(uint16_t & threadVersion) +CHIP_ERROR GenericOpenThreadBorderRouterDelegate::GetThreadVersion(uint16_t & threadVersion) { threadVersion = otThreadGetVersion(); return CHIP_NO_ERROR; } -CHIP_ERROR GenericThreadBorderRouterDelegate::GetInterfaceEnabled(bool & interfaceEnabled) +CHIP_ERROR GenericOpenThreadBorderRouterDelegate::GetInterfaceEnabled(bool & interfaceEnabled) { otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); @@ -95,7 +95,7 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::GetInterfaceEnabled(bool & interfa return CHIP_NO_ERROR; } -CHIP_ERROR GenericThreadBorderRouterDelegate::GetDataset(Thread::OperationalDataset & dataset, DatasetType type) +CHIP_ERROR GenericOpenThreadBorderRouterDelegate::GetDataset(Thread::OperationalDataset & dataset, DatasetType type) { otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); @@ -118,7 +118,7 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::GetDataset(Thread::OperationalData return CHIP_ERROR_NOT_FOUND; } -CHIP_ERROR GenericThreadBorderRouterDelegate::SetActiveDataset(const Thread::OperationalDataset & activeDataset, +CHIP_ERROR GenericOpenThreadBorderRouterDelegate::SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t randomNumber, ActivateDatasetCallback * callback) { CHIP_ERROR err = BackupActiveDataset(); @@ -134,9 +134,9 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::SetActiveDataset(const Thread::Ope return err; } -void GenericThreadBorderRouterDelegate::OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg) +void GenericOpenThreadBorderRouterDelegate::OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg) { - GenericThreadBorderRouterDelegate * delegate = reinterpret_cast(arg); + GenericOpenThreadBorderRouterDelegate * delegate = reinterpret_cast(arg); if (delegate && delegate->mCallback) { if (event->Type == DeviceLayer::DeviceEventType::kThreadConnectivityChange && @@ -150,7 +150,7 @@ void GenericThreadBorderRouterDelegate::OnPlatformEventHandler(const DeviceLayer } } -CHIP_ERROR GenericThreadBorderRouterDelegate::BackupActiveDataset() +CHIP_ERROR GenericOpenThreadBorderRouterDelegate::BackupActiveDataset() { // If active dataset is already backed up, return with no error CHIP_ERROR err = DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(kFailsafeThreadDatasetTlvsKey, nullptr, 0); @@ -163,14 +163,14 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::BackupActiveDataset() return DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(kFailsafeThreadDatasetTlvsKey, dataset.data(), dataset.size()); } -CHIP_ERROR GenericThreadBorderRouterDelegate::CommitActiveDataset() +CHIP_ERROR GenericOpenThreadBorderRouterDelegate::CommitActiveDataset() { // Delete Failsafe Key when committing. DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(kFailsafeThreadDatasetTlvsKey); return CHIP_NO_ERROR; } -CHIP_ERROR GenericThreadBorderRouterDelegate::RevertActiveDataset() +CHIP_ERROR GenericOpenThreadBorderRouterDelegate::RevertActiveDataset() { // The FailSafe Timer is triggered and the previous command request should be handled, so reset the callback. mCallback = nullptr; @@ -195,7 +195,7 @@ CHIP_ERROR GenericThreadBorderRouterDelegate::RevertActiveDataset() return CHIP_NO_ERROR; } -CHIP_ERROR GenericThreadBorderRouterDelegate::SetPendingDataset(const Thread::OperationalDataset & pendingDataset) +CHIP_ERROR GenericOpenThreadBorderRouterDelegate::SetPendingDataset(const Thread::OperationalDataset & pendingDataset) { otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h index 1a7de3bd4136ea..bb430f853e5c7e 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h @@ -29,14 +29,14 @@ namespace Clusters { namespace ThreadBorderRouterManagement { -class GenericThreadBorderRouterDelegate : public Delegate +class GenericOpenThreadBorderRouterDelegate : public Delegate { public: - static constexpr char kThreadBorderRourterName[] = "Espressif-ThreadBR"; + static constexpr char kThreadBorderRourterName[] = "OpenThread-ThreadBR"; static constexpr char kFailsafeThreadDatasetTlvsKey[] = "g/fs/td"; - GenericThreadBorderRouterDelegate() = default; - ~GenericThreadBorderRouterDelegate() = default; + GenericOpenThreadBorderRouterDelegate() = default; + ~GenericOpenThreadBorderRouterDelegate() = default; CHIP_ERROR Init() override; From 1ddbedd97b82c9918485b277067a412f628f8c03 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Mon, 1 Jul 2024 08:39:44 +0000 Subject: [PATCH 23/46] Restyled by clang-format --- src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp index a2ea7cb2e7c3c4..aa674f16c363e4 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp @@ -119,7 +119,7 @@ CHIP_ERROR GenericOpenThreadBorderRouterDelegate::GetDataset(Thread::Operational } CHIP_ERROR GenericOpenThreadBorderRouterDelegate::SetActiveDataset(const Thread::OperationalDataset & activeDataset, - uint32_t randomNumber, ActivateDatasetCallback * callback) + uint32_t randomNumber, ActivateDatasetCallback * callback) { CHIP_ERROR err = BackupActiveDataset(); if (err == CHIP_NO_ERROR) From be5b828d278c269e2e970024870a7da7e48188fc Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Mon, 1 Jul 2024 18:03:43 +0800 Subject: [PATCH 24/46] Try to fix CI tests --- .../thread-br-mgmt-server-utils.cpp | 41 +++++++++++++++++++ .../thread-br-mgmt-server.cpp | 12 +----- .../thread-br-mgmt-server.h | 4 ++ src/app/tests/BUILD.gn | 1 - ...estThreadBorderRouterManagementCluster.cpp | 8 +++- 5 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server-utils.cpp diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server-utils.cpp b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server-utils.cpp new file mode 100644 index 00000000000000..479b41760aad3f --- /dev/null +++ b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server-utils.cpp @@ -0,0 +1,41 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "app/server/Server.h" +#include "lib/core/DataModelTypes.h" + +namespace chip { +namespace app { +namespace Clusters { +namespace ThreadBorderRouterManagement { + +bool IsFailSafeArmed(FabricIndex accessingFabricIndex) +{ + auto & failSafeContext = Server::GetInstance().GetFailSafeContext(); + return failSafeContext.IsFailSafeArmed(accessingFabricIndex); +} + +void DisarmFailSafeTimer() +{ + auto & failSafeContext = Server::GetInstance().GetFailSafeContext(); + failSafeContext.DisarmFailSafe(); +} + +} // namespace ThreadBorderRouterManagement +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp index 82834af4f7e9da..4f74eb09593231 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp +++ b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp @@ -29,7 +29,6 @@ #include "app/MessageDef/StatusIB.h" #include "app/clusters/general-commissioning-server/general-commissioning-server.h" #include "app/data-model/Nullable.h" -#include "app/server/Server.h" #include "crypto/RandUtils.h" #include "lib/core/CHIPError.h" #include "lib/support/CodeUtils.h" @@ -53,12 +52,6 @@ static bool IsOverCASESession(CommandHandlerInterface::HandlerContext & ctx) exchangeCtx->GetSessionHandle()->AsSecureSession()->GetSecureSessionType() == Transport::SecureSession::Type::kCASE; } -static bool IsFailSafeArmed(CommandHandlerInterface::HandlerContext & ctx) -{ - auto & failSafeContext = Server::GetInstance().GetFailSafeContext(); - return failSafeContext.IsFailSafeArmed(ctx.mCommandHandler.GetAccessingFabricIndex()); -} - Status ServerInstance::HandleGetDatasetRequest(bool isOverCASESession, Delegate::DatasetType type, Thread::OperationalDataset & dataset) { @@ -165,7 +158,7 @@ void ServerInstance::InvokeCommand(HandlerContext & ctxt) mPath = ctx.mRequestPath; mAsyncCommandHandle = CommandHandler::Handle(&ctx.mCommandHandler); ctx.mCommandHandler.FlushAcksRightAwayOnSlowCommand(); - Status status = HandleSetActiveDatasetRequest(IsFailSafeArmed(ctx), req); + Status status = HandleSetActiveDatasetRequest(IsFailSafeArmed(ctx.mCommandHandler.GetAccessingFabricIndex()), req); if (status != Status::Success) { OnActivateDatasetComplete(mRandomNumber, ChipError(ChipError::SdkPart::kIMGlobalStatus, to_underlying(status))); @@ -341,8 +334,7 @@ void ServerInstance::OnActivateDatasetComplete(uint32_t randomNumber, CHIP_ERROR if (error == CHIP_NO_ERROR) { // The successful completion of the activation process SHALL disarm the fail-safe timer. - auto & failSafeContext = Server::GetInstance().GetFailSafeContext(); - failSafeContext.DisarmFailSafe(); + DisarmFailSafeTimer(); CommitSavedBreadcrumb(); } else diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h index 3dad445d029524..02e0b2c6e66076 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h @@ -89,6 +89,10 @@ class ServerInstance : public CommandHandlerInterface, public AttributeAccessInt uint32_t mRandomNumber; }; +bool IsFailSafeArmed(FabricIndex accessingFabricIndex); + +void DisarmFailSafeTimer(); + } // namespace ThreadBorderRouterManagement } // namespace Clusters } // namespace app diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn index 6484715319dc27..5956c46602d324 100644 --- a/src/app/tests/BUILD.gn +++ b/src/app/tests/BUILD.gn @@ -129,7 +129,6 @@ source_set("thread-border-router-management-test-srcs") { public_deps = [ "${chip_root}/src/app", "${chip_root}/src/app/common:cluster-objects", - "${chip_root}/src/app/server", "${chip_root}/src/app/util/mock:mock_ember", "${chip_root}/src/lib/core", ] diff --git a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp index 48beb3812e7c86..4bb0e754b2633b 100644 --- a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp +++ b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -38,6 +37,13 @@ void SetBreadcrumb(Attributes::Breadcrumb::TypeInfo::Type breadcrumb) {} } // namespace GeneralCommissioning namespace ThreadBorderRouterManagement { +// Mock functions +bool IsFailSafeArmed(FabricIndex accessingFabricIndex) +{ + return true; +} + +void DisarmFailSafeTimer() {} class TestDelegate : public Delegate { From 3419a00372fcc875111615c0976f5d668d6076ca Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Wed, 3 Jul 2024 11:44:08 +0800 Subject: [PATCH 25/46] some review changes --- .../OpenThread/GenericThreadBorderRouterDelegate.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h index bb430f853e5c7e..c15d4cb649d9db 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h @@ -32,10 +32,12 @@ namespace ThreadBorderRouterManagement { class GenericOpenThreadBorderRouterDelegate : public Delegate { public: - static constexpr char kThreadBorderRourterName[] = "OpenThread-ThreadBR"; static constexpr char kFailsafeThreadDatasetTlvsKey[] = "g/fs/td"; - GenericOpenThreadBorderRouterDelegate() = default; + GenericOpenThreadBorderRouterDelegate(const CharSpan &name) + { + strncpy(mThreadBorderRouterName, name.data(), std::min(name.size(), kBorderRouterNameMaxLength)); + } ~GenericOpenThreadBorderRouterDelegate() = default; CHIP_ERROR Init() override; @@ -48,12 +50,12 @@ class GenericOpenThreadBorderRouterDelegate : public Delegate CHIP_ERROR GetBorderRouterName(MutableCharSpan & borderRouterName) override { - if (borderRouterName.size() < strlen(kThreadBorderRourterName)) + if (borderRouterName.size() < strlen(mThreadBorderRouterName)) { return CHIP_ERROR_NO_MEMORY; } - strcpy(borderRouterName.data(), kThreadBorderRourterName); - borderRouterName.reduce_size(strlen(kThreadBorderRourterName)); + strcpy(borderRouterName.data(), mThreadBorderRouterName); + borderRouterName.reduce_size(strlen(mThreadBorderRouterName)); return CHIP_NO_ERROR; } @@ -81,6 +83,7 @@ class GenericOpenThreadBorderRouterDelegate : public Delegate ActivateDatasetCallback * mCallback = nullptr; Thread::OperationalDataset mStagingDataset = {}; uint32_t mRandomNumber; + char mThreadBorderRouterName[kBorderRouterNameMaxLength + 1]; }; } // namespace ThreadBorderRouterManagement } // namespace Clusters From 4098d938085c51f11d5da0699335f0a01342589e Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Wed, 3 Jul 2024 03:44:53 +0000 Subject: [PATCH 26/46] Restyled by clang-format --- src/platform/OpenThread/GenericThreadBorderRouterDelegate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h index c15d4cb649d9db..9316310c95755a 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h @@ -34,7 +34,7 @@ class GenericOpenThreadBorderRouterDelegate : public Delegate public: static constexpr char kFailsafeThreadDatasetTlvsKey[] = "g/fs/td"; - GenericOpenThreadBorderRouterDelegate(const CharSpan &name) + GenericOpenThreadBorderRouterDelegate(const CharSpan & name) { strncpy(mThreadBorderRouterName, name.data(), std::min(name.size(), kBorderRouterNameMaxLength)); } From a024728529395a10db3c2d80630de3531a8d8b68 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Wed, 3 Jul 2024 12:06:09 +0800 Subject: [PATCH 27/46] rename the source files --- src/app/chip_data_model.gni | 5 +++++ ....cpp => thread-border-router-management-server-utils.cpp} | 0 ...server.cpp => thread-border-router-management-server.cpp} | 2 +- ...gmt-server.h => thread-border-router-management-server.h} | 0 src/app/tests/BUILD.gn | 2 +- src/app/tests/TestThreadBorderRouterManagementCluster.cpp | 2 +- src/app/zap_cluster_list.json | 4 +++- 7 files changed, 11 insertions(+), 4 deletions(-) rename src/app/clusters/thread-border-router-management-server/{thread-br-mgmt-server-utils.cpp => thread-border-router-management-server-utils.cpp} (100%) rename src/app/clusters/thread-border-router-management-server/{thread-br-mgmt-server.cpp => thread-border-router-management-server.cpp} (99%) rename src/app/clusters/thread-border-router-management-server/{thread-br-mgmt-server.h => thread-border-router-management-server.h} (100%) diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index a68d193d241541..0fa3ac24ccc9f5 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -390,6 +390,11 @@ template("chip_data_model") { "${_app_root}/clusters/${cluster}/thread-network-diagnostics-provider.cpp", "${_app_root}/clusters/${cluster}/thread-network-diagnostics-provider.h", ] + } else if (cluster == "thread-border-router-management-server") { + sources += [ + "${_app_root}/clusters/${cluster}/${cluster}.cpp", + "${_app_root}/clusters/${cluster}/thread-border-router-management-server-utils.cpp", + ] } else { sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp" ] } diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server-utils.cpp b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server-utils.cpp similarity index 100% rename from src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server-utils.cpp rename to src/app/clusters/thread-border-router-management-server/thread-border-router-management-server-utils.cpp diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp similarity index 99% rename from src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp rename to src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp index 4f74eb09593231..b00e4c301781dd 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp +++ b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp @@ -15,7 +15,7 @@ * limitations under the License. */ -#include "thread-br-mgmt-server.h" +#include "thread-border-router-management-server.h" #include "app-common/zap-generated/cluster-objects.h" #include "app-common/zap-generated/ids/Attributes.h" diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.h similarity index 100% rename from src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.h rename to src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.h diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn index 5956c46602d324..d0ab2fc62a83f6 100644 --- a/src/app/tests/BUILD.gn +++ b/src/app/tests/BUILD.gn @@ -124,7 +124,7 @@ source_set("operational-state-test-srcs") { } source_set("thread-border-router-management-test-srcs") { - sources = [ "${chip_root}/src/app/clusters/thread-border-router-management-server/thread-br-mgmt-server.cpp" ] + sources = [ "${chip_root}/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp" ] public_deps = [ "${chip_root}/src/app", diff --git a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp index 4bb0e754b2633b..78571eecf76212 100644 --- a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp +++ b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include diff --git a/src/app/zap_cluster_list.json b/src/app/zap_cluster_list.json index dc324968991adc..a8aa4ce320b990 100644 --- a/src/app/zap_cluster_list.json +++ b/src/app/zap_cluster_list.json @@ -289,7 +289,9 @@ "THERMOSTAT_USER_INTERFACE_CONFIGURATION_CLUSTER": [ "thermostat-user-interface-configuration-server" ], - "THREAD_BORDER_ROUTER_MANAGEMENT_CLUSTER": [], + "THREAD_BORDER_ROUTER_MANAGEMENT_CLUSTER": [ + "thread-border-router-management-server" + ], "THREAD_NETWORK_DIAGNOSTICS_CLUSTER": [ "thread-network-diagnostics-server" ], From 00bd9d174d4bf5b3c444db0cae49c35c19e11a3b Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Thu, 4 Jul 2024 15:28:37 +0800 Subject: [PATCH 28/46] review changes --- ...thread-border-router-management-server.cpp | 20 +++++++------------ .../thread-border-router-management-server.h | 4 ++-- .../thread-br-delegate.h | 10 ++++++---- .../GenericThreadBorderRouterDelegate.cpp | 10 ++++++---- .../GenericThreadBorderRouterDelegate.h | 4 ++-- 5 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp index b00e4c301781dd..8ec95d84f1fc54 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp +++ b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp @@ -95,13 +95,9 @@ Status ServerInstance::HandleSetActiveDatasetRequest(bool failSafeArmed, return Status::InvalidInState; } - mBreadcrumb = req.breadcrumb; - mRandomNumber = Crypto::GetRandU32(); - CHIP_ERROR err = mDelegate->SetActiveDataset(activeDataset, mRandomNumber, this); - if (err != CHIP_NO_ERROR) - { - mRandomNumber = 0; - } + mBreadcrumb = req.breadcrumb; + mSetActiveDatasetSequenceNumber++; + CHIP_ERROR err = mDelegate->SetActiveDataset(activeDataset, mSetActiveDatasetSequenceNumber, this); return StatusIB(err).mStatus; } @@ -161,7 +157,8 @@ void ServerInstance::InvokeCommand(HandlerContext & ctxt) Status status = HandleSetActiveDatasetRequest(IsFailSafeArmed(ctx.mCommandHandler.GetAccessingFabricIndex()), req); if (status != Status::Success) { - OnActivateDatasetComplete(mRandomNumber, ChipError(ChipError::SdkPart::kIMGlobalStatus, to_underlying(status))); + OnActivateDatasetComplete(mSetActiveDatasetSequenceNumber, + ChipError(ChipError::SdkPart::kIMGlobalStatus, to_underlying(status))); } } else @@ -317,7 +314,7 @@ void ServerInstance::CommitSavedBreadcrumb() mBreadcrumb.ClearValue(); } -void ServerInstance::OnActivateDatasetComplete(uint32_t randomNumber, CHIP_ERROR error) +void ServerInstance::OnActivateDatasetComplete(uint32_t sequenceNum, CHIP_ERROR error) { auto commandHandleRef = std::move(mAsyncCommandHandle); auto commandHandle = commandHandleRef.Get(); @@ -325,12 +322,11 @@ void ServerInstance::OnActivateDatasetComplete(uint32_t randomNumber, CHIP_ERROR { return; } - if (mRandomNumber != randomNumber) + if (mSetActiveDatasetSequenceNumber != sequenceNum) { // Previous SetActiveDatasetRequest was handled. return; } - mRandomNumber = 0; if (error == CHIP_NO_ERROR) { // The successful completion of the activation process SHALL disarm the fail-safe timer. @@ -356,8 +352,6 @@ void ServerInstance::OnFailSafeTimerExpired() { return; } - // Reset the RandomNumeber so that the OnActivateDatasetComplete will not handle the previous SetActiveDatasetRequest command. - mRandomNumber = 0; commandHandle->AddStatus(mPath, Status::Timeout); } diff --git a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.h b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.h index 02e0b2c6e66076..36abeb6b39e40e 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.h +++ b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.h @@ -53,7 +53,7 @@ class ServerInstance : public CommandHandlerInterface, public AttributeAccessInt CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; // ActivateDatasetCallbackInterface - void OnActivateDatasetComplete(uint32_t randomNum, CHIP_ERROR error) override; + void OnActivateDatasetComplete(uint32_t sequenceNum, CHIP_ERROR error) override; private: friend class TestThreadBorderRouterManagementCluster; @@ -86,7 +86,7 @@ class ServerInstance : public CommandHandlerInterface, public AttributeAccessInt app::CommandHandler::Handle mAsyncCommandHandle; ConcreteCommandPath mPath = ConcreteCommandPath(0, 0, 0); Optional mBreadcrumb; - uint32_t mRandomNumber; + uint32_t mSetActiveDatasetSequenceNumber = 0; }; bool IsFailSafeArmed(FabricIndex accessingFabricIndex); diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h index 968ded553262be..c2f92710a83a1d 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h @@ -48,7 +48,7 @@ class Delegate // If the dataset is set successfully, OnActivateDatasetComplete should be called with CHIP_NO_ERROR when the // Border Router is attached to the Thread network. // If an error occurs while setting the active dataset, this callback should be called with the error. - virtual void OnActivateDatasetComplete(uint32_t randomNumber, CHIP_ERROR error) = 0; + virtual void OnActivateDatasetComplete(uint32_t sequenceNum, CHIP_ERROR error) = 0; }; enum class DatasetType : uint8_t @@ -72,14 +72,16 @@ class Delegate virtual CHIP_ERROR GetDataset(Thread::OperationalDataset & dataset, DatasetType type) = 0; // The Delegate implementation should back up the old active dataset at the beginning of function if no backup already exists. - // The Delegate implementation should store the random number and pass it to OnActivateDatasetComplete. - virtual CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t randomNum, + // The Delegate implementation must store the sequence number and pass it to OnActivateDatasetComplete. + virtual CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t sequenceNum, ActivateDatasetCallback * callback) = 0; // The Delegate implementation should remove the backup active dataset in this function. virtual CHIP_ERROR CommitActiveDataset() = 0; - // The Delegate implementation should restore the backup active dataset in this function. + // The Delegate implementation should restore the backup active dataset in this function. The delegate is allowed to call + // OnActivateDatasetComplete for the previous SetActiveDataset request even after this function is called as the sequence + // number passed to OnActivateDatasetComplete will be different. virtual CHIP_ERROR RevertActiveDataset() = 0; virtual CHIP_ERROR SetPendingDataset(const Thread::OperationalDataset & pendingDataset) = 0; diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp index aa674f16c363e4..5785387e315fb4 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp @@ -119,7 +119,7 @@ CHIP_ERROR GenericOpenThreadBorderRouterDelegate::GetDataset(Thread::Operational } CHIP_ERROR GenericOpenThreadBorderRouterDelegate::SetActiveDataset(const Thread::OperationalDataset & activeDataset, - uint32_t randomNumber, ActivateDatasetCallback * callback) + uint32_t sequenceNum, ActivateDatasetCallback * callback) { CHIP_ERROR err = BackupActiveDataset(); if (err == CHIP_NO_ERROR) @@ -128,8 +128,10 @@ CHIP_ERROR GenericOpenThreadBorderRouterDelegate::SetActiveDataset(const Thread: } if (err == CHIP_NO_ERROR) { - mRandomNumber = randomNumber; - mCallback = callback; + // We can change the stored sequence number because OnActivateDatasetComplete executed later must be called for this + // SetActiveDataset request + mSequenceNum = sequenceNum; + mCallback = callback; } return err; } @@ -142,7 +144,7 @@ void GenericOpenThreadBorderRouterDelegate::OnPlatformEventHandler(const DeviceL if (event->Type == DeviceLayer::DeviceEventType::kThreadConnectivityChange && event->ThreadConnectivityChange.Result == DeviceLayer::kConnectivity_Established) { - delegate->mCallback->OnActivateDatasetComplete(delegate->mRandomNumber, CHIP_NO_ERROR); + delegate->mCallback->OnActivateDatasetComplete(delegate->mSequenceNum, CHIP_NO_ERROR); // Delete Failsafe Keys after activating dataset is completed DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(kFailsafeThreadDatasetTlvsKey); delegate->mCallback = nullptr; diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h index 9316310c95755a..00bce93490ddb5 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h @@ -67,7 +67,7 @@ class GenericOpenThreadBorderRouterDelegate : public Delegate CHIP_ERROR GetDataset(Thread::OperationalDataset & dataset, DatasetType type) override; - CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t randomNumber, + CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t sequenceNum, ActivateDatasetCallback * callback) override; CHIP_ERROR RevertActiveDataset() override; @@ -82,7 +82,7 @@ class GenericOpenThreadBorderRouterDelegate : public Delegate CHIP_ERROR BackupActiveDataset(); ActivateDatasetCallback * mCallback = nullptr; Thread::OperationalDataset mStagingDataset = {}; - uint32_t mRandomNumber; + uint32_t mSequenceNum; char mThreadBorderRouterName[kBorderRouterNameMaxLength + 1]; }; } // namespace ThreadBorderRouterManagement From 4c5a0a2d403e0750d64d03b082cbb81d0f85d2c4 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Wed, 12 Jun 2024 17:54:02 +0800 Subject: [PATCH 29/46] some review changes --- src/app/chip_data_model.gni | 2 + .../GenericThreadBorderRouterDelegate.cpp | 45 ++++++------------- .../GenericThreadBorderRouterDelegate.h | 9 ++-- 3 files changed, 19 insertions(+), 37 deletions(-) diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index 0fa3ac24ccc9f5..b5b50f2bde4c3e 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -393,7 +393,9 @@ template("chip_data_model") { } else if (cluster == "thread-border-router-management-server") { sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp", + "${_app_root}/clusters/${cluster}/${cluster}.h", "${_app_root}/clusters/${cluster}/thread-border-router-management-server-utils.cpp", + "${_app_root}/clusters/${cluster}/thread-br-delegate.h", ] } else { sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp" ] diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp index 5785387e315fb4..a292c2c4de6eee 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp @@ -56,6 +56,7 @@ CHIP_ERROR GenericOpenThreadBorderRouterDelegate::Init() { mCallback = nullptr; ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler, reinterpret_cast(this))); + // When the Thread Border Router is reboot during SetActiveDataset, we need to revert the active dateset. ReturnErrorOnFailure(RevertActiveDataset()); return CHIP_NO_ERROR; } @@ -121,7 +122,8 @@ CHIP_ERROR GenericOpenThreadBorderRouterDelegate::GetDataset(Thread::Operational CHIP_ERROR GenericOpenThreadBorderRouterDelegate::SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t sequenceNum, ActivateDatasetCallback * callback) { - CHIP_ERROR err = BackupActiveDataset(); + // This function will never be invoked when there is an Active Dataset already configured. + CHIP_ERROR err = SaveThreadBorderRouterCommissioned(false); if (err == CHIP_NO_ERROR) { err = DeviceLayer::ThreadStackMgrImpl().AttachToThreadNetwork(activeDataset, nullptr); @@ -145,55 +147,34 @@ void GenericOpenThreadBorderRouterDelegate::OnPlatformEventHandler(const DeviceL event->ThreadConnectivityChange.Result == DeviceLayer::kConnectivity_Established) { delegate->mCallback->OnActivateDatasetComplete(delegate->mSequenceNum, CHIP_NO_ERROR); - // Delete Failsafe Keys after activating dataset is completed - DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(kFailsafeThreadDatasetTlvsKey); delegate->mCallback = nullptr; } } } -CHIP_ERROR GenericOpenThreadBorderRouterDelegate::BackupActiveDataset() +CHIP_ERROR GenericOpenThreadBorderRouterDelegate::SaveThreadBorderRouterCommissioned(bool commissioned) { - // If active dataset is already backed up, return with no error - CHIP_ERROR err = DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(kFailsafeThreadDatasetTlvsKey, nullptr, 0); - if (err == CHIP_NO_ERROR || err == CHIP_ERROR_BUFFER_TOO_SMALL) - { - return CHIP_NO_ERROR; - } - GetDataset(mStagingDataset, DatasetType::kActive); - ByteSpan dataset = mStagingDataset.AsByteSpan(); - return DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(kFailsafeThreadDatasetTlvsKey, dataset.data(), dataset.size()); + return DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(kFailsafeThreadBorderRouterCommissioned, commissioned); } CHIP_ERROR GenericOpenThreadBorderRouterDelegate::CommitActiveDataset() { - // Delete Failsafe Key when committing. - DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(kFailsafeThreadDatasetTlvsKey); - return CHIP_NO_ERROR; + return SaveThreadBorderRouterCommissioned(true); } CHIP_ERROR GenericOpenThreadBorderRouterDelegate::RevertActiveDataset() { // The FailSafe Timer is triggered and the previous command request should be handled, so reset the callback. mCallback = nullptr; - uint8_t datasetBytes[Thread::kSizeOperationalDataset]; - size_t datasetLength; - CHIP_ERROR err = DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(kFailsafeThreadDatasetTlvsKey, datasetBytes, - sizeof(datasetBytes), &datasetLength); - // If no backup could be found, it means the active datset has not been modified since the fail-safe was armed, - // so return with no error. - ReturnErrorCodeIf(err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND, CHIP_NO_ERROR); - if (err == CHIP_NO_ERROR) + bool threadCommissioned = true; + DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(kFailsafeThreadBorderRouterCommissioned, &threadCommissioned); + if (!threadCommissioned) { - err = mStagingDataset.Init(ByteSpan(datasetBytes, datasetLength)); + // If Thread is not commissioned, we will try to attach an empty Thread dataset and the Thread Border Router + // will stay uncommissioned + Thread::OperationalDataset emptyDataset = {}; + return DeviceLayer::ThreadStackMgrImpl().AttachToThreadNetwork(emptyDataset, nullptr); } - if (err == CHIP_NO_ERROR) - { - err = DeviceLayer::ThreadStackMgrImpl().AttachToThreadNetwork(mStagingDataset, nullptr); - } - - // Always delete the backup, regardless if it can be successfully restored. - DeviceLayer::PersistedStorage::KeyValueStoreMgr().Delete(kFailsafeThreadDatasetTlvsKey); return CHIP_NO_ERROR; } diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h index 00bce93490ddb5..5e82c10a0c59f7 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h @@ -32,11 +32,11 @@ namespace ThreadBorderRouterManagement { class GenericOpenThreadBorderRouterDelegate : public Delegate { public: - static constexpr char kFailsafeThreadDatasetTlvsKey[] = "g/fs/td"; + static constexpr char kFailsafeThreadBorderRouterCommissioned[] = "g/fs/tbrc"; - GenericOpenThreadBorderRouterDelegate(const CharSpan & name) + GenericOpenThreadBorderRouterDelegate(const char *name) { - strncpy(mThreadBorderRouterName, name.data(), std::min(name.size(), kBorderRouterNameMaxLength)); + strncpy(mThreadBorderRouterName, name, kBorderRouterNameMaxLength); } ~GenericOpenThreadBorderRouterDelegate() = default; @@ -79,9 +79,8 @@ class GenericOpenThreadBorderRouterDelegate : public Delegate static void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg); private: - CHIP_ERROR BackupActiveDataset(); + CHIP_ERROR SaveThreadBorderRouterCommissioned(bool commissioned); ActivateDatasetCallback * mCallback = nullptr; - Thread::OperationalDataset mStagingDataset = {}; uint32_t mSequenceNum; char mThreadBorderRouterName[kBorderRouterNameMaxLength + 1]; }; From f8b8f56418034ab3218b2e20e4371c1e87564888 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Mon, 8 Jul 2024 04:32:52 +0000 Subject: [PATCH 30/46] Restyled by clang-format --- .../OpenThread/GenericThreadBorderRouterDelegate.cpp | 2 +- .../OpenThread/GenericThreadBorderRouterDelegate.h | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp index a292c2c4de6eee..45cd9ae8615a75 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp @@ -165,7 +165,7 @@ CHIP_ERROR GenericOpenThreadBorderRouterDelegate::CommitActiveDataset() CHIP_ERROR GenericOpenThreadBorderRouterDelegate::RevertActiveDataset() { // The FailSafe Timer is triggered and the previous command request should be handled, so reset the callback. - mCallback = nullptr; + mCallback = nullptr; bool threadCommissioned = true; DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(kFailsafeThreadBorderRouterCommissioned, &threadCommissioned); if (!threadCommissioned) diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h index 5e82c10a0c59f7..cf70b2b981c71c 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h @@ -34,10 +34,7 @@ class GenericOpenThreadBorderRouterDelegate : public Delegate public: static constexpr char kFailsafeThreadBorderRouterCommissioned[] = "g/fs/tbrc"; - GenericOpenThreadBorderRouterDelegate(const char *name) - { - strncpy(mThreadBorderRouterName, name, kBorderRouterNameMaxLength); - } + GenericOpenThreadBorderRouterDelegate(const char * name) { strncpy(mThreadBorderRouterName, name, kBorderRouterNameMaxLength); } ~GenericOpenThreadBorderRouterDelegate() = default; CHIP_ERROR Init() override; @@ -80,7 +77,7 @@ class GenericOpenThreadBorderRouterDelegate : public Delegate private: CHIP_ERROR SaveThreadBorderRouterCommissioned(bool commissioned); - ActivateDatasetCallback * mCallback = nullptr; + ActivateDatasetCallback * mCallback = nullptr; uint32_t mSequenceNum; char mThreadBorderRouterName[kBorderRouterNameMaxLength + 1]; }; From 8ab955d5ff298a46c178438059d3b7aad9df0904 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Tue, 9 Jul 2024 10:42:05 +0800 Subject: [PATCH 31/46] review changes from marius --- .../thread-br-delegate.h | 12 +++++------- .../TestThreadBorderRouterManagementCluster.cpp | 2 -- .../OpenThread/GenericThreadBorderRouterDelegate.cpp | 10 +++------- .../OpenThread/GenericThreadBorderRouterDelegate.h | 2 -- 4 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h index c2f92710a83a1d..b56d93c92ef2b2 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h @@ -71,17 +71,15 @@ class Delegate virtual CHIP_ERROR GetDataset(Thread::OperationalDataset & dataset, DatasetType type) = 0; - // The Delegate implementation should back up the old active dataset at the beginning of function if no backup already exists. + // There should be no active dataset configured when calling this API, otherwise we should use SetPendingDataset. // The Delegate implementation must store the sequence number and pass it to OnActivateDatasetComplete. virtual CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t sequenceNum, ActivateDatasetCallback * callback) = 0; - // The Delegate implementation should remove the backup active dataset in this function. - virtual CHIP_ERROR CommitActiveDataset() = 0; - - // The Delegate implementation should restore the backup active dataset in this function. The delegate is allowed to call - // OnActivateDatasetComplete for the previous SetActiveDataset request even after this function is called as the sequence - // number passed to OnActivateDatasetComplete will be different. + // The function is called when Failsafe timer is triggered and the delegate implementation should clear the active dataset in + // this function to allow trying again a new SetActiveDataset operation. + // The delegate is allowed to call OnActivateDatasetComplete for the previous SetActiveDataset request even after this function + // is called as the sequence number passed to OnActivateDatasetComplete will be different. virtual CHIP_ERROR RevertActiveDataset() = 0; virtual CHIP_ERROR SetPendingDataset(const Thread::OperationalDataset & pendingDataset) = 0; diff --git a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp index 78571eecf76212..394c5f578342ae 100644 --- a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp +++ b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp @@ -118,8 +118,6 @@ class TestDelegate : public Delegate return CHIP_NO_ERROR; } - CHIP_ERROR CommitActiveDataset() override { return CHIP_NO_ERROR; } - CHIP_ERROR RevertActiveDataset() override { return CHIP_NO_ERROR; } CHIP_ERROR SetPendingDataset(const Thread::OperationalDataset & pendingDataset) override diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp index 45cd9ae8615a75..8d89bc2c9e0238 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp @@ -147,6 +147,7 @@ void GenericOpenThreadBorderRouterDelegate::OnPlatformEventHandler(const DeviceL event->ThreadConnectivityChange.Result == DeviceLayer::kConnectivity_Established) { delegate->mCallback->OnActivateDatasetComplete(delegate->mSequenceNum, CHIP_NO_ERROR); + SaveThreadBorderRouterCommissioned(true); delegate->mCallback = nullptr; } } @@ -157,11 +158,6 @@ CHIP_ERROR GenericOpenThreadBorderRouterDelegate::SaveThreadBorderRouterCommissi return DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(kFailsafeThreadBorderRouterCommissioned, commissioned); } -CHIP_ERROR GenericOpenThreadBorderRouterDelegate::CommitActiveDataset() -{ - return SaveThreadBorderRouterCommissioned(true); -} - CHIP_ERROR GenericOpenThreadBorderRouterDelegate::RevertActiveDataset() { // The FailSafe Timer is triggered and the previous command request should be handled, so reset the callback. @@ -170,8 +166,8 @@ CHIP_ERROR GenericOpenThreadBorderRouterDelegate::RevertActiveDataset() DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(kFailsafeThreadBorderRouterCommissioned, &threadCommissioned); if (!threadCommissioned) { - // If Thread is not commissioned, we will try to attach an empty Thread dataset and the Thread Border Router - // will stay uncommissioned + // If Thread is not commissioned, we will try to attach an empty Thread dataset and that will clear the one stored in the + // Thread stack since the SetActiveDataset operation fails and FailSafe timer is triggered. Thread::OperationalDataset emptyDataset = {}; return DeviceLayer::ThreadStackMgrImpl().AttachToThreadNetwork(emptyDataset, nullptr); } diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h index cf70b2b981c71c..0a5f0524fb963a 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h @@ -69,8 +69,6 @@ class GenericOpenThreadBorderRouterDelegate : public Delegate CHIP_ERROR RevertActiveDataset() override; - CHIP_ERROR CommitActiveDataset() override; - CHIP_ERROR SetPendingDataset(const Thread::OperationalDataset & pendingDataset) override; static void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg); From 0995ccbd126bcc9f437be60fbe9484030b3b8f22 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Fri, 12 Jul 2024 10:58:31 +0800 Subject: [PATCH 32/46] review changes --- src/app/chip_data_model.gni | 5 +- ...-border-router-management-server-utils.cpp | 41 --- ...thread-border-router-management-server.cpp | 167 ++++------ .../thread-border-router-management-server.h | 22 +- .../thread-br-delegate.h | 37 ++- ...estThreadBorderRouterManagementCluster.cpp | 288 +++++++++++------- .../GenericThreadBorderRouterDelegate.cpp | 97 +++--- .../GenericThreadBorderRouterDelegate.h | 41 ++- 8 files changed, 359 insertions(+), 339 deletions(-) delete mode 100644 src/app/clusters/thread-border-router-management-server/thread-border-router-management-server-utils.cpp diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index b5b50f2bde4c3e..d1a8e43a2495ec 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -392,9 +392,8 @@ template("chip_data_model") { ] } else if (cluster == "thread-border-router-management-server") { sources += [ - "${_app_root}/clusters/${cluster}/${cluster}.cpp", - "${_app_root}/clusters/${cluster}/${cluster}.h", - "${_app_root}/clusters/${cluster}/thread-border-router-management-server-utils.cpp", + "${_app_root}/clusters/${cluster}/thread-border-router-management-server.cpp", + "${_app_root}/clusters/${cluster}/thread-border-router-management-server.h", "${_app_root}/clusters/${cluster}/thread-br-delegate.h", ] } else { diff --git a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server-utils.cpp b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server-utils.cpp deleted file mode 100644 index 479b41760aad3f..00000000000000 --- a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server-utils.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Copyright (c) 2024 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "app/server/Server.h" -#include "lib/core/DataModelTypes.h" - -namespace chip { -namespace app { -namespace Clusters { -namespace ThreadBorderRouterManagement { - -bool IsFailSafeArmed(FabricIndex accessingFabricIndex) -{ - auto & failSafeContext = Server::GetInstance().GetFailSafeContext(); - return failSafeContext.IsFailSafeArmed(accessingFabricIndex); -} - -void DisarmFailSafeTimer() -{ - auto & failSafeContext = Server::GetInstance().GetFailSafeContext(); - failSafeContext.DisarmFailSafe(); -} - -} // namespace ThreadBorderRouterManagement -} // namespace Clusters -} // namespace app -} // namespace chip diff --git a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp index 8ec95d84f1fc54..c8948be3bb6a4b 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp +++ b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp @@ -29,8 +29,8 @@ #include "app/MessageDef/StatusIB.h" #include "app/clusters/general-commissioning-server/general-commissioning-server.h" #include "app/data-model/Nullable.h" -#include "crypto/RandUtils.h" #include "lib/core/CHIPError.h" +#include "lib/core/Optional.h" #include "lib/support/CodeUtils.h" #include "lib/support/Span.h" #include "lib/support/ThreadOperationalDataset.h" @@ -45,7 +45,7 @@ namespace ThreadBorderRouterManagement { using Protocols::InteractionModel::Status; -static bool IsOverCASESession(CommandHandlerInterface::HandlerContext & ctx) +static bool IsCommandOverCASESession(CommandHandlerInterface::HandlerContext & ctx) { Messaging::ExchangeContext * exchangeCtx = ctx.mCommandHandler.GetExchangeContext(); return exchangeCtx && exchangeCtx->HasSessionHandle() && exchangeCtx->GetSessionHandle()->IsSecureSession() && @@ -55,6 +55,7 @@ static bool IsOverCASESession(CommandHandlerInterface::HandlerContext & ctx) Status ServerInstance::HandleGetDatasetRequest(bool isOverCASESession, Delegate::DatasetType type, Thread::OperationalDataset & dataset) { + VerifyOrDie(mDelegate); if (!isOverCASESession) { return Status::UnsupportedAccess; @@ -68,44 +69,49 @@ Status ServerInstance::HandleGetDatasetRequest(bool isOverCASESession, Delegate: return Status::Success; } -Status ServerInstance::HandleSetActiveDatasetRequest(bool failSafeArmed, +Status ServerInstance::HandleSetActiveDatasetRequest(CommandHandler * commandHandler, const Commands::SetActiveDatasetRequest::DecodableType & req) { // The SetActiveDatasetRequest command SHALL be FailSafeArmed. Upon receiving this command, the Thread BR will set its // active dataset. If the dataset is set successfully, OnActivateDatasetComplete will be called with CHIP_NO_ERROR, prompting - // the Thread BR to respond with a success status and disarm the FailSafe timer. If an error occurs while setting the active - // dataset, the Thread BR should respond with a failure status. In this case, when the FailSafe timer expires, the active - // dataset set by this command will be reverted. If the FailSafe timer expires before the Thread BR responds, the Thread BR will - // respond with a timeout status and the active dataset should also be reverted. - ReturnErrorCodeIf(!failSafeArmed, Status::FailsafeRequired); - ReturnErrorCodeIf(!mDelegate, Status::InvalidInState); + // the Thread BR to respond with a success status. If an error occurs while setting the active dataset, the Thread BR should + // respond with a failure status. In this case, when the FailSafe timer expires, the active dataset set by this command will be + // reverted. If the FailSafe timer expires before the Thread BR responds, the Thread BR will respond with a timeout status and + // the active dataset should also be reverted. + VerifyOrDie(mDelegate); + VerifyOrReturnValue(mFailsafeContext.IsFailSafeArmed(commandHandler->GetAccessingFabricIndex()), Status::FailsafeRequired); Thread::OperationalDataset activeDataset; Thread::OperationalDataset currentActiveDataset; - uint64_t currentActiveDatasetTimestamp; + uint64_t currentActiveDatasetTimestamp = 0; // If any of the parameters in the ActiveDataset is invalid, the command SHALL fail with a status code // of INVALID_COMMAND. - ReturnErrorCodeIf(activeDataset.Init(req.activeDataset) != CHIP_NO_ERROR, Status::InvalidCommand); + VerifyOrReturnValue(activeDataset.Init(req.activeDataset) == CHIP_NO_ERROR, Status::InvalidCommand); // If this command is invoked when the ActiveDatasetTimestamp attribute is not null, the command SHALL // fail with a status code of INVALID_IN_STATE. - if (mDelegate->GetDataset(currentActiveDataset, Delegate::DatasetType::kActive) == CHIP_NO_ERROR && - currentActiveDataset.GetActiveTimestamp(currentActiveDatasetTimestamp) == CHIP_NO_ERROR) + if ((mDelegate->GetDataset(currentActiveDataset, Delegate::DatasetType::kActive) == CHIP_NO_ERROR) && + (currentActiveDataset.GetActiveTimestamp(currentActiveDatasetTimestamp) == CHIP_NO_ERROR)) { return Status::InvalidInState; } - - mBreadcrumb = req.breadcrumb; + // If there is a back end command process, return status BUSY. + if (mAsyncCommandHandle.Get()) + { + return Status::Busy; + } + commandHandler->FlushAcksRightAwayOnSlowCommand(); + mAsyncCommandHandle = CommandHandler::Handle(commandHandler); + mBreadcrumb = req.breadcrumb; mSetActiveDatasetSequenceNumber++; - CHIP_ERROR err = mDelegate->SetActiveDataset(activeDataset, mSetActiveDatasetSequenceNumber, this); - return StatusIB(err).mStatus; + mDelegate->SetActiveDataset(activeDataset, mSetActiveDatasetSequenceNumber, this); + return Status::Success; } Status ServerInstance::HandleSetPendingDatasetRequest(const Commands::SetPendingDatasetRequest::DecodableType & req) { - ReturnErrorCodeIf(!mDelegate, Status::InvalidInState); - bool panChangeSupported; - if (mDelegate->GetPanChangeSupported(panChangeSupported) != CHIP_NO_ERROR || !panChangeSupported) + VerifyOrDie(mDelegate); + if (!mDelegate->GetPanChangeSupported()) { return Status::UnsupportedCommand; } @@ -117,7 +123,7 @@ Status ServerInstance::HandleSetPendingDatasetRequest(const Commands::SetPending return StatusIB(err).mStatus; } -void AddDatasetResponse(CommandHandlerInterface::HandlerContext & ctx, Status status, Thread::OperationalDataset & dataset) +void AddDatasetResponse(CommandHandlerInterface::HandlerContext & ctx, Status status, const Thread::OperationalDataset & dataset) { if (status != Status::Success) { @@ -136,34 +142,26 @@ void ServerInstance::InvokeCommand(HandlerContext & ctxt) case Commands::GetActiveDatasetRequest::Id: HandleCommand(ctxt, [this](HandlerContext & ctx, const auto & req) { Thread::OperationalDataset dataset; - Status status = HandleGetActiveDatasetRequest(IsOverCASESession(ctx), dataset); + Status status = HandleGetActiveDatasetRequest(IsCommandOverCASESession(ctx), dataset); AddDatasetResponse(ctx, status, dataset); }); break; case Commands::GetPendingDatasetRequest::Id: HandleCommand(ctxt, [this](HandlerContext & ctx, const auto & req) { Thread::OperationalDataset dataset; - Status status = HandleGetPendingDatasetRequest(IsOverCASESession(ctx), dataset); + Status status = HandleGetPendingDatasetRequest(IsCommandOverCASESession(ctx), dataset); AddDatasetResponse(ctx, status, dataset); }); break; case Commands::SetActiveDatasetRequest::Id: HandleCommand(ctxt, [this](HandlerContext & ctx, const auto & req) { - if (!mAsyncCommandHandle.Get()) - { - mPath = ctx.mRequestPath; - mAsyncCommandHandle = CommandHandler::Handle(&ctx.mCommandHandler); - ctx.mCommandHandler.FlushAcksRightAwayOnSlowCommand(); - Status status = HandleSetActiveDatasetRequest(IsFailSafeArmed(ctx.mCommandHandler.GetAccessingFabricIndex()), req); - if (status != Status::Success) - { - OnActivateDatasetComplete(mSetActiveDatasetSequenceNumber, - ChipError(ChipError::SdkPart::kIMGlobalStatus, to_underlying(status))); - } - } - else + mPath = ctx.mRequestPath; + Status status = HandleSetActiveDatasetRequest(&ctx.mCommandHandler, req); + if (status != Status::Success) { - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Busy); + // If status is not Success, we should immediately report the status. Otherwise the async work will report the + // status to the client. + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); } }); break; @@ -177,55 +175,39 @@ void ServerInstance::InvokeCommand(HandlerContext & ctxt) } } -CHIP_ERROR ServerInstance::ReadFeatureMap(BitFlags & featureMap) +void ServerInstance::ReadFeatureMap(BitFlags & outFeatureMap) { - bool panChangeSupported; - ReturnErrorOnFailure(mDelegate->GetPanChangeSupported(panChangeSupported)); - if (panChangeSupported) + if (mDelegate->GetPanChangeSupported()) { - featureMap.Set(Feature::kPANChange); + outFeatureMap.Set(Feature::kPANChange); } - return CHIP_NO_ERROR; } -CHIP_ERROR ServerInstance::ReadBorderRouterName(MutableCharSpan & borderRouterName) +CHIP_ERROR ServerInstance::ReadBorderRouterName(MutableCharSpan & outBorderRouterName) { - ReturnErrorOnFailure(mDelegate->GetBorderRouterName(borderRouterName)); - ReturnErrorCodeIf(borderRouterName.size() > kBorderRouterNameMaxLength, CHIP_IM_GLOBAL_STATUS(ConstraintError)); + mDelegate->GetBorderRouterName(outBorderRouterName); + VerifyOrReturnValue(outBorderRouterName.size() <= kBorderRouterNameMaxLength, CHIP_IM_GLOBAL_STATUS(Failure)); return CHIP_NO_ERROR; } -CHIP_ERROR ServerInstance::ReadBorderAgentID(MutableByteSpan & borderAgentId) +CHIP_ERROR ServerInstance::ReadBorderAgentID(MutableByteSpan & outBorderAgentId) { - ReturnErrorOnFailure(mDelegate->GetBorderAgentId(borderAgentId)); - ReturnErrorCodeIf(borderAgentId.size() != kBorderAgentIdLength, CHIP_IM_GLOBAL_STATUS(ConstraintError)); + VerifyOrReturnValue((mDelegate->GetBorderAgentId(outBorderAgentId) == CHIP_NO_ERROR) && + (outBorderAgentId.size() == kBorderAgentIdLength), + CHIP_IM_GLOBAL_STATUS(Failure)); return CHIP_NO_ERROR; } -CHIP_ERROR ServerInstance::ReadThreadVersion(uint16_t & threadVersion) +Optional ServerInstance::ReadActiveDatasetTimestamp() { - return mDelegate->GetThreadVersion(threadVersion); -} - -CHIP_ERROR ServerInstance::ReadInterfaceEnabled(bool & interfaceEnabled) -{ - return mDelegate->GetInterfaceEnabled(interfaceEnabled); -} - -CHIP_ERROR ServerInstance::ReadActiveDatasetTimestamp(Optional & activeDatasetTimestamp) -{ - uint64_t activeDatasetTimestampValue; + uint64_t activeDatasetTimestampValue = 0; Thread::OperationalDataset activeDataset; - if (mDelegate->GetDataset(activeDataset, Delegate::DatasetType::kActive) == CHIP_NO_ERROR && - activeDataset.GetActiveTimestamp(activeDatasetTimestampValue) == CHIP_NO_ERROR) - { - activeDatasetTimestamp.SetValue(activeDatasetTimestampValue); - } - else + if ((mDelegate->GetDataset(activeDataset, Delegate::DatasetType::kActive) == CHIP_NO_ERROR) && + (activeDataset.GetActiveTimestamp(activeDatasetTimestampValue) == CHIP_NO_ERROR)) { - activeDatasetTimestamp.ClearValue(); + return MakeOptional(activeDatasetTimestampValue); } - return CHIP_NO_ERROR; + return NullOptional; } CHIP_ERROR ServerInstance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) @@ -234,27 +216,21 @@ CHIP_ERROR ServerInstance::Read(const ConcreteReadAttributePath & aPath, Attribu { return CHIP_ERROR_INVALID_ARGUMENT; } - if (!mDelegate) - { - ChipLogError(Zcl, "Thread Border Router Management server not initialized"); - return CHIP_ERROR_UNINITIALIZED; - } + VerifyOrDie(mDelegate); CHIP_ERROR status = CHIP_NO_ERROR; switch (aPath.mAttributeId) { case Globals::Attributes::FeatureMap::Id: { BitFlags featureMap; - status = ReadFeatureMap(featureMap); - if (status == CHIP_NO_ERROR) - { - status = aEncoder.Encode(featureMap); - } + ReadFeatureMap(featureMap); + status = aEncoder.Encode(featureMap); break; } case Attributes::BorderRouterName::Id: { - char borderRouterNameBuf[kBorderRouterNameMaxLength + 1]; + char borderRouterNameBuf[kBorderRouterNameMaxLength] = { 0 }; MutableCharSpan borderRouterName(borderRouterNameBuf); status = ReadBorderRouterName(borderRouterName); + // If there are any internal errors, the status will be returned and the client will get an error report. if (status == CHIP_NO_ERROR) { status = aEncoder.Encode(borderRouterName); @@ -262,7 +238,7 @@ CHIP_ERROR ServerInstance::Read(const ConcreteReadAttributePath & aPath, Attribu break; } case Attributes::BorderAgentID::Id: { - uint8_t borderAgentIDBuf[kBorderAgentIdLength]; + uint8_t borderAgentIDBuf[kBorderAgentIdLength] = { 0 }; MutableByteSpan borderAgentID(borderAgentIDBuf); status = ReadBorderAgentID(borderAgentID); if (status == CHIP_NO_ERROR) @@ -272,31 +248,19 @@ CHIP_ERROR ServerInstance::Read(const ConcreteReadAttributePath & aPath, Attribu break; } case Attributes::ThreadVersion::Id: { - uint16_t threadVersion; - status = ReadThreadVersion(threadVersion); - if (status == CHIP_NO_ERROR) - { - status = aEncoder.Encode(threadVersion); - } + uint16_t threadVersion = mDelegate->GetThreadVersion(); + status = aEncoder.Encode(threadVersion); break; } case Attributes::InterfaceEnabled::Id: { - bool interfaceEnabled; - status = ReadInterfaceEnabled(interfaceEnabled); - if (status == CHIP_NO_ERROR) - { - status = aEncoder.Encode(interfaceEnabled); - } + bool interfaceEnabled = mDelegate->GetInterfaceEnabled(); + status = aEncoder.Encode(interfaceEnabled); break; } case Attributes::ActiveDatasetTimestamp::Id: { - Optional activeDatasetTimestamp; - status = ReadActiveDatasetTimestamp(activeDatasetTimestamp); - if (status == CHIP_NO_ERROR) - { - status = activeDatasetTimestamp.HasValue() ? aEncoder.Encode(DataModel::MakeNullable(activeDatasetTimestamp.Value())) - : aEncoder.EncodeNull(); - } + Optional activeDatasetTimestamp = ReadActiveDatasetTimestamp(); + status = activeDatasetTimestamp.HasValue() ? aEncoder.Encode(DataModel::MakeNullable(activeDatasetTimestamp.Value())) + : aEncoder.EncodeNull(); break; } default: @@ -329,8 +293,7 @@ void ServerInstance::OnActivateDatasetComplete(uint32_t sequenceNum, CHIP_ERROR } if (error == CHIP_NO_ERROR) { - // The successful completion of the activation process SHALL disarm the fail-safe timer. - DisarmFailSafeTimer(); + // TODO: SPEC Issue #10022 CommitSavedBreadcrumb(); } else diff --git a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.h b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.h index 36abeb6b39e40e..6d9143948d035c 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.h +++ b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -38,9 +39,9 @@ class ServerInstance : public CommandHandlerInterface, public AttributeAccessInt { public: using Status = Protocols::InteractionModel::Status; - ServerInstance(EndpointId endpointId, Delegate * delegate) : + ServerInstance(EndpointId endpointId, Delegate * delegate, FailSafeContext & failSafeContext) : CommandHandlerInterface(Optional(endpointId), Id), - AttributeAccessInterface(Optional(endpointId), Id), mDelegate(delegate) + AttributeAccessInterface(Optional(endpointId), Id), mDelegate(delegate), mFailsafeContext(failSafeContext) {} virtual ~ServerInstance() = default; @@ -56,6 +57,7 @@ class ServerInstance : public CommandHandlerInterface, public AttributeAccessInt void OnActivateDatasetComplete(uint32_t sequenceNum, CHIP_ERROR error) override; private: + // TODO: Split the business logic from the unit test class friend class TestThreadBorderRouterManagementCluster; // Command Handlers Status HandleGetActiveDatasetRequest(bool isOverCASESession, Thread::OperationalDataset & dataset) @@ -66,17 +68,16 @@ class ServerInstance : public CommandHandlerInterface, public AttributeAccessInt { return HandleGetDatasetRequest(isOverCASESession, Delegate::DatasetType::kPending, dataset); } - Status HandleSetActiveDatasetRequest(bool failSafeArmed, const Commands::SetActiveDatasetRequest::DecodableType & req); + Status HandleSetActiveDatasetRequest(CommandHandler * commandHandler, + const Commands::SetActiveDatasetRequest::DecodableType & req); Status HandleSetPendingDatasetRequest(const Commands::SetPendingDatasetRequest::DecodableType & req); Status HandleGetDatasetRequest(bool isOverCASESession, Delegate::DatasetType type, Thread::OperationalDataset & dataset); - // Attribute Read handler - CHIP_ERROR ReadFeatureMap(BitFlags & feature); + // Attribute Read handlers + void ReadFeatureMap(BitFlags & feature); + Optional ReadActiveDatasetTimestamp(); CHIP_ERROR ReadBorderRouterName(MutableCharSpan & borderRouterName); CHIP_ERROR ReadBorderAgentID(MutableByteSpan & borderAgentId); - CHIP_ERROR ReadThreadVersion(uint16_t & threadVersion); - CHIP_ERROR ReadInterfaceEnabled(bool & interfaceEnable); - CHIP_ERROR ReadActiveDatasetTimestamp(Optional & activeDatasetTimestamp); static void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg); void OnFailSafeTimerExpired(); @@ -87,12 +88,9 @@ class ServerInstance : public CommandHandlerInterface, public AttributeAccessInt ConcreteCommandPath mPath = ConcreteCommandPath(0, 0, 0); Optional mBreadcrumb; uint32_t mSetActiveDatasetSequenceNumber = 0; + FailSafeContext & mFailsafeContext; }; -bool IsFailSafeArmed(FabricIndex accessingFabricIndex); - -void DisarmFailSafeTimer(); - } // namespace ThreadBorderRouterManagement } // namespace Clusters } // namespace app diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h index b56d93c92ef2b2..ae083ad421b028 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h @@ -17,12 +17,7 @@ #pragma once -#include -#include -#include #include -#include -#include #include #include @@ -48,6 +43,7 @@ class Delegate // If the dataset is set successfully, OnActivateDatasetComplete should be called with CHIP_NO_ERROR when the // Border Router is attached to the Thread network. // If an error occurs while setting the active dataset, this callback should be called with the error. + // The error input of this function could be SDK-range error for CHIP error or OpenThread-range error for Thread error. virtual void OnActivateDatasetComplete(uint32_t sequenceNum, CHIP_ERROR error) = 0; }; @@ -59,25 +55,40 @@ class Delegate virtual CHIP_ERROR Init() = 0; - virtual CHIP_ERROR GetPanChangeSupported(bool & panChangeSupported) = 0; + // Get whether PanChange feature is supported for the Thread BR. + virtual bool GetPanChangeSupported() = 0; - virtual CHIP_ERROR GetBorderRouterName(MutableCharSpan & borderRouterName) = 0; + // Get the BorderRouterName of the Thread BR, which will also be the service name of Thread BR's MeshCOP service. + virtual void GetBorderRouterName(MutableCharSpan & borderRouterName) = 0; + // Get the BorderAgentId of the Thread BR. + // @return + // -IncorrectState When Thread stack is not initialized. + // -InvalidArgument When the size of borderAgentId is not 16 bytes. + // -ThreadErrors When failing to get BorderAgentId. virtual CHIP_ERROR GetBorderAgentId(MutableByteSpan & borderAgentId) = 0; - virtual CHIP_ERROR GetThreadVersion(uint16_t & threadVersion) = 0; + // Get the Thread version which matches the value mapping defined in the "Version TLV" section of the Thread specification. + virtual uint16_t GetThreadVersion() = 0; - virtual CHIP_ERROR GetInterfaceEnabled(bool & interfaceEnabled) = 0; + // Get whether the associated IEEE 802.15.4 Thread interface is enabled or disabled. + virtual bool GetInterfaceEnabled() = 0; + // Get the active dataset or the pending dataset. + // @return + // -IncorrectState When Thread stack is not initialized. + // -NotFound when failing to get the dataset. virtual CHIP_ERROR GetDataset(Thread::OperationalDataset & dataset, DatasetType type) = 0; // There should be no active dataset configured when calling this API, otherwise we should use SetPendingDataset. // The Delegate implementation must store the sequence number and pass it to OnActivateDatasetComplete. - virtual CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t sequenceNum, - ActivateDatasetCallback * callback) = 0; + virtual void SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t sequenceNum, + ActivateDatasetCallback * callback) = 0; - // The function is called when Failsafe timer is triggered and the delegate implementation should clear the active dataset in - // this function to allow trying again a new SetActiveDataset operation. + // The function is called when Failsafe timer is triggered or when the Border Router reboots with a previous Failsafe timer + // started but not disarmed before reboot. The delegate implementation should check whether there is a previous SetActiveDataset + // request and revert the active dataset set by the previous SetActiveDataset. Since there should be no configured dataset when + // calling SetActiveDataset, this function will clear the active dataset to allow trying again a new SetActiveDataset operation. // The delegate is allowed to call OnActivateDatasetComplete for the previous SetActiveDataset request even after this function // is called as the sequence number passed to OnActivateDatasetComplete will be different. virtual CHIP_ERROR RevertActiveDataset() = 0; diff --git a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp index 394c5f578342ae..98a745312e5034 100644 --- a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp +++ b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp @@ -17,14 +17,18 @@ #include #include +#include #include #include #include #include +#include #include +#include #include #include #include +#include #include namespace chip { @@ -37,13 +41,6 @@ void SetBreadcrumb(Attributes::Breadcrumb::TypeInfo::Type breadcrumb) {} } // namespace GeneralCommissioning namespace ThreadBorderRouterManagement { -// Mock functions -bool IsFailSafeArmed(FabricIndex accessingFabricIndex) -{ - return true; -} - -void DisarmFailSafeTimer() {} class TestDelegate : public Delegate { @@ -53,52 +50,36 @@ class TestDelegate : public Delegate CHIP_ERROR Init() override { return CHIP_NO_ERROR; } - CHIP_ERROR GetPanChangeSupported(bool & panChangeSupported) override - { - panChangeSupported = mPanChangeSupported; - return CHIP_NO_ERROR; - } + bool GetPanChangeSupported() override { return mPanChangeSupported; } - CHIP_ERROR GetBorderRouterName(MutableCharSpan & borderRouterName) override + void GetBorderRouterName(MutableCharSpan & borderRouterName) override { size_t nameIndex = mUseInvalidBorderRouterName ? 1 : 0; - if (borderRouterName.size() > strlen(kTestName[nameIndex])) + if (borderRouterName.size() >= strlen(kTestName[nameIndex])) { - memcpy(borderRouterName.data(), kTestName[nameIndex], strlen(kTestName[nameIndex])); - borderRouterName.reduce_size(strlen(kTestName[nameIndex])); - return CHIP_NO_ERROR; + CopyCharSpanToMutableCharSpan(CharSpan(kTestName[nameIndex], strlen(kTestName[nameIndex])), borderRouterName); } - return CHIP_ERROR_BUFFER_TOO_SMALL; } CHIP_ERROR GetBorderAgentId(MutableByteSpan & borderAgentId) override { if (borderAgentId.size() >= mTestBorderAgentIdLen) { - memcpy(borderAgentId.data(), kTestBorderAgentId, mTestBorderAgentIdLen); - borderAgentId.reduce_size(mTestBorderAgentIdLen); + CopySpanToMutableSpan(ByteSpan(kTestBorderAgentId, mTestBorderAgentIdLen), borderAgentId); return CHIP_NO_ERROR; } return CHIP_ERROR_BUFFER_TOO_SMALL; } - CHIP_ERROR GetThreadVersion(uint16_t & threadVersion) override - { - threadVersion = kTestThreadVersion; - return CHIP_NO_ERROR; - } + uint16_t GetThreadVersion() override { return kTestThreadVersion; } - CHIP_ERROR GetInterfaceEnabled(bool & interfaceEnabled) override - { - interfaceEnabled = mInterfaceEnabled; - return CHIP_NO_ERROR; - } + bool GetInterfaceEnabled() override { return mInterfaceEnabled; } CHIP_ERROR GetDataset(Thread::OperationalDataset & dataset, DatasetType type) override { - if (type == DatasetType::kActive && mActiveDatasetLen) + if (type == DatasetType::kActive && mStoredActiveDatasetLen) { - dataset.Init(ByteSpan(mActiveDataset, mActiveDatasetLen)); + dataset.Init(ByteSpan(mStoredActiveDataset, mStoredActiveDatasetLen)); return CHIP_NO_ERROR; } if (type == DatasetType::kPending && mPendingDatasetLen) @@ -109,16 +90,22 @@ class TestDelegate : public Delegate return CHIP_IM_GLOBAL_STATUS(NotFound); } - CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t randomNumber, - ActivateDatasetCallback * callback) override + void SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t sequenceNumber, + ActivateDatasetCallback * callback) override { memcpy(mActiveDataset, activeDataset.AsByteSpan().data(), activeDataset.AsByteSpan().size()); - mActiveDatasetLen = activeDataset.AsByteSpan().size(); - mInterfaceEnabled = true; - return CHIP_NO_ERROR; + mActiveDatasetLen = activeDataset.AsByteSpan().size(); + mCallback = callback; + mSetActiveDatasetCommandSequenceNum = sequenceNumber; } - CHIP_ERROR RevertActiveDataset() override { return CHIP_NO_ERROR; } + CHIP_ERROR RevertActiveDataset() override + { + mStoredActiveDatasetLen = 0; + mInterfaceEnabled = false; + mCallback = nullptr; + return CHIP_NO_ERROR; + } CHIP_ERROR SetPendingDataset(const Thread::OperationalDataset & pendingDataset) override { @@ -127,39 +114,99 @@ class TestDelegate : public Delegate return CHIP_NO_ERROR; } + void ActivateActiveDataset() + { + memcpy(mStoredActiveDataset, mActiveDataset, Thread::kSizeOperationalDataset); + mStoredActiveDatasetLen = mActiveDatasetLen; + mInterfaceEnabled = true; + if (mCallback) + { + mCallback->OnActivateDatasetComplete(mSetActiveDatasetCommandSequenceNum, CHIP_NO_ERROR); + } + } + bool mPanChangeSupported = true; const char * kTestName[2] = { "TestName", "TestNameLength64________________________________________________" }; - const uint8_t kTestBorderAgentId[kBorderAgentIdLength] = { 0x0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }; - const uint16_t kTestThreadVersion = 4; - uint8_t mActiveDataset[Thread::kSizeOperationalDataset]; - size_t mActiveDatasetLen = 0; - uint8_t mPendingDataset[Thread::kSizeOperationalDataset]; - size_t mPendingDatasetLen = 0; - bool mUseInvalidBorderRouterName = true; - size_t mTestBorderAgentIdLen = kBorderAgentIdLength - 1; - bool mInterfaceEnabled = false; + const uint8_t kTestBorderAgentId[kBorderAgentIdLength] = { 0x0, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }; + const uint16_t kTestThreadVersion = 4; + uint8_t mActiveDataset[Thread::kSizeOperationalDataset] = { 0 }; + size_t mActiveDatasetLen = 0; + uint8_t mStoredActiveDataset[Thread::kSizeOperationalDataset] = { 0 }; + size_t mStoredActiveDatasetLen = 0; + uint8_t mPendingDataset[Thread::kSizeOperationalDataset] = { 0 }; + size_t mPendingDatasetLen = 0; + bool mUseInvalidBorderRouterName = true; + size_t mTestBorderAgentIdLen = kBorderAgentIdLength - 1; + bool mInterfaceEnabled = false; + uint32_t mSetActiveDatasetCommandSequenceNum = 0; + ActivateDatasetCallback * mCallback = nullptr; +}; + +constexpr EndpointId kTestEndpointId = 1; +constexpr FabricIndex kTestAccessingFabricIndex = 1; +static FailSafeContext sTestFailsafeContext; +static TestDelegate sTestDelegate; +static ServerInstance sTestSeverInstance(kTestEndpointId, &sTestDelegate, sTestFailsafeContext); + +class TestSetActiveDatasetCommandHandler : public CommandHandler +{ +public: + TestSetActiveDatasetCommandHandler() : mClusterStatus(Protocols::InteractionModel::Status::Success) {} + CHIP_ERROR FallibleAddStatus(const ConcreteCommandPath & aRequestCommandPath, + const Protocols::InteractionModel::ClusterStatusCode & aStatus, const char * context = nullptr) + { + return CHIP_NO_ERROR; + } + + void AddStatus(const ConcreteCommandPath & aRequestCommandPath, const Protocols::InteractionModel::ClusterStatusCode & aStatus, + const char * context = nullptr) + { + mClusterStatus = aStatus; + } + + FabricIndex GetAccessingFabricIndex() const { return kTestAccessingFabricIndex; } + + CHIP_ERROR AddResponseData(const ConcreteCommandPath & aRequestCommandPath, CommandId aResponseCommandId, + const DataModel::EncodableToTLV & aEncodable) + { + return CHIP_NO_ERROR; + } + + void AddResponse(const ConcreteCommandPath & aRequestCommandPath, CommandId aResponseCommandId, + const DataModel::EncodableToTLV & aEncodable) + {} + + bool IsTimedInvoke() const { return false; } + + void FlushAcksRightAwayOnSlowCommand() {} + + Access::SubjectDescriptor GetSubjectDescriptor() const + { + Access::SubjectDescriptor subjectDescriptor; + return subjectDescriptor; + } + + Messaging::ExchangeContext * GetExchangeContext() const { return nullptr; } + + Protocols::InteractionModel::ClusterStatusCode mClusterStatus; }; -constexpr chip::EndpointId sTestEndpointId = 1; -static TestDelegate * sTestDelegatePtr = nullptr; -static ServerInstance * sTestSeverInstancePtr = nullptr; +TestSetActiveDatasetCommandHandler sTestCommandHandler; class TestThreadBorderRouterManagementCluster : public ::testing::Test { public: static void SetUpTestSuite() { - sTestDelegatePtr = new ThreadBorderRouterManagement::TestDelegate(); - ASSERT_TRUE(sTestDelegatePtr); - sTestSeverInstancePtr = new ThreadBorderRouterManagement::ServerInstance(sTestEndpointId, sTestDelegatePtr); - ASSERT_TRUE(sTestSeverInstancePtr); + ASSERT_EQ(Platform::MemoryInit(), CHIP_NO_ERROR); + ASSERT_EQ(DeviceLayer::PlatformMgr().InitChipStack(), CHIP_NO_ERROR); } static void TearDownTestSuite() { - delete sTestDelegatePtr; - delete sTestSeverInstancePtr; + DeviceLayer::PlatformMgr().Shutdown(); + Platform::MemoryShutdown(); } void TestAttributeRead(); @@ -169,47 +216,59 @@ class TestThreadBorderRouterManagementCluster : public ::testing::Test // Test ReadXX functions in ThreadBorderRouterManagement ServerInstance TEST_F_FROM_FIXTURE(TestThreadBorderRouterManagementCluster, TestAttributeRead) { - BitFlags featureMap; - EXPECT_EQ(sTestSeverInstancePtr->ReadFeatureMap(featureMap), CHIP_NO_ERROR); + // FeatureMap attribute + BitFlags featureMap = BitFlags(); + // Make the PAN change feature supported in Test delegate. + sTestDelegate.mPanChangeSupported = true; + sTestSeverInstance.ReadFeatureMap(featureMap); EXPECT_TRUE(featureMap.Has(Feature::kPANChange)); - sTestDelegatePtr->mPanChangeSupported = false; + // Make the PAN change feature unsupported in Test delegate. + sTestDelegate.mPanChangeSupported = false; featureMap.ClearAll(); - EXPECT_EQ(sTestSeverInstancePtr->ReadFeatureMap(featureMap), CHIP_NO_ERROR); + sTestSeverInstance.ReadFeatureMap(featureMap); EXPECT_FALSE(featureMap.Has(Feature::kPANChange)); - char borderRouterName[kBorderRouterNameMaxLength + 10]; - MutableCharSpan nameSpan = MutableCharSpan(borderRouterName); - EXPECT_EQ(sTestSeverInstancePtr->ReadBorderRouterName(nameSpan), CHIP_IM_GLOBAL_STATUS(ConstraintError)); - nameSpan = MutableCharSpan(borderRouterName); - sTestDelegatePtr->mUseInvalidBorderRouterName = false; - EXPECT_EQ(sTestSeverInstancePtr->ReadBorderRouterName(nameSpan), CHIP_NO_ERROR); + // BorderRouterName attribute + // Use invalid BR name + sTestDelegate.mUseInvalidBorderRouterName = true; + char borderRouterName[kBorderRouterNameMaxLength + 10] = { 0 }; + MutableCharSpan nameSpan(borderRouterName); + EXPECT_EQ(sTestSeverInstance.ReadBorderRouterName(nameSpan), CHIP_IM_GLOBAL_STATUS(Failure)); + nameSpan = MutableCharSpan(borderRouterName); + // Use valid BR name + sTestDelegate.mUseInvalidBorderRouterName = false; + EXPECT_EQ(sTestSeverInstance.ReadBorderRouterName(nameSpan), CHIP_NO_ERROR); EXPECT_TRUE(nameSpan.data_equal(CharSpan("TestName", strlen("TestName")))); - uint8_t borderAgentId[kBorderAgentIdLength]; - MutableByteSpan agentIdSpan = MutableByteSpan(borderAgentId); - EXPECT_EQ(sTestSeverInstancePtr->ReadBorderAgentID(agentIdSpan), CHIP_IM_GLOBAL_STATUS(ConstraintError)); - agentIdSpan = MutableByteSpan(borderAgentId); - sTestDelegatePtr->mTestBorderAgentIdLen = kBorderAgentIdLength; - EXPECT_EQ(sTestSeverInstancePtr->ReadBorderAgentID(agentIdSpan), CHIP_NO_ERROR); - EXPECT_TRUE(agentIdSpan.data_equal(ByteSpan(sTestDelegatePtr->kTestBorderAgentId))); - uint16_t threadVersion; - EXPECT_EQ(sTestSeverInstancePtr->ReadThreadVersion(threadVersion), CHIP_NO_ERROR); - EXPECT_EQ(threadVersion, sTestDelegatePtr->kTestThreadVersion); - bool interfaceEnabled; - EXPECT_EQ(sTestSeverInstancePtr->ReadInterfaceEnabled(interfaceEnabled), CHIP_NO_ERROR); - EXPECT_FALSE(interfaceEnabled); - Optional timestamp; - EXPECT_EQ(sTestSeverInstancePtr->ReadActiveDatasetTimestamp(timestamp), CHIP_NO_ERROR); + // BorderAgentId attribute + uint8_t borderAgentId[kBorderAgentIdLength] = { 0 }; + MutableByteSpan agentIdSpan(borderAgentId); + // Use invalid border agent id + sTestDelegate.mTestBorderAgentIdLen = kBorderAgentIdLength - 1; + EXPECT_EQ(sTestSeverInstance.ReadBorderAgentID(agentIdSpan), CHIP_IM_GLOBAL_STATUS(Failure)); + agentIdSpan = MutableByteSpan(borderAgentId); + // Use valid border agent id + sTestDelegate.mTestBorderAgentIdLen = kBorderAgentIdLength; + EXPECT_EQ(sTestSeverInstance.ReadBorderAgentID(agentIdSpan), CHIP_NO_ERROR); + EXPECT_TRUE(agentIdSpan.data_equal(ByteSpan(sTestDelegate.kTestBorderAgentId))); + // ActiveDatasetTimestamp attribute + // The active dataset timestamp should be null when no active dataset is configured + Optional timestamp = sTestSeverInstance.ReadActiveDatasetTimestamp(); EXPECT_FALSE(timestamp.HasValue()); } TEST_F_FROM_FIXTURE(TestThreadBorderRouterManagementCluster, TestCommandHandle) { + // Test GetActiveDatasetRequest and GetPendingDatasetRequest commands Thread::OperationalDataset dataset; using DatasetType = Delegate::DatasetType; using Status = Protocols::InteractionModel::Status; - EXPECT_EQ(sTestSeverInstancePtr->HandleGetDatasetRequest(false, DatasetType::kActive, dataset), Status::UnsupportedAccess); - EXPECT_EQ(sTestSeverInstancePtr->HandleGetDatasetRequest(false, DatasetType::kPending, dataset), Status::UnsupportedAccess); - EXPECT_EQ(sTestSeverInstancePtr->HandleGetDatasetRequest(true, DatasetType::kActive, dataset), Status::NotFound); - EXPECT_EQ(sTestSeverInstancePtr->HandleGetDatasetRequest(true, DatasetType::kPending, dataset), Status::NotFound); + // The GetDataset requests should over CASE session. + EXPECT_EQ(sTestSeverInstance.HandleGetDatasetRequest(false /* isOverCASESession */, DatasetType::kActive, dataset), + Status::UnsupportedAccess); + EXPECT_EQ(sTestSeverInstance.HandleGetDatasetRequest(false, DatasetType::kPending, dataset), Status::UnsupportedAccess); + // The GetDataset should return NotFound when no dataset is configured. + EXPECT_EQ(sTestSeverInstance.HandleGetDatasetRequest(true, DatasetType::kActive, dataset), Status::NotFound); + EXPECT_EQ(sTestSeverInstance.HandleGetDatasetRequest(true, DatasetType::kPending, dataset), Status::NotFound); + // Test SetActiveDatasetRequest ThreadBorderRouterManagement::Commands::SetActiveDatasetRequest::DecodableType req1; uint8_t invalidDataset[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 }; uint8_t validDataset[] = { 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0b, 0x35, 0x06, @@ -218,26 +277,51 @@ TEST_F_FROM_FIXTURE(TestThreadBorderRouterManagementCluster, TestCommandHandle) 0xc5, 0x25, 0x7f, 0x68, 0x4c, 0x54, 0x9d, 0x6a, 0x57, 0x5e, 0x03, 0x0a, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x01, 0x02, 0xc1, 0x15, 0x04, 0x10, 0xcb, 0x13, 0x47, 0xeb, 0x0c, 0xd4, 0xb3, 0x5c, 0xd1, 0x42, 0xda, 0x5e, 0x6d, 0xf1, 0x8b, 0x88, 0x0c, 0x04, 0x02, 0xa0, 0xf7, 0xf8 }; - req1.activeDataset = ByteSpan(invalidDataset); - EXPECT_EQ(sTestSeverInstancePtr->HandleSetActiveDatasetRequest(false, req1), Status::FailsafeRequired); - EXPECT_EQ(sTestSeverInstancePtr->HandleSetActiveDatasetRequest(true, req1), Status::InvalidCommand); + Optional activeDatasetTimestamp = chip::NullOptional; + activeDatasetTimestamp = sTestSeverInstance.ReadActiveDatasetTimestamp(); + EXPECT_FALSE(activeDatasetTimestamp.HasValue()); + req1.activeDataset = ByteSpan(invalidDataset); + // SetActiveDatasetRequest is FailsafeRequired. + EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(&sTestCommandHandler, req1), Status::FailsafeRequired); + sTestFailsafeContext.ArmFailSafe(kTestAccessingFabricIndex, System::Clock::Seconds16(1)); + // SetActiveDatasetRequest should return InvalidCommand when dataset is invalid. + EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(&sTestCommandHandler, req1), Status::InvalidCommand); req1.activeDataset = ByteSpan(validDataset); - EXPECT_EQ(sTestSeverInstancePtr->HandleSetActiveDatasetRequest(true, req1), Status::Success); - EXPECT_EQ(sTestSeverInstancePtr->HandleGetDatasetRequest(true, DatasetType::kActive, dataset), Status::Success); + EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(&sTestCommandHandler, req1), Status::Success); + // When the Server is handling a SetActiveDatasetRequest command, it should return Busy after receiving another one. + EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(&sTestCommandHandler, req1), Status::Busy); + EXPECT_FALSE(sTestDelegate.mInterfaceEnabled); + EXPECT_EQ(sTestDelegate.mSetActiveDatasetCommandSequenceNum, static_cast(1)); + // Activate the dataset. + sTestDelegate.ActivateActiveDataset(); + EXPECT_EQ(sTestCommandHandler.mClusterStatus, + Protocols::InteractionModel::ClusterStatusCode(Protocols::InteractionModel::Status::Success)); + sTestFailsafeContext.DisarmFailSafe(); + // The Dataset should be updated. + EXPECT_EQ(sTestSeverInstance.HandleGetDatasetRequest(true, DatasetType::kActive, dataset), Status::Success); EXPECT_TRUE(dataset.AsByteSpan().data_equal(ByteSpan(validDataset))); - bool interfaceEnabled; - EXPECT_EQ(sTestSeverInstancePtr->ReadInterfaceEnabled(interfaceEnabled), CHIP_NO_ERROR); - EXPECT_TRUE(interfaceEnabled); - EXPECT_EQ(sTestSeverInstancePtr->HandleSetActiveDatasetRequest(true, req1), Status::InvalidInState); + EXPECT_TRUE(sTestDelegate.mInterfaceEnabled); + activeDatasetTimestamp = sTestSeverInstance.ReadActiveDatasetTimestamp(); + // activeDatasetTimestamp should have value. + EXPECT_TRUE(activeDatasetTimestamp.HasValue()); + sTestFailsafeContext.ArmFailSafe(kTestAccessingFabricIndex, System::Clock::Seconds16(1)); + // When ActiveDatasetTimestamp is not null, the set active dataset request should return InvalidInState. + EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(&sTestCommandHandler, req1), Status::InvalidInState); + sTestFailsafeContext.DisarmFailSafe(); + // Test SetPendingDatasetRequest command Commands::SetPendingDatasetRequest::DecodableType req2; + sTestDelegate.mPanChangeSupported = false; + req2.pendingDataset = ByteSpan(validDataset); + // SetPendingDatasetRequest is supported when PANChange feature is enabled. + EXPECT_EQ(sTestSeverInstance.HandleSetPendingDatasetRequest(req2), Status::UnsupportedCommand); + sTestDelegate.mPanChangeSupported = true; + req2.pendingDataset = ByteSpan(invalidDataset); + // SetPendingDatasetRequest should return InvalidCommand when dataset is invalid. + EXPECT_EQ(sTestSeverInstance.HandleSetPendingDatasetRequest(req2), Status::InvalidCommand); req2.pendingDataset = ByteSpan(validDataset); - EXPECT_EQ(sTestSeverInstancePtr->HandleSetPendingDatasetRequest(req2), Status::UnsupportedCommand); - sTestDelegatePtr->mPanChangeSupported = true; - req2.pendingDataset = ByteSpan(invalidDataset); - EXPECT_EQ(sTestSeverInstancePtr->HandleSetPendingDatasetRequest(req2), Status::InvalidCommand); - req2.pendingDataset = ByteSpan(validDataset); - EXPECT_EQ(sTestSeverInstancePtr->HandleSetPendingDatasetRequest(req2), Status::Success); - EXPECT_EQ(sTestSeverInstancePtr->HandleGetDatasetRequest(true, DatasetType::kPending, dataset), Status::Success); + // Success SetPendingDatasetRequest + EXPECT_EQ(sTestSeverInstance.HandleSetPendingDatasetRequest(req2), Status::Success); + EXPECT_EQ(sTestSeverInstance.HandleGetDatasetRequest(true, DatasetType::kPending, dataset), Status::Success); EXPECT_TRUE(dataset.AsByteSpan().data_equal(ByteSpan(validDataset))); } diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp index 8d89bc2c9e0238..4b494f8bacb320 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -57,7 +58,7 @@ CHIP_ERROR GenericOpenThreadBorderRouterDelegate::Init() mCallback = nullptr; ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler, reinterpret_cast(this))); // When the Thread Border Router is reboot during SetActiveDataset, we need to revert the active dateset. - ReturnErrorOnFailure(RevertActiveDataset()); + RevertActiveDataset(); return CHIP_NO_ERROR; } @@ -66,34 +67,34 @@ CHIP_ERROR GenericOpenThreadBorderRouterDelegate::GetBorderAgentId(MutableByteSp otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); otBorderAgentId borderAgentId; - if (borderAgentIdSpan.size() < sizeof(borderAgentId.mId)) + if (borderAgentIdSpan.size() != sizeof(borderAgentId.mId)) { return CHIP_ERROR_INVALID_ARGUMENT; } - ScopedThreadLock threadLock; - otError err = otBorderAgentGetId(otInst, &borderAgentId); - if (err == OT_ERROR_NONE) + otError otErr = OT_ERROR_NONE; + { + ScopedThreadLock threadLock; + otErr = otBorderAgentGetId(otInst, &borderAgentId); + } + if (otErr == OT_ERROR_NONE) { - memcpy(borderAgentIdSpan.data(), borderAgentId.mId, sizeof(borderAgentId.mId)); - borderAgentIdSpan.reduce_size(sizeof(borderAgentId.mId)); + CopySpanToMutableSpan(ByteSpan(borderAgentId.mId), borderAgentIdSpan); return CHIP_NO_ERROR; } - return CHIP_ERROR_INTERNAL; + return DeviceLayer::Internal::MapOpenThreadError(otErr); } -CHIP_ERROR GenericOpenThreadBorderRouterDelegate::GetThreadVersion(uint16_t & threadVersion) +uint16_t GenericOpenThreadBorderRouterDelegate::GetThreadVersion() { - threadVersion = otThreadGetVersion(); - return CHIP_NO_ERROR; + return otThreadGetVersion(); } -CHIP_ERROR GenericOpenThreadBorderRouterDelegate::GetInterfaceEnabled(bool & interfaceEnabled) +bool GenericOpenThreadBorderRouterDelegate::GetInterfaceEnabled() { otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); - VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnValue(otInst, false); ScopedThreadLock threadLock; - interfaceEnabled = otIp6IsEnabled(otInst); - return CHIP_NO_ERROR; + return otIp6IsEnabled(otInst); } CHIP_ERROR GenericOpenThreadBorderRouterDelegate::GetDataset(Thread::OperationalDataset & dataset, DatasetType type) @@ -101,41 +102,42 @@ CHIP_ERROR GenericOpenThreadBorderRouterDelegate::GetDataset(Thread::Operational otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); - ScopedThreadLock threadLock; otError otErr = OT_ERROR_NONE; otOperationalDatasetTlvs datasetTlvs; - if (type == DatasetType::kActive) - { - otErr = otDatasetGetActiveTlvs(otInst, &datasetTlvs); - } - else { - otErr = otDatasetGetPendingTlvs(otInst, &datasetTlvs); + ScopedThreadLock threadLock; + if (type == DatasetType::kActive) + { + otErr = otDatasetGetActiveTlvs(otInst, &datasetTlvs); + } + else + { + otErr = otDatasetGetPendingTlvs(otInst, &datasetTlvs); + } } if (otErr == OT_ERROR_NONE) { return dataset.Init(ByteSpan(datasetTlvs.mTlvs, datasetTlvs.mLength)); } - return CHIP_ERROR_NOT_FOUND; + return DeviceLayer::Internal::MapOpenThreadError(otErr); } -CHIP_ERROR GenericOpenThreadBorderRouterDelegate::SetActiveDataset(const Thread::OperationalDataset & activeDataset, - uint32_t sequenceNum, ActivateDatasetCallback * callback) +void GenericOpenThreadBorderRouterDelegate::SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t sequenceNum, + ActivateDatasetCallback * callback) { // This function will never be invoked when there is an Active Dataset already configured. - CHIP_ERROR err = SaveThreadBorderRouterCommissioned(false); + CHIP_ERROR err = SaveActiveDatasetConfigured(false); if (err == CHIP_NO_ERROR) { err = DeviceLayer::ThreadStackMgrImpl().AttachToThreadNetwork(activeDataset, nullptr); } - if (err == CHIP_NO_ERROR) + if (err != CHIP_NO_ERROR) { - // We can change the stored sequence number because OnActivateDatasetComplete executed later must be called for this - // SetActiveDataset request - mSequenceNum = sequenceNum; - mCallback = callback; + callback->OnActivateDatasetComplete(sequenceNum, err); + return; } - return err; + mSequenceNum = sequenceNum; + mCallback = callback; } void GenericOpenThreadBorderRouterDelegate::OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg) @@ -147,31 +149,36 @@ void GenericOpenThreadBorderRouterDelegate::OnPlatformEventHandler(const DeviceL event->ThreadConnectivityChange.Result == DeviceLayer::kConnectivity_Established) { delegate->mCallback->OnActivateDatasetComplete(delegate->mSequenceNum, CHIP_NO_ERROR); - SaveThreadBorderRouterCommissioned(true); + delegate->SaveActiveDatasetConfigured(true); delegate->mCallback = nullptr; } } } -CHIP_ERROR GenericOpenThreadBorderRouterDelegate::SaveThreadBorderRouterCommissioned(bool commissioned) +CHIP_ERROR GenericOpenThreadBorderRouterDelegate::SaveActiveDatasetConfigured(bool configured) { - return DeviceLayer::PersistedStorage::KeyValueStoreMgr().Put(kFailsafeThreadBorderRouterCommissioned, commissioned); + VerifyOrReturnError(mStorage, CHIP_ERROR_INTERNAL); + return mStorage->SyncSetKeyValue(kFailsafeActiveDatasetConfigured, &configured, sizeof(bool)); } CHIP_ERROR GenericOpenThreadBorderRouterDelegate::RevertActiveDataset() { // The FailSafe Timer is triggered and the previous command request should be handled, so reset the callback. - mCallback = nullptr; - bool threadCommissioned = true; - DeviceLayer::PersistedStorage::KeyValueStoreMgr().Get(kFailsafeThreadBorderRouterCommissioned, &threadCommissioned); - if (!threadCommissioned) + mCallback = nullptr; + bool activeDatasetConfigured = true; + uint16_t activeDatasetConfiguredLen = sizeof(bool); + VerifyOrReturnError(mStorage, CHIP_ERROR_INTERNAL); + mStorage->SyncGetKeyValue(kFailsafeActiveDatasetConfigured, &activeDatasetConfigured, activeDatasetConfiguredLen); + VerifyOrDie(activeDatasetConfiguredLen == sizeof(bool)); + if (!activeDatasetConfigured) { - // If Thread is not commissioned, we will try to attach an empty Thread dataset and that will clear the one stored in the - // Thread stack since the SetActiveDataset operation fails and FailSafe timer is triggered. + // The active dataset should be no configured after calling this function, so we will try to attach an empty Thread dataset + // and that will clear the one stored in the Thread stack since the SetActiveDataset operation fails and FailSafe timer is + // triggered. Thread::OperationalDataset emptyDataset = {}; return DeviceLayer::ThreadStackMgrImpl().AttachToThreadNetwork(emptyDataset, nullptr); + SaveActiveDatasetConfigured(false) } - return CHIP_NO_ERROR; } CHIP_ERROR GenericOpenThreadBorderRouterDelegate::SetPendingDataset(const Thread::OperationalDataset & pendingDataset) @@ -179,11 +186,13 @@ CHIP_ERROR GenericOpenThreadBorderRouterDelegate::SetPendingDataset(const Thread otInstance * otInst = DeviceLayer::ThreadStackMgrImpl().OTInstance(); VerifyOrReturnError(otInst, CHIP_ERROR_INCORRECT_STATE); - ScopedThreadLock threadLock; otOperationalDatasetTlvs datasetTlvs; memcpy(datasetTlvs.mTlvs, pendingDataset.AsByteSpan().data(), pendingDataset.AsByteSpan().size()); datasetTlvs.mLength = pendingDataset.AsByteSpan().size(); - ReturnErrorCodeIf(otDatasetSetPendingTlvs(otInst, &datasetTlvs) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); + { + ScopedThreadLock threadLock; + ReturnErrorCodeIf(otDatasetSetPendingTlvs(otInst, &datasetTlvs) != OT_ERROR_NONE, CHIP_ERROR_INTERNAL); + } return CHIP_NO_ERROR; } diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h index 0a5f0524fb963a..e4def6b79b0105 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h @@ -21,6 +21,7 @@ #include #include #include +#include #include namespace chip { @@ -32,40 +33,29 @@ namespace ThreadBorderRouterManagement { class GenericOpenThreadBorderRouterDelegate : public Delegate { public: - static constexpr char kFailsafeThreadBorderRouterCommissioned[] = "g/fs/tbrc"; - - GenericOpenThreadBorderRouterDelegate(const char * name) { strncpy(mThreadBorderRouterName, name, kBorderRouterNameMaxLength); } + static constexpr char kFailsafeActiveDatasetConfigured[] = "g/fs/tbradc"; + GenericOpenThreadBorderRouterDelegate(PersistentStorageDelegate * storage) : mStorage(storage) {} ~GenericOpenThreadBorderRouterDelegate() = default; CHIP_ERROR Init() override; - CHIP_ERROR GetPanChangeSupported(bool & panChangeSupported) override - { - panChangeSupported = true; - return CHIP_NO_ERROR; - } + bool GetPanChangeSupported() override { return true; } - CHIP_ERROR GetBorderRouterName(MutableCharSpan & borderRouterName) override + void GetBorderRouterName(MutableCharSpan & borderRouterName) override { - if (borderRouterName.size() < strlen(mThreadBorderRouterName)) - { - return CHIP_ERROR_NO_MEMORY; - } - strcpy(borderRouterName.data(), mThreadBorderRouterName); - borderRouterName.reduce_size(strlen(mThreadBorderRouterName)); - return CHIP_NO_ERROR; + CopyCharSpanToMutableCharSpan(CharSpan(mThreadBorderRouterName, strlen(mThreadBorderRouterName)), borderRouterName); } CHIP_ERROR GetBorderAgentId(MutableByteSpan & borderAgentId) override; - CHIP_ERROR GetThreadVersion(uint16_t & threadVersion) override; + uint16_t GetThreadVersion() override; - CHIP_ERROR GetInterfaceEnabled(bool & interfaceEnabled) override; + bool GetInterfaceEnabled() override; CHIP_ERROR GetDataset(Thread::OperationalDataset & dataset, DatasetType type) override; - CHIP_ERROR SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t sequenceNum, - ActivateDatasetCallback * callback) override; + void SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t sequenceNum, + ActivateDatasetCallback * callback) override; CHIP_ERROR RevertActiveDataset() override; @@ -73,11 +63,18 @@ class GenericOpenThreadBorderRouterDelegate : public Delegate static void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg); + void SetThreadBorderRouterName(const CharSpan & name) + { + MutableCharSpan borderRouterName(mThreadBorderRouterName); + CopyCharSpanToMutableCharSpan(name, borderRouterName); + } + private: - CHIP_ERROR SaveThreadBorderRouterCommissioned(bool commissioned); + CHIP_ERROR SaveActiveDatasetConfigured(bool configured); ActivateDatasetCallback * mCallback = nullptr; - uint32_t mSequenceNum; + uint32_t mSequenceNum = 0; char mThreadBorderRouterName[kBorderRouterNameMaxLength + 1]; + PersistentStorageDelegate * mStorage; }; } // namespace ThreadBorderRouterManagement } // namespace Clusters From 1e0c3b9978855ee910a2dc5b909d1699bb73f12e Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Fri, 12 Jul 2024 15:04:42 +0800 Subject: [PATCH 33/46] add commissioning complete action --- .../thread-border-router-management-server.cpp | 4 ++++ .../thread-br-delegate.h | 3 +++ src/app/tests/TestThreadBorderRouterManagementCluster.cpp | 3 +++ .../OpenThread/GenericThreadBorderRouterDelegate.cpp | 5 +++++ src/platform/OpenThread/GenericThreadBorderRouterDelegate.h | 2 ++ 5 files changed, 17 insertions(+) diff --git a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp index c8948be3bb6a4b..3a07041c4226ef 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp +++ b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp @@ -325,6 +325,10 @@ void ServerInstance::OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * { _this->OnFailSafeTimerExpired(); } + else if (event->Type == DeviceLayer::DeviceEventType::kCommissioningComplete) + { + _this->mDelegate->CommitActiveDataset(); + } } CHIP_ERROR ServerInstance::Init() diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h index ae083ad421b028..98af7c2794eb6a 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h @@ -85,6 +85,9 @@ class Delegate virtual void SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t sequenceNum, ActivateDatasetCallback * callback) = 0; + // This function will check save whether there is active dataset configured. + virtual CHIP_ERROR CommitActiveDataset() = 0; + // The function is called when Failsafe timer is triggered or when the Border Router reboots with a previous Failsafe timer // started but not disarmed before reboot. The delegate implementation should check whether there is a previous SetActiveDataset // request and revert the active dataset set by the previous SetActiveDataset. Since there should be no configured dataset when diff --git a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp index 98a745312e5034..5ba439156145c7 100644 --- a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp +++ b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp @@ -99,6 +99,8 @@ class TestDelegate : public Delegate mSetActiveDatasetCommandSequenceNum = sequenceNumber; } + CHIP_ERROR CommitActiveDataset() override { return CHIP_NO_ERROR; } + CHIP_ERROR RevertActiveDataset() override { mStoredActiveDatasetLen = 0; @@ -123,6 +125,7 @@ class TestDelegate : public Delegate { mCallback->OnActivateDatasetComplete(mSetActiveDatasetCommandSequenceNum, CHIP_NO_ERROR); } + mCallback = nullptr; } bool mPanChangeSupported = true; diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp index 4b494f8bacb320..55c47d0c210a42 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp @@ -161,6 +161,11 @@ CHIP_ERROR GenericOpenThreadBorderRouterDelegate::SaveActiveDatasetConfigured(bo return mStorage->SyncSetKeyValue(kFailsafeActiveDatasetConfigured, &configured, sizeof(bool)); } +CHIP_ERROR GenericOpenThreadBorderRouterDelegate::CommitActiveDataset() +{ + return SaveActiveDatasetConfigured(DeviceLayer::ThreadStackMgrImpl().IsThreadAttached()); +} + CHIP_ERROR GenericOpenThreadBorderRouterDelegate::RevertActiveDataset() { // The FailSafe Timer is triggered and the previous command request should be handled, so reset the callback. diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h index e4def6b79b0105..17ff32779b3945 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h @@ -57,6 +57,8 @@ class GenericOpenThreadBorderRouterDelegate : public Delegate void SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t sequenceNum, ActivateDatasetCallback * callback) override; + CHIP_ERROR CommitActiveDataset() override; + CHIP_ERROR RevertActiveDataset() override; CHIP_ERROR SetPendingDataset(const Thread::OperationalDataset & pendingDataset) override; From 6463cf367bb6cc044c65563940ecbf73bd8ef24d Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Fri, 12 Jul 2024 07:05:30 +0000 Subject: [PATCH 34/46] Restyled by clang-format --- src/app/tests/TestThreadBorderRouterManagementCluster.cpp | 2 +- src/platform/OpenThread/GenericThreadBorderRouterDelegate.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp index 5ba439156145c7..b7f420b53c6d71 100644 --- a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp +++ b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp @@ -281,7 +281,7 @@ TEST_F_FROM_FIXTURE(TestThreadBorderRouterManagementCluster, TestCommandHandle) 0x68, 0x72, 0x65, 0x61, 0x64, 0x01, 0x02, 0xc1, 0x15, 0x04, 0x10, 0xcb, 0x13, 0x47, 0xeb, 0x0c, 0xd4, 0xb3, 0x5c, 0xd1, 0x42, 0xda, 0x5e, 0x6d, 0xf1, 0x8b, 0x88, 0x0c, 0x04, 0x02, 0xa0, 0xf7, 0xf8 }; Optional activeDatasetTimestamp = chip::NullOptional; - activeDatasetTimestamp = sTestSeverInstance.ReadActiveDatasetTimestamp(); + activeDatasetTimestamp = sTestSeverInstance.ReadActiveDatasetTimestamp(); EXPECT_FALSE(activeDatasetTimestamp.HasValue()); req1.activeDataset = ByteSpan(invalidDataset); // SetActiveDatasetRequest is FailsafeRequired. diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h index 17ff32779b3945..1f9bae1129a0c1 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h @@ -74,7 +74,7 @@ class GenericOpenThreadBorderRouterDelegate : public Delegate private: CHIP_ERROR SaveActiveDatasetConfigured(bool configured); ActivateDatasetCallback * mCallback = nullptr; - uint32_t mSequenceNum = 0; + uint32_t mSequenceNum = 0; char mThreadBorderRouterName[kBorderRouterNameMaxLength + 1]; PersistentStorageDelegate * mStorage; }; From 2f1184f41b2c46213e1accfc03ec555af1adf581 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Fri, 12 Jul 2024 18:59:49 +0800 Subject: [PATCH 35/46] Only build TestThreadBorderRouterManagementCluster for no-fake platform --- src/app/tests/BUILD.gn | 8 +++++--- src/app/tests/TestThreadBorderRouterManagementCluster.cpp | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn index d0ab2fc62a83f6..7b29876f89eccf 100644 --- a/src/app/tests/BUILD.gn +++ b/src/app/tests/BUILD.gn @@ -187,7 +187,6 @@ chip_test_suite("tests") { "TestStatusIB.cpp", "TestStatusResponseMessage.cpp", "TestTestEventTriggerDelegate.cpp", - "TestThreadBorderRouterManagementCluster.cpp", "TestTimeSyncDataProvider.cpp", "TestTimedHandler.cpp", "TestWriteInteraction.cpp", @@ -201,7 +200,6 @@ chip_test_suite("tests") { ":operational-state-test-srcs", ":ota-requestor-test-srcs", ":power-cluster-test-srcs", - ":thread-border-router-management-test-srcs", ":time-sync-data-provider-test-srcs", "${chip_root}/src/app", "${chip_root}/src/app/common:cluster-objects", @@ -236,7 +234,11 @@ chip_test_suite("tests") { } if (!chip_fake_platform) { - test_sources += [ "TestFailSafeContext.cpp" ] + test_sources += [ + "TestFailSafeContext.cpp", + "TestThreadBorderRouterManagementCluster.cpp", + ] + public_deps += [ ":thread-border-router-management-test-srcs" ] } # DefaultICDClientStorage assumes that raw AES key is used by the application diff --git a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp index b7f420b53c6d71..c57776f2c3a4c5 100644 --- a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp +++ b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp @@ -286,7 +286,7 @@ TEST_F_FROM_FIXTURE(TestThreadBorderRouterManagementCluster, TestCommandHandle) req1.activeDataset = ByteSpan(invalidDataset); // SetActiveDatasetRequest is FailsafeRequired. EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(&sTestCommandHandler, req1), Status::FailsafeRequired); - sTestFailsafeContext.ArmFailSafe(kTestAccessingFabricIndex, System::Clock::Seconds16(1)); + EXPECT_EQ(sTestFailsafeContext.ArmFailSafe(kTestAccessingFabricIndex, System::Clock::Seconds16(1)), CHIP_NO_ERROR); // SetActiveDatasetRequest should return InvalidCommand when dataset is invalid. EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(&sTestCommandHandler, req1), Status::InvalidCommand); req1.activeDataset = ByteSpan(validDataset); @@ -307,7 +307,7 @@ TEST_F_FROM_FIXTURE(TestThreadBorderRouterManagementCluster, TestCommandHandle) activeDatasetTimestamp = sTestSeverInstance.ReadActiveDatasetTimestamp(); // activeDatasetTimestamp should have value. EXPECT_TRUE(activeDatasetTimestamp.HasValue()); - sTestFailsafeContext.ArmFailSafe(kTestAccessingFabricIndex, System::Clock::Seconds16(1)); + EXPECT_EQ(sTestFailsafeContext.ArmFailSafe(kTestAccessingFabricIndex, System::Clock::Seconds16(1)), CHIP_NO_ERROR); // When ActiveDatasetTimestamp is not null, the set active dataset request should return InvalidInState. EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(&sTestCommandHandler, req1), Status::InvalidInState); sTestFailsafeContext.DisarmFailSafe(); From 71e3d3cfa70501f55518f45d9733e162a6eedb99 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Mon, 15 Jul 2024 10:31:03 +0800 Subject: [PATCH 36/46] fix committing active dataset configured --- src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp index 55c47d0c210a42..8b94cdca073bca 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp @@ -149,7 +149,6 @@ void GenericOpenThreadBorderRouterDelegate::OnPlatformEventHandler(const DeviceL event->ThreadConnectivityChange.Result == DeviceLayer::kConnectivity_Established) { delegate->mCallback->OnActivateDatasetComplete(delegate->mSequenceNum, CHIP_NO_ERROR); - delegate->SaveActiveDatasetConfigured(true); delegate->mCallback = nullptr; } } From 387fb09b03ddaee7c45459c0a740361da77a61eb Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Thu, 18 Jul 2024 10:28:38 +0800 Subject: [PATCH 37/46] add attribute change report logic --- ...thread-border-router-management-server.cpp | 8 ++++- .../thread-border-router-management-server.h | 15 ++++++-- .../thread-br-delegate.h | 12 ++++++- ...estThreadBorderRouterManagementCluster.cpp | 6 ++-- .../GenericThreadBorderRouterDelegate.cpp | 36 +++++++++++++------ .../GenericThreadBorderRouterDelegate.h | 26 ++++++++++++-- 6 files changed, 83 insertions(+), 20 deletions(-) diff --git a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp index 3a07041c4226ef..f936b4b11dc287 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp +++ b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp @@ -303,6 +303,12 @@ void ServerInstance::OnActivateDatasetComplete(uint32_t sequenceNum, CHIP_ERROR commandHandle->AddStatus(mPath, StatusIB(error).mStatus); } +void ServerInstance::ReportAttributeChanged(AttributeId attributeId) +{ + MatterReportingAttributeChangeCallback(mServerEndpointId, Id, attributeId); +} + + void ServerInstance::OnFailSafeTimerExpired() { if (mDelegate) @@ -337,7 +343,7 @@ CHIP_ERROR ServerInstance::Init() ReturnErrorOnFailure(InteractionModelEngine::GetInstance()->RegisterCommandHandler(this)); VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE); ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler, reinterpret_cast(this))); - return mDelegate->Init(); + return mDelegate->Init(this); } } // namespace ThreadBorderRouterManagement diff --git a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.h b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.h index 6d9143948d035c..a2b6d7949ffdff 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.h +++ b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -35,13 +36,17 @@ namespace app { namespace Clusters { namespace ThreadBorderRouterManagement { -class ServerInstance : public CommandHandlerInterface, public AttributeAccessInterface, public Delegate::ActivateDatasetCallback +class ServerInstance : public CommandHandlerInterface, + public AttributeAccessInterface, + public Delegate::ActivateDatasetCallback, + public Delegate::AttributeChangeCallback { public: using Status = Protocols::InteractionModel::Status; ServerInstance(EndpointId endpointId, Delegate * delegate, FailSafeContext & failSafeContext) : CommandHandlerInterface(Optional(endpointId), Id), - AttributeAccessInterface(Optional(endpointId), Id), mDelegate(delegate), mFailsafeContext(failSafeContext) + AttributeAccessInterface(Optional(endpointId), Id), mDelegate(delegate), mServerEndpointId(endpointId), + mFailsafeContext(failSafeContext) {} virtual ~ServerInstance() = default; @@ -53,9 +58,12 @@ class ServerInstance : public CommandHandlerInterface, public AttributeAccessInt // AttributeAccessInterface CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; - // ActivateDatasetCallbackInterface + // ActivateDatasetCallback void OnActivateDatasetComplete(uint32_t sequenceNum, CHIP_ERROR error) override; + // AttributeChangeCallback + void ReportAttributeChanged(AttributeId attributeId) override; + private: // TODO: Split the business logic from the unit test class friend class TestThreadBorderRouterManagementCluster; @@ -88,6 +96,7 @@ class ServerInstance : public CommandHandlerInterface, public AttributeAccessInt ConcreteCommandPath mPath = ConcreteCommandPath(0, 0, 0); Optional mBreadcrumb; uint32_t mSetActiveDatasetSequenceNumber = 0; + EndpointId mServerEndpointId; FailSafeContext & mFailsafeContext; }; diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h index 98af7c2794eb6a..48fbce580df8b9 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h @@ -18,6 +18,7 @@ #pragma once #include +#include #include #include @@ -47,13 +48,22 @@ class Delegate virtual void OnActivateDatasetComplete(uint32_t sequenceNum, CHIP_ERROR error) = 0; }; + class AttributeChangeCallback + { + public: + AttributeChangeCallback() = default; + virtual ~AttributeChangeCallback() = default; + // If the attributes of the Thread Border Router Management is changed, ReportAttributeChanged should be called. + virtual void ReportAttributeChanged(AttributeId attributeId) = 0; + }; + enum class DatasetType : uint8_t { kActive, kPending, }; - virtual CHIP_ERROR Init() = 0; + virtual CHIP_ERROR Init(AttributeChangeCallback *attributeChangeCallback) = 0; // Get whether PanChange feature is supported for the Thread BR. virtual bool GetPanChangeSupported() = 0; diff --git a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp index c57776f2c3a4c5..a6915824fb2ea2 100644 --- a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp +++ b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -48,7 +49,7 @@ class TestDelegate : public Delegate TestDelegate() = default; ~TestDelegate() = default; - CHIP_ERROR Init() override { return CHIP_NO_ERROR; } + CHIP_ERROR Init(AttributeChangeCallback * callback) override { return CHIP_NO_ERROR; } bool GetPanChangeSupported() override { return mPanChangeSupported; } @@ -186,7 +187,8 @@ class TestSetActiveDatasetCommandHandler : public CommandHandler Access::SubjectDescriptor GetSubjectDescriptor() const { - Access::SubjectDescriptor subjectDescriptor; + Access::SubjectDescriptor subjectDescriptor = { kUndefinedFabricIndex, Access::AuthMode::kNone, kUndefinedNodeId, + kUndefinedCATs }; return subjectDescriptor; } diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp index 8b94cdca073bca..00cf2bce6b323d 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp @@ -53,9 +53,10 @@ class ScopedThreadLock ~ScopedThreadLock() { DeviceLayer::ThreadStackMgr().UnlockThreadStack(); } }; -CHIP_ERROR GenericOpenThreadBorderRouterDelegate::Init() +CHIP_ERROR GenericOpenThreadBorderRouterDelegate::Init(AttributeChangeCallback * callback) { - mCallback = nullptr; + mpActivateDatasetCallback = nullptr; + mpAttributeChangeCallback = callback; ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler, reinterpret_cast(this))); // When the Thread Border Router is reboot during SetActiveDataset, we need to revert the active dateset. RevertActiveDataset(); @@ -136,20 +137,35 @@ void GenericOpenThreadBorderRouterDelegate::SetActiveDataset(const Thread::Opera callback->OnActivateDatasetComplete(sequenceNum, err); return; } - mSequenceNum = sequenceNum; - mCallback = callback; + mSequenceNum = sequenceNum; + mpActivateDatasetCallback = callback; } void GenericOpenThreadBorderRouterDelegate::OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg) { GenericOpenThreadBorderRouterDelegate * delegate = reinterpret_cast(arg); - if (delegate && delegate->mCallback) + if (delegate) { - if (event->Type == DeviceLayer::DeviceEventType::kThreadConnectivityChange && - event->ThreadConnectivityChange.Result == DeviceLayer::kConnectivity_Established) + if ((event->Type == DeviceLayer::DeviceEventType::kThreadConnectivityChange) && + (event->ThreadConnectivityChange.Result == DeviceLayer::kConnectivity_Established) && + delegate->mpActivateDatasetCallback) { - delegate->mCallback->OnActivateDatasetComplete(delegate->mSequenceNum, CHIP_NO_ERROR); - delegate->mCallback = nullptr; + delegate->mpActivateDatasetCallback->OnActivateDatasetComplete(delegate->mSequenceNum, CHIP_NO_ERROR); + delegate->mpActivateDatasetCallback = nullptr; + } + } + if (event->Type == DeviceLayer::DeviceEventType::kThreadStateChange) + { + if (event->ThreadStateChange.OpenThread.Flags & OT_CHANGED_THREAD_NETIF_STATE) + { + DeviceLayer::SystemLayer().ScheduleLambda( + [delegate]() { delegate->mpAttributeChangeCallback->ReportAttributeChanged(Attributes::InterfaceEnabled::Id); }); + } + if (event->ThreadStateChange.OpenThread.Flags & OT_CHANGED_ACTIVE_DATASET) + { + DeviceLayer::SystemLayer().ScheduleLambda([delegate]() { + delegate->mpAttributeChangeCallback->ReportAttributeChanged(Attributes::ActiveDatasetTimestamp::Id); + }); } } } @@ -168,7 +184,7 @@ CHIP_ERROR GenericOpenThreadBorderRouterDelegate::CommitActiveDataset() CHIP_ERROR GenericOpenThreadBorderRouterDelegate::RevertActiveDataset() { // The FailSafe Timer is triggered and the previous command request should be handled, so reset the callback. - mCallback = nullptr; + mpActivateDatasetCallback = nullptr; bool activeDatasetConfigured = true; uint16_t activeDatasetConfiguredLen = sizeof(bool); VerifyOrReturnError(mStorage, CHIP_ERROR_INTERNAL); diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h index 1f9bae1129a0c1..079f1bd6e38edd 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.h @@ -18,11 +18,14 @@ #pragma once #include +#include #include +#include #include #include #include #include +#include namespace chip { namespace app { @@ -37,7 +40,7 @@ class GenericOpenThreadBorderRouterDelegate : public Delegate GenericOpenThreadBorderRouterDelegate(PersistentStorageDelegate * storage) : mStorage(storage) {} ~GenericOpenThreadBorderRouterDelegate() = default; - CHIP_ERROR Init() override; + CHIP_ERROR Init(AttributeChangeCallback * callback) override; bool GetPanChangeSupported() override { return true; } @@ -69,14 +72,31 @@ class GenericOpenThreadBorderRouterDelegate : public Delegate { MutableCharSpan borderRouterName(mThreadBorderRouterName); CopyCharSpanToMutableCharSpan(name, borderRouterName); + if (mpAttributeChangeCallback) + { + DeviceLayer::SystemLayer().ScheduleLambda( + [this]() { mpAttributeChangeCallback->ReportAttributeChanged(Attributes::BorderRouterName::Id); }); + } + } + + void NotifyBorderAgentIdChanged() + { + if (mpAttributeChangeCallback) + { + // OpenThread doesn't have callback or event for BorderAgentId change, we can only change the BorderAgentId with + // otBorderAgentSetId(). Please call this function with otBorderAgentSetId(). + DeviceLayer::SystemLayer().ScheduleLambda( + [this]() { mpAttributeChangeCallback->ReportAttributeChanged(Attributes::BorderAgentID::Id); }); + } } private: CHIP_ERROR SaveActiveDatasetConfigured(bool configured); - ActivateDatasetCallback * mCallback = nullptr; - uint32_t mSequenceNum = 0; + ActivateDatasetCallback * mpActivateDatasetCallback = nullptr; + uint32_t mSequenceNum = 0; char mThreadBorderRouterName[kBorderRouterNameMaxLength + 1]; PersistentStorageDelegate * mStorage; + AttributeChangeCallback * mpAttributeChangeCallback = nullptr; }; } // namespace ThreadBorderRouterManagement } // namespace Clusters From 9fa5a6c767adb4128bbbbba9888bda610c4b2cd3 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Thu, 18 Jul 2024 02:29:44 +0000 Subject: [PATCH 38/46] Restyled by clang-format --- .../thread-border-router-management-server.cpp | 1 - .../thread-border-router-management-server/thread-br-delegate.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp index f936b4b11dc287..09f2ed510ae4fe 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp +++ b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp @@ -308,7 +308,6 @@ void ServerInstance::ReportAttributeChanged(AttributeId attributeId) MatterReportingAttributeChangeCallback(mServerEndpointId, Id, attributeId); } - void ServerInstance::OnFailSafeTimerExpired() { if (mDelegate) diff --git a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h index 48fbce580df8b9..201540af96ecff 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h +++ b/src/app/clusters/thread-border-router-management-server/thread-br-delegate.h @@ -63,7 +63,7 @@ class Delegate kPending, }; - virtual CHIP_ERROR Init(AttributeChangeCallback *attributeChangeCallback) = 0; + virtual CHIP_ERROR Init(AttributeChangeCallback * attributeChangeCallback) = 0; // Get whether PanChange feature is supported for the Thread BR. virtual bool GetPanChangeSupported() = 0; From 872abd9596ffd3d13dbebf8a83e81890e37be878 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Thu, 18 Jul 2024 14:23:49 +0800 Subject: [PATCH 39/46] Don't build TestThreadBorderRouterManagementCluster with TestCommissioningWindowManager --- src/app/tests/BUILD.gn | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn index 7b29876f89eccf..159730a8282600 100644 --- a/src/app/tests/BUILD.gn +++ b/src/app/tests/BUILD.gn @@ -231,14 +231,13 @@ chip_test_suite("tests") { "${chip_root}/src/app/server", "${chip_root}/src/messaging/tests/echo:common", ] + } else if (!chip_fake_platform) { + test_sources += [ "TestThreadBorderRouterManagementCluster.cpp" ] + public_deps += [ ":thread-border-router-management-test-srcs" ] } if (!chip_fake_platform) { - test_sources += [ - "TestFailSafeContext.cpp", - "TestThreadBorderRouterManagementCluster.cpp", - ] - public_deps += [ ":thread-border-router-management-test-srcs" ] + test_sources += [ "TestFailSafeContext.cpp" ] } # DefaultICDClientStorage assumes that raw AES key is used by the application From 4dba805d00bb0906818b1d9ead7703665969c506 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Mon, 22 Jul 2024 10:14:48 +0800 Subject: [PATCH 40/46] review changes --- .../OpenThread/GenericThreadBorderRouterDelegate.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp index 00cf2bce6b323d..26bb08a39fa296 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp @@ -196,9 +196,11 @@ CHIP_ERROR GenericOpenThreadBorderRouterDelegate::RevertActiveDataset() // and that will clear the one stored in the Thread stack since the SetActiveDataset operation fails and FailSafe timer is // triggered. Thread::OperationalDataset emptyDataset = {}; - return DeviceLayer::ThreadStackMgrImpl().AttachToThreadNetwork(emptyDataset, nullptr); - SaveActiveDatasetConfigured(false) + CHIP_ERROR err = DeviceLayer::ThreadStackMgrImpl().AttachToThreadNetwork(emptyDataset, nullptr); + SaveActiveDatasetConfigured(false); + return err; } + return CHIP_NO_ERROR; } CHIP_ERROR GenericOpenThreadBorderRouterDelegate::SetPendingDataset(const Thread::OperationalDataset & pendingDataset) From 8a08287c829401591ae5b3aef3ef22934da6c924 Mon Sep 17 00:00:00 2001 From: "Restyled.io" Date: Mon, 22 Jul 2024 02:34:56 +0000 Subject: [PATCH 41/46] Restyled by clang-format --- src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp index 26bb08a39fa296..e1efc5357520af 100644 --- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp +++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp @@ -196,7 +196,7 @@ CHIP_ERROR GenericOpenThreadBorderRouterDelegate::RevertActiveDataset() // and that will clear the one stored in the Thread stack since the SetActiveDataset operation fails and FailSafe timer is // triggered. Thread::OperationalDataset emptyDataset = {}; - CHIP_ERROR err = DeviceLayer::ThreadStackMgrImpl().AttachToThreadNetwork(emptyDataset, nullptr); + CHIP_ERROR err = DeviceLayer::ThreadStackMgrImpl().AttachToThreadNetwork(emptyDataset, nullptr); SaveActiveDatasetConfigured(false); return err; } From c177a9ce7769bab684dffebc6f86f59d6b43d1d5 Mon Sep 17 00:00:00 2001 From: WanqQixiang Date: Tue, 23 Jul 2024 19:05:01 +0800 Subject: [PATCH 42/46] regenerate zap --- .../app-common/zap-generated/callback.h | 42 ------------------- 1 file changed, 42 deletions(-) diff --git a/zzz_generated/app-common/app-common/zap-generated/callback.h b/zzz_generated/app-common/app-common/zap-generated/callback.h index eee792c31c1c55..56d1487e8a4601 100644 --- a/zzz_generated/app-common/app-common/zap-generated/callback.h +++ b/zzz_generated/app-common/app-common/zap-generated/callback.h @@ -6449,48 +6449,6 @@ bool emberAfColorControlClusterMoveColorTemperatureCallback( bool emberAfColorControlClusterStepColorTemperatureCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::ColorControl::Commands::StepColorTemperature::DecodableType & commandData); -/** - * @brief Thread Network Directory Cluster AddNetwork Command callback (from client) - */ -bool emberAfThreadNetworkDirectoryClusterAddNetworkCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::ThreadNetworkDirectory::Commands::AddNetwork::DecodableType & commandData); -/** - * @brief Thread Network Directory Cluster RemoveNetwork Command callback (from client) - */ -bool emberAfThreadNetworkDirectoryClusterRemoveNetworkCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::ThreadNetworkDirectory::Commands::RemoveNetwork::DecodableType & commandData); -/** - * @brief Thread Network Directory Cluster GetOperationalDataset Command callback (from client) - */ -bool emberAfThreadNetworkDirectoryClusterGetOperationalDatasetCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::ThreadNetworkDirectory::Commands::GetOperationalDataset::DecodableType & commandData); -/** - * @brief Thread Border Router Management Cluster GetActiveDatasetRequest Command callback (from client) - */ -bool emberAfThreadBorderRouterManagementClusterGetActiveDatasetRequestCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::ThreadBorderRouterManagement::Commands::GetActiveDatasetRequest::DecodableType & commandData); -/** - * @brief Thread Border Router Management Cluster GetPendingDatasetRequest Command callback (from client) - */ -bool emberAfThreadBorderRouterManagementClusterGetPendingDatasetRequestCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::ThreadBorderRouterManagement::Commands::GetPendingDatasetRequest::DecodableType & commandData); -/** - * @brief Thread Border Router Management Cluster SetActiveDatasetRequest Command callback (from client) - */ -bool emberAfThreadBorderRouterManagementClusterSetActiveDatasetRequestCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::ThreadBorderRouterManagement::Commands::SetActiveDatasetRequest::DecodableType & commandData); -/** - * @brief Thread Border Router Management Cluster SetPendingDatasetRequest Command callback (from client) - */ -bool emberAfThreadBorderRouterManagementClusterSetPendingDatasetRequestCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::ThreadBorderRouterManagement::Commands::SetPendingDatasetRequest::DecodableType & commandData); /** * @brief Channel Cluster ChangeChannel Command callback (from client) */ From b89eb4fe266242eec266680980fadba98a583bfb Mon Sep 17 00:00:00 2001 From: Hrishikesh Dhayagude Date: Mon, 29 Jul 2024 23:02:03 +0530 Subject: [PATCH 43/46] Fix the compilation error Update the code as `chip::app::InteractionModelEngine::RegisterCommandHandler` is now replaced by `chip::app::CommandHandlerInterfaceRegistry::RegisterCommandHandler` --- .../thread-border-router-management-server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp index 09f2ed510ae4fe..838d7ea4a10d43 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp +++ b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp @@ -339,7 +339,7 @@ void ServerInstance::OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * CHIP_ERROR ServerInstance::Init() { ReturnErrorCodeIf(!mDelegate, CHIP_ERROR_INVALID_ARGUMENT); - ReturnErrorOnFailure(InteractionModelEngine::GetInstance()->RegisterCommandHandler(this)); + ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::GetInstance()->RegisterCommandHandler(this)); VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE); ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler, reinterpret_cast(this))); return mDelegate->Init(this); From ac173d6267a61b69d4e18aa9760457ae638f9854 Mon Sep 17 00:00:00 2001 From: Hrishikesh Dhayagude Date: Mon, 29 Jul 2024 23:20:35 +0530 Subject: [PATCH 44/46] Update thread-border-router-management-server.cpp --- .../thread-border-router-management-server.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp index 838d7ea4a10d43..d2ff4a90814a87 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp +++ b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp @@ -26,6 +26,7 @@ #include "app/CommandHandler.h" #include "app/CommandHandlerInterface.h" #include "app/InteractionModelEngine.h" +#include "app/CommandHandlerInterfaceRegistry.h" #include "app/MessageDef/StatusIB.h" #include "app/clusters/general-commissioning-server/general-commissioning-server.h" #include "app/data-model/Nullable.h" From 23bcb7d2321f3666b63442f2bea10bacfef586f4 Mon Sep 17 00:00:00 2001 From: Hrishikesh Dhayagude Date: Mon, 29 Jul 2024 23:25:58 +0530 Subject: [PATCH 45/46] Update thread-border-router-management-server.cpp --- .../thread-border-router-management-server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp index d2ff4a90814a87..ef0ad2c76e6ed3 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp +++ b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp @@ -340,7 +340,7 @@ void ServerInstance::OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * CHIP_ERROR ServerInstance::Init() { ReturnErrorCodeIf(!mDelegate, CHIP_ERROR_INVALID_ARGUMENT); - ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::GetInstance()->RegisterCommandHandler(this)); + ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::RegisterCommandHandler(this)); VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE); ReturnErrorOnFailure(DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler, reinterpret_cast(this))); return mDelegate->Init(this); From e13880a32b99d16384856fb5fc5a65cca9f46d7e Mon Sep 17 00:00:00 2001 From: Hrishikesh Dhayagude Date: Mon, 29 Jul 2024 23:32:14 +0530 Subject: [PATCH 46/46] Change the sequence of the header file inclusion --- .../thread-border-router-management-server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp index ef0ad2c76e6ed3..5592da410100c2 100644 --- a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp +++ b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp @@ -25,8 +25,8 @@ #include "app/AttributeValueEncoder.h" #include "app/CommandHandler.h" #include "app/CommandHandlerInterface.h" -#include "app/InteractionModelEngine.h" #include "app/CommandHandlerInterfaceRegistry.h" +#include "app/InteractionModelEngine.h" #include "app/MessageDef/StatusIB.h" #include "app/clusters/general-commissioning-server/general-commissioning-server.h" #include "app/data-model/Nullable.h"