Mesh: Add Deep Hops Left field support. (#990)

This commit is contained in:
Łukasz Duda
2016-11-21 16:46:30 +00:00
committed by Jonathan Hui
parent 9de7f12c24
commit 47ff5ec0c3
4 changed files with 148 additions and 44 deletions
+89 -16
View File
@@ -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;
/**
+48 -27
View File
@@ -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 &&
+10 -1
View File
@@ -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);
+1
View File
@@ -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; }