diff --git a/src/core/thread/lowpan.cpp b/src/core/thread/lowpan.cpp index 67d0570eb..6a780d811 100644 --- a/src/core/thread/lowpan.cpp +++ b/src/core/thread/lowpan.cpp @@ -54,9 +54,22 @@ Lowpan::Lowpan(Instance &aInstance) { } -void Lowpan::CopyContext(const Context &aContext, Ip6::Address &aAddress) +void Lowpan::FindContextForId(uint8_t aContextId, Context &aContext) const { - aAddress.SetPrefix(aContext.mPrefix); + if (Get().GetContext(aContextId, aContext) != kErrorNone) + { + aContext.Clear(); + } +} + +void Lowpan::FindContextToCompressAddress(const Ip6::Address &aIp6Address, Context &aContext) const +{ + Error error = Get().GetContext(aIp6Address, aContext); + + if ((error != kErrorNone) || !aContext.mCompressFlag) + { + aContext.Clear(); + } } Error Lowpan::ComputeIid(const Mac::Address &aMacAddr, const Context &aContext, Ip6::Address &aIpAddress) @@ -197,9 +210,10 @@ Error Lowpan::CompressMulticast(const Ip6::Address &aIpAddr, uint16_t &aHcCtl, F } else { - // Check if multicast address can be compressed using Context ID 0. - if (Get().GetContext(0, multicastContext) == kErrorNone && - multicastContext.mPrefix.GetLength() == aIpAddr.mFields.m8[3] && + // Check if multicast address can be compressed using Context ID 0 (mesh local prefix) + FindContextForId(0, multicastContext); + + if (multicastContext.mPrefix.GetLength() == aIpAddr.mFields.m8[3] && memcmp(multicastContext.mPrefix.GetBytes(), aIpAddr.mFields.m8 + 4, 8) == 0) { aHcCtl |= kHcDstAddrContext | kHcDstAddrMode0; @@ -253,38 +267,23 @@ Error Lowpan::Compress(Message & aMessage, FrameBuilder & aFrameBuilder, uint8_t & aHeaderDepth) { - Error error = kErrorNone; - NetworkData::Leader &networkData = Get(); - uint16_t startOffset = aMessage.GetOffset(); - uint16_t hcCtl = kHcDispatch; - uint16_t hcCtlOffset = 0; - Ip6::Header ip6Header; - uint8_t * ip6HeaderBytes = reinterpret_cast(&ip6Header); - Context srcContext, dstContext; - bool srcContextValid, dstContextValid; - uint8_t nextHeader; - uint8_t ecn; - uint8_t dscp; - uint8_t headerDepth = 0; - uint8_t headerMaxDepth = aHeaderDepth; + Error error = kErrorNone; + uint16_t startOffset = aMessage.GetOffset(); + uint16_t hcCtl = kHcDispatch; + uint16_t hcCtlOffset = 0; + Ip6::Header ip6Header; + uint8_t * ip6HeaderBytes = reinterpret_cast(&ip6Header); + Context srcContext, dstContext; + uint8_t nextHeader; + uint8_t ecn; + uint8_t dscp; + uint8_t headerDepth = 0; + uint8_t headerMaxDepth = aHeaderDepth; SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), ip6Header)); - srcContextValid = - (networkData.GetContext(ip6Header.GetSource(), srcContext) == kErrorNone && srcContext.mCompressFlag); - - if (!srcContextValid) - { - IgnoreError(networkData.GetContext(0, srcContext)); - } - - dstContextValid = - (networkData.GetContext(ip6Header.GetDestination(), dstContext) == kErrorNone && dstContext.mCompressFlag); - - if (!dstContextValid) - { - IgnoreError(networkData.GetContext(0, dstContext)); - } + FindContextToCompressAddress(ip6Header.GetSource(), srcContext); + FindContextToCompressAddress(ip6Header.GetDestination(), dstContext); // Lowpan HC Control Bits hcCtlOffset = aFrameBuilder.GetLength(); @@ -379,7 +378,7 @@ Error Lowpan::Compress(Message & aMessage, { SuccessOrExit(error = CompressSourceIid(aMacSource, ip6Header.GetSource(), srcContext, hcCtl, aFrameBuilder)); } - else if (srcContextValid) + else if (srcContext.mIsValid) { hcCtl |= kHcSrcAddrContext; SuccessOrExit(error = CompressSourceIid(aMacSource, ip6Header.GetSource(), srcContext, hcCtl, aFrameBuilder)); @@ -399,7 +398,7 @@ Error Lowpan::Compress(Message & aMessage, SuccessOrExit( error = CompressDestinationIid(aMacDest, ip6Header.GetDestination(), dstContext, hcCtl, aFrameBuilder)); } - else if (dstContextValid) + else if (dstContext.mIsValid) { hcCtl |= kHcDstAddrContext; SuccessOrExit( @@ -641,13 +640,14 @@ Error Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header, const Mac::Address &aMacDest, FrameData & aFrameData) { - NetworkData::Leader &networkData = Get(); - Error error = kErrorParse; - uint16_t hcCtl; - uint8_t byte; - Context srcContext, dstContext; - bool srcContextValid = true, dstContextValid = true; - uint8_t nextHeader; + Error error = kErrorParse; + uint16_t hcCtl; + uint8_t byte; + uint8_t srcContextId = 0; + uint8_t dstContextId = 0; + Context srcContext; + Context dstContext; + uint8_t nextHeader; SuccessOrExit(aFrameData.ReadBigEndianUint16(hcCtl)); @@ -655,28 +655,16 @@ Error Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header, VerifyOrExit((hcCtl & kHcDispatchMask) == kHcDispatch); // Context Identifier - srcContext.mPrefix.SetLength(0); - dstContext.mPrefix.SetLength(0); - if ((hcCtl & kHcContextId) != 0) { SuccessOrExit(aFrameData.ReadUint8(byte)); - if (networkData.GetContext(byte >> 4, srcContext) != kErrorNone) - { - srcContextValid = false; - } + srcContextId = (byte >> 4); + dstContextId = (byte & 0xf); + } - if (networkData.GetContext(byte & 0xf, dstContext) != kErrorNone) - { - dstContextValid = false; - } - } - else - { - IgnoreError(networkData.GetContext(0, srcContext)); - IgnoreError(networkData.GetContext(0, dstContext)); - } + FindContextForId(srcContextId, srcContext); + FindContextForId(dstContextId, dstContext); aIp6Header.Clear(); aIp6Header.InitVersionTrafficClassFlow(); @@ -775,8 +763,8 @@ Error Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header, } else { - VerifyOrExit(srcContextValid); - CopyContext(srcContext, aIp6Header.GetSource()); + VerifyOrExit(srcContext.mIsValid); + aIp6Header.GetSource().SetPrefix(srcContext.mPrefix); } } @@ -815,8 +803,8 @@ Error Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header, } else { - VerifyOrExit(dstContextValid); - CopyContext(dstContext, aIp6Header.GetDestination()); + VerifyOrExit(dstContext.mIsValid); + aIp6Header.GetDestination().SetPrefix(dstContext.mPrefix); } } else @@ -854,7 +842,7 @@ Error Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header, switch (hcCtl & kHcDstAddrModeMask) { case 0: - VerifyOrExit(dstContextValid); + VerifyOrExit(dstContext.mIsValid); SuccessOrExit(aFrameData.ReadBytes(aIp6Header.GetDestination().mFields.m8 + 1, 2)); aIp6Header.GetDestination().mFields.m8[3] = dstContext.mPrefix.GetLength(); memcpy(aIp6Header.GetDestination().mFields.m8 + 4, dstContext.mPrefix.GetBytes(), 8); diff --git a/src/core/thread/lowpan.hpp b/src/core/thread/lowpan.hpp index b49e225cb..3eec74dc8 100644 --- a/src/core/thread/lowpan.hpp +++ b/src/core/thread/lowpan.hpp @@ -36,6 +36,7 @@ #include "openthread-core-config.h" +#include "common/clearable.hpp" #include "common/debug.hpp" #include "common/frame_builder.hpp" #include "common/frame_data.hpp" @@ -73,11 +74,12 @@ using ot::Encoding::BigEndian::HostSwap16; * This structure represents a LOWPAN_IPHC Context. * */ -struct Context +struct Context : public Clearable { Ip6::Prefix mPrefix; ///< The Prefix uint8_t mContextId; ///< The Context ID. bool mCompressFlag; ///< The Context compression flag. + bool mIsValid; ///< Indicates whether the context is valid. }; /** @@ -268,6 +270,8 @@ private: static constexpr uint8_t kUdpChecksum = 1 << 2; static constexpr uint8_t kUdpPortMask = 3 << 0; + void FindContextForId(uint8_t aContextId, Context &aContext) const; + void FindContextToCompressAddress(const Ip6::Address &aIp6Address, Context &aContext) const; Error Compress(Message & aMessage, const Mac::Address &aMacSource, const Mac::Address &aMacDest, @@ -292,7 +296,6 @@ private: Error DecompressUdpHeader(Message &aMessage, FrameData &aFrameData, uint16_t aDatagramLength); Error DispatchToNextHeader(uint8_t aDispatch, uint8_t &aNextHeader); - static void CopyContext(const Context &aContext, Ip6::Address &aAddress); static Error ComputeIid(const Mac::Address &aMacAddr, const Context &aContext, Ip6::Address &aIpAddress); }; diff --git a/src/core/thread/network_data_leader.cpp b/src/core/thread/network_data_leader.cpp index 0207c390f..19e57450c 100644 --- a/src/core/thread/network_data_leader.cpp +++ b/src/core/thread/network_data_leader.cpp @@ -137,9 +137,7 @@ Error LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aCon if (Get().IsMeshLocalAddress(aAddress)) { - aContext.mPrefix.Set(Get().GetMeshLocalPrefix()); - aContext.mContextId = Mle::kMeshLocalPrefixContextId; - aContext.mCompressFlag = true; + GetContextForMeshLocalPrefix(aContext); } while ((prefix = FindNextMatchingPrefix(aAddress, prefix)) != nullptr) @@ -156,6 +154,7 @@ Error LeaderBase::GetContext(const Ip6::Address &aAddress, Lowpan::Context &aCon aContext.mPrefix.Set(prefix->GetPrefix(), prefix->GetPrefixLength()); aContext.mContextId = contextTlv->GetContextId(); aContext.mCompressFlag = contextTlv->IsCompress(); + aContext.mIsValid = true; } } @@ -170,9 +169,7 @@ Error LeaderBase::GetContext(uint8_t aContextId, Lowpan::Context &aContext) cons if (aContextId == Mle::kMeshLocalPrefixContextId) { - aContext.mPrefix.Set(Get().GetMeshLocalPrefix()); - aContext.mContextId = Mle::kMeshLocalPrefixContextId; - aContext.mCompressFlag = true; + GetContextForMeshLocalPrefix(aContext); ExitNow(error = kErrorNone); } @@ -188,6 +185,7 @@ Error LeaderBase::GetContext(uint8_t aContextId, Lowpan::Context &aContext) cons aContext.mPrefix.Set(prefix->GetPrefix(), prefix->GetPrefixLength()); aContext.mContextId = contextTlv->GetContextId(); aContext.mCompressFlag = contextTlv->IsCompress(); + aContext.mIsValid = true; ExitNow(error = kErrorNone); } @@ -195,6 +193,14 @@ exit: return error; } +void LeaderBase::GetContextForMeshLocalPrefix(Lowpan::Context &aContext) const +{ + aContext.mPrefix.Set(Get().GetMeshLocalPrefix()); + aContext.mContextId = Mle::kMeshLocalPrefixContextId; + aContext.mCompressFlag = true; + aContext.mIsValid = true; +} + bool LeaderBase::IsOnMesh(const Ip6::Address &aAddress) const { const PrefixTlv *prefix = nullptr; diff --git a/src/core/thread/network_data_leader.hpp b/src/core/thread/network_data_leader.hpp index 54765ef73..556112f36 100644 --- a/src/core/thread/network_data_leader.hpp +++ b/src/core/thread/network_data_leader.hpp @@ -298,6 +298,7 @@ private: uint16_t * aRloc16) const; Error DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t *aRloc16) const; Error SteeringDataCheck(const FilterIndexes &aFilterIndexes) const; + void GetContextForMeshLocalPrefix(Lowpan::Context &aContext) const; uint8_t mTlvBuffer[kMaxSize]; };