Skip to content

Commit

Permalink
Implement Thread Network Directory server (#34343)
Browse files Browse the repository at this point in the history
* Update Thread Network Directory cluster definition

- Use octstr[8] for ExtendedPanID fields
- Add ActiveTimestamp to ThreadNetworkStruct
- Remove NetworkChanged event

PreferredExtendedPanID is nullable, so the uint64 representation is not
suitable because the value 0xFFF... is disallowed as a null marker. Change all
related attributes / fields to octstr[8] to be consistent.

Also add the cluster to the relevant meta-data files.

See CHIP-Specifications/connectedhomeip-spec#10019

* zap_regen_all

* Implement Thread Network Directory server

Also add it to the network-manager example app.

* Apply suggestions from code review

Co-authored-by: Boris Zbarsky <[email protected]>
Co-authored-by: Kiel Oleson <[email protected]>

* Apply suggestions from code review

Co-authored-by: Boris Zbarsky <[email protected]>

* Remove stale zap generated files

* Address review comments

Remove DefaultInstance() and weak cluster init function and instead provide a
DefaultThreadNetworkDirectoryServer sub-class that's easy to instantiate with
the default storage implementation.

Roll back in-memory state on persistent storage failure and add tests for this.

Add documentation about ByteSpan lifetimes in OperationalDataset class.

Add comments to MTRDemuxingStorage.mm

* Use emberAf...ClusterInitCallback (not ...Server)

* Address review comments

* Avoid conversion warning

---------

Co-authored-by: Boris Zbarsky <[email protected]>
Co-authored-by: Kiel Oleson <[email protected]>
  • Loading branch information
3 people authored Jul 19, 2024
1 parent 2eb95ca commit c024e4f
Show file tree
Hide file tree
Showing 70 changed files with 1,788 additions and 721 deletions.
11 changes: 11 additions & 0 deletions examples/network-manager-app/linux/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@
*/

#include <AppMain.h>
#include <app/clusters/thread-network-directory-server/thread-network-directory-server.h>
#include <app/clusters/wifi-network-management-server/wifi-network-management-server.h>
#include <lib/core/CHIPSafeCasts.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/Span.h>

#include <optional>

using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
Expand All @@ -32,6 +36,13 @@ ByteSpan ByteSpanFromCharSpan(CharSpan span)
return ByteSpan(Uint8::from_const_char(span.data()), span.size());
}

std::optional<DefaultThreadNetworkDirectoryServer> gThreadNetworkDirectoryServer;
void emberAfThreadNetworkDirectoryClusterInitCallback(chip::EndpointId endpoint)
{
VerifyOrDie(!gThreadNetworkDirectoryServer);
gThreadNetworkDirectoryServer.emplace(endpoint).Init();
}

int main(int argc, char * argv[])
{
if (ChipLinuxAppInit(argc, argv) != 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1195,6 +1195,51 @@ cluster WiFiNetworkManagement = 1105 {
command access(invoke: administer) NetworkPassphraseRequest(): NetworkPassphraseResponse = 0;
}

/** Manages the names and credentials of Thread networks visible to the user. */
cluster ThreadNetworkDirectory = 1107 {
revision 1;

struct ThreadNetworkStruct {
octet_string<8> extendedPanID = 0;
char_string<16> networkName = 1;
int16u channel = 2;
int64u activeTimestamp = 3;
}

attribute access(read: manage, write: manage) nullable octet_string<8> preferredExtendedPanID = 0;
readonly attribute access(read: operate) ThreadNetworkStruct threadNetworks[] = 1;
readonly attribute int8u threadNetworkTableSize = 2;
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;

request struct AddNetworkRequest {
octet_string<254> operationalDataset = 0;
}

request struct RemoveNetworkRequest {
octet_string<8> extendedPanID = 0;
}

request struct GetOperationalDatasetRequest {
octet_string<8> extendedPanID = 0;
}

response struct OperationalDatasetResponse = 3 {
octet_string<254> operationalDataset = 0;
}

/** Adds an entry to the ThreadNetworks list. */
timed command access(invoke: manage) AddNetwork(AddNetworkRequest): DefaultSuccess = 0;
/** Removes an entry from the ThreadNetworks list. */
timed command access(invoke: manage) RemoveNetwork(RemoveNetworkRequest): DefaultSuccess = 1;
/** Retrieves a Thread Operational Dataset from the ThreadNetworks list. */
timed command GetOperationalDataset(GetOperationalDatasetRequest): OperationalDatasetResponse = 2;
}

endpoint 0 {
device type ma_rootdevice = 22, version 1;

Expand Down Expand Up @@ -1473,6 +1518,23 @@ endpoint 1 {
handle command NetworkPassphraseRequest;
handle command NetworkPassphraseResponse;
}

server cluster ThreadNetworkDirectory {
callback attribute preferredExtendedPanID;
callback attribute threadNetworks;
callback attribute threadNetworkTableSize;
callback attribute generatedCommandList;
callback attribute acceptedCommandList;
callback attribute eventList;
callback attribute attributeList;
ram attribute featureMap default = 0;
ram attribute clusterRevision default = 1;

handle command AddNetwork;
handle command RemoveNetwork;
handle command GetOperationalDataset;
handle command OperationalDatasetResponse;
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -3349,6 +3349,194 @@
"reportableChange": 0
}
]
},
{
"name": "Thread Network Directory",
"code": 1107,
"mfgCode": null,
"define": "THREAD_NETWORK_DIRECTORY_CLUSTER",
"side": "server",
"enabled": 1,
"commands": [
{
"name": "AddNetwork",
"code": 0,
"mfgCode": null,
"source": "client",
"isIncoming": 1,
"isEnabled": 1
},
{
"name": "RemoveNetwork",
"code": 1,
"mfgCode": null,
"source": "client",
"isIncoming": 1,
"isEnabled": 1
},
{
"name": "GetOperationalDataset",
"code": 2,
"mfgCode": null,
"source": "client",
"isIncoming": 1,
"isEnabled": 1
},
{
"name": "OperationalDatasetResponse",
"code": 3,
"mfgCode": null,
"source": "server",
"isIncoming": 0,
"isEnabled": 1
}
],
"attributes": [
{
"name": "PreferredExtendedPanID",
"code": 0,
"mfgCode": null,
"side": "server",
"type": "octet_string",
"included": 1,
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
},
{
"name": "ThreadNetworks",
"code": 1,
"mfgCode": null,
"side": "server",
"type": "array",
"included": 1,
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
},
{
"name": "ThreadNetworkTableSize",
"code": 2,
"mfgCode": null,
"side": "server",
"type": "int8u",
"included": 1,
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
},
{
"name": "GeneratedCommandList",
"code": 65528,
"mfgCode": null,
"side": "server",
"type": "array",
"included": 1,
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
},
{
"name": "AcceptedCommandList",
"code": 65529,
"mfgCode": null,
"side": "server",
"type": "array",
"included": 1,
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
},
{
"name": "EventList",
"code": 65530,
"mfgCode": null,
"side": "server",
"type": "array",
"included": 1,
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
},
{
"name": "AttributeList",
"code": 65531,
"mfgCode": null,
"side": "server",
"type": "array",
"included": 1,
"storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
},
{
"name": "FeatureMap",
"code": 65532,
"mfgCode": null,
"side": "server",
"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": "server",
"type": "int16u",
"included": 1,
"storageOption": "RAM",
"singleton": 0,
"bounded": 0,
"defaultValue": "1",
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
}
]
}
]
}
Expand Down
1 change: 1 addition & 0 deletions scripts/rules.matterlint
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ load "../src/app/zap-templates/zcl/data-model/chip/thermostat-user-interface-con
load "../src/app/zap-templates/zcl/data-model/chip/thermostat-cluster.xml";
load "../src/app/zap-templates/zcl/data-model/chip/thread-border-router-management-cluster.xml";
load "../src/app/zap-templates/zcl/data-model/chip/thread-network-diagnostics-cluster.xml";
load "../src/app/zap-templates/zcl/data-model/chip/thread-network-directory-cluster.xml";
load "../src/app/zap-templates/zcl/data-model/chip/time-format-localization-cluster.xml";
load "../src/app/zap-templates/zcl/data-model/chip/time-synchronization-cluster.xml";
load "../src/app/zap-templates/zcl/data-model/chip/timer-cluster.xml";
Expand Down
3 changes: 3 additions & 0 deletions src/app/AttributeAccessInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ class AttributeAccessInterface
(!mEndpointId.HasValue() || !aOther.mEndpointId.HasValue() || mEndpointId.Value() == aOther.mEndpointId.Value());
}

protected:
Optional<EndpointId> GetEndpointId() { return mEndpointId; }

private:
Optional<EndpointId> mEndpointId;
ClusterId mClusterId;
Expand Down
2 changes: 2 additions & 0 deletions src/app/CommandHandlerInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@ class CommandHandlerInterface
}
}

Optional<EndpointId> GetEndpointId() { return mEndpointId; }

private:
Optional<EndpointId> mEndpointId;
ClusterId mClusterId;
Expand Down
8 changes: 8 additions & 0 deletions src/app/chip_data_model.gni
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,14 @@ 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-network-directory-server") {
sources += [
"${_app_root}/clusters/${cluster}/${cluster}.cpp",
"${_app_root}/clusters/${cluster}/${cluster}.h",
"${_app_root}/clusters/${cluster}/DefaultThreadNetworkDirectoryStorage.cpp",
"${_app_root}/clusters/${cluster}/DefaultThreadNetworkDirectoryStorage.h",
"${_app_root}/clusters/${cluster}/ThreadNetworkDirectoryStorage.h",
]
} else {
sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp" ]
}
Expand Down
Loading

0 comments on commit c024e4f

Please sign in to comment.