mirror of
https://github.com/espressif/openthread.git
synced 2026-08-02 00:57:47 +00:00
Mesh: Add Deep Hops Left field support. (#990)
This commit is contained in:
committed by
Jonathan Hui
parent
9de7f12c24
commit
47ff5ec0c3
+89
-16
@@ -82,11 +82,6 @@ struct Context
|
||||
class Lowpan
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
kHopsLeft = 14,
|
||||
};
|
||||
|
||||
/**
|
||||
* This constructor initializes the object.
|
||||
*
|
||||
@@ -226,6 +221,46 @@ OT_TOOL_PACKED_BEGIN
|
||||
class MeshHeader
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
kAdditionalHopsLeft = 1 ///< The additional value that is added to predicted value of the route cost.
|
||||
};
|
||||
|
||||
/**
|
||||
* Default constructor for the object.
|
||||
*
|
||||
*/
|
||||
MeshHeader() { memset(this, 0, sizeof(*this)); }
|
||||
|
||||
/**
|
||||
* Mesh Header constructor that takes frame @p aFrame as a parameter.
|
||||
*
|
||||
* @param[in] aFrame The pointer to the frame.
|
||||
*
|
||||
*/
|
||||
MeshHeader(const uint8_t *aFrame) {
|
||||
mDispatchHopsLeft = *aFrame++;
|
||||
mDeepHopsLeft = IsDeepHopsLeftField() ? *aFrame++ : 0;
|
||||
memcpy(&mAddress, aFrame, sizeof(mAddress));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mesh Header constructor that takes message object @p aMessage as a parameter.
|
||||
*
|
||||
* @param[in] aMessage The message object.
|
||||
*
|
||||
*/
|
||||
MeshHeader(const Message &aMessage) {
|
||||
aMessage.Read(0, sizeof(mDispatchHopsLeft), &mDispatchHopsLeft);
|
||||
|
||||
if (IsDeepHopsLeftField()) {
|
||||
aMessage.Read(1, sizeof(mDeepHopsLeft) + sizeof(mAddress), &mDeepHopsLeft);
|
||||
}
|
||||
else {
|
||||
aMessage.Read(1, sizeof(mAddress), &mAddress);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method initializes the header.
|
||||
*
|
||||
@@ -250,13 +285,22 @@ public:
|
||||
*/
|
||||
bool IsValid() { return (mDispatchHopsLeft & kSourceShort) && (mDispatchHopsLeft & kDestinationShort); }
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the header contains Deep Hops Left field.
|
||||
*
|
||||
* @retval TRUE If the header does contain Deep Hops Left field.
|
||||
* @retval FALSE If the header does not contain Deep Hops Left field.
|
||||
*
|
||||
*/
|
||||
bool IsDeepHopsLeftField() { return (mDispatchHopsLeft & kHopsLeftMask) == kDeepHopsLeft; }
|
||||
|
||||
/**
|
||||
* This static method returns the size of the Mesh Header in bytes.
|
||||
*
|
||||
* @returns The size of the Mesh Header in bytes.
|
||||
*
|
||||
*/
|
||||
static uint8_t GetHeaderLength() { return sizeof(MeshHeader); }
|
||||
uint8_t GetHeaderLength() { return sizeof(*this) - (IsDeepHopsLeftField() ? 0 : sizeof(mDeepHopsLeft)) ; }
|
||||
|
||||
/**
|
||||
* This method returns the Hops Left value.
|
||||
@@ -264,7 +308,7 @@ public:
|
||||
* @returns The Hops Left value.
|
||||
*
|
||||
*/
|
||||
uint8_t GetHopsLeft() { return mDispatchHopsLeft & kHopsLeftMask; }
|
||||
uint8_t GetHopsLeft() { return IsDeepHopsLeftField() ? mDeepHopsLeft : mDispatchHopsLeft & kHopsLeftMask; }
|
||||
|
||||
/**
|
||||
* This method sets the Hops Left value.
|
||||
@@ -272,7 +316,15 @@ public:
|
||||
* @param[in] aHops The Hops Left value.
|
||||
*
|
||||
*/
|
||||
void SetHopsLeft(uint8_t aHops) { mDispatchHopsLeft = (mDispatchHopsLeft & ~kHopsLeftMask) | aHops; }
|
||||
void SetHopsLeft(uint8_t aHops) {
|
||||
if (aHops < kDeepHopsLeft && !IsDeepHopsLeftField()) {
|
||||
mDispatchHopsLeft = (mDispatchHopsLeft & ~kHopsLeftMask) | aHops;
|
||||
}
|
||||
else {
|
||||
mDispatchHopsLeft = (mDispatchHopsLeft & ~kHopsLeftMask) | kDeepHopsLeft;
|
||||
mDeepHopsLeft = aHops;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the Mesh Source address.
|
||||
@@ -280,7 +332,7 @@ public:
|
||||
* @returns The Mesh Source address.
|
||||
*
|
||||
*/
|
||||
uint16_t GetSource() { return HostSwap16(mSource); }
|
||||
uint16_t GetSource() { return HostSwap16(mAddress.mSource); }
|
||||
|
||||
/**
|
||||
* This method sets the Mesh Source address.
|
||||
@@ -288,7 +340,7 @@ public:
|
||||
* @param[in] aSource The Mesh Source address.
|
||||
*
|
||||
*/
|
||||
void SetSource(uint16_t aSource) { mSource = HostSwap16(aSource); }
|
||||
void SetSource(uint16_t aSource) { mAddress.mSource = HostSwap16(aSource); }
|
||||
|
||||
/**
|
||||
* This method returns the Mesh Destination address.
|
||||
@@ -296,7 +348,7 @@ public:
|
||||
* @returns The Mesh Destination address.
|
||||
*
|
||||
*/
|
||||
uint16_t GetDestination() { return HostSwap16(mDestination); }
|
||||
uint16_t GetDestination() { return HostSwap16(mAddress.mDestination); }
|
||||
|
||||
/**
|
||||
* This method sets the Mesh Destination address.
|
||||
@@ -304,21 +356,42 @@ public:
|
||||
* @param[in] aDestination The Mesh Destination address.
|
||||
*
|
||||
*/
|
||||
void SetDestination(uint16_t aDestination) { mDestination = HostSwap16(aDestination); }
|
||||
void SetDestination(uint16_t aDestination) { mAddress.mDestination = HostSwap16(aDestination); }
|
||||
|
||||
/**
|
||||
* This method appends Mesh Header to the @p aFrame frame.
|
||||
*
|
||||
* @param[in] aFrame The pointer to the frame.
|
||||
*
|
||||
*/
|
||||
void AppendTo(uint8_t *aFrame) {
|
||||
*aFrame++ = mDispatchHopsLeft;
|
||||
|
||||
if (IsDeepHopsLeftField()) {
|
||||
*aFrame++ = mDeepHopsLeft;
|
||||
}
|
||||
|
||||
memcpy(aFrame, &mAddress, sizeof(mAddress));
|
||||
}
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kDispatch = 2 << 6,
|
||||
kDispatchMask = 3 << 6,
|
||||
kHopsLeftMask = 0xf << 0,
|
||||
kHopsLeftMask = 0x0f,
|
||||
kSourceShort = 1 << 5,
|
||||
kDestinationShort = 1 << 4,
|
||||
kDeepHopsLeft = 0x0f
|
||||
};
|
||||
|
||||
uint8_t mDispatchHopsLeft;
|
||||
uint16_t mSource;
|
||||
uint16_t mDestination;
|
||||
uint8_t mDispatchHopsLeft;
|
||||
uint8_t mDeepHopsLeft;
|
||||
struct
|
||||
{
|
||||
uint16_t mSource;
|
||||
uint16_t mDestination;
|
||||
} mAddress OT_TOOL_PACKED_FIELD;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
|
||||
@@ -372,7 +372,6 @@ ThreadError MeshForwarder::SendMessage(Message &aMessage)
|
||||
Ip6::Header ip6Header;
|
||||
uint8_t numChildren;
|
||||
Child *children;
|
||||
Lowpan::MeshHeader meshHeader;
|
||||
|
||||
switch (aMessage.GetType())
|
||||
{
|
||||
@@ -418,7 +417,8 @@ ThreadError MeshForwarder::SendMessage(Message &aMessage)
|
||||
break;
|
||||
|
||||
case Message::kType6lowpan:
|
||||
aMessage.Read(0, meshHeader.GetHeaderLength(), &meshHeader);
|
||||
{
|
||||
Lowpan::MeshHeader meshHeader(aMessage);
|
||||
|
||||
if ((neighbor = mMle.GetNeighbor(meshHeader.GetDestination())) != NULL &&
|
||||
(neighbor->mMode & Mle::ModeTlv::kModeRxOnWhenIdle) == 0)
|
||||
@@ -437,6 +437,7 @@ ThreadError MeshForwarder::SendMessage(Message &aMessage)
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Message::kTypeMacDataPoll:
|
||||
aMessage.SetDirectTransmission();
|
||||
@@ -510,7 +511,6 @@ Message *MeshForwarder::GetIndirectTransmission(const Child &aChild)
|
||||
Message *message = NULL;
|
||||
uint8_t childIndex = mMle.GetChildIndex(aChild);
|
||||
Ip6::Header ip6Header;
|
||||
Lowpan::MeshHeader meshHeader;
|
||||
|
||||
for (message = mSendQueue.GetHead(); message; message = message->GetNext())
|
||||
{
|
||||
@@ -543,7 +543,8 @@ Message *MeshForwarder::GetIndirectTransmission(const Child &aChild)
|
||||
break;
|
||||
|
||||
case Message::kType6lowpan:
|
||||
message->Read(0, meshHeader.GetHeaderLength(), &meshHeader);
|
||||
{
|
||||
Lowpan::MeshHeader meshHeader(*message);
|
||||
|
||||
mAddMeshHeader = true;
|
||||
mMeshDest = meshHeader.GetDestination();
|
||||
@@ -553,6 +554,7 @@ Message *MeshForwarder::GetIndirectTransmission(const Child &aChild)
|
||||
mMacDest.mLength = sizeof(mMacDest.mShortAddress);
|
||||
mMacDest.mShortAddress = meshHeader.GetDestination();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
@@ -566,12 +568,10 @@ exit:
|
||||
ThreadError MeshForwarder::UpdateMeshRoute(Message &aMessage)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Lowpan::MeshHeader meshHeader;
|
||||
Lowpan::MeshHeader meshHeader(aMessage);
|
||||
Neighbor *neighbor;
|
||||
uint16_t nextHop;
|
||||
|
||||
aMessage.Read(0, meshHeader.GetHeaderLength(), &meshHeader);
|
||||
|
||||
nextHop = mMle.GetNextHop(meshHeader.GetDestination());
|
||||
|
||||
if (nextHop != Mac::kShortAddrInvalid)
|
||||
@@ -1027,9 +1027,10 @@ ThreadError MeshForwarder::SendFragment(Message &aMessage, Mac::Frame &aFrame)
|
||||
Mac::Address meshDest, meshSource;
|
||||
uint16_t fcf;
|
||||
Lowpan::FragmentHeader *fragmentHeader;
|
||||
Lowpan::MeshHeader *meshHeader;
|
||||
Lowpan::MeshHeader meshHeader;
|
||||
uint8_t *payload;
|
||||
uint8_t headerLength;
|
||||
uint8_t hopsLeft;
|
||||
uint16_t payloadLength;
|
||||
int hcLength;
|
||||
uint16_t fragmentLength;
|
||||
@@ -1134,13 +1135,31 @@ ThreadError MeshForwarder::SendFragment(Message &aMessage, Mac::Frame &aFrame)
|
||||
// initialize Mesh header
|
||||
if (mAddMeshHeader)
|
||||
{
|
||||
meshHeader = reinterpret_cast<Lowpan::MeshHeader *>(payload);
|
||||
meshHeader->Init();
|
||||
meshHeader->SetHopsLeft(Lowpan::Lowpan::kHopsLeft);
|
||||
meshHeader->SetSource(mMeshSource);
|
||||
meshHeader->SetDestination(mMeshDest);
|
||||
payload += meshHeader->GetHeaderLength();
|
||||
headerLength += meshHeader->GetHeaderLength();
|
||||
// Calculate the number of predicted hops.
|
||||
hopsLeft = mMle.GetRouteCost(mMeshDest);
|
||||
hopsLeft += mMle.GetLinkCost(mMle.GetRouterId(mMle.GetNextHop(mMeshDest)));
|
||||
|
||||
// The hopsLft field MUST be incremented by one if the device is not
|
||||
// an active Router.
|
||||
if (!mMle.IsActiveRouter(mMeshSource))
|
||||
{
|
||||
hopsLeft += 1;
|
||||
}
|
||||
|
||||
// The hopsLft field MUST be incremented by one if the destination RLOC16
|
||||
// is not that of an active Router.
|
||||
if (!mMle.IsActiveRouter(mMeshDest))
|
||||
{
|
||||
hopsLeft += 1;
|
||||
}
|
||||
|
||||
meshHeader.Init();
|
||||
meshHeader.SetHopsLeft(hopsLeft + Lowpan::MeshHeader::kAdditionalHopsLeft);
|
||||
meshHeader.SetSource(mMeshSource);
|
||||
meshHeader.SetDestination(mMeshDest);
|
||||
meshHeader.AppendTo(payload);
|
||||
payload += meshHeader.GetHeaderLength();
|
||||
headerLength += meshHeader.GetHeaderLength();
|
||||
}
|
||||
|
||||
// copy IPv6 Header
|
||||
@@ -1472,23 +1491,23 @@ void MeshForwarder::HandleMesh(uint8_t *aFrame, uint8_t aFrameLength, const Thre
|
||||
Message *message = NULL;
|
||||
Mac::Address meshDest;
|
||||
Mac::Address meshSource;
|
||||
Lowpan::MeshHeader *meshHeader = reinterpret_cast<Lowpan::MeshHeader *>(aFrame);
|
||||
Lowpan::MeshHeader meshHeader(aFrame);
|
||||
|
||||
// Length Check
|
||||
VerifyOrExit(meshHeader->GetHeaderLength() <= aFrameLength, error = kThreadError_Drop);
|
||||
VerifyOrExit(meshHeader.GetHeaderLength() <= aFrameLength, error = kThreadError_Drop);
|
||||
|
||||
// Security Check: only process Mesh Header frames that had security enabled.
|
||||
VerifyOrExit(aMessageInfo.mLinkSecurity && meshHeader->IsValid(), error = kThreadError_Security);
|
||||
VerifyOrExit(aMessageInfo.mLinkSecurity && meshHeader.IsValid(), error = kThreadError_Security);
|
||||
|
||||
meshSource.mLength = sizeof(meshSource.mShortAddress);
|
||||
meshSource.mShortAddress = meshHeader->GetSource();
|
||||
meshSource.mShortAddress = meshHeader.GetSource();
|
||||
meshDest.mLength = sizeof(meshDest.mShortAddress);
|
||||
meshDest.mShortAddress = meshHeader->GetDestination();
|
||||
meshDest.mShortAddress = meshHeader.GetDestination();
|
||||
|
||||
if (meshDest.mShortAddress == mMac.GetShortAddress())
|
||||
{
|
||||
aFrame += meshHeader->GetHeaderLength();
|
||||
aFrameLength -= meshHeader->GetHeaderLength();
|
||||
aFrame += meshHeader.GetHeaderLength();
|
||||
aFrameLength -= meshHeader.GetHeaderLength();
|
||||
|
||||
if (reinterpret_cast<Lowpan::FragmentHeader *>(aFrame)->IsFragmentHeader())
|
||||
{
|
||||
@@ -1503,11 +1522,12 @@ void MeshForwarder::HandleMesh(uint8_t *aFrame, uint8_t aFrameLength, const Thre
|
||||
ExitNow(error = kThreadError_Parse);
|
||||
}
|
||||
}
|
||||
else if (meshHeader->GetHopsLeft() > 0)
|
||||
else if (meshHeader.GetHopsLeft() > 0)
|
||||
{
|
||||
SuccessOrExit(error = CheckReachability(aFrame, aFrameLength, meshSource, meshDest));
|
||||
|
||||
meshHeader->SetHopsLeft(meshHeader->GetHopsLeft() - 1);
|
||||
meshHeader.SetHopsLeft(meshHeader.GetHopsLeft() - 1);
|
||||
meshHeader.AppendTo(aFrame);
|
||||
|
||||
VerifyOrExit((message = mNetif.GetIp6().mMessagePool.New(Message::kType6lowpan, 0)) != NULL,
|
||||
error = kThreadError_NoBufs);
|
||||
@@ -1537,11 +1557,12 @@ ThreadError MeshForwarder::CheckReachability(uint8_t *aFrame, uint8_t aFrameLeng
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Ip6::Header ip6Header;
|
||||
Lowpan::MeshHeader meshHeader(aFrame);
|
||||
|
||||
// skip mesh header
|
||||
VerifyOrExit(Lowpan::MeshHeader::GetHeaderLength() <= aFrameLength, error = kThreadError_Drop);
|
||||
aFrame += Lowpan::MeshHeader::GetHeaderLength();
|
||||
aFrameLength -= Lowpan::MeshHeader::GetHeaderLength();
|
||||
VerifyOrExit(meshHeader.GetHeaderLength() <= aFrameLength, error = kThreadError_Drop);
|
||||
aFrame += meshHeader.GetHeaderLength();
|
||||
aFrameLength -= meshHeader.GetHeaderLength();
|
||||
|
||||
// skip fragment header
|
||||
if (aFrameLength >= 1 &&
|
||||
|
||||
@@ -334,6 +334,16 @@ public:
|
||||
*/
|
||||
uint8_t GetRouteCost(uint16_t aRloc16) const;
|
||||
|
||||
/**
|
||||
* This method returns the link cost to the given Router.
|
||||
*
|
||||
* @param[in] aRouterId The Router ID.
|
||||
*
|
||||
* @returns The link cost to the Router.
|
||||
*
|
||||
*/
|
||||
uint8_t GetLinkCost(uint8_t aRouterId);
|
||||
|
||||
/**
|
||||
* This method returns the current Router ID Sequence value.
|
||||
*
|
||||
@@ -654,7 +664,6 @@ private:
|
||||
ThreadError AppendRoute(Message &aMessage);
|
||||
ThreadError AppendActiveDataset(Message &aMessage);
|
||||
ThreadError AppendPendingDataset(Message &aMessage);
|
||||
uint8_t GetLinkCost(uint8_t aRouterId);
|
||||
void GetChildInfo(Child &aChild, otChildInfo &aChildInfo);
|
||||
ThreadError HandleDetachStart(void);
|
||||
ThreadError HandleChildStart(otMleAttachFilter aFilter);
|
||||
|
||||
@@ -76,6 +76,7 @@ public:
|
||||
void SetNetworkIdTimeout(uint8_t) { }
|
||||
|
||||
uint8_t GetRouteCost(uint16_t) const { return 0; }
|
||||
uint8_t GetLinkCost(uint16_t) { return 0; }
|
||||
|
||||
uint8_t GetRouterIdSequence(void) const { return 0; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user