[mesh-forwarder] add function to decompress IPv6 Header (#3014)

This commit is contained in:
Zhanglong Xia
2018-09-06 07:28:08 -10:00
committed by Jonathan Hui
parent 5d993e9868
commit b83fa59914
4 changed files with 96 additions and 54 deletions
+2 -2
View File
@@ -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.
+53
View File
@@ -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<const Lowpan::MeshHeader *>(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<const Lowpan::FragmentHeader *>(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<uint8_t>(aFrame - start) + static_cast<uint8_t>(headerLength);
exit:
return error;
}
otError MeshForwarder::HandleFrameRequest(Mac::Sender &aSender, Mac::Frame &aFrame)
{
return aSender.GetOwner<MeshForwarder>().HandleFrameRequest(aFrame);
+13
View File
@@ -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);
+28 -52
View File
@@ -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<Lowpan::FragmentHeader *>(aFrame)->IsFragmentHeader())
{
VerifyOrExit(sizeof(Lowpan::FragmentHeader) <= aFrameLength, error = OT_ERROR_DROP);
VerifyOrExit(reinterpret_cast<Lowpan::FragmentHeader *>(aFrame)->GetDatagramOffset() == 0);
aFrame += reinterpret_cast<Lowpan::FragmentHeader *>(aFrame)->GetHeaderLength();
aFrameLength -= reinterpret_cast<Lowpan::FragmentHeader *>(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<Lowpan::MeshHeader *>(aFrame)->IsMeshHeader())
{
aFrame += reinterpret_cast<Lowpan::MeshHeader *>(aFrame)->GetHeaderLength();
aFrameLength -= reinterpret_cast<Lowpan::MeshHeader *>(aFrame)->GetHeaderLength();
}
// skip fragment header
if (aFrameLength >= 1 && reinterpret_cast<Lowpan::FragmentHeader *>(aFrame)->IsFragmentHeader())
{
VerifyOrExit(sizeof(Lowpan::FragmentHeader) <= aFrameLength);
VerifyOrExit(reinterpret_cast<Lowpan::FragmentHeader *>(aFrame)->GetDatagramOffset() == 0);
aFrame += reinterpret_cast<Lowpan::FragmentHeader *>(aFrame)->GetHeaderLength();
aFrameLength -= reinterpret_cast<Lowpan::FragmentHeader *>(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());