[mesh-forwarder] add logs for forwarded MeshHeader messages (#2783)

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).
This commit is contained in:
Abtin Keshavarzian
2018-06-19 12:22:29 -07:00
committed by Jonathan Hui
parent 403723dc82
commit 9e2d7181ae
5 changed files with 450 additions and 111 deletions
+63 -20
View File
@@ -598,6 +598,7 @@ exit:
}
int Lowpan::DecompressBaseHeader(Ip6::Header & aIp6Header,
bool & aCompressedNextHeader,
const Mac::Address &aMacSource,
const Mac::Address &aMacDest,
const uint8_t * aBuf,
@@ -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
@@ -963,12 +969,11 @@ 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)
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);
@@ -976,39 +981,41 @@ int Lowpan::DecompressUdpHeader(Message &aMessage, const uint8_t *aBuf, uint16_t
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;
@@ -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,
@@ -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;
@@ -1204,5 +1221,31 @@ exit:
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
+43 -14
View File
@@ -138,21 +138,35 @@ public:
/**
* 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
{
@@ -279,7 +293,7 @@ public:
* @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.
@@ -288,7 +302,7 @@ public:
* @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.
@@ -297,7 +311,7 @@ public:
* @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.
@@ -305,7 +319,7 @@ public:
* @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.
@@ -313,7 +327,10 @@ public:
* @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.
@@ -340,7 +357,7 @@ public:
* @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.
@@ -356,7 +373,7 @@ public:
* @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.
@@ -372,7 +389,7 @@ public:
* @param[in] aFrame The pointer to the frame.
*
*/
void AppendTo(uint8_t *aFrame)
void AppendTo(uint8_t *aFrame) const
{
*aFrame++ = mDispatchHopsLeft;
@@ -441,6 +458,18 @@ public:
*/
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.
*
+297 -71
View File
@@ -157,7 +157,7 @@ void MeshForwarder::RemoveMessage(Message &aMessage)
}
mSendQueue.Dequeue(aMessage);
LogIp6Message(kMessageEvict, aMessage, NULL, OT_ERROR_NO_BUFS);
LogMessage(kMessageEvict, aMessage, NULL, OT_ERROR_NO_BUFS);
aMessage.Free();
}
@@ -284,7 +284,7 @@ Message *MeshForwarder::GetDirectTransmission(void)
case OT_ERROR_DROP:
case OT_ERROR_NO_BUFS:
mSendQueue.Dequeue(*curMessage);
LogIp6Message(kMessageDrop, *curMessage, NULL, error);
LogMessage(kMessageDrop, *curMessage, NULL, error);
curMessage->Free();
continue;
@@ -1001,7 +1001,7 @@ void MeshForwarder::HandleSentFrame(Mac::Frame &aFrame, otError aError)
if (mMessageNextOffset >= mSendMessage->GetLength())
{
LogIp6Message(kMessageTransmit, *mSendMessage, &macDest, aError);
LogMessage(kMessageTransmit, *mSendMessage, &macDest, aError);
if (aError == OT_ERROR_NONE)
{
@@ -1309,7 +1309,7 @@ void MeshForwarder::ClearReassemblyList(void)
next = message->GetNext();
mReassemblyList.Dequeue(*message);
LogIp6Message(kMessageReassemblyDrop, *message, NULL, OT_ERROR_NO_FRAME_RECEIVED);
LogMessage(kMessageReassemblyDrop, *message, NULL, OT_ERROR_NO_FRAME_RECEIVED);
mIpCounters.mRxFailure++;
message->Free();
@@ -1339,7 +1339,7 @@ void MeshForwarder::HandleReassemblyTimer(void)
{
mReassemblyList.Dequeue(*message);
LogIp6Message(kMessageReassemblyDrop, *message, NULL, OT_ERROR_REASSEMBLY_TIMEOUT);
LogMessage(kMessageReassemblyDrop, *message, NULL, OT_ERROR_REASSEMBLY_TIMEOUT);
mIpCounters.mRxFailure++;
message->Free();
@@ -1408,7 +1408,7 @@ otError MeshForwarder::HandleDatagram(Message & aMessage,
{
ThreadNetif &netif = GetNetif();
LogIp6Message(kMessageReceive, aMessage, &aMacSource, OT_ERROR_NONE);
LogMessage(kMessageReceive, aMessage, &aMacSource, OT_ERROR_NONE);
mIpCounters.mRxSuccess++;
return netif.GetIp6().HandleDatagram(aMessage, &netif, netif.GetInterfaceId(), &aLinkInfo, false);
@@ -1421,78 +1421,68 @@ void MeshForwarder::HandleDataPollTimeout(Mac::Receiver &aReceiver)
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
void MeshForwarder::LogIp6Message(MessageAction aAction,
const Message & aMessage,
const Mac::Address *aMacAddress,
otError aError)
otError MeshForwarder::ParseIp6UdpTcpHeader(const Message &aMessage,
Ip6::Header & aIp6Header,
uint16_t & aChecksum,
uint16_t & aSourcePort,
uint16_t & aDestPort)
{
uint16_t checksum = 0;
Ip6::Header ip6Header;
Ip6::IpProto protocol;
const char * actionText;
const char * priorityText;
bool shouldLogRss = false;
bool shouldLogSrcDstAddresses = (OPENTHREAD_CONFIG_LOG_SRC_DST_IP_ADDRESSES != 0);
otError error = OT_ERROR_PARSE;
union
{
Ip6::UdpHeader udp;
Ip6::TcpHeader tcp;
} header;
VerifyOrExit(aMessage.GetType() == Message::kTypeIp6);
aChecksum = 0;
aSourcePort = 0;
aDestPort = 0;
VerifyOrExit(sizeof(ip6Header) == aMessage.Read(0, sizeof(ip6Header), &ip6Header));
VerifyOrExit(ip6Header.IsVersion6());
VerifyOrExit(sizeof(Ip6::Header) == aMessage.Read(0, sizeof(Ip6::Header), &aIp6Header));
VerifyOrExit(aIp6Header.IsVersion6());
protocol = ip6Header.GetNextHeader();
switch (protocol)
switch (aIp6Header.GetNextHeader())
{
case Ip6::kProtoUdp:
{
Ip6::UdpHeader udpHeader;
if (sizeof(udpHeader) == aMessage.Read(sizeof(ip6Header), sizeof(udpHeader), &udpHeader))
{
checksum = udpHeader.GetChecksum();
}
VerifyOrExit(sizeof(Ip6::UdpHeader) == aMessage.Read(sizeof(Ip6::Header), sizeof(Ip6::UdpHeader), &header.udp));
aChecksum = header.udp.GetChecksum();
aSourcePort = header.udp.GetSourcePort();
aDestPort = header.udp.GetDestinationPort();
break;
}
case Ip6::kProtoTcp:
{
Ip6::TcpHeader tcpHeader;
if (sizeof(tcpHeader) == aMessage.Read(sizeof(ip6Header), sizeof(tcpHeader), &tcpHeader))
{
checksum = tcpHeader.GetChecksum();
}
VerifyOrExit(sizeof(Ip6::TcpHeader) == aMessage.Read(sizeof(Ip6::Header), sizeof(Ip6::TcpHeader), &header.tcp));
aChecksum = header.tcp.GetChecksum();
aSourcePort = header.tcp.GetSourcePort();
aDestPort = header.tcp.GetDestinationPort();
break;
}
default:
break;
}
error = OT_ERROR_NONE;
exit:
return error;
}
const char *MeshForwarder::MessageActionToString(MessageAction aAction, otError aError)
{
const char *actionText = "";
switch (aAction)
{
case kMessageReceive:
actionText = "Received";
shouldLogRss = true;
actionText = "Received";
break;
case kMessageTransmit:
if (aError == OT_ERROR_NONE)
{
actionText = "Sent";
}
else
{
actionText = "Failed to send";
}
actionText = (aError == OT_ERROR_NONE) ? "Sent" : "Failed to send";
break;
case kMessagePrepareIndirect:
actionText = "Prepping indir tx";
shouldLogSrcDstAddresses = false;
actionText = "Prepping indir tx";
break;
case kMessageDrop:
@@ -1500,19 +1490,21 @@ void MeshForwarder::LogIp6Message(MessageAction aAction,
break;
case kMessageReassemblyDrop:
actionText = "Dropping (reassembly queue)";
shouldLogRss = true;
actionText = "Dropping (reassembly queue)";
break;
case kMessageEvict:
actionText = "Evicting";
break;
default:
actionText = "";
break;
}
return actionText;
}
const char *MeshForwarder::MessagePriorityToString(const Message &aMessage)
{
const char *priorityText = "unknown";
switch (aMessage.GetPriority())
{
case Message::kPriorityHigh:
@@ -1530,30 +1522,264 @@ void MeshForwarder::LogIp6Message(MessageAction aAction,
case Message::kPriorityVeryLow:
priorityText = "verylow";
break;
default:
priorityText = "unknown";
break;
}
otLogInfoMac(GetInstance(), "%s IPv6 %s msg, len:%d, chksum:%04x%s%s, sec:%s%s%s, prio:%s%s%s", actionText,
Ip6::Ip6::IpProtoToString(protocol), aMessage.GetLength(), checksum,
return priorityText;
}
#if OPENTHREAD_CONFIG_LOG_SRC_DST_IP_ADDRESSES
void MeshForwarder::LogIp6SourceDestAddresses(Ip6::Header &aIp6Header, uint16_t aSourcePort, uint16_t aDestPort)
{
if (aSourcePort != 0)
{
otLogInfoMac(GetInstance(), "\tsrc:[%s]:%d", aIp6Header.GetSource().ToString().AsCString(), aSourcePort);
}
else
{
otLogInfoMac(GetInstance(), "\tsrc:[%s]", aIp6Header.GetSource().ToString().AsCString());
}
if (aDestPort != 0)
{
otLogInfoMac(GetInstance(), "\tdst:[%s]:%d", aIp6Header.GetDestination().ToString().AsCString(), aDestPort);
}
else
{
otLogInfoMac(GetInstance(), "\tdst:[%s]", aIp6Header.GetDestination().ToString().AsCString());
}
}
#else
void MeshForwarder::LogIp6SourceDestAddresses(Ip6::Header &, uint16_t, uint16_t)
{
}
#endif
void MeshForwarder::LogIp6Message(MessageAction aAction,
const Message & aMessage,
const Mac::Address *aMacAddress,
otError aError)
{
Ip6::Header ip6Header;
uint16_t checksum;
uint16_t sourcePort;
uint16_t destPort;
bool shouldLogRss;
SuccessOrExit(ParseIp6UdpTcpHeader(aMessage, ip6Header, checksum, sourcePort, destPort));
shouldLogRss = (aAction == kMessageReceive) || (aAction == kMessageReassemblyDrop);
otLogInfoMac(GetInstance(), "%s IPv6 %s msg, len:%d, chksum:%04x%s%s, sec:%s%s%s, prio:%s%s%s",
MessageActionToString(aAction, aError), Ip6::Ip6::IpProtoToString(ip6Header.GetNextHeader()),
aMessage.GetLength(), checksum,
(aMacAddress == NULL) ? "" : ((aAction == kMessageReceive) ? ", from:" : ", to:"),
(aMacAddress == NULL) ? "" : aMacAddress->ToString().AsCString(),
aMessage.IsLinkSecurityEnabled() ? "yes" : "no", (aError == OT_ERROR_NONE) ? "" : ", error:",
(aError == OT_ERROR_NONE) ? "" : otThreadErrorToString(aError), priorityText,
(aError == OT_ERROR_NONE) ? "" : otThreadErrorToString(aError), MessagePriorityToString(aMessage),
shouldLogRss ? ", rss:" : "", shouldLogRss ? aMessage.GetRssAverager().ToString().AsCString() : "");
if (shouldLogSrcDstAddresses)
if (aAction != kMessagePrepareIndirect)
{
otLogInfoMac(GetInstance(), "src: %s", ip6Header.GetSource().ToString().AsCString());
otLogInfoMac(GetInstance(), "dst: %s", ip6Header.GetDestination().ToString().AsCString());
LogIp6SourceDestAddresses(ip6Header, sourcePort, destPort);
}
exit:
return;
}
otError MeshForwarder::LogMeshFragmentHeader(MessageAction aAction,
const Message & aMessage,
const Mac::Address *aMacAddress,
otError aError,
uint16_t & aOffset,
Mac::Address & aMeshSource,
Mac::Address & aMeshDest)
{
otError error = OT_ERROR_FAILED;
bool hasFragmentHeader = false;
bool shouldLogRss;
Lowpan::MeshHeader meshHeader;
Lowpan::FragmentHeader fragmentHeader;
SuccessOrExit(meshHeader.Init(aMessage));
VerifyOrExit(meshHeader.IsMeshHeader());
aMeshSource.SetShort(meshHeader.GetSource());
aMeshDest.SetShort(meshHeader.GetDestination());
aOffset = meshHeader.GetHeaderLength();
if (fragmentHeader.Init(aMessage, aOffset) == OT_ERROR_NONE)
{
hasFragmentHeader = true;
aOffset += fragmentHeader.GetHeaderLength();
}
shouldLogRss = (aAction == kMessageReceive) || (aAction == kMessageReassemblyDrop);
otLogInfoMac(
GetInstance(), "%s mesh frame, len:%d%s%s, msrc:%s, mdst:%s, hops:%d, frag:%s, sec:%s%s%s%s%s",
MessageActionToString(aAction, aError), aMessage.GetLength(),
(aMacAddress == NULL) ? "" : ((aAction == kMessageReceive) ? ", from:" : ", to:"),
(aMacAddress == NULL) ? "" : aMacAddress->ToString().AsCString(), aMeshSource.ToString().AsCString(),
aMeshDest.ToString().AsCString(), meshHeader.GetHopsLeft() + ((aAction == kMessageReceive) ? 1 : 0),
hasFragmentHeader ? "yes" : "no", aMessage.IsLinkSecurityEnabled() ? "yes" : "no",
(aError == OT_ERROR_NONE) ? "" : ", error:", (aError == OT_ERROR_NONE) ? "" : otThreadErrorToString(aError),
shouldLogRss ? ", rss:" : "", shouldLogRss ? aMessage.GetRssAverager().ToString().AsCString() : "");
if (hasFragmentHeader)
{
otLogInfoMac(GetInstance(), "\tFrag tag:%04x, offset:%d, size:%d", fragmentHeader.GetDatagramTag(),
fragmentHeader.GetDatagramOffset(), fragmentHeader.GetDatagramSize());
VerifyOrExit(fragmentHeader.GetDatagramOffset() == 0);
}
error = OT_ERROR_NONE;
exit:
return error;
}
otError MeshForwarder::DecompressIp6UdpTcpHeader(const Message & aMessage,
uint16_t aOffset,
const Mac::Address &aMeshSource,
const Mac::Address &aMeshDest,
Ip6::Header & aIp6Header,
uint16_t & aChecksum,
uint16_t & aSourcePort,
uint16_t & aDestPort)
{
otError error = OT_ERROR_PARSE;
Lowpan::Lowpan &lowpan = GetNetif().GetLowpan();
int headerLength;
bool nextHeaderCompressed;
uint8_t frameBuffer[sizeof(Ip6::Header)];
uint16_t frameLength;
union
{
Ip6::UdpHeader udp;
Ip6::TcpHeader tcp;
} header;
aChecksum = 0;
aSourcePort = 0;
aDestPort = 0;
// Read and decompress the IPv6 header
frameLength = aMessage.Read(aOffset, sizeof(frameBuffer), frameBuffer);
headerLength =
lowpan.DecompressBaseHeader(aIp6Header, nextHeaderCompressed, aMeshSource, aMeshDest, frameBuffer, frameLength);
VerifyOrExit(headerLength >= 0);
aOffset += headerLength;
// Read and decompress UDP or TCP header
switch (aIp6Header.GetNextHeader())
{
case Ip6::kProtoUdp:
if (nextHeaderCompressed)
{
frameLength = aMessage.Read(aOffset, sizeof(Ip6::UdpHeader), frameBuffer);
headerLength = lowpan.DecompressUdpHeader(header.udp, frameBuffer, frameLength);
VerifyOrExit(headerLength >= 0);
}
else
{
VerifyOrExit(sizeof(Ip6::UdpHeader) == aMessage.Read(aOffset, sizeof(Ip6::UdpHeader), &header.udp));
}
aChecksum = header.udp.GetChecksum();
aSourcePort = header.udp.GetSourcePort();
aDestPort = header.udp.GetDestinationPort();
break;
case Ip6::kProtoTcp:
VerifyOrExit(sizeof(Ip6::TcpHeader) == aMessage.Read(aOffset, sizeof(Ip6::TcpHeader), &header.tcp));
aChecksum = header.tcp.GetChecksum();
aSourcePort = header.tcp.GetSourcePort();
aDestPort = header.tcp.GetDestinationPort();
break;
default:
break;
}
error = OT_ERROR_NONE;
exit:
return error;
}
void MeshForwarder::LogMeshIpHeader(const Message & aMessage,
uint16_t aOffset,
const Mac::Address &aMeshSource,
const Mac::Address &aMeshDest)
{
uint16_t checksum;
uint16_t sourcePort;
uint16_t destPort;
Ip6::Header ip6Header;
SuccessOrExit(DecompressIp6UdpTcpHeader(aMessage, aOffset, aMeshSource, aMeshDest, ip6Header, checksum, sourcePort,
destPort));
otLogInfoMac(GetInstance(), "\tIPv6 %s msg, chksum:%04x, prio:%s",
Ip6::Ip6::IpProtoToString(ip6Header.GetNextHeader()), checksum, MessagePriorityToString(aMessage));
LogIp6SourceDestAddresses(ip6Header, sourcePort, destPort);
exit:
return;
}
void MeshForwarder::LogMeshMessage(MessageAction aAction,
const Message & aMessage,
const Mac::Address *aMacAddress,
otError aError)
{
uint16_t offset;
Mac::Address meshSource;
Mac::Address meshDest;
SuccessOrExit(LogMeshFragmentHeader(aAction, aMessage, aMacAddress, aError, offset, meshSource, meshDest));
// When log action is `kMessageTransmit` we do not include
// the IPv6 header info in the logs, as the same info is
// logged when the same Mesh Header message was received
// and info about it was logged.
VerifyOrExit(aAction != kMessageTransmit);
LogMeshIpHeader(aMessage, offset, meshSource, meshDest);
exit:
return;
}
void MeshForwarder::LogMessage(MessageAction aAction,
const Message & aMessage,
const Mac::Address *aMacAddress,
otError aError)
{
switch (aMessage.GetType())
{
case Message::kTypeIp6:
LogIp6Message(aAction, aMessage, aMacAddress, aError);
break;
case Message::kType6lowpan:
LogMeshMessage(aAction, aMessage, aMacAddress, aError);
break;
default:
break;
}
}
void MeshForwarder::LogFrame(const char *aActionText, const Mac::Frame &aFrame, otError aError)
{
if (aError != OT_ERROR_NONE)
@@ -1594,7 +1820,7 @@ void MeshForwarder::LogLowpanHcFrameDrop(otError aError,
#else // #if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
void MeshForwarder::LogIp6Message(MessageAction, const Message &, const Mac::Address *, otError)
void MeshForwarder::LogMessage(MessageAction, const Message &, const Mac::Address *, otError)
{
}
+35 -1
View File
@@ -326,7 +326,7 @@ private:
otError GetDestinationRlocByServiceAloc(uint16_t aServiceAloc, uint16_t &aMeshDest);
void LogIp6Message(MessageAction aAction, const Message &aMessage, const Mac::Address *aMacAddress, otError aError);
void LogMessage(MessageAction aAction, const Message &aMessage, const Mac::Address *aAddress, otError aError);
void LogFrame(const char *aActionText, const Mac::Frame &aFrame, otError aError);
void LogFragmentFrameDrop(otError aError,
uint8_t aFrameLength,
@@ -340,6 +340,40 @@ private:
const Mac::Address &aMacDest,
bool aIsSecure);
#if (OPENTHREAD_CONFIG_LOG_LEVEL >= OT_LOG_LEVEL_INFO) && (OPENTHREAD_CONFIG_LOG_MAC == 1)
const char *MessageActionToString(MessageAction aAction, otError aError);
const char *MessagePriorityToString(const Message &aMessage);
otError ParseIp6UdpTcpHeader(const Message &aMessage,
Ip6::Header & aIp6Header,
uint16_t & aChecksum,
uint16_t & aSourcePort,
uint16_t & aDestPort);
otError DecompressIp6UdpTcpHeader(const Message & aMessage,
uint16_t aOffset,
const Mac::Address &aMeshSource,
const Mac::Address &aMeshDest,
Ip6::Header & aIp6Header,
uint16_t & aChecksum,
uint16_t & aSourcePort,
uint16_t & aDestPort);
otError LogMeshFragmentHeader(MessageAction aAction,
const Message & aMessage,
const Mac::Address *aMacAddress,
otError aError,
uint16_t & aOffset,
Mac::Address & aMeshSource,
Mac::Address & aMeshDest);
void LogIp6SourceDestAddresses(Ip6::Header &aIp6Header, uint16_t aSourcePort, uint16_t aDestPort);
void LogMeshIpHeader(const Message & aMessage,
uint16_t aOffset,
const Mac::Address &aMeshSource,
const Mac::Address &aMeshDest);
void LogMeshMessage(MessageAction aAction, const Message &aMessage, const Mac::Address *aAddress, otError aError);
void LogIp6Message(MessageAction aAction, const Message &aMessage, const Mac::Address *aAddress, otError aError);
#endif
Mac::Receiver mMacReceiver;
Mac::Sender mMacSender;
TimerMilli mDiscoverTimer;
+12 -5
View File
@@ -174,7 +174,7 @@ void MeshForwarder::HandleResolved(const Ip6::Address &aEid, otError aError)
}
else
{
LogIp6Message(kMessageDrop, *cur, NULL, aError);
LogMessage(kMessageDrop, *cur, NULL, aError);
cur->Free();
}
}
@@ -361,7 +361,7 @@ void MeshForwarder::RemoveDataResponseMessages(void)
}
mSendQueue.Dequeue(*message);
LogIp6Message(kMessageDrop, *message, NULL, OT_ERROR_NONE);
LogMessage(kMessageDrop, *message, NULL, OT_ERROR_NONE);
message->Free();
}
}
@@ -459,7 +459,7 @@ Message *MeshForwarder::GetIndirectTransmission(Child &aChild)
{
Mac::Address macAddr;
LogIp6Message(kMessagePrepareIndirect, *message, &aChild.GetMacAddress(macAddr), OT_ERROR_NONE);
LogMessage(kMessagePrepareIndirect, *message, &aChild.GetMacAddress(macAddr), OT_ERROR_NONE);
}
return message;
@@ -830,6 +830,7 @@ otError MeshForwarder::CheckReachability(uint8_t * aFrame,
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);
@@ -850,7 +851,8 @@ otError MeshForwarder::CheckReachability(uint8_t * aFrame,
// only process IPv6 packets
VerifyOrExit(aFrameLength >= 1 && Lowpan::Lowpan::IsLowpanHc(aFrame));
VerifyOrExit(netif.GetLowpan().DecompressBaseHeader(ip6Header, aMeshSource, aMeshDest, aFrame, aFrameLength) > 0,
VerifyOrExit(netif.GetLowpan().DecompressBaseHeader(ip6Header, nextHeaderCompressed, aMeshSource, aMeshDest, aFrame,
aFrameLength) > 0,
error = OT_ERROR_DROP);
error = netif.GetMle().CheckReachability(aMeshSource.GetShort(), aMeshDest.GetShort(), ip6Header);
@@ -915,6 +917,9 @@ void MeshForwarder::HandleMesh(uint8_t * aFrame,
message->Write(0, aFrameLength, aFrame);
message->SetLinkSecurityEnabled(aLinkInfo.mLinkSecurity);
message->SetPanId(aLinkInfo.mPanId);
message->AddRss(aLinkInfo.mRss);
LogMessage(kMessageReceive, *message, &aMacSource, OT_ERROR_NONE);
SendMessage(*message);
}
@@ -942,6 +947,7 @@ void MeshForwarder::UpdateRoutes(uint8_t * aFrame,
ThreadNetif &netif = GetNetif();
Ip6::Header ip6Header;
Neighbor * neighbor;
bool nextHeaderCompressed;
VerifyOrExit(!aMeshDest.IsBroadcast() && aMeshSource.IsShort());
@@ -965,7 +971,8 @@ void MeshForwarder::UpdateRoutes(uint8_t * aFrame,
// only process IPv6 packets
VerifyOrExit(aFrameLength >= 1 && Lowpan::Lowpan::IsLowpanHc(aFrame));
VerifyOrExit(netif.GetLowpan().DecompressBaseHeader(ip6Header, aMeshSource, aMeshDest, aFrame, aFrameLength) > 0);
VerifyOrExit(netif.GetLowpan().DecompressBaseHeader(ip6Header, nextHeaderCompressed, aMeshSource, aMeshDest, aFrame,
aFrameLength) > 0);
netif.GetAddressResolver().UpdateCacheEntry(ip6Header.GetSource(), aMeshSource.GetShort());