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++)
{
if (children[i].mState == Child::kStateValid &&
children[i].mDataRequest)
{
mSendMessage = GetIndirectTransmission(children[i]);
Child &child = 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
{
if (children[i].mAddSrcMatchEntryShort)
{
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));
}
}
mMacSource.mLength = sizeof(mMacSource.mExtAddress);
memcpy(mMacSource.mExtAddress.m8, mNetif.GetMac().GetExtAddress(), sizeof(mMacDest.mExtAddress));
mNetif.GetMac().SendFrameRequest(mMacSender);
ExitNow();
mMacDest.mLength = sizeof(mMacDest.mExtAddress);
memcpy(mMacDest.mExtAddress.m8, child.mMacAddr.m8, sizeof(mMacDest.mExtAddress));
}
}
mNetif.GetMac().SendFrameRequest(mMacSender);
ExitNow();
}
if ((mSendMessage = GetDirectTransmission()) != NULL)
@@ -554,7 +573,6 @@ Message *MeshForwarder::GetIndirectTransmission(const Child &aChild)
{
Message *message = NULL;
uint8_t childIndex = mNetif.GetMle().GetChildIndex(aChild);
Ip6::Header ip6Header;
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:
message->Read(0, sizeof(ip6Header), &ip6Header);
{
Ip6::Header ip6Header;
aMessage.Read(0, sizeof(ip6Header), &ip6Header);
mAddMeshHeader = false;
GetMacSourceAddress(ip6Header.GetSource(), mMacSource);
@@ -580,17 +604,26 @@ Message *MeshForwarder::GetIndirectTransmission(const Child &aChild)
}
else
{
mMacDest.mLength = sizeof(mMacDest.mShortAddress);
mMacDest.mShortAddress = aChild.mValid.mRloc16;
if (aChild.mAddSrcMatchEntryShort)
{
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;
}
case Message::kType6lowpan:
{
Lowpan::MeshHeader meshHeader;
IgnoreReturnValue(meshHeader.Init(*message));
IgnoreReturnValue(meshHeader.Init(aMessage));
mAddMeshHeader = true;
mMeshDest = meshHeader.GetDestination();
mMeshSource = meshHeader.GetSource();
@@ -605,12 +638,8 @@ Message *MeshForwarder::GetIndirectTransmission(const Child &aChild)
assert(false);
break;
}
exit:
return message;
}
ThreadError MeshForwarder::UpdateMeshRoute(Message &aMessage)
{
ThreadError error = kThreadError_None;
@@ -1548,11 +1577,19 @@ void MeshForwarder::HandleSentFrame(Mac::Frame &aFrame, ThreadError aError)
if (mMessageNextOffset < mSendMessage->GetLength())
{
child->mFragmentOffset = mMessageNextOffset;
if (mSendMessage == child->mIndirectSendMessage)
{
child->mFragmentOffset = mMessageNextOffset;
}
}
else
{
child->mFragmentOffset = 0;
if (mSendMessage == child->mIndirectSendMessage)
{
child->mFragmentOffset = 0;
child->mIndirectSendMessage = NULL;
}
mSendMessage->ClearChildMask(mNetif.GetMle().GetChildIndex(*child));
if ((child->mMode & Mle::ModeTlv::kModeRxOnWhenIdle) == 0)
+1
View File
@@ -233,6 +233,7 @@ private:
ThreadError GetMacSourceAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr);
Message *GetDirectTransmission(void);
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,
const ThreadMessageInfo &aMessageInfo);
void HandleFragment(uint8_t *aFrame, uint8_t aPayloadLength,
+3 -1
View File
@@ -39,6 +39,7 @@
#include <net/ip6.hpp>
#include <thread/mle_tlvs.hpp>
#include <thread/link_quality.hpp>
#include <common/message.hpp>
namespace Thread {
@@ -107,7 +108,8 @@ public:
};
Ip6::Address mIp6Address[kMaxIp6AddressPerChild]; ///< Registered IPv6 addresses
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
{
uint8_t mRequestTlvs[kMaxRequestTlvs]; ///< Requested MLE TLVs