diff --git a/src/core/radio/trel_link.hpp b/src/core/radio/trel_link.hpp index 01f819c18..825bb33c0 100644 --- a/src/core/radio/trel_link.hpp +++ b/src/core/radio/trel_link.hpp @@ -75,8 +75,8 @@ class Link : public InstanceLocator public: enum { - kMtuSize = OT_RADIO_FRAME_MAX_SIZE, ///< MTU size for TREL frame. - kFcsSize = 2, ///< FCS size for TREL frame. + kMtuSize = 1280 - 48 - sizeof(Header), ///< MTU size for TREL frame. + kFcsSize = 0, ///< FCS size for TREL frame. }; /** diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index 7586f95d9..71a83ff82 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -579,6 +579,7 @@ uint16_t MeshForwarder::PrepareDataFrame(Mac::TxFrame & aFrame, uint16_t fcf; uint8_t *payload; uint8_t headerLength; + uint16_t maxPayloadLength; uint16_t payloadLength; uint16_t fragmentLength; uint16_t dstpan; @@ -665,7 +666,8 @@ start: IgnoreError(Get().AppendHeaderIe(aMessage.IsTimeSync(), aFrame)); #endif - payload = aFrame.GetPayload(); + payload = aFrame.GetPayload(); + maxPayloadLength = aFrame.GetMaxPayloadLength(); headerLength = 0; @@ -679,6 +681,24 @@ start: uint16_t meshHeaderLength; uint8_t hopsLeft; + // Mesh Header frames are forwarded by routers over multiple + // hops to reach a final destination. The forwarding path can + // have routers supporting different radio links with varying + // MTU sizes. Since the originator of the frame does not know the + // path and the MTU sizes of supported radio links by the routers + // in the path, we limit the max payload length of a Mesh Header + // frame to a fixed minimum value (derived from 15.4 radio) + // ensuring it can be handled by any radio link. + // + // Maximum payload length is calculated by subtracting the frame + // header and footer lengths from the MTU size. The footer + // length is derived by removing the `aFrame.GetFcsSize()` and + // then adding the fixed `kMeshHeaderFrameFcsSize` instead + // (updating the FCS size in the calculation of footer length). + + maxPayloadLength = kMeshHeaderFrameMtu - aFrame.GetHeaderLength() - + (aFrame.GetFooterLength() - aFrame.GetFcsSize() + kMeshHeaderFrameFcsSize); + if (mle.IsChild()) { // REED sets hopsLeft to max (16) + 1. It does not know the route cost. @@ -718,8 +738,8 @@ start: // Compress IPv6 Header if (aMessage.GetOffset() == 0) { - Lowpan::BufferWriter buffer(payload, aFrame.GetMaxPayloadLength() - headerLength - - Lowpan::FragmentHeader::kFirstFragmentHeaderSize); + Lowpan::BufferWriter buffer(payload, + maxPayloadLength - headerLength - Lowpan::FragmentHeader::kFirstFragmentHeaderSize); uint8_t hcLength; Mac::Address meshSource, meshDest; otError error; @@ -743,7 +763,7 @@ start: hcLength = static_cast(buffer.GetWritePointer() - payload); headerLength += hcLength; payloadLength = aMessage.GetLength() - aMessage.GetOffset(); - fragmentLength = aFrame.GetMaxPayloadLength() - headerLength; + fragmentLength = maxPayloadLength - headerLength; if ((payloadLength > fragmentLength) || aAddFragHeader) { @@ -777,7 +797,7 @@ start: payload += Lowpan::FragmentHeader::kFirstFragmentHeaderSize; headerLength += Lowpan::FragmentHeader::kFirstFragmentHeaderSize; - fragmentLength = aFrame.GetMaxPayloadLength() - headerLength; + fragmentLength = maxPayloadLength - headerLength; if (payloadLength > fragmentLength) { @@ -809,7 +829,7 @@ start: payload += fragmentHeaderLength; headerLength += fragmentHeaderLength; - fragmentLength = aFrame.GetMaxPayloadLength() - headerLength; + fragmentLength = maxPayloadLength - headerLength; if (payloadLength > fragmentLength) { diff --git a/src/core/thread/mesh_forwarder.hpp b/src/core/thread/mesh_forwarder.hpp index 884744e56..6a54d584f 100644 --- a/src/core/thread/mesh_forwarder.hpp +++ b/src/core/thread/mesh_forwarder.hpp @@ -327,7 +327,9 @@ public: private: enum : uint8_t { - kReassemblyTimeout = OPENTHREAD_CONFIG_6LOWPAN_REASSEMBLY_TIMEOUT, // Reassembly timeout (in seconds). + kReassemblyTimeout = OPENTHREAD_CONFIG_6LOWPAN_REASSEMBLY_TIMEOUT, // Reassembly timeout (in seconds). + kMeshHeaderFrameMtu = OT_RADIO_FRAME_MAX_SIZE, // Max. MTU allowed when generating a Mesh Header frame. + kMeshHeaderFrameFcsSize = sizeof(uint16_t), // Frame FCS size for Mesh Header frame. }; enum MessageAction ///< Defines the action parameter in `LogMessageInfo()` method.