Skip to content

Commit 6af9683

Browse files
Damian-Nordicpull[bot]
authored andcommitted
[mrp] Align MRP backoff time calculation with spec (#21356)
* [mrp] Align ReliableMessageMgr::GetBackoff() naming with spec Make variables and comments in the function more aligned with the current spec version so that it is easier to compare the code with the spec. Signed-off-by: Damian Krolik <[email protected]> * [mrp] Implement MRP_BACKOFF_MARGIN Base interval (active or idle) should be multiplied by MRP_BACKOFF_MARGIN = 1.1 before putting it in the MRP backoff formula. Signed-off-by: Damian Krolik <[email protected]> * [mrp] Increase MRP backoff time for SED sender When sender is sleepy, it may take more time until it receives an acknowledgment from a peer, so MRP backoff time should be extended by the sleepy active interval. Signed-off-by: Damian Krolik <[email protected]>
1 parent 5c3f7b5 commit 6af9683

File tree

4 files changed

+117
-48
lines changed

4 files changed

+117
-48
lines changed

src/messaging/ReliableMessageMgr.cpp

+51-25
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <messaging/ExchangeMgr.h>
3535
#include <messaging/Flags.h>
3636
#include <messaging/ReliableMessageContext.h>
37+
#include <platform/ConnectivityManager.h>
3738

3839
using namespace chip::System::Clock::Literals;
3940

@@ -202,40 +203,65 @@ CHIP_ERROR ReliableMessageMgr::AddToRetransTable(ReliableMessageContext * rc, Re
202203
return CHIP_NO_ERROR;
203204
}
204205

205-
System::Clock::Timestamp ReliableMessageMgr::GetBackoff(System::Clock::Timestamp backoffBase, uint8_t sendCount)
206+
System::Clock::Timestamp ReliableMessageMgr::GetBackoff(System::Clock::Timestamp baseInterval, uint8_t sendCount)
206207
{
207-
static constexpr uint32_t MRP_BACKOFF_JITTER_BASE = 1024;
208-
static constexpr uint32_t MRP_BACKOFF_BASE_NUMERATOR = 16;
209-
static constexpr uint32_t MRP_BACKOFF_BASE_DENOMENATOR = 10;
210-
static constexpr uint32_t MRP_BACKOFF_THRESHOLD = 1;
211-
212-
System::Clock::Timestamp backoff = backoffBase;
213-
214-
// Implement `t = i⋅MRP_BACKOFF_BASE^max(0,n−MRP_BACKOFF_THRESHOLD)` from Section 4.11.2.1. Retransmissions
215-
216-
// Generate fixed point equivalent of `retryCount = max(0,n−MRP_BACKOFF_THRESHOLD)`
217-
int retryCount = sendCount - MRP_BACKOFF_THRESHOLD;
218-
if (retryCount < 0)
219-
retryCount = 0; // Enforce floor
220-
if (retryCount > 4)
221-
retryCount = 4; // Enforce reasonable maximum after 5 tries
222-
223-
// Generate fixed point equivalent of `backoff = i⋅1.6^retryCount`
208+
// See section "4.11.8. Parameters and Constants" for the parameters below:
209+
// MRP_BACKOFF_JITTER = 0.25
210+
constexpr uint32_t MRP_BACKOFF_JITTER_BASE = 1024;
211+
// MRP_BACKOFF_MARGIN = 1.1
212+
constexpr uint32_t MRP_BACKOFF_MARGIN_NUMERATOR = 1127;
213+
constexpr uint32_t MRP_BACKOFF_MARGIN_DENOMINATOR = 1024;
214+
// MRP_BACKOFF_BASE = 1.6
215+
constexpr uint32_t MRP_BACKOFF_BASE_NUMERATOR = 16;
216+
constexpr uint32_t MRP_BACKOFF_BASE_DENOMINATOR = 10;
217+
constexpr int MRP_BACKOFF_THRESHOLD = 1;
218+
219+
// Implement `i = MRP_BACKOFF_MARGIN * i` from section "4.11.2.1. Retransmissions", where:
220+
// i == baseInterval
221+
baseInterval = baseInterval * MRP_BACKOFF_MARGIN_NUMERATOR / MRP_BACKOFF_MARGIN_DENOMINATOR;
222+
223+
// Implement:
224+
// mrpBackoffTime = i * MRP_BACKOFF_BASE^(max(0,n-MRP_BACKOFF_THRESHOLD)) * (1.0 + random(0,1) * MRP_BACKOFF_JITTER)
225+
// from section "4.11.2.1. Retransmissions", where:
226+
// i == baseInterval
227+
// n == sendCount
228+
229+
// 1. Calculate exponent `max(0,n−MRP_BACKOFF_THRESHOLD)`
230+
int exponent = sendCount - MRP_BACKOFF_THRESHOLD;
231+
if (exponent < 0)
232+
exponent = 0; // Enforce floor
233+
if (exponent > 4)
234+
exponent = 4; // Enforce reasonable maximum after 5 tries
235+
236+
// 2. Calculate `mrpBackoffTime = i * MRP_BACKOFF_BASE^(max(0,n-MRP_BACKOFF_THRESHOLD))`
224237
uint32_t backoffNum = 1;
225238
uint32_t backoffDenom = 1;
226-
for (int i = 0; i < retryCount; i++)
239+
240+
for (int i = 0; i < exponent; i++)
227241
{
228242
backoffNum *= MRP_BACKOFF_BASE_NUMERATOR;
229-
backoffDenom *= MRP_BACKOFF_BASE_DENOMENATOR;
243+
backoffDenom *= MRP_BACKOFF_BASE_DENOMINATOR;
230244
}
231-
backoff = backoff * backoffNum / backoffDenom;
232245

233-
// Implement jitter scaler: `t *= (1.0+random(0,1)⋅MRP_BACKOFF_JITTER)`
234-
// where jitter is random multiplier from 1.000 to 1.250:
246+
System::Clock::Timestamp mrpBackoffTime = baseInterval * backoffNum / backoffDenom;
247+
248+
// 3. Calculate `mrpBackoffTime *= (1.0 + random(0,1) * MRP_BACKOFF_JITTER)`
235249
uint32_t jitter = MRP_BACKOFF_JITTER_BASE + Crypto::GetRandU8();
236-
backoff = backoff * jitter / MRP_BACKOFF_JITTER_BASE;
250+
mrpBackoffTime = mrpBackoffTime * jitter / MRP_BACKOFF_JITTER_BASE;
251+
252+
#if CHIP_DEVICE_CONFIG_ENABLE_SED
253+
// Implement:
254+
// "A sleepy sender SHOULD increase t to also account for its own sleepy interval
255+
// required to receive the acknowledgment"
256+
DeviceLayer::ConnectivityManager::SEDIntervalsConfig sedIntervals;
257+
258+
if (DeviceLayer::ConnectivityMgr().GetSEDIntervalsConfig(sedIntervals) == CHIP_NO_ERROR)
259+
{
260+
mrpBackoffTime += System::Clock::Timestamp(sedIntervals.ActiveIntervalMS);
261+
}
262+
#endif
237263

238-
return backoff;
264+
return mrpBackoffTime;
239265
}
240266

241267
void ReliableMessageMgr::StartRetransmision(RetransTableEntry * entry)

src/messaging/ReliableMessageMgr.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -101,15 +101,15 @@ class ReliableMessageMgr
101101
/**
102102
* Calculate the backoff timer for the retransmission.
103103
*
104-
* @param[in] backoffBase The base interval to use for the backoff calculation, either the active or idle interval.
104+
* @param[in] baseInterval The base interval to use for the backoff calculation, either the active or idle interval.
105105
* @param[in] sendCount Count of how many times this message
106106
* has been retransmitted so far (0 if it has
107107
* been sent only once with no retransmits,
108108
* 1 if it has been sent twice, etc).
109109
*
110110
* @retval The backoff time value, including jitter.
111111
*/
112-
static System::Clock::Timestamp GetBackoff(System::Clock::Timestamp backoffBase, uint8_t sendCount);
112+
static System::Clock::Timestamp GetBackoff(System::Clock::Timestamp baseInterval, uint8_t sendCount);
113113

114114
/**
115115
* Start retranmisttion of cached encryped packet for current entry.

src/messaging/tests/TestReliableMessageProtocol.cpp

+63-20
Original file line numberDiff line numberDiff line change
@@ -183,44 +183,86 @@ struct BackoffComplianceTestVector theBackoffComplianceTestVector[] = {
183183
{
184184
.sendCount = 0,
185185
.backoffBase = System::Clock::Timeout(300),
186-
.backoffMin = System::Clock::Timeout(300),
187-
.backoffMax = System::Clock::Timeout(375),
186+
.backoffMin = System::Clock::Timeout(330),
187+
.backoffMax = System::Clock::Timeout(413),
188188
},
189189
{
190190
.sendCount = 1,
191191
.backoffBase = System::Clock::Timeout(300),
192-
.backoffMin = System::Clock::Timeout(300),
193-
.backoffMax = System::Clock::Timeout(375),
192+
.backoffMin = System::Clock::Timeout(330),
193+
.backoffMax = System::Clock::Timeout(413),
194194
},
195195
{
196196
.sendCount = 2,
197197
.backoffBase = System::Clock::Timeout(300),
198-
.backoffMin = System::Clock::Timeout(480),
199-
.backoffMax = System::Clock::Timeout(600),
198+
.backoffMin = System::Clock::Timeout(528),
199+
.backoffMax = System::Clock::Timeout(660),
200200
},
201201
{
202202
.sendCount = 3,
203203
.backoffBase = System::Clock::Timeout(300),
204-
.backoffMin = System::Clock::Timeout(768),
205-
.backoffMax = System::Clock::Timeout(960),
204+
.backoffMin = System::Clock::Timeout(844),
205+
.backoffMax = System::Clock::Timeout(1057),
206206
},
207207
{
208208
.sendCount = 4,
209209
.backoffBase = System::Clock::Timeout(300),
210-
.backoffMin = System::Clock::Timeout(1228),
211-
.backoffMax = System::Clock::Timeout(1536),
210+
.backoffMin = System::Clock::Timeout(1351),
211+
.backoffMax = System::Clock::Timeout(1690),
212212
},
213213
{
214214
.sendCount = 5,
215215
.backoffBase = System::Clock::Timeout(300),
216-
.backoffMin = System::Clock::Timeout(1966),
217-
.backoffMax = System::Clock::Timeout(2458),
216+
.backoffMin = System::Clock::Timeout(2162),
217+
.backoffMax = System::Clock::Timeout(2704),
218218
},
219219
{
220220
.sendCount = 6,
221221
.backoffBase = System::Clock::Timeout(300),
222-
.backoffMin = System::Clock::Timeout(1966),
223-
.backoffMax = System::Clock::Timeout(2458),
222+
.backoffMin = System::Clock::Timeout(2162),
223+
.backoffMax = System::Clock::Timeout(2704),
224+
},
225+
{
226+
.sendCount = 0,
227+
.backoffBase = System::Clock::Timeout(4000),
228+
.backoffMin = System::Clock::Timeout(4400),
229+
.backoffMax = System::Clock::Timeout(5500),
230+
},
231+
{
232+
.sendCount = 1,
233+
.backoffBase = System::Clock::Timeout(4000),
234+
.backoffMin = System::Clock::Timeout(4400),
235+
.backoffMax = System::Clock::Timeout(5500),
236+
},
237+
{
238+
.sendCount = 2,
239+
.backoffBase = System::Clock::Timeout(4000),
240+
.backoffMin = System::Clock::Timeout(7040),
241+
.backoffMax = System::Clock::Timeout(8800),
242+
},
243+
{
244+
.sendCount = 3,
245+
.backoffBase = System::Clock::Timeout(4000),
246+
.backoffMin = System::Clock::Timeout(11264),
247+
.backoffMax = System::Clock::Timeout(14081),
248+
},
249+
{
250+
.sendCount = 4,
251+
.backoffBase = System::Clock::Timeout(4000),
252+
.backoffMin = System::Clock::Timeout(18022),
253+
.backoffMax = System::Clock::Timeout(22529),
254+
},
255+
{
256+
.sendCount = 5,
257+
.backoffBase = System::Clock::Timeout(4000),
258+
.backoffMin = System::Clock::Timeout(28835),
259+
.backoffMax = System::Clock::Timeout(36045),
260+
},
261+
{
262+
.sendCount = 6,
263+
.backoffBase = System::Clock::Timeout(4000),
264+
.backoffMin = System::Clock::Timeout(28835),
265+
.backoffMax = System::Clock::Timeout(36045),
224266
},
225267
};
226268

@@ -323,7 +365,7 @@ void CheckResendApplicationMessage(nlTestSuite * inSuite, void * inContext)
323365
NL_TEST_ASSERT(inSuite, loopback.mDroppedMessageCount == 1);
324366
NL_TEST_ASSERT(inSuite, rm->TestGetCountRetransTable() == 1);
325367

326-
// Wait for the initial message to fail (should take 300-375ms)
368+
// Wait for the initial message to fail (should take 330-413ms)
327369
ctx.GetIOContext().DriveIOUntil(1000_ms32, [&] { return loopback.mSentMessageCount >= 2; });
328370
now = System::SystemClock().GetMonotonicTimestamp();
329371
timeoutTime = now - startTime;
@@ -340,7 +382,7 @@ void CheckResendApplicationMessage(nlTestSuite * inSuite, void * inContext)
340382
NL_TEST_ASSERT(inSuite, loopback.mDroppedMessageCount == 2);
341383
NL_TEST_ASSERT(inSuite, rm->TestGetCountRetransTable() == 1);
342384

343-
// Wait for the 1st retry to fail (should take 300-375ms)
385+
// Wait for the 1st retry to fail (should take 330-413ms)
344386
ctx.GetIOContext().DriveIOUntil(1000_ms32, [&] { return loopback.mSentMessageCount >= 3; });
345387
now = System::SystemClock().GetMonotonicTimestamp();
346388
timeoutTime = now - startTime;
@@ -357,7 +399,7 @@ void CheckResendApplicationMessage(nlTestSuite * inSuite, void * inContext)
357399
NL_TEST_ASSERT(inSuite, loopback.mDroppedMessageCount == 3);
358400
NL_TEST_ASSERT(inSuite, rm->TestGetCountRetransTable() == 1);
359401

360-
// Wait for the 2nd retry to fail (should take 480-600msms)
402+
// Wait for the 2nd retry to fail (should take 528-660ms)
361403
ctx.GetIOContext().DriveIOUntil(1000_ms32, [&] { return loopback.mSentMessageCount >= 4; });
362404
now = System::SystemClock().GetMonotonicTimestamp();
363405
timeoutTime = now - startTime;
@@ -374,8 +416,8 @@ void CheckResendApplicationMessage(nlTestSuite * inSuite, void * inContext)
374416
NL_TEST_ASSERT(inSuite, loopback.mDroppedMessageCount == 4);
375417
NL_TEST_ASSERT(inSuite, rm->TestGetCountRetransTable() == 1);
376418

377-
// Wait for the 3rd retry to fail (should take 768-960ms)
378-
ctx.GetIOContext().DriveIOUntil(1000_ms32, [&] { return loopback.mSentMessageCount >= 5; });
419+
// Wait for the 3rd retry to fail (should take 845-1056ms)
420+
ctx.GetIOContext().DriveIOUntil(1500_ms32, [&] { return loopback.mSentMessageCount >= 5; });
379421
now = System::SystemClock().GetMonotonicTimestamp();
380422
timeoutTime = now - startTime;
381423
ChipLogProgress(Test, "Attempt #4 Timeout : %d ms", timeoutTime.count());
@@ -1613,7 +1655,8 @@ void CheckGetBackoff(nlTestSuite * inSuite, void * inContext)
16131655
{
16141656
struct BackoffComplianceTestVector * test = &theBackoffComplianceTestVector[i];
16151657
System::Clock::Timeout backoff = ReliableMessageMgr::GetBackoff(test->backoffBase, test->sendCount);
1616-
ChipLogProgress(Test, "Backoff # %d: %" PRIu32, test->sendCount, (uint32_t) backoff.count());
1658+
ChipLogProgress(Test, "Backoff base %" PRIu32 " # %d: %" PRIu32, test->backoffBase.count(), test->sendCount,
1659+
backoff.count());
16171660

16181661
NL_TEST_ASSERT(inSuite, backoff >= test->backoffMin);
16191662
NL_TEST_ASSERT(inSuite, backoff <= test->backoffMax);

src/protocols/secure_channel/tests/TestPASESession.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ void SecurePairingHandshakeTestCommon(nlTestSuite * inSuite, void * inContext, S
279279

280280
while (delegate.mMessageDropped)
281281
{
282-
chip::test_utils::SleepMillis(85);
282+
chip::test_utils::SleepMillis(100);
283283
delegate.mMessageDropped = false;
284284
ReliableMessageMgr::Timeout(&ctx.GetSystemLayer(), ctx.GetExchangeManager().GetReliableMessageMgr());
285285
ctx.DrainAndServiceIO();

0 commit comments

Comments
 (0)