From 47ff5ec0c3af9e7bf560bdfa2a54d81216da1347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Duda?= Date: Mon, 21 Nov 2016 17:46:30 +0100 Subject: [PATCH] Mesh: Add Deep Hops Left field support. (#990) --- src/core/thread/lowpan.hpp | 105 ++++++++++++++++++++++++----- src/core/thread/mesh_forwarder.cpp | 75 +++++++++++++-------- src/core/thread/mle_router_ftd.hpp | 11 ++- src/core/thread/mle_router_mtd.hpp | 1 + 4 files changed, 148 insertions(+), 44 deletions(-) diff --git a/src/core/thread/lowpan.hpp b/src/core/thread/lowpan.hpp index 393c041e0..5a3c03b41 100644 --- a/src/core/thread/lowpan.hpp +++ b/src/core/thread/lowpan.hpp @@ -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; /** diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index 9db57f2f2..bb602a00e 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -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(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(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(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 && diff --git a/src/core/thread/mle_router_ftd.hpp b/src/core/thread/mle_router_ftd.hpp index 1beff1b98..ff081906e 100644 --- a/src/core/thread/mle_router_ftd.hpp +++ b/src/core/thread/mle_router_ftd.hpp @@ -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); diff --git a/src/core/thread/mle_router_mtd.hpp b/src/core/thread/mle_router_mtd.hpp index 1d474af6f..7d18ce56b 100644 --- a/src/core/thread/mle_router_mtd.hpp +++ b/src/core/thread/mle_router_mtd.hpp @@ -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; }