diff --git a/src/core/thread/lowpan.cpp b/src/core/thread/lowpan.cpp index c7c63a5e1..146b5974a 100644 --- a/src/core/thread/lowpan.cpp +++ b/src/core/thread/lowpan.cpp @@ -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(cur[0])); cur++; remaining--; + aCompressedNextHeader = false; + } + else + { + aCompressedNextHeader = true; } // Hop Limit @@ -963,12 +969,11 @@ exit: return (error == OT_ERROR_NONE) ? static_cast(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(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(aBufLength - (cur - aBuf))); + udpHeader.SetLength(sizeof(udpHeader) + static_cast(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(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 diff --git a/src/core/thread/lowpan.hpp b/src/core/thread/lowpan.hpp index f63bcc4f8..b5fd0ba2b 100644 --- a/src/core/thread/lowpan.hpp +++ b/src/core/thread/lowpan.hpp @@ -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. * diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index abed38266..9bc03f6bc 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -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) { } diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp index 7e05bf44f..0dbdc1d22 100644 --- a/src/core/thread/mesh_forwarder.hpp +++ b/src/core/thread/mesh_forwarder.hpp @@ -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; diff --git a/src/core/thread/mesh_forwarder_ftd.cpp b/src/core/thread/mesh_forwarder_ftd.cpp index f1d98e34e..efc8c0bca 100644 --- a/src/core/thread/mesh_forwarder_ftd.cpp +++ b/src/core/thread/mesh_forwarder_ftd.cpp @@ -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());