From 2582210e4f90f68763617c2b6aa3ec3cc1214620 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Wed, 1 Jun 2022 10:09:08 -0400 Subject: [PATCH] Fix how group multicast addresses are constructed. (#19023) They should be using fabric id, not fabric index. Fixes https://github.com/project-chip/connectedhomeip/issues/18935 --- src/app/server/Server.cpp | 4 +- src/app/server/Server.h | 29 +- src/app/tests/suites/TestGroupMessaging.yaml | 317 +++++++++++- src/transport/SessionManager.cpp | 10 +- .../chip-tool/zap-generated/test/Commands.h | 458 +++++++++++++++++- 5 files changed, 785 insertions(+), 33 deletions(-) diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 7786661dea2c4c..2e09a087d029bc 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -174,7 +174,7 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) #endif ); - err = mListener.Init(&mTransports); + err = mListener.Init(this); SuccessOrExit(err); mGroupsProvider->SetListener(&mListener); @@ -309,7 +309,7 @@ void Server::RejoinExistingMulticastGroups() while (iterator->Next(groupInfo)) { err = mTransports.MulticastGroupJoinLeave( - Transport::PeerAddress::Multicast(fabric.GetFabricIndex(), groupInfo.group_id), true); + Transport::PeerAddress::Multicast(fabric.GetFabricId(), groupInfo.group_id), true); if (err != CHIP_NO_ERROR) { ChipLogError(AppServer, "Error when trying to join Group %u of fabric index %u : %" CHIP_ERROR_FORMAT, diff --git a/src/app/server/Server.h b/src/app/server/Server.h index 1e9919f1767a88..66e7b223a161e0 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -270,18 +270,25 @@ class Server public: GroupDataProviderListener() {} - CHIP_ERROR Init(ServerTransportMgr * transports) + CHIP_ERROR Init(Server * server) { - VerifyOrReturnError(transports != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(server != nullptr, CHIP_ERROR_INVALID_ARGUMENT); - mTransports = transports; + mServer = server; return CHIP_NO_ERROR; }; void OnGroupAdded(chip::FabricIndex fabric_index, const Credentials::GroupDataProvider::GroupInfo & new_group) override { - if (mTransports->MulticastGroupJoinLeave(Transport::PeerAddress::Multicast(fabric_index, new_group.group_id), true) != - CHIP_NO_ERROR) + FabricInfo * fabric = mServer->GetFabricTable().FindFabricWithIndex(fabric_index); + if (fabric == nullptr) + { + ChipLogError(AppServer, "Group added to nonexistent fabric?"); + return; + } + + if (mServer->GetTransportManager().MulticastGroupJoinLeave( + Transport::PeerAddress::Multicast(fabric->GetFabricId(), new_group.group_id), true) != CHIP_NO_ERROR) { ChipLogError(AppServer, "Unable to listen to group"); } @@ -289,11 +296,19 @@ class Server void OnGroupRemoved(chip::FabricIndex fabric_index, const Credentials::GroupDataProvider::GroupInfo & old_group) override { - mTransports->MulticastGroupJoinLeave(Transport::PeerAddress::Multicast(fabric_index, old_group.group_id), false); + FabricInfo * fabric = mServer->GetFabricTable().FindFabricWithIndex(fabric_index); + if (fabric == nullptr) + { + ChipLogError(AppServer, "Group added to nonexistent fabric?"); + return; + } + + mServer->GetTransportManager().MulticastGroupJoinLeave( + Transport::PeerAddress::Multicast(fabric->GetFabricId(), old_group.group_id), false); }; private: - ServerTransportMgr * mTransports; + Server * mServer; }; class ServerFabricDelegate final : public chip::FabricTable::Delegate diff --git a/src/app/tests/suites/TestGroupMessaging.yaml b/src/app/tests/suites/TestGroupMessaging.yaml index 54f6e5d2343a21..10bf56f48cdac8 100644 --- a/src/app/tests/suites/TestGroupMessaging.yaml +++ b/src/app/tests/suites/TestGroupMessaging.yaml @@ -22,6 +22,15 @@ config: nodeId: 0x12344321 cluster: "Basic" endpoint: 0 + nodeId2: + type: NODE_ID + defaultValue: 0x43211234 + discriminator: + type: INT16U + defaultValue: 3840 + payload: + type: CHAR_STRING + defaultValue: "MT:-24J0AFN00KA0648G00" # This value needs to be generated automatically tests: - label: "Wait for the commissioned device to be retrieved" @@ -109,8 +118,8 @@ tests: arguments: value: [ - { FabricIndex: 1, GroupId: 0x0101, GroupKeySetID: 0x01a1 }, - { FabricIndex: 1, GroupId: 0x0102, GroupKeySetID: 0x01a2 }, + { FabricIndex: 0, GroupId: 0x0101, GroupKeySetID: 0x01a1 }, + { FabricIndex: 0, GroupId: 0x0102, GroupKeySetID: 0x01a2 }, ] - label: "Install ACLs" @@ -152,6 +161,16 @@ tests: arguments: value: "xyzzy" + # Give the group write time to actually happen; unicast delivery can outrace + # multicast if the unicast packet is sent immediately after the multicast one. + - label: "Wait for write 1" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 100 + # Test Pair 2 : Validates previous group write attribute with a unicast to read - label: "Read back Attribute" command: "readAttribute" @@ -167,6 +186,16 @@ tests: arguments: value: "" + # Give the group write time to actually happen; unicast delivery can outrace + # multicast if the unicast packet is sent immediately after the multicast one. + - label: "Wait for write 2" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 100 + # Test Pair 3 : Validates previous group write attribute with a unicast to read - label: "Read back Attribute" command: "readAttribute" @@ -175,11 +204,29 @@ tests: value: "" # Test Pair 4 : Sends a Group command + - label: "Check on/off attribute value is false for endpoint 1" + cluster: "On/Off" + command: "readAttribute" + attribute: "OnOff" + endpoint: 1 + response: + value: 0 + - label: "Turn On the light to see attribute change" cluster: "On/Off" command: "On" groupId: 0x0101 + # Give the group invoke time to actually happen; unicast delivery can outrace + # multicast if the unicast packet is sent immediately after the multicast one. + - label: "Wait for command 3" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 100 + # Test Pair 4 : Validates previous group command with a unicast to read - label: "Check on/off attribute value is true after on command for endpoint 1" @@ -190,6 +237,11 @@ tests: response: value: 1 + - label: "Turn off the light to get ready for the next test" + cluster: "On/Off" + command: "Off" + endpoint: 1 + - label: "Cleanup ACLs" cluster: "Access Control" command: "writeAttribute" @@ -205,3 +257,264 @@ tests: Targets: null, }, ] + + - label: "Open Commissioning Window from alpha" + cluster: "AdministratorCommissioning" + command: "OpenBasicCommissioningWindow" + timedInteractionTimeoutMs: 10000 + arguments: + values: + - name: "CommissioningTimeout" + value: 180 + + # We want to repeat all that from the "gamma" fabric, where our fabric + # index is 3 but the device's will be 2, so we have different fabric + # indices for the same fabric id. + - label: "Commission from gamma" + identity: "gamma" + cluster: "CommissionerCommands" + command: "PairWithCode" + arguments: + values: + - name: "nodeId" + value: nodeId2 + - name: "payload" + value: payload + + - label: "Wait for the commissioned device to be retrieved for gamma" + identity: "gamma" + cluster: "DelayCommands" + command: "WaitForCommissionee" + arguments: + values: + - name: "nodeId" + value: nodeId2 + + - label: "Add Group 1 (endpoint 1) for gamma" + identity: "gamma" + cluster: "Groups" + command: "AddGroup" + endpoint: 1 + arguments: + values: + - name: "groupId" + value: 0x0101 + - name: "groupName" + value: "Group #1" + response: + values: + - name: "status" + value: 0 + - name: "groupId" + value: 0x0101 + + - label: "Add Group 2 (endpoint 0) for gamma" + identity: "gamma" + cluster: "Groups" + command: "AddGroup" + endpoint: 0 + arguments: + values: + - name: "groupId" + value: 0x0102 + - name: "groupName" + value: "Group #2" + response: + values: + - name: "status" + value: 0 + - name: "groupId" + value: 0x0102 + + - label: "KeySet Write 1 for gamma" + identity: "gamma" + cluster: "Group Key Management" + command: "KeySetWrite" + arguments: + values: + - name: "GroupKeySet" + value: { + GroupKeySetID: 0x01a1, + # TODO Revert this once MCSP is implemented + # GroupKeySecurityPolicy: 1, + GroupKeySecurityPolicy: 0, # 0 => TrustFirst + EpochKey0: "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf", + EpochStartTime0: 1110000, + EpochKey1: "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf", + EpochStartTime1: 1110001, + EpochKey2: "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf", + EpochStartTime2: 1110002, + } + + - label: "KeySet Write 2 for gamma" + identity: "gamma" + cluster: "Group Key Management" + command: "KeySetWrite" + arguments: + values: + - name: "GroupKeySet" + value: { + GroupKeySetID: 0x01a2, + GroupKeySecurityPolicy: 0, # TrustFirst + EpochKey0: "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf", + EpochStartTime0: 2220000, + EpochKey1: "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef", + EpochStartTime1: 2220001, + EpochKey2: "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff", + EpochStartTime2: 2220002, + } + + - label: "Write Group Keys for gamma" + identity: "gamma" + cluster: "Group Key Management" + command: "writeAttribute" + attribute: "GroupKeyMap" + arguments: + value: + [ + { FabricIndex: 0, GroupId: 0x0101, GroupKeySetID: 0x01a1 }, + { FabricIndex: 0, GroupId: 0x0102, GroupKeySetID: 0x01a2 }, + ] + + - label: "Install ACLs for gamma" + identity: "gamma" + cluster: "Access Control" + command: "writeAttribute" + attribute: "ACL" + arguments: + value: [ + # Any CASE can administer + { + FabricIndex: 0, + Privilege: 5, # administer + AuthMode: 2, # case + Subjects: null, + Targets: null, + }, + # Any group can manage + { + FabricIndex: 0, + Privilege: 4, # manage + AuthMode: 3, # group + Subjects: null, + Targets: null, + }, + ] + + # Test Pair 1 : Check initial value (ensure it's not the test value) + - label: "Read initial Attribute value for gamma" + identity: "gamma" + command: "readAttribute" + attribute: "nodeLabel" + response: + value: "" + + # Test Pair 2 : Sends a Group Write Attribute + - label: "Group Write Attribute for gamma" + identity: "gamma" + command: "writeAttribute" + attribute: "nodeLabel" + groupId: 0x0102 + arguments: + value: "xyzzy" + + # Give the group write time to actually happen; unicast delivery can outrace + # multicast if the unicast packet is sent immediately after the multicast one. + - label: "Wait for write 1 for gamma" + identity: "gamma" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 100 + + # Test Pair 2 : Validates previous group write attribute with a unicast to read + - label: "Read back Attribute for gamma" + identity: "gamma" + command: "readAttribute" + attribute: "nodeLabel" + response: + value: "xyzzy" + + # Test Pair 3 : Sends a Group Write Attribute + - label: "Restore initial Attribute value for gamma" + identity: "gamma" + command: "writeAttribute" + attribute: "nodeLabel" + groupId: 0x0102 + arguments: + value: "" + + # Give the group write time to actually happen; unicast delivery can outrace + # multicast if the unicast packet is sent immediately after the multicast one. + - label: "Wait for write 2 for gamma" + identity: "gamma" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 100 + + # Test Pair 3 : Validates previous group write attribute with a unicast to read + - label: "Read back Attribute for gamma" + identity: "gamma" + command: "readAttribute" + attribute: "nodeLabel" + response: + value: "" + + # Test Pair 4 : Sends a Group command + - label: "Check on/off attribute value is false for endpoint 1 for gamma" + cluster: "On/Off" + command: "readAttribute" + attribute: "OnOff" + endpoint: 1 + response: + value: 0 + + - label: "Turn On the light to see attribute change for gamma" + identity: "gamma" + cluster: "On/Off" + command: "On" + groupId: 0x0101 + + # Give the group invoke time to actually happen; unicast delivery can outrace + # multicast if the unicast packet is sent immediately after the multicast one. + - label: "Wait for command 3 for gamma" + identity: "gamma" + cluster: "DelayCommands" + command: "WaitForMs" + arguments: + values: + - name: "ms" + value: 100 + + # Test Pair 4 : Validates previous group command with a unicast to read + - label: + "Check on/off attribute value is true after on command for endpoint 1 + for gamma" + cluster: "On/Off" + command: "readAttribute" + attribute: "OnOff" + endpoint: 1 + response: + value: 1 + + - label: "Cleanup ACLs for gamma" + identity: "gamma" + cluster: "Access Control" + command: "writeAttribute" + attribute: "ACL" + arguments: + value: [ + # Any CASE can administer + { + FabricIndex: 0, + Privilege: 5, # administer + AuthMode: 2, # case + Subjects: null, + Targets: null, + }, + ] diff --git a/src/transport/SessionManager.cpp b/src/transport/SessionManager.cpp index cc3d8e2759de17..f68ae57f535dae 100644 --- a/src/transport/SessionManager.cpp +++ b/src/transport/SessionManager.cpp @@ -267,15 +267,19 @@ CHIP_ERROR SessionManager::SendPreparedMessage(const SessionHandle & sessionHand { case Transport::Session::SessionType::kGroupOutgoing: { auto groupSession = sessionHandle->AsOutgoingGroupSession(); - multicastAddress = Transport::PeerAddress::Multicast(groupSession->GetFabricIndex(), groupSession->GetGroupId()); - destination = &multicastAddress; + + FabricInfo * fabric = mFabricTable->FindFabricWithIndex(groupSession->GetFabricIndex()); + VerifyOrReturnError(fabric != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + + multicastAddress = Transport::PeerAddress::Multicast(fabric->GetFabricId(), groupSession->GetGroupId()); + destination = &multicastAddress; char addressStr[Transport::PeerAddress::kMaxToStringSize]; multicastAddress.ToString(addressStr, Transport::PeerAddress::kMaxToStringSize); ChipLogProgress(Inet, "Sending %s msg %p with MessageCounter:" ChipLogFormatMessageCounter " to %d" " at monotonic time: " ChipLogFormatX64 - " msec to Multicast IPV6 address : %s with GroupID of %d and fabric Id of %d", + " msec to Multicast IPV6 address : %s with GroupID of %d and fabric index of %x", "encrypted group", &preparedMessage, preparedMessage.GetMessageCounter(), groupSession->GetGroupId(), ChipLogValueX64(System::SystemClock().GetMonotonicMilliseconds64().count()), addressStr, groupSession->GetGroupId(), groupSession->GetFabricIndex()); diff --git a/zzz_generated/chip-tool/zap-generated/test/Commands.h b/zzz_generated/chip-tool/zap-generated/test/Commands.h index cde2260e55f3a2..effeb67f7d84b0 100644 --- a/zzz_generated/chip-tool/zap-generated/test/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/test/Commands.h @@ -63829,11 +63829,14 @@ class Test_TC_DL_2_11Suite : public TestCommand class TestGroupMessagingSuite : public TestCommand { public: - TestGroupMessagingSuite(CredentialIssuerCommands * credsIssuerConfig) : TestCommand("TestGroupMessaging", 15, credsIssuerConfig) + TestGroupMessagingSuite(CredentialIssuerCommands * credsIssuerConfig) : TestCommand("TestGroupMessaging", 41, credsIssuerConfig) { AddArgument("nodeId", 0, UINT64_MAX, &mNodeId); AddArgument("cluster", &mCluster); AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint); + AddArgument("nodeId2", 0, UINT64_MAX, &mNodeId2); + AddArgument("discriminator", 0, UINT16_MAX, &mDiscriminator); + AddArgument("payload", &mPayload); AddArgument("timeout", 0, UINT16_MAX, &mTimeout); } @@ -63848,6 +63851,9 @@ class TestGroupMessagingSuite : public TestCommand chip::Optional mNodeId; chip::Optional mCluster; chip::Optional mEndpoint; + chip::Optional mNodeId2; + chip::Optional mDiscriminator; + chip::Optional mPayload; chip::Optional mTimeout; chip::EndpointId GetEndpoint(chip::EndpointId endpoint) { return mEndpoint.HasValue() ? mEndpoint.Value() : endpoint; } @@ -63910,6 +63916,10 @@ class TestGroupMessagingSuite : public TestCommand VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; case 9: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 10: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::CharSpan value; @@ -63917,10 +63927,14 @@ class TestGroupMessagingSuite : public TestCommand VerifyOrReturn(CheckValueAsString("nodeLabel", value, chip::CharSpan("xyzzy", 5))); } break; - case 10: + case 11: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; - case 11: + case 12: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 13: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { chip::CharSpan value; @@ -63928,10 +63942,22 @@ class TestGroupMessagingSuite : public TestCommand VerifyOrReturn(CheckValueAsString("nodeLabel", value, chip::CharSpan("", 0))); } break; - case 12: + case 14: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + bool value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("onOff", value, 0)); + } break; - case 13: + case 15: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 16: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 17: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); { bool value; @@ -63939,7 +63965,117 @@ class TestGroupMessagingSuite : public TestCommand VerifyOrReturn(CheckValue("onOff", value, 1)); } break; - case 14: + case 18: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 19: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 20: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 21: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 22: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 23: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::app::Clusters::Groups::Commands::AddGroupResponse::DecodableType value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("status", value.status, 0)); + + VerifyOrReturn(CheckValue("groupId", value.groupId, 257U)); + } + break; + case 24: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::app::Clusters::Groups::Commands::AddGroupResponse::DecodableType value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("status", value.status, 0)); + + VerifyOrReturn(CheckValue("groupId", value.groupId, 258U)); + } + break; + case 25: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 26: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 27: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 28: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 29: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::CharSpan value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValueAsString("nodeLabel", value, chip::CharSpan("", 0))); + } + break; + case 30: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 31: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 32: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::CharSpan value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValueAsString("nodeLabel", value, chip::CharSpan("xyzzy", 5))); + } + break; + case 33: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 34: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 35: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + chip::CharSpan value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValueAsString("nodeLabel", value, chip::CharSpan("", 0))); + } + break; + case 36: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + bool value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("onOff", value, 0)); + } + break; + case 37: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + break; + case 38: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + shouldContinue = true; + break; + case 39: + VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); + { + bool value; + VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value))); + VerifyOrReturn(CheckValue("onOff", value, 1)); + } + break; + case 40: VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0)); break; default: @@ -64065,11 +64201,11 @@ class TestGroupMessagingSuite : public TestCommand listHolder_0->mList[0].groupId = 257U; listHolder_0->mList[0].groupKeySetID = 417U; - listHolder_0->mList[0].fabricIndex = 1; + listHolder_0->mList[0].fabricIndex = 0; listHolder_0->mList[1].groupId = 258U; listHolder_0->mList[1].groupKeySetID = 418U; - listHolder_0->mList[1].fabricIndex = 1; + listHolder_0->mList[1].fabricIndex = 0; value = chip::app::DataModel::List( listHolder_0->mList, 2); @@ -64117,34 +64253,67 @@ class TestGroupMessagingSuite : public TestCommand return WriteGroupAttribute(kIdentityAlpha, 258, Basic::Id, Basic::Attributes::NodeLabel::Id, value, chip::NullOptional); } case 9: { - LogStep(9, "Read back Attribute"); + LogStep(9, "Wait for write 1"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs(kIdentityAlpha, value); + } + case 10: { + LogStep(10, "Read back Attribute"); return ReadAttribute(kIdentityAlpha, GetEndpoint(0), Basic::Id, Basic::Attributes::NodeLabel::Id, true, chip::NullOptional); } - case 10: { - LogStep(10, "Restore initial Attribute value"); + case 11: { + LogStep(11, "Restore initial Attribute value"); ListFreer listFreer; chip::CharSpan value; value = chip::Span("garbage: not in length on purpose", 0); return WriteGroupAttribute(kIdentityAlpha, 258, Basic::Id, Basic::Attributes::NodeLabel::Id, value, chip::NullOptional); } - case 11: { - LogStep(11, "Read back Attribute"); + case 12: { + LogStep(12, "Wait for write 2"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs(kIdentityAlpha, value); + } + case 13: { + LogStep(13, "Read back Attribute"); return ReadAttribute(kIdentityAlpha, GetEndpoint(0), Basic::Id, Basic::Attributes::NodeLabel::Id, true, chip::NullOptional); } - case 12: { - LogStep(12, "Turn On the light to see attribute change"); + case 14: { + LogStep(14, "Check on/off attribute value is false for endpoint 1"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), OnOff::Id, OnOff::Attributes::OnOff::Id, true, chip::NullOptional); + } + case 15: { + LogStep(15, "Turn On the light to see attribute change"); ListFreer listFreer; chip::app::Clusters::OnOff::Commands::On::Type value; return SendGroupCommand(kIdentityAlpha, 257, OnOff::Id, OnOff::Commands::On::Id, value); } - case 13: { - LogStep(13, "Check on/off attribute value is true after on command for endpoint 1"); + case 16: { + LogStep(16, "Wait for command 3"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs(kIdentityAlpha, value); + } + case 17: { + LogStep(17, "Check on/off attribute value is true after on command for endpoint 1"); return ReadAttribute(kIdentityAlpha, GetEndpoint(1), OnOff::Id, OnOff::Attributes::OnOff::Id, true, chip::NullOptional); } - case 14: { - LogStep(14, "Cleanup ACLs"); + case 18: { + LogStep(18, "Turn off the light to get ready for the next test"); + ListFreer listFreer; + chip::app::Clusters::OnOff::Commands::Off::Type value; + return SendCommand(kIdentityAlpha, GetEndpoint(1), OnOff::Id, OnOff::Commands::Off::Id, value, chip::NullOptional + + ); + } + case 19: { + LogStep(19, "Cleanup ACLs"); ListFreer listFreer; chip::app::DataModel::List value; @@ -64164,6 +64333,257 @@ class TestGroupMessagingSuite : public TestCommand return WriteAttribute(kIdentityAlpha, GetEndpoint(0), AccessControl::Id, AccessControl::Attributes::Acl::Id, value, chip::NullOptional, chip::NullOptional); } + case 20: { + LogStep(20, "Open Commissioning Window from alpha"); + ListFreer listFreer; + chip::app::Clusters::AdministratorCommissioning::Commands::OpenBasicCommissioningWindow::Type value; + value.commissioningTimeout = 180U; + return SendCommand(kIdentityAlpha, GetEndpoint(0), AdministratorCommissioning::Id, + AdministratorCommissioning::Commands::OpenBasicCommissioningWindow::Id, value, + chip::Optional(10000), chip::NullOptional + + ); + } + case 21: { + LogStep(21, "Commission from gamma"); + ListFreer listFreer; + chip::app::Clusters::CommissionerCommands::Commands::PairWithCode::Type value; + value.nodeId = mNodeId2.HasValue() ? mNodeId2.Value() : 1126240820ULL; + value.payload = mPayload.HasValue() ? mPayload.Value() : chip::Span("MT:-24J0AFN00KA0648G00", 22); + return PairWithCode(kIdentityGamma, value); + } + case 22: { + LogStep(22, "Wait for the commissioned device to be retrieved for gamma"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForCommissionee::Type value; + value.nodeId = mNodeId2.HasValue() ? mNodeId2.Value() : 1126240820ULL; + return WaitForCommissionee(kIdentityGamma, value); + } + case 23: { + LogStep(23, "Add Group 1 (endpoint 1) for gamma"); + ListFreer listFreer; + chip::app::Clusters::Groups::Commands::AddGroup::Type value; + value.groupId = 257U; + value.groupName = chip::Span("Group #1garbage: not in length on purpose", 8); + return SendCommand(kIdentityGamma, GetEndpoint(1), Groups::Id, Groups::Commands::AddGroup::Id, value, chip::NullOptional + + ); + } + case 24: { + LogStep(24, "Add Group 2 (endpoint 0) for gamma"); + ListFreer listFreer; + chip::app::Clusters::Groups::Commands::AddGroup::Type value; + value.groupId = 258U; + value.groupName = chip::Span("Group #2garbage: not in length on purpose", 8); + return SendCommand(kIdentityGamma, GetEndpoint(0), Groups::Id, Groups::Commands::AddGroup::Id, value, chip::NullOptional + + ); + } + case 25: { + LogStep(25, "KeySet Write 1 for gamma"); + ListFreer listFreer; + chip::app::Clusters::GroupKeyManagement::Commands::KeySetWrite::Type value; + + value.groupKeySet.groupKeySetID = 417U; + value.groupKeySet.groupKeySecurityPolicy = + static_cast(0); + value.groupKeySet.epochKey0.SetNonNull(); + value.groupKeySet.epochKey0.Value() = chip::ByteSpan( + chip::Uint8::from_const_char( + "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257garbage: not in length on purpose"), + 16); + value.groupKeySet.epochStartTime0.SetNonNull(); + value.groupKeySet.epochStartTime0.Value() = 1110000ULL; + value.groupKeySet.epochKey1.SetNonNull(); + value.groupKeySet.epochKey1.Value() = chip::ByteSpan( + chip::Uint8::from_const_char( + "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277garbage: not in length on purpose"), + 16); + value.groupKeySet.epochStartTime1.SetNonNull(); + value.groupKeySet.epochStartTime1.Value() = 1110001ULL; + value.groupKeySet.epochKey2.SetNonNull(); + value.groupKeySet.epochKey2.Value() = chip::ByteSpan( + chip::Uint8::from_const_char( + "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317garbage: not in length on purpose"), + 16); + value.groupKeySet.epochStartTime2.SetNonNull(); + value.groupKeySet.epochStartTime2.Value() = 1110002ULL; + + return SendCommand(kIdentityGamma, GetEndpoint(0), GroupKeyManagement::Id, + GroupKeyManagement::Commands::KeySetWrite::Id, value, chip::NullOptional + + ); + } + case 26: { + LogStep(26, "KeySet Write 2 for gamma"); + ListFreer listFreer; + chip::app::Clusters::GroupKeyManagement::Commands::KeySetWrite::Type value; + + value.groupKeySet.groupKeySetID = 418U; + value.groupKeySet.groupKeySecurityPolicy = + static_cast(0); + value.groupKeySet.epochKey0.SetNonNull(); + value.groupKeySet.epochKey0.Value() = chip::ByteSpan( + chip::Uint8::from_const_char( + "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337garbage: not in length on purpose"), + 16); + value.groupKeySet.epochStartTime0.SetNonNull(); + value.groupKeySet.epochStartTime0.Value() = 2220000ULL; + value.groupKeySet.epochKey1.SetNonNull(); + value.groupKeySet.epochKey1.Value() = chip::ByteSpan( + chip::Uint8::from_const_char( + "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357garbage: not in length on purpose"), + 16); + value.groupKeySet.epochStartTime1.SetNonNull(); + value.groupKeySet.epochStartTime1.Value() = 2220001ULL; + value.groupKeySet.epochKey2.SetNonNull(); + value.groupKeySet.epochKey2.Value() = chip::ByteSpan( + chip::Uint8::from_const_char( + "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377garbage: not in length on purpose"), + 16); + value.groupKeySet.epochStartTime2.SetNonNull(); + value.groupKeySet.epochStartTime2.Value() = 2220002ULL; + + return SendCommand(kIdentityGamma, GetEndpoint(0), GroupKeyManagement::Id, + GroupKeyManagement::Commands::KeySetWrite::Id, value, chip::NullOptional + + ); + } + case 27: { + LogStep(27, "Write Group Keys for gamma"); + ListFreer listFreer; + chip::app::DataModel::List value; + + { + auto * listHolder_0 = new ListHolder(2); + listFreer.add(listHolder_0); + + listHolder_0->mList[0].groupId = 257U; + listHolder_0->mList[0].groupKeySetID = 417U; + listHolder_0->mList[0].fabricIndex = 0; + + listHolder_0->mList[1].groupId = 258U; + listHolder_0->mList[1].groupKeySetID = 418U; + listHolder_0->mList[1].fabricIndex = 0; + + value = chip::app::DataModel::List( + listHolder_0->mList, 2); + } + return WriteAttribute(kIdentityGamma, GetEndpoint(0), GroupKeyManagement::Id, + GroupKeyManagement::Attributes::GroupKeyMap::Id, value, chip::NullOptional, chip::NullOptional); + } + case 28: { + LogStep(28, "Install ACLs for gamma"); + ListFreer listFreer; + chip::app::DataModel::List value; + + { + auto * listHolder_0 = new ListHolder(2); + listFreer.add(listHolder_0); + + listHolder_0->mList[0].privilege = static_cast(5); + listHolder_0->mList[0].authMode = static_cast(2); + listHolder_0->mList[0].subjects.SetNull(); + listHolder_0->mList[0].targets.SetNull(); + listHolder_0->mList[0].fabricIndex = 0; + + listHolder_0->mList[1].privilege = static_cast(4); + listHolder_0->mList[1].authMode = static_cast(3); + listHolder_0->mList[1].subjects.SetNull(); + listHolder_0->mList[1].targets.SetNull(); + listHolder_0->mList[1].fabricIndex = 0; + + value = chip::app::DataModel::List( + listHolder_0->mList, 2); + } + return WriteAttribute(kIdentityGamma, GetEndpoint(0), AccessControl::Id, AccessControl::Attributes::Acl::Id, value, + chip::NullOptional, chip::NullOptional); + } + case 29: { + LogStep(29, "Read initial Attribute value for gamma"); + return ReadAttribute(kIdentityGamma, GetEndpoint(0), Basic::Id, Basic::Attributes::NodeLabel::Id, true, + chip::NullOptional); + } + case 30: { + LogStep(30, "Group Write Attribute for gamma"); + ListFreer listFreer; + chip::CharSpan value; + value = chip::Span("xyzzygarbage: not in length on purpose", 5); + return WriteGroupAttribute(kIdentityGamma, 258, Basic::Id, Basic::Attributes::NodeLabel::Id, value, chip::NullOptional); + } + case 31: { + LogStep(31, "Wait for write 1 for gamma"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs(kIdentityGamma, value); + } + case 32: { + LogStep(32, "Read back Attribute for gamma"); + return ReadAttribute(kIdentityGamma, GetEndpoint(0), Basic::Id, Basic::Attributes::NodeLabel::Id, true, + chip::NullOptional); + } + case 33: { + LogStep(33, "Restore initial Attribute value for gamma"); + ListFreer listFreer; + chip::CharSpan value; + value = chip::Span("garbage: not in length on purpose", 0); + return WriteGroupAttribute(kIdentityGamma, 258, Basic::Id, Basic::Attributes::NodeLabel::Id, value, chip::NullOptional); + } + case 34: { + LogStep(34, "Wait for write 2 for gamma"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs(kIdentityGamma, value); + } + case 35: { + LogStep(35, "Read back Attribute for gamma"); + return ReadAttribute(kIdentityGamma, GetEndpoint(0), Basic::Id, Basic::Attributes::NodeLabel::Id, true, + chip::NullOptional); + } + case 36: { + LogStep(36, "Check on/off attribute value is false for endpoint 1 for gamma"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), OnOff::Id, OnOff::Attributes::OnOff::Id, true, chip::NullOptional); + } + case 37: { + LogStep(37, "Turn On the light to see attribute change for gamma"); + ListFreer listFreer; + chip::app::Clusters::OnOff::Commands::On::Type value; + return SendGroupCommand(kIdentityGamma, 257, OnOff::Id, OnOff::Commands::On::Id, value); + } + case 38: { + LogStep(38, "Wait for command 3 for gamma"); + ListFreer listFreer; + chip::app::Clusters::DelayCommands::Commands::WaitForMs::Type value; + value.ms = 100UL; + return WaitForMs(kIdentityGamma, value); + } + case 39: { + LogStep(39, "Check on/off attribute value is true after on command for endpoint 1 for gamma"); + return ReadAttribute(kIdentityAlpha, GetEndpoint(1), OnOff::Id, OnOff::Attributes::OnOff::Id, true, chip::NullOptional); + } + case 40: { + LogStep(40, "Cleanup ACLs for gamma"); + ListFreer listFreer; + chip::app::DataModel::List value; + + { + auto * listHolder_0 = new ListHolder(1); + listFreer.add(listHolder_0); + + listHolder_0->mList[0].privilege = static_cast(5); + listHolder_0->mList[0].authMode = static_cast(2); + listHolder_0->mList[0].subjects.SetNull(); + listHolder_0->mList[0].targets.SetNull(); + listHolder_0->mList[0].fabricIndex = 0; + + value = chip::app::DataModel::List( + listHolder_0->mList, 1); + } + return WriteAttribute(kIdentityGamma, GetEndpoint(0), AccessControl::Id, AccessControl::Attributes::Acl::Id, value, + chip::NullOptional, chip::NullOptional); + } } return CHIP_NO_ERROR; }