From ea29b88f78c351a13bfb3dadc01383f4ec1aac29 Mon Sep 17 00:00:00 2001 From: Rongli Sun Date: Sat, 18 Jan 2020 05:23:52 +0800 Subject: [PATCH] [coap] clear cached coap requests with rloc source when rloc changes (#4485) This commit helps to reduce unnecessary CoAP retransmission when rloc changes. When comes to SRV_DATA.ntf, it also helps to avoid invalid network data registration. Take the issue reported in #4472 as example, in a Thread Network with packet loss, the child server may switch parents frequently, there might be cached SRV_DATA.ntf including old rloc16, both the cached one and new one might be sent after switched, causing Leader improperly contain two server entries in the Network Data. --- src/core/coap/coap.cpp | 18 ++++++++++++++++++ src/core/coap/coap.hpp | 8 ++++++++ src/core/thread/mle.cpp | 6 ++++++ 3 files changed, 32 insertions(+) diff --git a/src/core/coap/coap.cpp b/src/core/coap/coap.cpp index ab2624944..9b3f86753 100644 --- a/src/core/coap/coap.cpp +++ b/src/core/coap/coap.cpp @@ -79,6 +79,24 @@ void CoapBase::ClearRequestsAndResponses(void) mResponsesQueue.DequeueAllResponses(); } +void CoapBase::ClearRequests(const Ip6::Address &aAddress) +{ + Message *nextMessage; + + // Remove pending messages with the specified source. + for (Message *message = static_cast(mPendingRequests.GetHead()); message != NULL; message = nextMessage) + { + CoapMetadata coapMetadata; + nextMessage = static_cast(message->GetNext()); + coapMetadata.ReadFrom(*message); + + if (coapMetadata.mSourceAddress == aAddress) + { + FinalizeCoapTransaction(*message, coapMetadata, NULL, NULL, OT_ERROR_ABORT); + } + } +} + otError CoapBase::AddResource(Resource &aResource) { return mResources.Add(aResource); diff --git a/src/core/coap/coap.hpp b/src/core/coap/coap.hpp index 5cd8ce9ba..ffdf97c5d 100644 --- a/src/core/coap/coap.hpp +++ b/src/core/coap/coap.hpp @@ -453,6 +453,14 @@ public: */ void ClearRequestsAndResponses(void); + /** + * This method clears requests with specified source address used by this CoAP agent. + * + * @param[in] aAddress A reference to the specified address. + * + */ + void ClearRequests(const Ip6::Address &aAddress); + /** * This method adds a resource to the CoAP server. * diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 6a3127268..1c1c80cc7 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -978,6 +978,12 @@ void Mle::SetRloc16(uint16_t aRloc16) if (aRloc16 != oldRloc16) { otLogNoteMle("RLOC16 %04x -> %04x", oldRloc16, aRloc16); + + // Clear cached CoAP with old RLOC source + if (oldRloc16 != Mac::kShortAddrInvalid) + { + Get().ClearRequests(mMeshLocal16.GetAddress()); + } } Get().RemoveUnicastAddress(mMeshLocal16);