Handle message re-order for outbound indirect messages (#1298)

This commit makes the following changes:

- A new field is added in child table, `mIndirectSendMessage` which
  stores a pointer to the current outbound indirect message for the
  child. The current offset for the message (in case of 6lowpan
  fragmentation) is stored in `mFragmentOffset` (as before).

- `GetIndirectTransmission()` is simplified to provide the
  next indirect message for a given child, and the preparation of
  the source/dest addresses for an indirect message is included in a
  new method `PrepareIndirectTransmission()`.

- In preparation of source address, if `mAddSrcMatchEntryShort` is
  not set for a child, then the long/extended address is used.

This commit addresses the issue where a re-ordering of messages in
the queue (due to message priority) could cause an incorrect
fragment offset to be applied to an outbound message.
This commit is contained in:
Abtin Keshavarzian
2017-02-10 09:17:51 -08:00
committed by Jonathan Hui
parent 177b572c87
commit 0823158ac8
3 changed files with 73 additions and 33 deletions
+69 -32
View File
@@ -243,32 +243,51 @@ void MeshForwarder::ScheduleTransmissionTask()
for (int i = 0; i < numChildren; i++) for (int i = 0; i < numChildren; i++)
{ {
if (children[i].mState == Child::kStateValid && Child &child = children[i];
children[i].mDataRequest)
{
mSendMessage = GetIndirectTransmission(children[i]);
if (mSendMessage != NULL) if (child.mState != Child::kStateValid || !child.mDataRequest)
{
continue;
}
mSendMessage = child.mIndirectSendMessage;
if (mSendMessage == NULL)
{
mSendMessage = GetIndirectTransmission(child);
child.mIndirectSendMessage = mSendMessage;
child.mFragmentOffset = 0;
}
if (mSendMessage != NULL)
{
mSendMessage->SetOffset(child.mFragmentOffset);
PrepareIndirectTransmission(*mSendMessage, child);
}
else
{
// A NULL `mSendMessage` triggers an empty frame to be sent to the child.
if (child.mAddSrcMatchEntryShort)
{ {
mSendMessage->SetOffset(children[i].mFragmentOffset); mMacSource.mLength = sizeof(mMacSource.mShortAddress);
mMacSource.mShortAddress = mNetif.GetMac().GetShortAddress();
mMacDest.mLength = sizeof(mMacDest.mShortAddress);
mMacDest.mShortAddress = child.mValid.mRloc16;
} }
else else
{ {
if (children[i].mAddSrcMatchEntryShort) mMacSource.mLength = sizeof(mMacSource.mExtAddress);
{ memcpy(mMacSource.mExtAddress.m8, mNetif.GetMac().GetExtAddress(), sizeof(mMacDest.mExtAddress));
mMacDest.mLength = sizeof(mMacDest.mShortAddress);
mMacDest.mShortAddress = children[i].mValid.mRloc16;
}
else
{
mMacDest.mLength = sizeof(mMacDest.mExtAddress);
memcpy(mMacDest.mExtAddress.m8, children[i].mMacAddr.m8, sizeof(mMacDest.mExtAddress));
}
}
mNetif.GetMac().SendFrameRequest(mMacSender); mMacDest.mLength = sizeof(mMacDest.mExtAddress);
ExitNow(); memcpy(mMacDest.mExtAddress.m8, child.mMacAddr.m8, sizeof(mMacDest.mExtAddress));
}
} }
mNetif.GetMac().SendFrameRequest(mMacSender);
ExitNow();
} }
if ((mSendMessage = GetDirectTransmission()) != NULL) if ((mSendMessage = GetDirectTransmission()) != NULL)
@@ -554,7 +573,6 @@ Message *MeshForwarder::GetIndirectTransmission(const Child &aChild)
{ {
Message *message = NULL; Message *message = NULL;
uint8_t childIndex = mNetif.GetMle().GetChildIndex(aChild); uint8_t childIndex = mNetif.GetMle().GetChildIndex(aChild);
Ip6::Header ip6Header;
for (message = mSendQueue.GetHead(); message; message = message->GetNext()) for (message = mSendQueue.GetHead(); message; message = message->GetNext())
{ {
@@ -564,12 +582,18 @@ Message *MeshForwarder::GetIndirectTransmission(const Child &aChild)
} }
} }
VerifyOrExit(message != NULL, ;); return message;
}
switch (message->GetType()) void MeshForwarder::PrepareIndirectTransmission(const Message &aMessage, const Child &aChild)
{
switch (aMessage.GetType())
{ {
case Message::kTypeIp6: case Message::kTypeIp6:
message->Read(0, sizeof(ip6Header), &ip6Header); {
Ip6::Header ip6Header;
aMessage.Read(0, sizeof(ip6Header), &ip6Header);
mAddMeshHeader = false; mAddMeshHeader = false;
GetMacSourceAddress(ip6Header.GetSource(), mMacSource); GetMacSourceAddress(ip6Header.GetSource(), mMacSource);
@@ -580,17 +604,26 @@ Message *MeshForwarder::GetIndirectTransmission(const Child &aChild)
} }
else else
{ {
mMacDest.mLength = sizeof(mMacDest.mShortAddress); if (aChild.mAddSrcMatchEntryShort)
mMacDest.mShortAddress = aChild.mValid.mRloc16; {
mMacDest.mLength = sizeof(mMacDest.mShortAddress);
mMacDest.mShortAddress = aChild.mValid.mRloc16;
}
else
{
mMacDest.mLength = sizeof(mMacDest.mExtAddress);
memcpy(mMacDest.mExtAddress.m8, aChild.mMacAddr.m8, sizeof(mMacDest.mExtAddress));
}
} }
break; break;
}
case Message::kType6lowpan: case Message::kType6lowpan:
{ {
Lowpan::MeshHeader meshHeader; Lowpan::MeshHeader meshHeader;
IgnoreReturnValue(meshHeader.Init(*message)); IgnoreReturnValue(meshHeader.Init(aMessage));
mAddMeshHeader = true; mAddMeshHeader = true;
mMeshDest = meshHeader.GetDestination(); mMeshDest = meshHeader.GetDestination();
mMeshSource = meshHeader.GetSource(); mMeshSource = meshHeader.GetSource();
@@ -605,12 +638,8 @@ Message *MeshForwarder::GetIndirectTransmission(const Child &aChild)
assert(false); assert(false);
break; break;
} }
exit:
return message;
} }
ThreadError MeshForwarder::UpdateMeshRoute(Message &aMessage) ThreadError MeshForwarder::UpdateMeshRoute(Message &aMessage)
{ {
ThreadError error = kThreadError_None; ThreadError error = kThreadError_None;
@@ -1548,11 +1577,19 @@ void MeshForwarder::HandleSentFrame(Mac::Frame &aFrame, ThreadError aError)
if (mMessageNextOffset < mSendMessage->GetLength()) if (mMessageNextOffset < mSendMessage->GetLength())
{ {
child->mFragmentOffset = mMessageNextOffset; if (mSendMessage == child->mIndirectSendMessage)
{
child->mFragmentOffset = mMessageNextOffset;
}
} }
else else
{ {
child->mFragmentOffset = 0; if (mSendMessage == child->mIndirectSendMessage)
{
child->mFragmentOffset = 0;
child->mIndirectSendMessage = NULL;
}
mSendMessage->ClearChildMask(mNetif.GetMle().GetChildIndex(*child)); mSendMessage->ClearChildMask(mNetif.GetMle().GetChildIndex(*child));
if ((child->mMode & Mle::ModeTlv::kModeRxOnWhenIdle) == 0) if ((child->mMode & Mle::ModeTlv::kModeRxOnWhenIdle) == 0)
+1
View File
@@ -233,6 +233,7 @@ private:
ThreadError GetMacSourceAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr); ThreadError GetMacSourceAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr);
Message *GetDirectTransmission(void); Message *GetDirectTransmission(void);
Message *GetIndirectTransmission(const Child &aChild); Message *GetIndirectTransmission(const Child &aChild);
void PrepareIndirectTransmission(const Message &aMessage, const Child &aChild);
void HandleMesh(uint8_t *aFrame, uint8_t aPayloadLength, const Mac::Address &aMacSource, void HandleMesh(uint8_t *aFrame, uint8_t aPayloadLength, const Mac::Address &aMacSource,
const ThreadMessageInfo &aMessageInfo); const ThreadMessageInfo &aMessageInfo);
void HandleFragment(uint8_t *aFrame, uint8_t aPayloadLength, void HandleFragment(uint8_t *aFrame, uint8_t aPayloadLength,
+3 -1
View File
@@ -39,6 +39,7 @@
#include <net/ip6.hpp> #include <net/ip6.hpp>
#include <thread/mle_tlvs.hpp> #include <thread/mle_tlvs.hpp>
#include <thread/link_quality.hpp> #include <thread/link_quality.hpp>
#include <common/message.hpp>
namespace Thread { namespace Thread {
@@ -107,7 +108,8 @@ public:
}; };
Ip6::Address mIp6Address[kMaxIp6AddressPerChild]; ///< Registered IPv6 addresses Ip6::Address mIp6Address[kMaxIp6AddressPerChild]; ///< Registered IPv6 addresses
uint32_t mTimeout; ///< Child timeout uint32_t mTimeout; ///< Child timeout
uint16_t mFragmentOffset; ///< 6LoWPAN fragment offset uint16_t mFragmentOffset; ///< 6LoWPAN fragment offset for the indirect message
Message *mIndirectSendMessage; ///< Current indirect message being sent.
union union
{ {
uint8_t mRequestTlvs[kMaxRequestTlvs]; ///< Requested MLE TLVs uint8_t mRequestTlvs[kMaxRequestTlvs]; ///< Requested MLE TLVs