diff --git a/src/lib/spinel/multi_frame_buffer.hpp b/src/lib/spinel/multi_frame_buffer.hpp index 9a374cd6a..2c90d9069 100644 --- a/src/lib/spinel/multi_frame_buffer.hpp +++ b/src/lib/spinel/multi_frame_buffer.hpp @@ -309,14 +309,27 @@ public: * * Saved frame can be retrieved later using `GetNextSavedFrame()`. * + * @retval OT_ERROR_NONE Successfully saved the buffer and prepared the write pointer for the next frame. + * @retval OT_ERROR_NO_BUFS Insufficient buffer space. */ - void SaveFrame(void) + otError SaveFrame(void) { - Encoding::LittleEndian::WriteUint16(GetSkipLength() + GetLength(), mWriteFrameStart + kHeaderTotalLengthOffset); - mWriteFrameStart = mWritePointer; - IgnoreError(SetSkipLength(0)); - mWritePointer = GetFrame(); - mRemainingLength = static_cast(mBuffer + kSize - mWritePointer); + otError error = OT_ERROR_NONE; + + // If the next header will overflow the buffer, we can't save the frame. + if (!CanWrite(kHeaderSize)) + { + error = OT_ERROR_NO_BUFS; + } + else + { + Encoding::LittleEndian::WriteUint16(GetSkipLength() + GetLength(), + mWriteFrameStart + kHeaderTotalLengthOffset); + mWriteFrameStart = mWritePointer; + IgnoreError(SetSkipLength(0)); + } + + return error; } /** diff --git a/src/lib/spinel/radio_spinel_impl.hpp b/src/lib/spinel/radio_spinel_impl.hpp index 35e7baa42..02898e5a7 100644 --- a/src/lib/spinel/radio_spinel_impl.hpp +++ b/src/lib/spinel/radio_spinel_impl.hpp @@ -530,13 +530,14 @@ void RadioSpinel::HandleNotification(SpinelInterface::RxFrameBuff } exit: - if (shouldSaveFrame) - { - aFrameBuffer.SaveFrame(); - } - else + if (!shouldSaveFrame || aFrameBuffer.SaveFrame() != OT_ERROR_NONE) { aFrameBuffer.DiscardFrame(); + + if (shouldSaveFrame) + { + otLogCritPlat("RX Spinel buffer full, dropped incoming frame"); + } } UpdateParseErrorCount(error);