From c416b72cb65b2e9a20b408013aeadd80a538e4a5 Mon Sep 17 00:00:00 2001 From: Jintao Lin Date: Thu, 15 Oct 2020 22:36:51 +0800 Subject: [PATCH] [low-power] add an Enh-ACK frame link layer counter (#5583) On the transmitter side, only maintain a single frame counter, and never reuse it. On the receiver side, maintain a second incoming frame counter eFC alongside FC for each device, where eFC >= FC >= 0. When an Enh-ACK is received, verify it against eFC. Update eFC to be equal to the received frame counter. Do not touch FC. When a frame other than Enh-ACK is received, verify it against FC. Update both eFC and FC to be equal to the received frame counter. --- src/core/mac/mac.cpp | 55 ++++++++++++++++++++------------- src/core/thread/key_manager.cpp | 3 ++ src/core/thread/mle.cpp | 3 ++ src/core/thread/mle_router.cpp | 3 ++ src/core/thread/topology.hpp | 28 +++++++++++++++++ 5 files changed, 71 insertions(+), 21 deletions(-) diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index 3a7a5e03b..582232bcb 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -1637,6 +1637,12 @@ otError Mac::ProcessReceiveSecurity(RxFrame &aFrame, const Address &aSrcAddr, Ne } aNeighbor->SetLinkFrameCounter(frameCounter + 1); +#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 + if ((frameCounter + 1) > aNeighbor->GetLinkAckFrameCounter()) + { + aNeighbor->SetLinkAckFrameCounter(frameCounter + 1); + } +#endif if (keySequence > keyManager.GetCurrentKeySequence()) { @@ -1658,8 +1664,10 @@ otError Mac::ProcessEnhAckSecurity(TxFrame &aTxFrame, RxFrame &aAckFrame) uint8_t txKeyId; uint8_t ackKeyId; uint8_t keyIdMode; + uint32_t frameCounter; Address srcAddr; - Neighbor * neighbor; + Address dstAddr; + Neighbor * neighbor = nullptr; KeyManager &keyManager = Get(); const Key * macKey; @@ -1677,35 +1685,32 @@ otError Mac::ProcessEnhAckSecurity(TxFrame &aTxFrame, RxFrame &aAckFrame) VerifyOrExit(txKeyId == ackKeyId, OT_NOOP); + IgnoreError(aAckFrame.GetFrameCounter(frameCounter)); + otLogDebgMac("Rx security - Ack frame counter %u", frameCounter); + IgnoreError(aAckFrame.GetSrcAddr(srcAddr)); - if (srcAddr.IsShort()) + if (!srcAddr.IsNone()) { neighbor = Get().FindNeighbor(srcAddr); - - if (neighbor != nullptr) - { - srcAddr.SetExtended(neighbor->GetExtAddress()); - } } - - if (!srcAddr.IsExtended()) + else { - // Get Enh-ACK source address from transmitted frame destination address - IgnoreError(aTxFrame.GetDstAddr(srcAddr)); + IgnoreError(aTxFrame.GetDstAddr(dstAddr)); - if (srcAddr.IsShort()) + if (!dstAddr.IsNone()) { - neighbor = Get().FindNeighbor(srcAddr); - - if (neighbor != nullptr) - { - srcAddr.SetExtended(neighbor->GetExtAddress()); - } + // Get neighbor from destination address of transmitted frame + neighbor = Get().FindNeighbor(dstAddr); } } - VerifyOrExit(srcAddr.IsExtended(), OT_NOOP); + if (!srcAddr.IsExtended() && neighbor != nullptr) + { + srcAddr.SetExtended(neighbor->GetExtAddress()); + } + + VerifyOrExit(srcAddr.IsExtended() && neighbor != nullptr, OT_NOOP); ackKeyId--; @@ -1726,9 +1731,17 @@ otError Mac::ProcessEnhAckSecurity(TxFrame &aTxFrame, RxFrame &aAckFrame) ExitNow(); } - if (aAckFrame.ProcessReceiveAesCcm(srcAddr.GetExtended(), *macKey) == OT_ERROR_NONE) + if (neighbor->IsStateValid()) { - error = OT_ERROR_NONE; + VerifyOrExit(frameCounter >= neighbor->GetLinkAckFrameCounter(), OT_NOOP); + } + + error = aAckFrame.ProcessReceiveAesCcm(srcAddr.GetExtended(), *macKey); + SuccessOrExit(error); + + if (neighbor->IsStateValid()) + { + neighbor->SetLinkAckFrameCounter(frameCounter + 1); } exit: diff --git a/src/core/thread/key_manager.cpp b/src/core/thread/key_manager.cpp index 1c96cd0cd..1be031cdd 100644 --- a/src/core/thread/key_manager.cpp +++ b/src/core/thread/key_manager.cpp @@ -118,6 +118,7 @@ otError KeyManager::SetMasterKey(const MasterKey &aKey) parent = &Get().GetParent(); parent->SetKeySequence(0); parent->SetLinkFrameCounter(0); + parent->SetLinkAckFrameCounter(0); parent->SetMleFrameCounter(0); #if OPENTHREAD_FTD @@ -126,6 +127,7 @@ otError KeyManager::SetMasterKey(const MasterKey &aKey) { router.SetKeySequence(0); router.SetLinkFrameCounter(0); + router.SetLinkAckFrameCounter(0); router.SetMleFrameCounter(0); } @@ -134,6 +136,7 @@ otError KeyManager::SetMasterKey(const MasterKey &aKey) { child.SetKeySequence(0); child.SetLinkFrameCounter(0); + child.SetLinkAckFrameCounter(0); child.SetMleFrameCounter(0); } #endif diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index a2a7063dd..822db7116 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -2630,6 +2630,7 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn VerifyOrExit(keySequence > neighbor->GetKeySequence(), error = OT_ERROR_DUPLICATED); neighbor->SetKeySequence(keySequence); neighbor->SetLinkFrameCounter(0); + neighbor->SetLinkAckFrameCounter(0); } neighbor->SetMleFrameCounter(frameCounter + 1); @@ -3261,6 +3262,7 @@ void Mle::HandleParentResponse(const Message &aMessage, const Ip6::MessageInfo & mParentCandidate.SetExtAddress(extAddress); mParentCandidate.SetRloc16(sourceAddress); mParentCandidate.SetLinkFrameCounter(linkFrameCounter); + mParentCandidate.SetLinkAckFrameCounter(linkFrameCounter); mParentCandidate.SetMleFrameCounter(mleFrameCounter); mParentCandidate.SetVersion(static_cast(version)); mParentCandidate.SetDeviceMode(DeviceMode(DeviceMode::kModeFullThreadDevice | DeviceMode::kModeRxOnWhenIdle | @@ -3557,6 +3559,7 @@ void Mle::HandleChildUpdateResponse(const Message & aMessage, } mParent.SetLinkFrameCounter(linkFrameCounter); + mParent.SetLinkAckFrameCounter(linkFrameCounter); mParent.SetMleFrameCounter(mleFrameCounter); mParent.SetState(Neighbor::kStateValid); diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 5db680926..3a30efafb 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -953,6 +953,7 @@ otError MleRouter::HandleLinkAccept(const Message & aMessage, router->SetExtAddress(extAddr); router->SetRloc16(sourceAddress); router->SetLinkFrameCounter(linkFrameCounter); + router->SetLinkAckFrameCounter(linkFrameCounter); router->SetMleFrameCounter(mleFrameCounter); router->SetLastHeard(TimerMilli::GetNow()); router->SetDeviceMode(DeviceMode(DeviceMode::kModeFullThreadDevice | DeviceMode::kModeRxOnWhenIdle | @@ -2288,6 +2289,7 @@ void MleRouter::HandleChildIdRequest(const Message & aMessage, child->SetLastHeard(TimerMilli::GetNow()); child->SetLinkFrameCounter(linkFrameCounter); + child->SetLinkAckFrameCounter(linkFrameCounter); child->SetMleFrameCounter(mleFrameCounter); child->SetKeySequence(aKeySequence); child->SetDeviceMode(mode); @@ -2609,6 +2611,7 @@ void MleRouter::HandleChildUpdateResponse(const Message & aMessage, { case OT_ERROR_NONE: child->SetLinkFrameCounter(linkFrameCounter); + child->SetLinkAckFrameCounter(linkFrameCounter); break; case OT_ERROR_NOT_FOUND: break; diff --git a/src/core/thread/topology.hpp b/src/core/thread/topology.hpp index 573ef7567..2d1240439 100644 --- a/src/core/thread/topology.hpp +++ b/src/core/thread/topology.hpp @@ -415,6 +415,31 @@ public: */ void SetLinkFrameCounter(uint32_t aFrameCounter) { mValidPending.mValid.mLinkFrameCounter = aFrameCounter; } +#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 + /** + * This method gets the link ACK frame counter value. + * + * @returns The link ACK frame counter value. + * + */ + uint32_t GetLinkAckFrameCounter(void) const { return mValidPending.mValid.mLinkAckFrameCounter; } +#endif + + /** + * This method sets the link ACK frame counter value. + * + * @param[in] aAckFrameCounter The link ACK frame counter value. + * + */ + void SetLinkAckFrameCounter(uint32_t aAckFrameCounter) + { +#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 + mValidPending.mValid.mLinkAckFrameCounter = aAckFrameCounter; +#else + OT_UNUSED_VARIABLE(aAckFrameCounter); +#endif + } + /** * This method gets the MLE frame counter value. * @@ -582,6 +607,9 @@ private: { uint32_t mLinkFrameCounter; ///< The Link Frame Counter uint32_t mMleFrameCounter; ///< The MLE Frame Counter +#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 + uint32_t mLinkAckFrameCounter; ///< The Link Ack Frame Counter +#endif } mValid; struct {