diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index a6367e42e..ebc93ac9a 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -929,7 +929,9 @@ Mac::TxFrame *MeshForwarder::PrepareFrame(Mac::TxFrames &aTxFrames) #if OPENTHREAD_FTD case Message::kType6lowpan: - mMessageNextOffset = Get().PrepareMeshFrame(*frame, *mSendMessage, mMacAddrs); + mMessageNextOffset = mSendMessage->GetLength(); + VerifyOrExit(Get().PrepareMeshFrame(*frame, *mSendMessage, mMacAddrs) == kErrorNone, + frame = nullptr); break; case Message::kTypeSupervision: diff --git a/src/core/thread/message_framer.cpp b/src/core/thread/message_framer.cpp index 53a8e031f..a991b18c7 100644 --- a/src/core/thread/message_framer.cpp +++ b/src/core/thread/message_framer.cpp @@ -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 diff --git a/src/core/thread/message_framer.hpp b/src/core/thread/message_framer.hpp index be94ea6c1..2440cea2b 100644 --- a/src/core/thread/message_framer.hpp +++ b/src/core/thread/message_framer.hpp @@ -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 diff --git a/tests/unit/test_lowpan.cpp b/tests/unit/test_lowpan.cpp index b22aee91c..6ef8fd947 100644 --- a/tests/unit/test_lowpan.cpp +++ b/tests/unit/test_lowpan.cpp @@ -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().Allocate(Message::kType6lowpan); + VerifyOrQuit(message != nullptr); + + SuccessOrQuit(instance->Get().PrepareMeshFrame(txFrame, *message, macAddrs)); + maxPayload = txFrame.GetMtu() - txFrame.GetLength(); + + SuccessOrQuit(message->SetLength(maxPayload)); + SuccessOrQuit(instance->Get().PrepareMeshFrame(txFrame, *message, macAddrs)); + VerifyOrQuit(txFrame.GetLength() == txFrame.GetMtu()); + + SuccessOrQuit(message->SetLength(maxPayload + 1)); + VerifyOrQuit(instance->Get().PrepareMeshFrame(txFrame, *message, macAddrs) == kErrorNoBufs); + + SuccessOrQuit(message->SetLength(maxPayload - 1)); + SuccessOrQuit(instance->Get().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;