Skip to content

Commit

Permalink
Add a Matter.framework API for configuring MRP parameters. (#32548)
Browse files Browse the repository at this point in the history
* Add a Matter.framework API for configuring MRP parameters.

Also fixes a typo in the ReliableMessageMgr API Matter.framework uses.

* Address review comment.
  • Loading branch information
bzbarsky-apple authored Mar 12, 2024
1 parent deca2a0 commit bf7241d
Show file tree
Hide file tree
Showing 13 changed files with 334 additions and 3 deletions.
5 changes: 5 additions & 0 deletions examples/darwin-framework-tool/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,11 @@ executable("darwin-framework-tool") {
"commands/common/MTRLogging.h",
"commands/common/RemoteDataModelLogger.h",
"commands/common/RemoteDataModelLogger.mm",
"commands/configuration/Commands.h",
"commands/configuration/ResetMRPParametersCommand.h",
"commands/configuration/ResetMRPParametersCommand.mm",
"commands/configuration/SetMRPParametersCommand.h",
"commands/configuration/SetMRPParametersCommand.mm",
"commands/delay/Commands.h",
"commands/delay/SleepCommand.h",
"commands/delay/SleepCommand.mm",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ inline constexpr char kIdentityGamma[] = "gamma";

class CHIPCommandBridge : public Command {
public:
CHIPCommandBridge(const char * commandName)
: Command(commandName)
CHIPCommandBridge(const char * commandName, const char * helpText = nullptr)
: Command(commandName, helpText)
{
AddArgument("commissioner-name", &mCommissionerName);
AddArgument("commissioner-nodeId", 0, UINT64_MAX, &mCommissionerNodeId,
Expand Down
36 changes: 36 additions & 0 deletions examples/darwin-framework-tool/commands/configuration/Commands.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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.
*
*/

#pragma once

#import <Matter/Matter.h>

#include "ResetMRPParametersCommand.h"
#include "SetMRPParametersCommand.h"

void registerCommandsConfiguration(Commands & commands)
{
const char * clusterName = "Configuration";

commands_list clusterCommands = {
make_unique<SetMRPParametersCommand>(),
make_unique<ResetMRPParametersCommand>(),
};

commands.RegisterCommandSet(clusterName, clusterCommands, "Commands for configuring various state of the Matter framework.");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* 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.
*/

#pragma once

#import <Matter/Matter.h>

#include "../common/CHIPCommandBridge.h"

class ResetMRPParametersCommand : public CHIPCommandBridge
{
public:
ResetMRPParametersCommand() : CHIPCommandBridge("reset-mrp-parameters", "Reset MRP parameters to default values.") {}

protected:
/////////// CHIPCommandBridge Interface /////////
CHIP_ERROR RunCommand() override;

// Our command is synchronous, so no need to wait.
chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::kZero; }
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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 "ResetMRPParametersCommand.h"

CHIP_ERROR ResetMRPParametersCommand::RunCommand()
{
MTRSetMessageReliabilityParameters(nil, nil, nil, nil);
return CHIP_NO_ERROR;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* 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.
*/

#pragma once

#import <Matter/Matter.h>

#include "../common/CHIPCommandBridge.h"

class SetMRPParametersCommand : public CHIPCommandBridge
{
public:
SetMRPParametersCommand() :
CHIPCommandBridge("set-mrp-parameters", "Set various MRP parameters. At least one value must be provided.")
{
AddArgument("idle-interval", 0, UINT32_MAX, &mIdleRetransmitMs,
"Our MRP idle interval (SII) in milliseconds. Defaults to current value if not set.");
AddArgument("active-interval", 0, UINT32_MAX, &mActiveRetransmitMs,
"Our MRP active interval (SAI) in milliseconds. Defaults to current value if not set.");
AddArgument("active-threshold", 0, UINT32_MAX, &mActiveThresholdMs,
"Our MRP active threshold: how long we stay in active mode before transitioning to idle mode. Defaults to "
"current value if not set.");
AddArgument("additional-retransmit-delay", 0, UINT32_MAX, &mAdditionalRetransmitDelayMs,
"Additional delay between retransmits that we do. Defaults to current value if not set.");
}

protected:
/////////// CHIPCommandBridge Interface /////////
CHIP_ERROR RunCommand() override;

// Our command is synchronous, so no need to wait.
chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::kZero; }

chip::Optional<uint32_t> mIdleRetransmitMs;
chip::Optional<uint32_t> mActiveRetransmitMs;
chip::Optional<uint32_t> mActiveThresholdMs;
chip::Optional<uint64_t> mAdditionalRetransmitDelayMs;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* 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 "SetMRPParametersCommand.h"

using namespace chip;

namespace {

template <typename T>
NSNumber * _Nullable AsNumber(const Optional<T> & value)
{
if (!value.HasValue()) {
return nil;
}

return @(value.Value());
}

} // anonymous namespace

CHIP_ERROR SetMRPParametersCommand::RunCommand()
{
if (!mIdleRetransmitMs.HasValue() && !mActiveRetransmitMs.HasValue() && !mActiveThresholdMs.HasValue() && !mAdditionalRetransmitDelayMs.HasValue()) {
ChipLogError(chipTool, "set-mrp-parameters needs to have at least one argument provided");
return CHIP_ERROR_INVALID_ARGUMENT;
}

MTRSetMessageReliabilityParameters(AsNumber(mIdleRetransmitMs),
AsNumber(mActiveRetransmitMs),
AsNumber(mActiveThresholdMs),
AsNumber(mAdditionalRetransmitDelayMs));
return CHIP_NO_ERROR;
}
2 changes: 2 additions & 0 deletions examples/darwin-framework-tool/main.mm
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include "commands/bdx/Commands.h"
#include "commands/common/Commands.h"
#include "commands/configuration/Commands.h"
#include "commands/delay/Commands.h"
#include "commands/discover/Commands.h"
#include "commands/interactive/Commands.h"
Expand All @@ -46,6 +47,7 @@ int main(int argc, const char * argv[])
registerCommandsPayload(commands);
registerClusterOtaSoftwareUpdateProviderInteractive(commands);
registerCommandsStorage(commands);
registerCommandsConfiguration(commands);
registerClusters(commands);
return commands.Run(argc, (char **) argv);
}
Expand Down
33 changes: 33 additions & 0 deletions src/darwin/Framework/CHIP/MTRDeviceControllerFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,39 @@ MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4))

@end

/**
* Set the Message Reliability Protocol parameters for all controllers. This
* allows control over retransmit delays to account for high-latency networks.
*
* Setting all arguments to nil will reset to the MRP parameters to their
* default values.
*
* Setting some arguments to non-nil will change just those values, keeping
* current values for any arguments that are nil (not resetting them to
* defaults).
*
* Non-nil arguments are specified as an integer number of milliseconds.
*
* @param idleRetransmitMs the minimal interval between retransmits for someone
* sending messages to us, when they think we are
* "idle" and might have our radio only turned on
* intermittently.
* @param activeRetransmitMs the minimal interval between retransmits for
* someone sending messages to us, when they think we
* are "active" and have the radio turned on
* consistently.
* @param activeThresholdMs the amount of time we will stay in "active" mode after
* network activity.
* @param additionalRetransmitDelayMs additional delay between retransmits for
* messages we send, on top of whatever delay
* the other side requests via its MRP
* parameters.
*/
MTR_EXTERN MTR_NEWLY_AVAILABLE void MTRSetMessageReliabilityParameters(NSNumber * _Nullable idleRetransmitMs,
NSNumber * _Nullable activeRetransmitMs,
NSNumber * _Nullable activeThresholdMs,
NSNumber * _Nullable additionalRetransmitDelayMs);

MTR_DEPRECATED(
"Please use MTRDeviceControllerFactoryParams", ios(16.1, 16.4), macos(13.0, 13.3), watchos(9.1, 9.4), tvos(16.1, 16.4))
@interface MTRControllerFactoryParams : MTRDeviceControllerFactoryParams
Expand Down
67 changes: 67 additions & 0 deletions src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@
#import "MTRServerCluster_Internal.h"
#import "MTRServerEndpoint_Internal.h"
#import "MTRSessionResumptionStorageBridge.h"
#import "MTRUnfairLock.h"
#import "NSDataSpanConversion.h"

#import <os/lock.h>

#include <app/server/Dnssd.h>
#include <app/util/af.h>
#include <controller/CHIPDeviceControllerFactory.h>
#include <credentials/CHIPCert.h>
Expand All @@ -62,6 +64,8 @@
#include <crypto/RawKeySessionKeystore.h>
#include <lib/support/Pool.h>
#include <lib/support/TestPersistentStorageDelegate.h>
#include <messaging/ReliableMessageMgr.h>
#include <messaging/ReliableMessageProtocolConfig.h>
#include <platform/PlatformManager.h>

#include <cstdlib>
Expand Down Expand Up @@ -968,6 +972,33 @@ - (MTRDeviceController * _Nullable)maybeInitializeOTAProvider:(MTRDeviceControll
return controller;
}

- (void)resetOperationalAdvertising
{
if (![self checkIsRunning:nil]) {
// No need to reset anything; we are not running, so not
// advertising.
return;
}

if (!self.advertiseOperational) {
// No need to reset anything; we are not advertising the things that
// would need to get reset.
return;
}

std::lock_guard lock(_controllersLock);
if (_controllers.count != 0) {
// We have a running controller. That means we likely need to reset
// operational advertising for that controller.
dispatch_async(_chipWorkQueue, ^{
// StartServer() is the only API we have for resetting DNS-SD
// advertising. It sure would be nice if there were a "restart"
// that was a no-op if the DNS-SD server was not already
// running.
app::DnssdServer::Instance().StartServer();
});
}
}
@end

@implementation MTRDeviceControllerFactory (InternalMethods)
Expand Down Expand Up @@ -1449,3 +1480,39 @@ - (void)setCdCerts:(nullable NSArray<NSData *> *)cdCerts
}

@end

void MTRSetMessageReliabilityParameters(NSNumber * _Nullable idleRetransmitMs,
NSNumber * _Nullable activeRetransmitMs,
NSNumber * _Nullable activeThresholdMs,
NSNumber * _Nullable additionalRetransmitDelayMs)
{
bool resetAdvertising = false;
if (idleRetransmitMs == nil && activeRetransmitMs == nil && activeThresholdMs == nil && additionalRetransmitDelayMs == nil) {
Messaging::ReliableMessageMgr::SetAdditionalMRPBackoffTime(NullOptional);
resetAdvertising = ReliableMessageProtocolConfig::SetLocalMRPConfig(NullOptional);
} else {
if (additionalRetransmitDelayMs != nil) {
System::Clock::Milliseconds64 additionalBackoff(additionalRetransmitDelayMs.unsignedLongLongValue);
Messaging::ReliableMessageMgr::SetAdditionalMRPBackoffTime(MakeOptional(additionalBackoff));
}

// Get current MRP parameters, then override the things we were asked to
// override.
ReliableMessageProtocolConfig mrpConfig = GetLocalMRPConfig().ValueOr(GetDefaultMRPConfig());
if (idleRetransmitMs != nil) {
mrpConfig.mIdleRetransTimeout = System::Clock::Milliseconds32(idleRetransmitMs.unsignedLongValue);
}
if (activeRetransmitMs != nil) {
mrpConfig.mActiveRetransTimeout = System::Clock::Milliseconds32(activeRetransmitMs.unsignedLongValue);
}
if (activeThresholdMs != nil) {
mrpConfig.mActiveThresholdTime = System::Clock::Milliseconds32(activeThresholdMs.unsignedLongValue);
}

resetAdvertising = ReliableMessageProtocolConfig::SetLocalMRPConfig(MakeOptional(mrpConfig));
}

if (resetAdvertising) {
[[MTRDeviceControllerFactory sharedInstance] resetOperationalAdvertising];
}
}
Loading

0 comments on commit bf7241d

Please sign in to comment.