Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TBRM: Add missing PendingDatasetTimestamp attribute and CASE session check #34768

Merged
merged 8 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1504,6 +1504,7 @@ provisional cluster ThreadBorderRouterManagement = 1106 {
provisional readonly attribute int16u threadVersion = 2;
provisional readonly attribute boolean interfaceEnabled = 3;
provisional readonly attribute nullable int64u activeDatasetTimestamp = 4;
provisional readonly attribute nullable int64u pendingDatasetTimestamp = 5;
readonly attribute command_id generatedCommandList[] = 65528;
readonly attribute command_id acceptedCommandList[] = 65529;
readonly attribute event_id eventList[] = 65530;
Expand Down Expand Up @@ -1865,6 +1866,7 @@ endpoint 1 {
callback attribute threadVersion;
callback attribute interfaceEnabled;
callback attribute activeDatasetTimestamp;
callback attribute pendingDatasetTimestamp;
callback attribute generatedCommandList;
callback attribute acceptedCommandList;
callback attribute eventList;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3420,7 +3420,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": "",
"defaultValue": null,
wqx6 marked this conversation as resolved.
Show resolved Hide resolved
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
Expand All @@ -3436,7 +3436,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": "",
"defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
Expand All @@ -3452,7 +3452,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": "",
"defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
Expand All @@ -3468,7 +3468,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": "",
"defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
Expand All @@ -3484,6 +3484,22 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
},
{
"name": "PendingDatasetTimestamp",
"code": 5,
"mfgCode": null,
"side": "server",
"type": "int64u",
"included": 1,
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": "",
"reportable": 1,
"minInterval": 1,
Expand All @@ -3500,7 +3516,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": "",
"defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
Expand All @@ -3516,7 +3532,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": "",
"defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
Expand All @@ -3532,7 +3548,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": "",
"defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
Expand All @@ -3548,7 +3564,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": "",
"defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
Expand All @@ -3564,7 +3580,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": "",
"defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "platform/CHIPDeviceEvent.h"
#include "platform/PlatformManager.h"
#include "protocols/interaction_model/StatusCode.h"
#include <optional>

namespace chip {
namespace app {
Expand All @@ -46,21 +47,24 @@ namespace ThreadBorderRouterManagement {

using Protocols::InteractionModel::Status;

static bool IsCommandOverCASESession(CommandHandlerInterface::HandlerContext & ctx)
bool ServerInstance::IsCommandOverCASESession(CommandHandlerInterface::HandlerContext & ctx)
{
#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
if (mSkipCASESessionCheck)
{
return true;
}
#endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
Messaging::ExchangeContext * exchangeCtx = ctx.mCommandHandler.GetExchangeContext();
return exchangeCtx && exchangeCtx->HasSessionHandle() && exchangeCtx->GetSessionHandle()->IsSecureSession() &&
exchangeCtx->GetSessionHandle()->AsSecureSession()->GetSecureSessionType() == Transport::SecureSession::Type::kCASE;
}

Status ServerInstance::HandleGetDatasetRequest(bool isOverCASESession, Delegate::DatasetType type,
Status ServerInstance::HandleGetDatasetRequest(CommandHandlerInterface::HandlerContext & ctx, Delegate::DatasetType type,
Thread::OperationalDataset & dataset)
{
VerifyOrDie(mDelegate);
if (!isOverCASESession)
{
return Status::UnsupportedAccess;
}
VerifyOrReturnValue(IsCommandOverCASESession(ctx), Status::UnsupportedAccess);

CHIP_ERROR err = mDelegate->GetDataset(dataset, type);
if (err != CHIP_NO_ERROR)
Expand All @@ -70,7 +74,7 @@ Status ServerInstance::HandleGetDatasetRequest(bool isOverCASESession, Delegate:
return Status::Success;
}

Status ServerInstance::HandleSetActiveDatasetRequest(CommandHandler * commandHandler,
Status ServerInstance::HandleSetActiveDatasetRequest(CommandHandlerInterface::HandlerContext & ctx,
const Commands::SetActiveDatasetRequest::DecodableType & req)
{
// The SetActiveDatasetRequest command SHALL be FailSafeArmed. Upon receiving this command, the Thread BR will set its
Expand All @@ -80,7 +84,8 @@ Status ServerInstance::HandleSetActiveDatasetRequest(CommandHandler * commandHan
// 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);
VerifyOrReturnValue(IsCommandOverCASESession(ctx), Status::UnsupportedAccess);
VerifyOrReturnValue(mFailsafeContext.IsFailSafeArmed(ctx.mCommandHandler.GetAccessingFabricIndex()), Status::FailsafeRequired);

Thread::OperationalDataset activeDataset;
Thread::OperationalDataset currentActiveDataset;
Expand All @@ -101,17 +106,19 @@ Status ServerInstance::HandleSetActiveDatasetRequest(CommandHandler * commandHan
{
return Status::Busy;
}
commandHandler->FlushAcksRightAwayOnSlowCommand();
mAsyncCommandHandle = CommandHandler::Handle(commandHandler);
ctx.mCommandHandler.FlushAcksRightAwayOnSlowCommand();
mAsyncCommandHandle = CommandHandler::Handle(&ctx.mCommandHandler);
mBreadcrumb = req.breadcrumb;
mSetActiveDatasetSequenceNumber++;
mDelegate->SetActiveDataset(activeDataset, mSetActiveDatasetSequenceNumber, this);
return Status::Success;
}

Status ServerInstance::HandleSetPendingDatasetRequest(const Commands::SetPendingDatasetRequest::DecodableType & req)
Status ServerInstance::HandleSetPendingDatasetRequest(CommandHandlerInterface::HandlerContext & ctx,
const Commands::SetPendingDatasetRequest::DecodableType & req)
{
VerifyOrDie(mDelegate);
VerifyOrReturnValue(IsCommandOverCASESession(ctx), Status::UnsupportedAccess);
if (!mDelegate->GetPanChangeSupported())
{
return Status::UnsupportedCommand;
Expand Down Expand Up @@ -143,21 +150,21 @@ void ServerInstance::InvokeCommand(HandlerContext & ctxt)
case Commands::GetActiveDatasetRequest::Id:
HandleCommand<Commands::GetActiveDatasetRequest::DecodableType>(ctxt, [this](HandlerContext & ctx, const auto & req) {
Thread::OperationalDataset dataset;
Status status = HandleGetActiveDatasetRequest(IsCommandOverCASESession(ctx), dataset);
Status status = HandleGetActiveDatasetRequest(ctx, dataset);
AddDatasetResponse(ctx, status, dataset);
});
break;
case Commands::GetPendingDatasetRequest::Id:
HandleCommand<Commands::GetPendingDatasetRequest::DecodableType>(ctxt, [this](HandlerContext & ctx, const auto & req) {
Thread::OperationalDataset dataset;
Status status = HandleGetPendingDatasetRequest(IsCommandOverCASESession(ctx), dataset);
Status status = HandleGetPendingDatasetRequest(ctx, dataset);
AddDatasetResponse(ctx, status, dataset);
});
break;
case Commands::SetActiveDatasetRequest::Id:
HandleCommand<Commands::SetActiveDatasetRequest::DecodableType>(ctxt, [this](HandlerContext & ctx, const auto & req) {
mPath = ctx.mRequestPath;
Status status = HandleSetActiveDatasetRequest(&ctx.mCommandHandler, req);
Status status = HandleSetActiveDatasetRequest(ctx, req);
if (status != Status::Success)
{
// If status is not Success, we should immediately report the status. Otherwise the async work will report the
Expand All @@ -168,7 +175,8 @@ void ServerInstance::InvokeCommand(HandlerContext & ctxt)
break;
case Commands::SetPendingDatasetRequest::Id:
HandleCommand<Commands::SetPendingDatasetRequest::DecodableType>(ctxt, [this](HandlerContext & ctx, const auto & req) {
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, HandleSetPendingDatasetRequest(req));
Status status = HandleSetPendingDatasetRequest(ctx, req);
ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
});
break;
default:
Expand Down Expand Up @@ -199,16 +207,28 @@ CHIP_ERROR ServerInstance::ReadBorderAgentID(MutableByteSpan & outBorderAgentId)
return CHIP_NO_ERROR;
}

Optional<uint64_t> ServerInstance::ReadActiveDatasetTimestamp()
std::optional<uint64_t> ServerInstance::ReadActiveDatasetTimestamp()
{
uint64_t activeDatasetTimestampValue = 0;
Thread::OperationalDataset activeDataset;
if ((mDelegate->GetDataset(activeDataset, Delegate::DatasetType::kActive) == CHIP_NO_ERROR) &&
(activeDataset.GetActiveTimestamp(activeDatasetTimestampValue) == CHIP_NO_ERROR))
{
return MakeOptional(activeDatasetTimestampValue);
return std::make_optional(activeDatasetTimestampValue);
}
return std::nullopt;
}

std::optional<uint64_t> ServerInstance::ReadPendingDatasetTimestamp()
{
uint64_t pendingDatasetTimestampValue = 0;
Thread::OperationalDataset pendingDataset;
if ((mDelegate->GetDataset(pendingDataset, Delegate::DatasetType::kPending) == CHIP_NO_ERROR) &&
(pendingDataset.GetActiveTimestamp(pendingDatasetTimestampValue) == CHIP_NO_ERROR))
{
return std::make_optional(pendingDatasetTimestampValue);
}
return NullOptional;
return std::nullopt;
}

CHIP_ERROR ServerInstance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
Expand Down Expand Up @@ -259,9 +279,13 @@ CHIP_ERROR ServerInstance::Read(const ConcreteReadAttributePath & aPath, Attribu
break;
}
case Attributes::ActiveDatasetTimestamp::Id: {
Optional<uint64_t> activeDatasetTimestamp = ReadActiveDatasetTimestamp();
status = activeDatasetTimestamp.HasValue() ? aEncoder.Encode(DataModel::MakeNullable(activeDatasetTimestamp.Value()))
: aEncoder.EncodeNull();
std::optional<uint64_t> activeDatasetTimestamp = ReadActiveDatasetTimestamp();
status = activeDatasetTimestamp.has_value() ? aEncoder.Encode(activeDatasetTimestamp.value()) : aEncoder.EncodeNull();
break;
}
case Attributes::PendingDatasetTimestamp::Id: {
std::optional<uint64_t> pendingDatasetTimestamp = ReadPendingDatasetTimestamp();
status = pendingDatasetTimestamp.has_value() ? aEncoder.Encode(pendingDatasetTimestamp.value()) : aEncoder.EncodeNull();
break;
}
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,25 +64,30 @@ class ServerInstance : public CommandHandlerInterface,
// TODO: Split the business logic from the unit test class
friend class TestThreadBorderRouterManagementCluster;
// Command Handlers
Status HandleGetActiveDatasetRequest(bool isOverCASESession, Thread::OperationalDataset & dataset)
Status HandleGetActiveDatasetRequest(HandlerContext & ctx, Thread::OperationalDataset & dataset)
{
return HandleGetDatasetRequest(isOverCASESession, Delegate::DatasetType::kActive, dataset);
return HandleGetDatasetRequest(ctx, Delegate::DatasetType::kActive, dataset);
}
Status HandleGetPendingDatasetRequest(bool isOverCASESession, Thread::OperationalDataset & dataset)
Status HandleGetPendingDatasetRequest(HandlerContext & ctx, Thread::OperationalDataset & dataset)
{
return HandleGetDatasetRequest(isOverCASESession, Delegate::DatasetType::kPending, dataset);
return HandleGetDatasetRequest(ctx, Delegate::DatasetType::kPending, dataset);
}
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);
Status HandleSetActiveDatasetRequest(HandlerContext & ctx, const Commands::SetActiveDatasetRequest::DecodableType & req);
Status HandleSetPendingDatasetRequest(HandlerContext & ctx, const Commands::SetPendingDatasetRequest::DecodableType & req);
Status HandleGetDatasetRequest(HandlerContext & ctx, Delegate::DatasetType type, Thread::OperationalDataset & dataset);

// Attribute Read handlers
void ReadFeatureMap(BitFlags<Feature> & feature);
Optional<uint64_t> ReadActiveDatasetTimestamp();
std::optional<uint64_t> ReadActiveDatasetTimestamp();
std::optional<uint64_t> ReadPendingDatasetTimestamp();
CHIP_ERROR ReadBorderRouterName(MutableCharSpan & borderRouterName);
CHIP_ERROR ReadBorderAgentID(MutableByteSpan & borderAgentId);

#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
void SetSkipCASESessionCheck(bool skipCheck) { mSkipCASESessionCheck = skipCheck; }
bool mSkipCASESessionCheck;
#endif
bool IsCommandOverCASESession(CommandHandlerInterface::HandlerContext & ctx);
static void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
void OnFailSafeTimerExpired();
void CommitSavedBreadcrumb();
Expand Down
Loading
Loading