mirror of
https://github.com/espressif/openthread.git
synced 2026-08-20 01:19:51 +00:00
[low-power] fix CSL scheduler to avoid packets stuck in queue (#5833)
This commit: - Fixes the issue in CSL scheduler dealing with multiple SSEDs. - Fixes the issue when CSL tx attempts reach max, CSL transmission to this child cannot resume. - Reset CSL sync status after child mode change to RxOnWhenIdle. - Adds MLE version, CSL synchronization status and queued message count to child table.
This commit is contained in:
@@ -53,7 +53,7 @@ extern "C" {
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (47)
|
||||
#define OPENTHREAD_API_VERSION (48)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
@@ -67,10 +67,13 @@ typedef struct
|
||||
int8_t mLastRssi; ///< Last observed RSSI
|
||||
uint16_t mFrameErrorRate; ///< Frame error rate (0xffff->100%). Requires error tracking feature.
|
||||
uint16_t mMessageErrorRate; ///< (IPv6) msg error rate (0xffff->100%). Requires error tracking feature.
|
||||
uint16_t mQueuedMessageCnt; ///< Number of queued messages for the child.
|
||||
uint8_t mVersion; ///< MLE version
|
||||
bool mRxOnWhenIdle : 1; ///< rx-on-when-idle
|
||||
bool mFullThreadDevice : 1; ///< Full Thread Device
|
||||
bool mFullNetworkData : 1; ///< Full Network Data
|
||||
bool mIsStateRestoring : 1; ///< Is in restoring state
|
||||
bool mIsCslSynced : 1; ///< Is child CSL synchronized
|
||||
} otChildInfo;
|
||||
|
||||
#define OT_CHILD_IP6_ADDRESS_ITERATOR_INIT 0 ///< Initializer for otChildIP6AddressIterator
|
||||
|
||||
+4
-4
@@ -403,10 +403,10 @@ Print table of attached children.
|
||||
|
||||
```bash
|
||||
> child table
|
||||
| ID | RLOC16 | Timeout | Age | LQ In | C_VN |R|S|D|N| Extended MAC |
|
||||
+-----+--------+------------+------------+-------+------+-+-+-+-+------------------+
|
||||
| 1 | 0xe001 | 240 | 44 | 3 | 237 |1|1|1|1| d28d7f875888fccb |
|
||||
| 2 | 0xe002 | 240 | 27 | 3 | 237 |0|1|0|1| e2b3540590b0fd87 |
|
||||
| ID | RLOC16 | Timeout | Age | LQ In | C_VN |R|D|N|Ver|CSL|QMsgCnt| Extended MAC |
|
||||
+-----+--------+------------+------------+-------+------+-+-+-+---+---+-------+------------------+
|
||||
| 1 | 0xc801 | 240 | 24 | 3 | 131 |1|0|0| 3| 0 | 0 | 4ecede68435358ac |
|
||||
| 2 | 0xc802 | 240 | 2 | 3 | 131 |0|0|0| 3| 1 | 0 | a672a601d2ce37d8 |
|
||||
Done
|
||||
```
|
||||
|
||||
|
||||
+7
-2
@@ -782,8 +782,10 @@ otError Interpreter::ProcessChild(uint8_t aArgsLength, char *aArgs[])
|
||||
|
||||
if (isTable)
|
||||
{
|
||||
OutputLine("| ID | RLOC16 | Timeout | Age | LQ In | C_VN |R|D|N| Extended MAC |");
|
||||
OutputLine("+-----+--------+------------+------------+-------+------+-+-+-+------------------+");
|
||||
OutputLine(
|
||||
"| ID | RLOC16 | Timeout | Age | LQ In | C_VN |R|D|N|Ver|CSL|QMsgCnt| Extended MAC |");
|
||||
OutputLine(
|
||||
"+-----+--------+------------+------------+-------+------+-+-+-+---+---+-------+------------------+");
|
||||
}
|
||||
|
||||
maxChildren = otThreadGetMaxAllowedChildren(mInstance);
|
||||
@@ -806,6 +808,9 @@ otError Interpreter::ProcessChild(uint8_t aArgsLength, char *aArgs[])
|
||||
OutputFormat("|%1d", childInfo.mRxOnWhenIdle);
|
||||
OutputFormat("|%1d", childInfo.mFullThreadDevice);
|
||||
OutputFormat("|%1d", childInfo.mFullNetworkData);
|
||||
OutputFormat("|%3d", childInfo.mVersion);
|
||||
OutputFormat("| %1d ", childInfo.mIsCslSynced);
|
||||
OutputFormat("| %5d ", childInfo.mQueuedMessageCnt);
|
||||
OutputFormat("| ");
|
||||
OutputExtAddress(childInfo.mExtAddress);
|
||||
OutputLine(" |");
|
||||
|
||||
@@ -105,7 +105,6 @@ public:
|
||||
void SetIndirectKeyId(uint8_t aKeyId) { mIndirectKeyId = aKeyId; }
|
||||
|
||||
uint8_t GetIndirectTxAttempts(void) const { return mIndirectTxAttempts; }
|
||||
void SetIndirectTxAttemptsToMax(void) { mIndirectTxAttempts = kMaxPollTriggeredTxAttempts; }
|
||||
void ResetIndirectTxAttempts(void) { mIndirectTxAttempts = 0; }
|
||||
void IncrementIndirectTxAttempts(void) { mIndirectTxAttempts++; }
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ void CslTxScheduler::Clear(void)
|
||||
{
|
||||
for (Child &child : Get<ChildTable>().Iterate(Child::kInStateAnyExceptInvalid))
|
||||
{
|
||||
child.SetCslTxAttempts(0);
|
||||
child.ResetCslTxAttempts();
|
||||
child.SetCslSynchronized(false);
|
||||
child.SetCslChannel(0);
|
||||
child.SetCslTimeout(0);
|
||||
@@ -128,8 +128,7 @@ void CslTxScheduler::RescheduleCslTx(void)
|
||||
uint32_t delay;
|
||||
uint32_t cslTxDelay;
|
||||
|
||||
if (!child.IsCslSynchronized() || child.GetIndirectMessageCount() == 0 ||
|
||||
child.GetCslTxAttempts() >= kMaxCslTriggeredTxAttempts)
|
||||
if (!child.IsCslSynchronized() || child.GetIndirectMessageCount() == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -233,12 +232,20 @@ void CslTxScheduler::HandleSentFrame(const Mac::TxFrame &aFrame, otError aError,
|
||||
aChild.ResetCslTxAttempts();
|
||||
aChild.ResetIndirectTxAttempts();
|
||||
break;
|
||||
|
||||
case OT_ERROR_NO_ACK:
|
||||
aChild.IncrementCslTxAttempts();
|
||||
|
||||
otLogInfoMac("CSL tx to child %04x failed, attempt %d/%d", aChild.GetRloc16(), aChild.GetCslTxAttempts(),
|
||||
kMaxCslTriggeredTxAttempts);
|
||||
|
||||
if (aChild.GetCslTxAttempts() >= kMaxCslTriggeredTxAttempts)
|
||||
{
|
||||
// CSL transmission attempts reach max, consider child out of sync
|
||||
aChild.SetCslSynchronized(false);
|
||||
aChild.ResetCslTxAttempts();
|
||||
}
|
||||
|
||||
// Fall through
|
||||
case OT_ERROR_CHANNEL_ACCESS_FAILURE:
|
||||
case OT_ERROR_ABORT:
|
||||
|
||||
@@ -79,9 +79,8 @@ public:
|
||||
{
|
||||
public:
|
||||
uint8_t GetCslTxAttempts(void) const { return mCslTxAttempts; }
|
||||
void SetCslTxAttempts(uint8_t aCslTxAttempts) { mCslTxAttempts = aCslTxAttempts; }
|
||||
void IncrementCslTxAttempts(void) { mCslTxAttempts++; }
|
||||
void ResetCslTxAttempts(void) { SetCslTxAttempts(0); }
|
||||
void ResetCslTxAttempts(void) { mCslTxAttempts = 0; }
|
||||
|
||||
bool IsCslSynchronized(void) const { return mCslSynchronized && mCslPeriod > 0; }
|
||||
void SetCslSynchronized(bool aCslSynchronized) { mCslSynchronized = aCslSynchronized; }
|
||||
|
||||
@@ -321,14 +321,15 @@ void IndirectSender::UpdateIndirectMessage(Child &aChild)
|
||||
aChild.SetIndirectFragmentOffset(0);
|
||||
aChild.SetIndirectTxSuccess(true);
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
||||
mCslTxScheduler.Update();
|
||||
#endif
|
||||
|
||||
if (message != nullptr)
|
||||
{
|
||||
Mac::Address childAddress;
|
||||
|
||||
mDataPollHandler.HandleNewFrame(aChild);
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
||||
mCslTxScheduler.Update();
|
||||
#endif
|
||||
|
||||
aChild.GetMacAddress(childAddress);
|
||||
Get<MeshForwarder>().LogMessage(MeshForwarder::kMessagePrepareIndirect, *message, &childAddress, OT_ERROR_NONE);
|
||||
|
||||
@@ -2482,6 +2482,14 @@ void MleRouter::HandleChildUpdateRequest(const Message & aMessage,
|
||||
|
||||
childDidChange = true;
|
||||
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
||||
if (child->IsRxOnWhenIdle())
|
||||
{
|
||||
// Clear CSL synchronization state
|
||||
child->SetCslSynchronized(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
// The `IndirectSender::HandleChildModeChange()` needs to happen
|
||||
// after "Child Update" message is fully parsed to ensure that
|
||||
// any registered IPv6 addresses included in the "Child Update"
|
||||
|
||||
@@ -211,10 +211,17 @@ void Child::Info::SetFrom(const Child &aChild)
|
||||
mLastRssi = aChild.GetLinkInfo().GetLastRss();
|
||||
mFrameErrorRate = aChild.GetLinkInfo().GetFrameErrorRate();
|
||||
mMessageErrorRate = aChild.GetLinkInfo().GetMessageErrorRate();
|
||||
mQueuedMessageCnt = aChild.GetIndirectMessageCount();
|
||||
mVersion = aChild.GetVersion();
|
||||
mRxOnWhenIdle = aChild.IsRxOnWhenIdle();
|
||||
mFullThreadDevice = aChild.IsFullThreadDevice();
|
||||
mFullNetworkData = aChild.IsFullNetworkData();
|
||||
mIsStateRestoring = aChild.IsStateRestoring();
|
||||
#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
|
||||
mIsCslSynced = aChild.IsCslSynchronized();
|
||||
#else
|
||||
mIsCslSynced = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
const Ip6::Address *Child::AddressIterator::GetAddress(void) const
|
||||
|
||||
@@ -46,9 +46,9 @@ expect "Done"
|
||||
|
||||
switch_node 1
|
||||
send "child table\n"
|
||||
expect "| ID | RLOC16 | Timeout | Age | LQ In | C_VN |R|D|N| Extended MAC |"
|
||||
expect "+-----+--------+------------+------------+-------+------+-+-+-+------------------+"
|
||||
expect -re "\\| +(\\d+) \\| 0x$rloc \\| +\\d+ \\| +\\d+ \\| +\\d+ \\| +\\d+ \\|\\d\\|\\d\\|\\d\\| $extaddr \\|"
|
||||
expect "| ID | RLOC16 | Timeout | Age | LQ In | C_VN |R|D|N|Ver|CSL|QMsgCnt| Extended MAC |"
|
||||
expect "+-----+--------+------------+------------+-------+------+-+-+-+---+---+-------+------------------+"
|
||||
expect -re "\\| +(\\d+) \\| 0x$rloc \\| +\\d+ \\| +\\d+ \\| +\\d+ \\| +\\d+ \\|\\d\\|\\d\\|\\d\\| *\\d+\\| \\d \\| +\\d+ \\| $extaddr \\|"
|
||||
set child_id $expect_out(1,string)
|
||||
expect "Done"
|
||||
send "child list\n"
|
||||
|
||||
Reference in New Issue
Block a user