mirror of
https://github.com/espressif/openthread.git
synced 2026-09-15 13:40:06 +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++)
|
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)
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user