Skip to content

Commit

Permalink
[mesh-forwarder] add logs for forwarded MeshHeader messages (#2783)
Browse files Browse the repository at this point in the history
This commit adds a new method `MeshForwarder::LogMeshMessage()` to log
info about messages with `MeshHeader` (messages that are forwarded by
device). The new logs indicate  when a message is received/sent or
possibly dropped. The immediate source and destination for the
received or sent frame is logged. The new logs include info from
`MeshHeader` such as mesh source, mesh destination, number of hops
left. If the message is fragmented, info from fragment header such as
datagram tag and offset is included in the logs. For a non-fragmented
or a  first fragment, `LogMeshMessage()` will also decompress the IPv6
and transport (UDP/TCP) headers and provide info from them such as
IPv6 source/destination addresses, UDP/TCP checksum, source/destination
port numbers.

In addition to the new logs, this commit add the following changes:
- Adds `\t` to log lines which are grouped (make it easier to read).
- Adds `const` qualifiers to some methods in `Lowpan::MeshHeader`.
- Adds new method in `FragmentHeader` to init it from a `Message`.
- Refactors/updates some methods in `Lowpan` class (e.g., adding new
  public method to decompress LOWPAN_NHC UDP header).
  • Loading branch information
abtink authored and jwhui committed Jun 19, 2018
1 parent 403723d commit 9e2d718
Show file tree
Hide file tree
Showing 5 changed files with 449 additions and 110 deletions.
83 changes: 63 additions & 20 deletions src/core/thread/lowpan.cpp
Expand Up @@ -598,6 +598,7 @@ otError Lowpan::DispatchToNextHeader(uint8_t aDispatch, Ip6::IpProto &aNextHeade
}

int Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header,
bool & aCompressedNextHeader,
const Mac::Address &aMacSource,
const Mac::Address &aMacDest,
const uint8_t * aBuf,
Expand Down Expand Up @@ -685,6 +686,11 @@ int Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header,
aIp6Header.SetNextHeader(static_cast<Ip6::IpProto>(cur[0]));
cur++;
remaining--;
aCompressedNextHeader = false;
}
else
{
aCompressedNextHeader = true;
}

// Hop Limit
Expand Down Expand Up @@ -963,52 +969,53 @@ int Lowpan::DecompressExtensionHeader(Message &aMessage, const uint8_t *aBuf, ui
return (error == OT_ERROR_NONE) ? static_cast<int>(cur - aBuf) : -1;
}

int Lowpan::DecompressUdpHeader(Message &aMessage, const uint8_t *aBuf, uint16_t aBufLength, uint16_t aDatagramLength)
int Lowpan::DecompressUdpHeader(Ip6::UdpHeader &aUdpHeader, const uint8_t *aBuf, uint16_t aBufLength)
{
otError error = OT_ERROR_PARSE;
const uint8_t *cur = aBuf;
uint16_t remaining = aBufLength;
Ip6::UdpHeader udpHeader;
uint8_t udpCtl;

VerifyOrExit(remaining >= 1);
udpCtl = cur[0];
cur++;
remaining--;

memset(&udpHeader, 0, sizeof(udpHeader));
VerifyOrExit((udpCtl & kUdpDispatchMask) == kUdpDispatch);

memset(&aUdpHeader, 0, sizeof(aUdpHeader));

// source and dest ports
switch (udpCtl & kUdpPortMask)
{
case 0:
VerifyOrExit(remaining >= 4);
udpHeader.SetSourcePort(ReadUint16(cur));
udpHeader.SetDestinationPort(ReadUint16(cur + 2));
aUdpHeader.SetSourcePort(ReadUint16(cur));
aUdpHeader.SetDestinationPort(ReadUint16(cur + 2));
cur += 4;
remaining -= 4;
break;

case 1:
VerifyOrExit(remaining >= 3);
udpHeader.SetSourcePort(ReadUint16(cur));
udpHeader.SetDestinationPort(0xf000 | cur[2]);
aUdpHeader.SetSourcePort(ReadUint16(cur));
aUdpHeader.SetDestinationPort(0xf000 | cur[2]);
cur += 3;
remaining -= 3;
break;

case 2:
VerifyOrExit(remaining >= 3);
udpHeader.SetSourcePort(0xf000 | cur[0]);
udpHeader.SetDestinationPort(ReadUint16(cur + 1));
aUdpHeader.SetSourcePort(0xf000 | cur[0]);
aUdpHeader.SetDestinationPort(ReadUint16(cur + 1));
cur += 3;
remaining -= 3;
break;

case 3:
VerifyOrExit(remaining >= 1);
udpHeader.SetSourcePort(0xf0b0 | (cur[0] >> 4));
udpHeader.SetDestinationPort(0xf0b0 | (cur[0] & 0xf));
aUdpHeader.SetSourcePort(0xf0b0 | (cur[0] >> 4));
aUdpHeader.SetDestinationPort(0xf0b0 | (cur[0] & 0xf));
cur += 1;
remaining -= 1;
break;
Expand All @@ -1022,27 +1029,39 @@ int Lowpan::DecompressUdpHeader(Message &aMessage, const uint8_t *aBuf, uint16_t
else
{
VerifyOrExit(remaining >= 2);
udpHeader.SetChecksum(ReadUint16(cur));
aUdpHeader.SetChecksum(ReadUint16(cur));
cur += 2;
}

error = OT_ERROR_NONE;

exit:
return (error == OT_ERROR_NONE) ? static_cast<int>(cur - aBuf) : -1;
}

int Lowpan::DecompressUdpHeader(Message &aMessage, const uint8_t *aBuf, uint16_t aBufLength, uint16_t aDatagramLength)
{
Ip6::UdpHeader udpHeader;
int headerLen = -1;

headerLen = DecompressUdpHeader(udpHeader, aBuf, aBufLength);
VerifyOrExit(headerLen >= 0);

// length
if (aDatagramLength == 0)
{
udpHeader.SetLength(sizeof(udpHeader) + static_cast<uint16_t>(aBufLength - (cur - aBuf)));
udpHeader.SetLength(sizeof(udpHeader) + static_cast<uint16_t>(aBufLength - headerLen));
}
else
{
udpHeader.SetLength(aDatagramLength - aMessage.GetOffset());
}

SuccessOrExit(aMessage.Append(&udpHeader, sizeof(udpHeader)));
VerifyOrExit(aMessage.Append(&udpHeader, sizeof(udpHeader)) == OT_ERROR_NONE, headerLen = -1);
aMessage.MoveOffset(sizeof(udpHeader));

error = OT_ERROR_NONE;

exit:
return (error == OT_ERROR_NONE) ? static_cast<int>(cur - aBuf) : -1;
return headerLen;
}

int Lowpan::Decompress(Message & aMessage,
Expand All @@ -1063,9 +1082,7 @@ int Lowpan::Decompress(Message & aMessage,
uint16_t currentOffset = aMessage.GetOffset();

VerifyOrExit(remaining >= 2);
compressed = ((ReadUint16(cur) & kHcNextHeader) != 0);

VerifyOrExit((rval = DecompressBaseHeader(ip6Header, aMacSource, aMacDest, cur, remaining)) >= 0);
VerifyOrExit((rval = DecompressBaseHeader(ip6Header, compressed, aMacSource, aMacDest, cur, remaining)) >= 0);

cur += rval;
remaining -= rval;
Expand Down Expand Up @@ -1204,5 +1221,31 @@ otError FragmentHeader::Init(const uint8_t *aFrame, uint8_t aFrameLength)
return error;
}

otError FragmentHeader::Init(const Message &aMessage, uint16_t aOffset)
{
otError error = OT_ERROR_NONE;
uint16_t bytesRead;

bytesRead = aMessage.Read(aOffset, sizeof(mDispatchSize), &mDispatchSize);
VerifyOrExit(bytesRead == sizeof(mDispatchSize), error = OT_ERROR_PARSE);
aOffset += bytesRead;

VerifyOrExit(IsFragmentHeader(), error = OT_ERROR_PARSE);

bytesRead = aMessage.Read(aOffset, sizeof(mTag), &mTag);
VerifyOrExit(bytesRead == sizeof(mTag), error = OT_ERROR_PARSE);
aOffset += bytesRead;

if (IsOffsetPresent())
{
bytesRead = aMessage.Read(aOffset, sizeof(mOffset), &mOffset);
VerifyOrExit(bytesRead == sizeof(mOffset), error = OT_ERROR_PARSE);
aOffset += bytesRead;
}

exit:
return error;
}

} // namespace Lowpan
} // namespace ot
57 changes: 43 additions & 14 deletions src/core/thread/lowpan.hpp
Expand Up @@ -138,21 +138,35 @@ class Lowpan : public InstanceLocator
/**
* This method decompresses a LOWPAN_IPHC header.
*
* @param[out] aHeader A reference where the IPv6 header will be placed.
* @param[in] aMacSource The MAC source address.
* @param[in] aMacDest The MAC destination address.
* @param[in] aBuf A pointer to the LOWPAN_IPHC header.
* @param[in] aBufLength The number of bytes in @p aBuf.
* @param[out] aHeader A reference where the IPv6 header will be placed.
* @param[out] aCommpressedNextHeader A boolean reference to output whether next header is compressed or not.
* @param[in] aMacSource The MAC source address.
* @param[in] aMacDest The MAC destination address.
* @param[in] aBuf A pointer to the LOWPAN_IPHC header.
* @param[in] aBufLength The number of bytes in @p aBuf.
*
* @returns The size of the compressed header in bytes.
* @returns The size of the compressed header in bytes or -1 if decompression fails.
*
*/
int DecompressBaseHeader(Ip6::Header & aHeader,
bool & aCompressedNextHeader,
const Mac::Address &aMacSource,
const Mac::Address &aMacDest,
const uint8_t * aBuf,
uint16_t aBufLength);

/**
* This method decompresses a LOWPAN_NHC UDP header.
*
* @param[out] aUdpHeader A reference where the UDP header will be placed.
* @param[in] aBuf A pointer to the LOWPAN_NHC header.
* @param[in] aBufLength The number of bytes in @p aBuf.
*
* @returns The size of the compressed header in bytes or -1 if decompression fails.
*
*/
int DecompressUdpHeader(Ip6::UdpHeader &aUdpHeader, const uint8_t *aBuf, uint16_t aBufLength);

private:
enum
{
Expand Down Expand Up @@ -279,7 +293,7 @@ class MeshHeader
* @retval FALSE If the header does not match the Mesh Header dispatch value.
*
*/
bool IsMeshHeader(void) { return (mDispatchHopsLeft & kDispatchMask) == kDispatch; }
bool IsMeshHeader(void) const { return (mDispatchHopsLeft & kDispatchMask) == kDispatch; }

/**
* This method indicates whether or not the Mesh Header appears to be well-formed.
Expand All @@ -288,7 +302,7 @@ class MeshHeader
* @retval FALSE If the header does not appear to be well-formed.
*
*/
bool IsValid(void) { return (mDispatchHopsLeft & kSourceShort) && (mDispatchHopsLeft & kDestinationShort); }
bool IsValid(void) const { return (mDispatchHopsLeft & kSourceShort) && (mDispatchHopsLeft & kDestinationShort); }

/**
* This method indicates whether or not the header contains Deep Hops Left field.
Expand All @@ -297,23 +311,26 @@ class MeshHeader
* @retval FALSE If the header does not contain Deep Hops Left field.
*
*/
bool IsDeepHopsLeftField(void) { return (mDispatchHopsLeft & kHopsLeftMask) == kDeepHopsLeft; }
bool IsDeepHopsLeftField(void) const { 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.
*
*/
uint8_t GetHeaderLength(void) { return sizeof(*this) - (IsDeepHopsLeftField() ? 0 : sizeof(mDeepHopsLeft)); }
uint8_t GetHeaderLength(void) const { return sizeof(*this) - (IsDeepHopsLeftField() ? 0 : sizeof(mDeepHopsLeft)); }

/**
* This method returns the Hops Left value.
*
* @returns The Hops Left value.
*
*/
uint8_t GetHopsLeft(void) { return IsDeepHopsLeftField() ? mDeepHopsLeft : mDispatchHopsLeft & kHopsLeftMask; }
uint8_t GetHopsLeft(void) const
{
return IsDeepHopsLeftField() ? mDeepHopsLeft : mDispatchHopsLeft & kHopsLeftMask;
}

/**
* This method sets the Hops Left value.
Expand All @@ -340,7 +357,7 @@ class MeshHeader
* @returns The Mesh Source address.
*
*/
uint16_t GetSource(void) { return HostSwap16(mAddress.mSource); }
uint16_t GetSource(void) const { return HostSwap16(mAddress.mSource); }

/**
* This method sets the Mesh Source address.
Expand All @@ -356,7 +373,7 @@ class MeshHeader
* @returns The Mesh Destination address.
*
*/
uint16_t GetDestination(void) { return HostSwap16(mAddress.mDestination); }
uint16_t GetDestination(void) const { return HostSwap16(mAddress.mDestination); }

/**
* This method sets the Mesh Destination address.
Expand All @@ -372,7 +389,7 @@ class MeshHeader
* @param[in] aFrame The pointer to the frame.
*
*/
void AppendTo(uint8_t *aFrame)
void AppendTo(uint8_t *aFrame) const
{
*aFrame++ = mDispatchHopsLeft;

Expand Down Expand Up @@ -441,6 +458,18 @@ class FragmentHeader
*/
otError Init(const uint8_t *aFrame, uint8_t aFrameLength);

/**
* This method initializes the fragment header from a message @p aMessage.
*
* @param[in] aMessage The message object.
* @param[in] aOffset An offset into the message to read the header.
*
* @retval OT_ERROR_NONE Fragment Header initialized successfully.
* @retval OT_ERROR_PARSE Fragment header could not be initialized (e.g., no frag header or message too short).
*
*/
otError Init(const Message &aMessage, uint16_t aOffset);

/**
* This method indicates whether or not the header is a Fragment Header.
*
Expand Down

0 comments on commit 9e2d718

Please sign in to comment.