Skip to content

Commit e882141

Browse files
mkardous-silabsrestyled-commitsbzbarsky-apple
authored
[ICD] Refactor ICDCounter logic (project-chip#31957)
* Refactor ICD Check-In counter Fix initial Check-In counter value * Add basic integration tests to validate behavior * Restyled by whitespace * Restyled by prettier-yaml * rename source_set * Rename constant name * Apply suggestions from code review Co-authored-by: Boris Zbarsky <bzbarsky@apple.com> * addres review comments * Add init/shutdown unit-test for the ICDManager * Fix Build.gn - multiple inclusion of CheckInMessage.cpp --------- Co-authored-by: Restyled.io <commits@restyled.io> Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
1 parent 21b998a commit e882141

File tree

11 files changed

+181
-101
lines changed

11 files changed

+181
-101
lines changed

src/app/clusters/icd-management-server/icd-management-server.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ CHIP_ERROR IcdManagementAttributeAccess::ReadRegisteredClients(EndpointId endpoi
149149

150150
CHIP_ERROR IcdManagementAttributeAccess::ReadICDCounter(EndpointId endpoint, AttributeValueEncoder & encoder)
151151
{
152-
return encoder.Encode(mICDConfigurationData->GetICDCounter());
152+
return encoder.Encode(mICDConfigurationData->GetICDCounter().GetValue());
153153
}
154154

155155
CHIP_ERROR IcdManagementAttributeAccess::ReadClientsSupportedPerFabric(EndpointId endpoint, AttributeValueEncoder & encoder)
@@ -292,7 +292,7 @@ Status ICDManagementServer::RegisterClient(CommandHandler * commandObj, const Co
292292
TriggerICDMTableUpdatedEvent();
293293
}
294294

295-
icdCounter = mICDConfigurationData->GetICDCounter();
295+
icdCounter = mICDConfigurationData->GetICDCounter().GetValue();
296296
return InteractionModel::Status::Success;
297297
}
298298

src/app/icd/server/BUILD.gn

+1
Original file line numberDiff line numberDiff line change
@@ -115,5 +115,6 @@ source_set("configuration-data") {
115115
":icd-server-config",
116116
"${chip_root}/src/lib/core",
117117
"${chip_root}/src/lib/support",
118+
"${chip_root}/src/protocols/secure_channel:check-in-counter",
118119
]
119120
}

src/app/icd/server/ICDConfigurationData.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <lib/core/Optional.h>
2121
#include <lib/support/TimeUtils.h>
2222
#include <platform/CHIPDeviceConfig.h>
23+
#include <protocols/secure_channel/CheckInCounter.h>
2324
#include <system/SystemClock.h>
2425

2526
namespace chip {
@@ -44,7 +45,7 @@ class TestICDManager;
4445
class ICDConfigurationData
4546
{
4647
public:
47-
static constexpr uint32_t ICD_CHECK_IN_COUNTER_MIN_INCREMENT = 100;
48+
static constexpr uint32_t kICDCounterPersistenceIncrement = 100;
4849

4950
enum class ICDMode : uint8_t
5051
{
@@ -60,7 +61,7 @@ class ICDConfigurationData
6061

6162
System::Clock::Milliseconds16 GetActiveModeThreshold() { return mActiveThreshold; }
6263

63-
uint32_t GetICDCounter() { return mICDCounter; }
64+
Protocols::SecureChannel::CheckInCounter & GetICDCounter() { return mICDCounter; }
6465

6566
uint16_t GetClientsSupportedPerFabric() { return mFabricClientsSupported; }
6667

@@ -99,7 +100,6 @@ class ICDConfigurationData
99100
friend class chip::app::TestICDManager;
100101

101102
void SetICDMode(ICDMode mode) { mICDMode = mode; };
102-
void SetICDCounter(uint32_t count) { mICDCounter = count; }
103103
void SetSlowPollingInterval(System::Clock::Milliseconds32 slowPollInterval) { mSlowPollingInterval = slowPollInterval; };
104104
void SetFastPollingInterval(System::Clock::Milliseconds32 fastPollInterval) { mFastPollingInterval = fastPollInterval; };
105105

@@ -137,7 +137,7 @@ class ICDConfigurationData
137137

138138
System::Clock::Milliseconds16 mActiveThreshold = System::Clock::Milliseconds16(CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS);
139139

140-
uint32_t mICDCounter = 0;
140+
Protocols::SecureChannel::CheckInCounter mICDCounter;
141141

142142
static_assert((CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC) >= 1,
143143
"Spec requires the minimum of supported clients per fabric be equal or greater to 1.");

src/app/icd/server/ICDManager.cpp

+7-52
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ void ICDManager::Init(PersistentStorageDelegate * storage, FabricTable * fabricT
7272
mExchangeManager = exchangeManager;
7373
mSubManager = manager;
7474

75-
VerifyOrDie(InitCounter() == CHIP_NO_ERROR);
75+
VerifyOrDie(ICDConfigurationData::GetInstance().GetICDCounter().Init(mStorage, DefaultStorageKeyAllocator::ICDCheckInCounter(),
76+
ICDConfigurationData::kICDCounterPersistenceIncrement) ==
77+
CHIP_NO_ERROR);
7678

7779
UpdateICDMode();
7880
UpdateOperationState(OperationalState::IdleMode);
@@ -115,7 +117,8 @@ void ICDManager::SendCheckInMsgs()
115117
#if !CONFIG_BUILD_FOR_HOST_UNIT_TEST
116118
VerifyOrDie(mStorage != nullptr);
117119
VerifyOrDie(mFabricTable != nullptr);
118-
uint32_t counter = ICDConfigurationData::GetInstance().GetICDCounter();
120+
121+
uint32_t counterValue = ICDConfigurationData::GetInstance().GetICDCounter().GetNextCheckInCounterValue();
119122
bool counterIncremented = false;
120123

121124
for (const auto & fabricInfo : *mFabricTable)
@@ -156,7 +159,7 @@ void ICDManager::SendCheckInMsgs()
156159
{
157160
counterIncremented = true;
158161

159-
if (CHIP_NO_ERROR != IncrementCounter())
162+
if (CHIP_NO_ERROR != ICDConfigurationData::GetInstance().GetICDCounter().Advance())
160163
{
161164
ChipLogError(AppServer, "Incremented ICDCounter but failed to access/save to Persistent storage");
162165
}
@@ -167,7 +170,7 @@ void ICDManager::SendCheckInMsgs()
167170
ICDCheckInSender * sender = mICDSenderPool.CreateObject(mExchangeManager);
168171
VerifyOrReturn(sender != nullptr, ChipLogError(AppServer, "Failed to allocate ICDCheckinSender"));
169172

170-
if (CHIP_NO_ERROR != sender->RequestResolve(entry, mFabricTable, counter))
173+
if (CHIP_NO_ERROR != sender->RequestResolve(entry, mFabricTable, counterValue))
171174
{
172175
ChipLogError(AppServer, "Failed to send ICD Check-In");
173176
}
@@ -176,54 +179,6 @@ void ICDManager::SendCheckInMsgs()
176179
#endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
177180
}
178181

179-
CHIP_ERROR ICDManager::InitCounter()
180-
{
181-
CHIP_ERROR err;
182-
uint32_t temp;
183-
uint16_t size = static_cast<uint16_t>(sizeof(uint32_t));
184-
185-
err = mStorage->SyncGetKeyValue(DefaultStorageKeyAllocator::ICDCheckInCounter().KeyName(), &temp, size);
186-
if (err == CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND)
187-
{
188-
// First time retrieving the counter
189-
temp = chip::Crypto::GetRandU32();
190-
}
191-
else if (err != CHIP_NO_ERROR)
192-
{
193-
return err;
194-
}
195-
196-
ICDConfigurationData::GetInstance().SetICDCounter(temp);
197-
temp += ICDConfigurationData::ICD_CHECK_IN_COUNTER_MIN_INCREMENT;
198-
199-
// Increment the count directly to minimize flash write.
200-
return mStorage->SyncSetKeyValue(DefaultStorageKeyAllocator::ICDCheckInCounter().KeyName(), &temp, size);
201-
}
202-
203-
CHIP_ERROR ICDManager::IncrementCounter()
204-
{
205-
uint32_t temp = 0;
206-
StorageKeyName key = DefaultStorageKeyAllocator::ICDCheckInCounter();
207-
uint16_t size = static_cast<uint16_t>(sizeof(uint32_t));
208-
209-
ICDConfigurationData::GetInstance().mICDCounter++;
210-
211-
if (mStorage == nullptr)
212-
{
213-
return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
214-
}
215-
216-
ReturnErrorOnFailure(mStorage->SyncGetKeyValue(key.KeyName(), &temp, size));
217-
218-
if (temp == ICDConfigurationData::GetInstance().mICDCounter)
219-
{
220-
temp = ICDConfigurationData::GetInstance().mICDCounter + ICDConfigurationData::ICD_CHECK_IN_COUNTER_MIN_INCREMENT;
221-
return mStorage->SyncSetKeyValue(key.KeyName(), &temp, size);
222-
}
223-
224-
return CHIP_NO_ERROR;
225-
}
226-
227182
void ICDManager::UpdateICDMode()
228183
{
229184
assertChipStackLockedByCurrentThread();

src/app/icd/server/ICDManager.h

-4
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,6 @@ class ICDManager : public ICDListener
122122
*/
123123
static void OnTransitionToIdle(System::Layer * aLayer, void * appState);
124124

125-
// ICD Counter
126-
CHIP_ERROR IncrementCounter();
127-
CHIP_ERROR InitCounter();
128-
129125
uint8_t mOpenExchangeContextCount = 0;
130126
uint8_t mCheckInRequestCount = 0;
131127

src/app/tests/TestICDManager.cpp

+16-9
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <lib/support/TestPersistentStorageDelegate.h>
2828
#include <lib/support/TimeUtils.h>
2929
#include <lib/support/UnitTestContext.h>
30+
#include <lib/support/UnitTestExtendedAssertions.h>
3031
#include <lib/support/UnitTestRegistration.h>
3132
#include <nlunit-test.h>
3233
#include <system/SystemLayerImpl.h>
@@ -113,7 +114,7 @@ class TestContext : public chip::Test::AppContext
113114
CHIP_ERROR SetUp() override
114115
{
115116
ReturnErrorOnFailure(chip::Test::AppContext::SetUp());
116-
mICDManager.Init(&testStorage, &GetFabricTable(), &mKeystore, &GetExchangeManager(), &mSubManager);
117+
mICDManager.Init(&testStorage, &GetFabricTable(), &mKeystore, &GetExchangeManager(), &mSubInfoProvider);
117118
mICDManager.RegisterObserver(&mICDStateObserver);
118119
return CHIP_NO_ERROR;
119120
}
@@ -128,12 +129,12 @@ class TestContext : public chip::Test::AppContext
128129
System::Clock::Internal::MockClock mMockClock;
129130
TestSessionKeystoreImpl mKeystore;
130131
app::ICDManager mICDManager;
131-
TestSubscriptionsInfoProvider mSubManager;
132+
TestSubscriptionsInfoProvider mSubInfoProvider;
132133
TestPersistentStorageDelegate testStorage;
134+
TestICDStateObserver mICDStateObserver;
133135

134136
private:
135137
System::Clock::ClockBase * mRealClock;
136-
TestICDStateObserver mICDStateObserver;
137138
};
138139

139140
} // namespace
@@ -196,7 +197,7 @@ class TestICDManager
196197
ctx->mICDManager.SetTestFeatureMapValue(0x07);
197198

198199
// Set that there are no matching subscriptions
199-
ctx->mSubManager.SetReturnValue(false);
200+
ctx->mSubInfoProvider.SetReturnValue(false);
200201

201202
// Set New durations for test case
202203
Milliseconds32 oldActiveModeDuration = icdConfigData.GetActiveModeDuration();
@@ -275,7 +276,7 @@ class TestICDManager
275276
ctx->mICDManager.SetTestFeatureMapValue(0x07);
276277

277278
// Set that there are not matching subscriptions
278-
ctx->mSubManager.SetReturnValue(true);
279+
ctx->mSubInfoProvider.SetReturnValue(true);
279280

280281
// Set New durations for test case
281282
Milliseconds32 oldActiveModeDuration = icdConfigData.GetActiveModeDuration();
@@ -506,10 +507,16 @@ class TestICDManager
506507
static void TestICDCounter(nlTestSuite * aSuite, void * aContext)
507508
{
508509
TestContext * ctx = static_cast<TestContext *>(aContext);
509-
uint32_t counter = ICDConfigurationData::GetInstance().GetICDCounter();
510-
ctx->mICDManager.IncrementCounter();
511-
uint32_t counter2 = ICDConfigurationData::GetInstance().GetICDCounter();
512-
NL_TEST_ASSERT(aSuite, (counter + 1) == counter2);
510+
uint32_t counter = ICDConfigurationData::GetInstance().GetICDCounter().GetValue();
511+
512+
// Shut down and reinit ICDManager to increment counter
513+
ctx->mICDManager.Shutdown();
514+
ctx->mICDManager.Init(&(ctx->testStorage), &(ctx->GetFabricTable()), &(ctx->mKeystore), &(ctx->GetExchangeManager()),
515+
&(ctx->mSubInfoProvider));
516+
ctx->mICDManager.RegisterObserver(&(ctx->mICDStateObserver));
517+
518+
NL_TEST_ASSERT_EQUALS(aSuite, counter + ICDConfigurationData::kICDCounterPersistenceIncrement,
519+
ICDConfigurationData::GetInstance().GetICDCounter().GetValue());
513520
}
514521

515522
static void TestOnSubscriptionReport(nlTestSuite * aSuite, void * aContext)

src/app/tests/suites/TestIcdManagementCluster.yaml

+42-20
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ config:
1818
nodeId: 0x12344321
1919
cluster: "ICD Management"
2020
endpoint: 0
21+
beforeRebootICDCounter:
22+
type: int32u
23+
defaultValue: 0
2124

2225
tests:
2326
- label: "Read the commissioner node ID"
@@ -36,6 +39,26 @@ tests:
3639
- name: "nodeId"
3740
value: nodeId
3841

42+
# chip-tool will register itself with the ICD during the tests.
43+
- label: "Read RegisteredClients For Registration During Commissioning"
44+
command: "readAttribute"
45+
attribute: "RegisteredClients"
46+
response:
47+
value:
48+
[
49+
{
50+
CheckInNodeID: commissionerNodeId,
51+
MonitoredSubject: commissionerNodeId,
52+
},
53+
]
54+
55+
- label: "Unregister Client Registered During Commissioning"
56+
command: "UnregisterClient"
57+
arguments:
58+
values:
59+
- name: "CheckInNodeID"
60+
value: commissionerNodeId
61+
3962
- label: "Read Feature Map"
4063
command: "readAttribute"
4164
attribute: "FeatureMap"
@@ -68,6 +91,25 @@ tests:
6891
type: int32u
6992
minValue: 0x0
7093
maxValue: 0xFFFFFFFF
94+
saveAs: beforeRebootICDCounter
95+
96+
- label: "Reboot target device"
97+
cluster: "SystemCommands"
98+
command: "Reboot"
99+
100+
- label: "Connect to the device again"
101+
cluster: "DelayCommands"
102+
command: "WaitForCommissionee"
103+
arguments:
104+
values:
105+
- name: "nodeId"
106+
value: nodeId
107+
108+
- label: "Read ICDCounter after reboot"
109+
command: "readAttribute"
110+
attribute: "ICDCounter"
111+
response:
112+
value: beforeRebootICDCounter + 100
71113

72114
- label: "Read UserActiveModeTriggerHint"
73115
command: "readAttribute"
@@ -119,26 +161,6 @@ tests:
119161
response:
120162
error: NOT_FOUND
121163

122-
# chip-tool will register itself with the ICD during the tests.
123-
- label: "Read RegisteredClients For Registration During Commissioning"
124-
command: "readAttribute"
125-
attribute: "RegisteredClients"
126-
response:
127-
value:
128-
[
129-
{
130-
CheckInNodeID: commissionerNodeId,
131-
MonitoredSubject: commissionerNodeId,
132-
},
133-
]
134-
135-
- label: "Unregister Client Registered During Commissioning"
136-
command: "UnregisterClient"
137-
arguments:
138-
values:
139-
- name: "CheckInNodeID"
140-
value: commissionerNodeId
141-
142164
- label: "Register 1.0 (key too short)"
143165
command: "RegisterClient"
144166
arguments:

src/lib/support/PersistedCounter.h

+21-7
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,12 @@ class PersistedCounter : public MonotonicallyIncreasingCounter<T>
9292
ReturnErrorOnFailure(ReadStartValue(startValue));
9393

9494
#if CHIP_CONFIG_PERSISTED_COUNTER_DEBUG_LOGGING
95-
// Compiler should optimize these branches.
96-
if (is_same_v<decltype(T), uint64_t>)
95+
if constexpr (std::is_same_v<decltype(startValue), uint64_t>)
9796
{
9897
ChipLogDetail(EventLogging, "PersistedCounter::Init() aEpoch 0x" ChipLogFormatX64 " startValue 0x" ChipLogFormatX64,
9998
ChipLogValueX64(aEpoch), ChipLogValueX64(startValue));
10099
}
101-
else if (is_same_v<decltype(T), uint32_t>)
100+
else if (std::is_same_v<decltype(startValue), uint32_t>)
102101
{
103102
ChipLogDetail(EventLogging, "PersistedCounter::Init() aEpoch 0x%" PRIx32 " startValue 0x%" PRIx32,
104103
static_cast<uint32_t>(aEpoch), static_cast<uint32_t>(startValue));
@@ -151,8 +150,7 @@ class PersistedCounter : public MonotonicallyIncreasingCounter<T>
151150
{
152151
mNextEpoch = aStartValue;
153152
#if CHIP_CONFIG_PERSISTED_COUNTER_DEBUG_LOGGING
154-
// Compiler should optimize these branches.
155-
if (is_same_v<decltype(T), uint64_t>)
153+
if constexpr (std::is_same_v<decltype(aStartValue), uint64_t>)
156154
{
157155
ChipLogDetail(EventLogging, "PersistedCounter::WriteStartValue() aStartValue 0x" ChipLogFormatX64,
158156
ChipLogValueX64(aStartValue));
@@ -178,7 +176,7 @@ class PersistedCounter : public MonotonicallyIncreasingCounter<T>
178176
*/
179177
CHIP_ERROR ReadStartValue(T & aStartValue)
180178
{
181-
T valueLE = 0;
179+
T valueLE = GetInitialCounterValue();
182180
uint16_t size = sizeof(valueLE);
183181

184182
VerifyOrReturnError(mKey.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
@@ -206,12 +204,28 @@ class PersistedCounter : public MonotonicallyIncreasingCounter<T>
206204
aStartValue = Encoding::LittleEndian::HostSwap<T>(valueLE);
207205

208206
#if CHIP_CONFIG_PERSISTED_COUNTER_DEBUG_LOGGING
209-
ChipLogDetail(EventLogging, "PersistedCounter::ReadStartValue() aStartValue 0x%x", aStartValue);
207+
if constexpr (std::is_same_v<decltype(aStartValue), uint64_t>)
208+
{
209+
ChipLogDetail(EventLogging, "PersistedCounter::ReadStartValue() aStartValue 0x" ChipLogFormatX64,
210+
ChipLogValueX64(aStartValue));
211+
}
212+
else
213+
{
214+
ChipLogDetail(EventLogging, "PersistedCounter::ReadStartValue() aStartValue 0x%" PRIx32,
215+
static_cast<uint32_t>(aStartValue));
216+
}
210217
#endif
211218

212219
return CHIP_NO_ERROR;
213220
}
214221

222+
/**
223+
* @brief Get the Initial Counter Value
224+
*
225+
* By default, persisted counters start off at 0.
226+
*/
227+
virtual inline T GetInitialCounterValue() { return 0; }
228+
215229
PersistentStorageDelegate * mStorage = nullptr; // start value is stored here
216230
StorageKeyName mKey;
217231
T mEpoch = 0; // epoch modulus value

0 commit comments

Comments
 (0)