From 925f75cf06d305ae370a7990cf8ad33e0f0db188 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 7 Jan 2020 14:06:45 -0800 Subject: [PATCH] [mesh-forwarder] limit the Mesh Header frame MTU (#4440) This commit allows us to use different MTU on different radio links. 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. --- src/core/radio/trel_link.hpp | 4 ++-- src/core/thread/mesh_forwarder.cpp | 32 ++++++++++++++++++++++++------ src/core/thread/mesh_forwarder.hpp | 4 +++- 3 files changed, 31 insertions(+), 9 deletions(-) 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.