From b83fa59914fe9456d824bbd48d7ec461179da957 Mon Sep 17 00:00:00 2001 From: Zhanglong Xia Date: Fri, 7 Sep 2018 01:28:08 +0800 Subject: [PATCH] [mesh-forwarder] add function to decompress IPv6 Header (#3014) --- src/core/thread/lowpan.hpp | 4 +- src/core/thread/mesh_forwarder.cpp | 53 +++++++++++++++++ src/core/thread/mesh_forwarder.hpp | 13 +++++ src/core/thread/mesh_forwarder_ftd.cpp | 80 +++++++++----------------- 4 files changed, 96 insertions(+), 54 deletions(-) diff --git a/src/core/thread/lowpan.hpp b/src/core/thread/lowpan.hpp index b5fd0ba2b..ce988eb19 100644 --- a/src/core/thread/lowpan.hpp +++ b/src/core/thread/lowpan.hpp @@ -97,7 +97,7 @@ public: * @retval TRUE If the header matches the LOWPAN_IPHC dispatch value. * @retval FALSE If the header does not match the LOWPAN_IPHC dispatch value. */ - static bool IsLowpanHc(uint8_t *aHeader) + static bool IsLowpanHc(const uint8_t *aHeader) { return (aHeader[0] & (Lowpan::kHcDispatchMask >> 8)) == (Lowpan::kHcDispatch >> 8); } @@ -477,7 +477,7 @@ public: * @retval FALSE If the header does not match the Fragment Header dispatch value. * */ - bool IsFragmentHeader(void) { return (HostSwap16(mDispatchSize) & kDispatchMask) == kDispatch; } + bool IsFragmentHeader(void) const { return (HostSwap16(mDispatchSize) & kDispatchMask) == kDispatch; } /** * This method returns the Fragment Header length. diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index f7dbd2673..42db06ac6 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -453,6 +453,59 @@ otError MeshForwarder::GetMacDestinationAddress(const Ip6::Address &aIp6Addr, Ma return OT_ERROR_NONE; } +otError MeshForwarder::SkipMeshHeader(const uint8_t *&aFrame, uint8_t &aFrameLength) +{ + otError error = OT_ERROR_NONE; + Lowpan::MeshHeader meshHeader; + + VerifyOrExit(aFrameLength >= 1 && reinterpret_cast(aFrame)->IsMeshHeader()); + + SuccessOrExit(error = meshHeader.Init(aFrame, aFrameLength)); + aFrame += meshHeader.GetHeaderLength(); + aFrameLength -= meshHeader.GetHeaderLength(); + +exit: + return error; +} + +otError MeshForwarder::DecompressIp6Header(const uint8_t * aFrame, + uint8_t aFrameLength, + const Mac::Address &aMacSource, + const Mac::Address &aMacDest, + Ip6::Header & aIp6Header, + uint8_t & aHeaderLength, + bool & aNextHeaderCompressed) +{ + Lowpan::Lowpan & lowpan = GetNetif().GetLowpan(); + otError error = OT_ERROR_NONE; + const uint8_t * start = aFrame; + Lowpan::FragmentHeader fragmentHeader; + int headerLength; + + SuccessOrExit(error = SkipMeshHeader(aFrame, aFrameLength)); + + if (aFrameLength >= 1 && reinterpret_cast(aFrame)->IsFragmentHeader()) + { + SuccessOrExit(error = fragmentHeader.Init(aFrame, aFrameLength)); + + // only the first fragment header is followed by a LOWPAN_IPHC header + VerifyOrExit(fragmentHeader.GetDatagramOffset() == 0, error = OT_ERROR_NOT_FOUND); + + aFrame += fragmentHeader.GetHeaderLength(); + aFrameLength -= fragmentHeader.GetHeaderLength(); + } + + VerifyOrExit(aFrameLength >= 1 && Lowpan::Lowpan::IsLowpanHc(aFrame), error = OT_ERROR_NOT_FOUND); + headerLength = + lowpan.DecompressBaseHeader(aIp6Header, aNextHeaderCompressed, aMacSource, aMacDest, aFrame, aFrameLength); + + VerifyOrExit(headerLength > 0, error = OT_ERROR_PARSE); + aHeaderLength = static_cast(aFrame - start) + static_cast(headerLength); + +exit: + return error; +} + otError MeshForwarder::HandleFrameRequest(Mac::Sender &aSender, Mac::Frame &aFrame) { return aSender.GetOwner().HandleFrameRequest(aFrame); diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp index 985120c88..7ecb13ed9 100644 --- a/src/core/thread/mesh_forwarder.hpp +++ b/src/core/thread/mesh_forwarder.hpp @@ -271,6 +271,19 @@ private: const Mac::Address &aMeshSource, const Mac::Address &aMeshDest); + otError SkipMeshHeader(const uint8_t *&aFrame, uint8_t &aFrameLength); + otError DecompressIp6Header(const uint8_t * aFrame, + uint8_t aFrameLength, + const Mac::Address &aMacSource, + const Mac::Address &aMacDest, + Ip6::Header & aIp6Header, + uint8_t & aHeaderLength, + bool & aNextHeaderCompressed); + otError GetIp6Header(const uint8_t * aFrame, + uint8_t aFrameLength, + const Mac::Address &aMacSource, + const Mac::Address &aMacDest, + Ip6::Header & aIp6Header); otError GetMacDestinationAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr); otError GetMacSourceAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr); Message *GetDirectTransmission(void); diff --git a/src/core/thread/mesh_forwarder_ftd.cpp b/src/core/thread/mesh_forwarder_ftd.cpp index 079a9d8c9..8c30e3c47 100644 --- a/src/core/thread/mesh_forwarder_ftd.cpp +++ b/src/core/thread/mesh_forwarder_ftd.cpp @@ -829,43 +829,42 @@ exit: return error; } +otError MeshForwarder::GetIp6Header(const uint8_t * aFrame, + uint8_t aFrameLength, + const Mac::Address &aMacSource, + const Mac::Address &aMacDest, + Ip6::Header & aIp6Header) +{ + uint8_t headerLength; + bool nextHeaderCompressed; + + return DecompressIp6Header(aFrame, aFrameLength, aMacSource, aMacDest, aIp6Header, headerLength, + nextHeaderCompressed); +} + otError MeshForwarder::CheckReachability(uint8_t * aFrame, uint8_t aFrameLength, const Mac::Address &aMeshSource, const Mac::Address &aMeshDest) { - ThreadNetif & netif = GetNetif(); - otError error = OT_ERROR_NONE; - Ip6::Header ip6Header; - Lowpan::MeshHeader meshHeader; - bool nextHeaderCompressed; - - VerifyOrExit(meshHeader.Init(aFrame, aFrameLength) == OT_ERROR_NONE, error = OT_ERROR_DROP); - - // skip mesh header - aFrame += meshHeader.GetHeaderLength(); - aFrameLength -= meshHeader.GetHeaderLength(); - - // skip fragment header - if (aFrameLength >= 1 && reinterpret_cast(aFrame)->IsFragmentHeader()) - { - VerifyOrExit(sizeof(Lowpan::FragmentHeader) <= aFrameLength, error = OT_ERROR_DROP); - VerifyOrExit(reinterpret_cast(aFrame)->GetDatagramOffset() == 0); - - aFrame += reinterpret_cast(aFrame)->GetHeaderLength(); - aFrameLength -= reinterpret_cast(aFrame)->GetHeaderLength(); - } - - // only process IPv6 packets - VerifyOrExit(aFrameLength >= 1 && Lowpan::Lowpan::IsLowpanHc(aFrame)); - - VerifyOrExit(netif.GetLowpan().DecompressBaseHeader(ip6Header, nextHeaderCompressed, aMeshSource, aMeshDest, aFrame, - aFrameLength) > 0, - error = OT_ERROR_DROP); + ThreadNetif &netif = GetNetif(); + otError error = OT_ERROR_NONE; + Ip6::Header ip6Header; + SuccessOrExit(error = GetIp6Header(aFrame, aFrameLength, aMeshSource, aMeshDest, ip6Header)); error = netif.GetMle().CheckReachability(aMeshSource.GetShort(), aMeshDest.GetShort(), ip6Header); exit: + // the message may not contain an IPv6 header + if (error == OT_ERROR_NOT_FOUND) + { + error = OT_ERROR_NONE; + } + else if (error != OT_ERROR_NONE) + { + error = OT_ERROR_DROP; + } + return error; } @@ -955,32 +954,9 @@ void MeshForwarder::UpdateRoutes(uint8_t * aFrame, ThreadNetif &netif = GetNetif(); Ip6::Header ip6Header; Neighbor * neighbor; - bool nextHeaderCompressed; VerifyOrExit(!aMeshDest.IsBroadcast() && aMeshSource.IsShort()); - - // skip mesh header - if (aFrameLength >= 1 && reinterpret_cast(aFrame)->IsMeshHeader()) - { - aFrame += reinterpret_cast(aFrame)->GetHeaderLength(); - aFrameLength -= reinterpret_cast(aFrame)->GetHeaderLength(); - } - - // skip fragment header - if (aFrameLength >= 1 && reinterpret_cast(aFrame)->IsFragmentHeader()) - { - VerifyOrExit(sizeof(Lowpan::FragmentHeader) <= aFrameLength); - VerifyOrExit(reinterpret_cast(aFrame)->GetDatagramOffset() == 0); - - aFrame += reinterpret_cast(aFrame)->GetHeaderLength(); - aFrameLength -= reinterpret_cast(aFrame)->GetHeaderLength(); - } - - // only process IPv6 packets - VerifyOrExit(aFrameLength >= 1 && Lowpan::Lowpan::IsLowpanHc(aFrame)); - - VerifyOrExit(netif.GetLowpan().DecompressBaseHeader(ip6Header, nextHeaderCompressed, aMeshSource, aMeshDest, aFrame, - aFrameLength) > 0); + SuccessOrExit(GetIp6Header(aFrame, aFrameLength, aMeshSource, aMeshDest, ip6Header)); netif.GetAddressResolver().UpdateCacheEntry(ip6Header.GetSource(), aMeshSource.GetShort());