[mesh-forwarder] reject oversized mesh frames (#13758)

This commit updates MessageFramer::PrepareMeshFrame() to return an Error
and propagate the result of PayloadBuilder::AppendBytesFromMessage()
instead of asserting with SuccessOrAssert().

When MeshForwarder::PrepareFrame() receives an error from
PrepareMeshFrame(), it advances mMessageNextOffset to the end of the
message and aborts frame preparation so the oversized mesh message is
dropped cleanly without retrying.
This commit is contained in:
Jonathan Hui
2026-10-19 19:37:52 -07:00
committed by GitHub
parent 5cdc59e75d
commit 293a20bc96
4 changed files with 60 additions and 6 deletions
+3 -1
View File
@@ -929,7 +929,9 @@ Mac::TxFrame *MeshForwarder::PrepareFrame(Mac::TxFrames &aTxFrames)
#if OPENTHREAD_FTD
case Message::kType6lowpan:
mMessageNextOffset = Get<MessageFramer>().PrepareMeshFrame(*frame, *mSendMessage, mMacAddrs);
mMessageNextOffset = mSendMessage->GetLength();
VerifyOrExit(Get<MessageFramer>().PrepareMeshFrame(*frame, *mSendMessage, mMacAddrs) == kErrorNone,
frame = nullptr);
break;
case Message::kTypeSupervision:
+5 -3
View File
@@ -356,8 +356,9 @@ start:
#if OPENTHREAD_FTD
uint16_t MessageFramer::PrepareMeshFrame(Mac::TxFrame &aFrame, Message &aMessage, const Mac::Addresses &aMacAddrs)
Error MessageFramer::PrepareMeshFrame(Mac::TxFrame &aFrame, Message &aMessage, const Mac::Addresses &aMacAddrs)
{
Error error;
Mac::TxFrame::BuildInfo buildInfo;
Mac::TxFrame::PayloadBuilder frameBuilder;
@@ -369,10 +370,11 @@ uint16_t MessageFramer::PrepareMeshFrame(Mac::TxFrame &aFrame, Message &aMessage
PrepareMacHeaders(aFrame, buildInfo, frameBuilder, &aMessage);
SuccessOrAssert(frameBuilder.AppendBytesFromMessage(aMessage, 0, aMessage.GetLength()));
SuccessOrExit(error = frameBuilder.AppendBytesFromMessage(aMessage, 0, aMessage.GetLength()));
aFrame.FinishPayload(frameBuilder);
return aMessage.GetLength();
exit:
return error;
}
#endif // OPENTHREAD_FTD
+4 -2
View File
@@ -115,9 +115,11 @@ public:
* @param[in] aMessage The 6LoWPAN Mesh message.
* @param[in] aMacAddrs The MAC source and destination addresses.
*
* @returns The next offset into @p aMessage after the prepared frame.
* @retval kErrorNone Successfully prepared the frame.
* @retval kErrorNoBufs The message does not fit in the frame.
* @retval kErrorParse Failed to read payload from @p aMessage.
*/
uint16_t PrepareMeshFrame(Mac::TxFrame &aFrame, Message &aMessage, const Mac::Addresses &aMacAddrs);
Error PrepareMeshFrame(Mac::TxFrame &aFrame, Message &aMessage, const Mac::Addresses &aMacAddrs);
#endif // OPENTHREAD_FTD
+48
View File
@@ -2161,6 +2161,51 @@ void TestLowpanDecompressRecursion(void)
printf("PASS\n\n");
}
#if OPENTHREAD_FTD
void TestPrepareMeshFrame(void)
{
Instance *instance = testInitInstance();
Message *message;
Mac::Addresses macAddrs;
Mac::TxFrame txFrame{};
uint8_t psdu[OT_RADIO_FRAME_MAX_SIZE];
uint16_t maxPayload;
printf("\n=== Test name: Prepare Mesh Frame ===\n\n");
VerifyOrQuit(instance != nullptr);
txFrame.mPsdu = psdu;
#if OPENTHREAD_CONFIG_MULTI_RADIO
txFrame.SetRadioType(Radio::kTypeIeee802154);
#endif
macAddrs.mSource.SetShort(0x1000);
macAddrs.mDestination.SetShort(0x2000);
message = instance->Get<MessagePool>().Allocate(Message::kType6lowpan);
VerifyOrQuit(message != nullptr);
SuccessOrQuit(instance->Get<MessageFramer>().PrepareMeshFrame(txFrame, *message, macAddrs));
maxPayload = txFrame.GetMtu() - txFrame.GetLength();
SuccessOrQuit(message->SetLength(maxPayload));
SuccessOrQuit(instance->Get<MessageFramer>().PrepareMeshFrame(txFrame, *message, macAddrs));
VerifyOrQuit(txFrame.GetLength() == txFrame.GetMtu());
SuccessOrQuit(message->SetLength(maxPayload + 1));
VerifyOrQuit(instance->Get<MessageFramer>().PrepareMeshFrame(txFrame, *message, macAddrs) == kErrorNoBufs);
SuccessOrQuit(message->SetLength(maxPayload - 1));
SuccessOrQuit(instance->Get<MessageFramer>().PrepareMeshFrame(txFrame, *message, macAddrs));
VerifyOrQuit(txFrame.GetLength() == txFrame.GetMtu() - 1);
message->Free();
testFreeInstance(instance);
printf("PASS\n\n");
}
#endif // OPENTHREAD_FTD
} // namespace ot
int main(void)
@@ -2169,6 +2214,9 @@ int main(void)
ot::TestLowpanMeshHeader();
ot::TestLowpanFragmentHeader();
ot::TestLowpanDecompressRecursion();
#if OPENTHREAD_FTD
ot::TestPrepareMeshFrame();
#endif
printf("All tests passed\n");
return 0;