mirror of
https://github.com/espressif/openthread.git
synced 2026-09-01 06:49:54 +00:00
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:
committed by
Jonathan Hui
parent
177b572c87
commit
0823158ac8
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user