Skip to content

Commit

Permalink
Get plumbing in place for TBRM cluster certification tests (project-c…
Browse files Browse the repository at this point in the history
…hip#34696)

* Add TBRM cluster to network-manager-app and add TC_TBRM_2_1 script

Also fix some GN dependency issues. The TBRM delegate is currently a crude mock.

* zap_regen_all
  • Loading branch information
ksperling-apple authored Aug 2, 2024
1 parent 33288b0 commit 44afdd2
Show file tree
Hide file tree
Showing 12 changed files with 513 additions and 11 deletions.
1 change: 1 addition & 0 deletions examples/network-manager-app/linux/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ executable("matter-network-manager-app") {
sources = [
"include/CHIPProjectAppConfig.h",
"main.cpp",
"tbrm.cpp",
]

deps = [
Expand Down
131 changes: 131 additions & 0 deletions examples/network-manager-app/linux/tbrm.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* Copyright (c) 2024 Project CHIP Authors
* All rights reserved.
*
* 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/clusters/thread-border-router-management-server/thread-border-router-management-server.h>
#include <app/server/Server.h>
#include <lib/core/CHIPEncoding.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/Span.h>
#include <lib/support/ThreadOperationalDataset.h>
#include <platform/CHIPDeviceLayer.h>

#include <optional>

using namespace chip;
using namespace chip::literals;
using namespace chip::app;
using namespace chip::app::Clusters;

namespace {
class FakeBorderRouterDelegate final : public ThreadBorderRouterManagement::Delegate
{
CHIP_ERROR Init(AttributeChangeCallback * attributeChangeCallback) override
{
mAttributeChangeCallback = attributeChangeCallback;
return CHIP_NO_ERROR;
}

bool GetPanChangeSupported() override { return true; }

void GetBorderRouterName(MutableCharSpan & borderRouterName) override
{
CopyCharSpanToMutableCharSpan("netman-br"_span, borderRouterName);
}

CHIP_ERROR GetBorderAgentId(MutableByteSpan & borderAgentId) override
{
static constexpr uint8_t kBorderAgentId[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
VerifyOrReturnError(borderAgentId.size() == 16, CHIP_ERROR_INVALID_ARGUMENT);
return CopySpanToMutableSpan(ByteSpan(kBorderAgentId), borderAgentId);
}

uint16_t GetThreadVersion() override { return /* Thread 1.3.1 */ 5; }

bool GetInterfaceEnabled() override { return !mActiveDataset.IsEmpty(); }

CHIP_ERROR GetDataset(Thread::OperationalDataset & dataset, DatasetType type) override
{
Thread::OperationalDataset * source;
switch (type)
{
case DatasetType::kActive:
source = &mActiveDataset;
break;
case DatasetType::kPending:
source = &mPendingDataset;
break;
default:
return CHIP_ERROR_INVALID_ARGUMENT;
}
VerifyOrReturnError(!source->IsEmpty(), CHIP_ERROR_NOT_FOUND);
return dataset.Init(source->AsByteSpan());
}

void SetActiveDataset(const Thread::OperationalDataset & activeDataset, uint32_t sequenceNum,
ActivateDatasetCallback * callback) override
{
if (mActivateDatasetCallback != nullptr)
{
callback->OnActivateDatasetComplete(sequenceNum, CHIP_ERROR_INCORRECT_STATE);
return;
}

CHIP_ERROR err = mActiveDataset.Init(activeDataset.AsByteSpan());
if (err != CHIP_NO_ERROR)
{
callback->OnActivateDatasetComplete(sequenceNum, err);
return;
}

mActivateDatasetCallback = callback;
mActivateDatasetSequence = sequenceNum;
DeviceLayer::SystemLayer().StartTimer(System::Clock::Milliseconds32(3000), CompleteDatasetActivation, this);
}

CHIP_ERROR CommitActiveDataset() override { return CHIP_NO_ERROR; }
CHIP_ERROR RevertActiveDataset() override { return CHIP_ERROR_NOT_IMPLEMENTED; }
CHIP_ERROR SetPendingDataset(const Thread::OperationalDataset & pendingDataset) override { return CHIP_ERROR_NOT_IMPLEMENTED; }

private:
static void CompleteDatasetActivation(System::Layer *, void * context)
{
auto * self = static_cast<FakeBorderRouterDelegate *>(context);
auto * callback = self->mActivateDatasetCallback;
auto sequenceNum = self->mActivateDatasetSequence;
self->mActivateDatasetCallback = nullptr;
callback->OnActivateDatasetComplete(sequenceNum, CHIP_NO_ERROR);
}

AttributeChangeCallback * mAttributeChangeCallback;
Thread::OperationalDataset mActiveDataset;
Thread::OperationalDataset mPendingDataset;

ActivateDatasetCallback * mActivateDatasetCallback = nullptr;
uint32_t mActivateDatasetSequence;
};

FakeBorderRouterDelegate gBorderRouterDelegate{};
} // namespace

std::optional<ThreadBorderRouterManagement::ServerInstance> gThreadBorderRouterManagementServer;
void emberAfThreadBorderRouterManagementClusterInitCallback(EndpointId endpoint)
{
VerifyOrDie(!gThreadBorderRouterManagementServer);
gThreadBorderRouterManagementServer.emplace(endpoint, &gBorderRouterDelegate, Server::GetInstance().GetFailSafeContext())
.Init();
}
Original file line number Diff line number Diff line change
Expand Up @@ -1491,6 +1491,49 @@ provisional cluster WiFiNetworkManagement = 1105 {
command access(invoke: manage) NetworkPassphraseRequest(): NetworkPassphraseResponse = 0;
}

/** Manage the Thread network of Thread Border Router */
provisional cluster ThreadBorderRouterManagement = 1106 {
revision 1;

bitmap Feature : bitmap32 {
kPANChange = 0x1;
}

provisional readonly attribute char_string<63> borderRouterName = 0;
provisional readonly attribute octet_string<254> borderAgentID = 1;
provisional readonly attribute int16u threadVersion = 2;
provisional readonly attribute boolean interfaceEnabled = 3;
provisional readonly attribute nullable int64u activeDatasetTimestamp = 4;
readonly attribute command_id generatedCommandList[] = 65528;
readonly attribute command_id acceptedCommandList[] = 65529;
readonly attribute event_id eventList[] = 65530;
readonly attribute attrib_id attributeList[] = 65531;
readonly attribute bitmap32 featureMap = 65532;
readonly attribute int16u clusterRevision = 65533;

response struct DatasetResponse = 2 {
octet_string<254> dataset = 0;
}

request struct SetActiveDatasetRequestRequest {
octet_string<254> activeDataset = 0;
optional int64u breadcrumb = 1;
}

request struct SetPendingDatasetRequestRequest {
octet_string<254> pendingDataset = 0;
}

/** Command to request the active operational dataset of the Thread network to which the border router is connected. This command must be sent over a valid CASE session */
command access(invoke: manage) GetActiveDatasetRequest(): DatasetResponse = 0;
/** Command to request the pending dataset of the Thread network to which the border router is connected. This command must be sent over a valid CASE session */
command access(invoke: manage) GetPendingDatasetRequest(): DatasetResponse = 1;
/** Command to set or update the active Dataset of the Thread network to which the Border Router is connected. */
command access(invoke: manage) SetActiveDatasetRequest(SetActiveDatasetRequestRequest): DefaultSuccess = 3;
/** Command set or update the pending Dataset of the Thread network to which the Border Router is connected. */
command access(invoke: manage) SetPendingDatasetRequest(SetPendingDatasetRequestRequest): DefaultSuccess = 4;
}

/** Manages the names and credentials of Thread networks visible to the user. */
provisional cluster ThreadNetworkDirectory = 1107 {
revision 1;
Expand Down Expand Up @@ -1816,6 +1859,25 @@ endpoint 1 {
handle command NetworkPassphraseResponse;
}

server cluster ThreadBorderRouterManagement {
callback attribute borderRouterName;
callback attribute borderAgentID;
callback attribute threadVersion;
callback attribute interfaceEnabled;
callback attribute activeDatasetTimestamp;
callback attribute generatedCommandList;
callback attribute acceptedCommandList;
callback attribute eventList;
callback attribute attributeList;
callback attribute featureMap;
ram attribute clusterRevision default = 1;

handle command GetActiveDatasetRequest;
handle command GetPendingDatasetRequest;
handle command DatasetResponse;
handle command SetActiveDatasetRequest;
}

server cluster ThreadNetworkDirectory {
callback attribute preferredExtendedPanID;
callback attribute threadNetworks;
Expand Down
Loading

0 comments on commit 44afdd2

Please sign in to comment.