mirror of
https://github.com/espressif/openthread.git
synced 2026-08-20 01:19:51 +00:00
[mesh-forwarder] use FrameBuidler in PrepareDataFrame() (#7964)
This commit updates `MeshForwarder::PrepareDataFrame()` to use `FrameBuilder` to prepare the frame. It also updates `Lowpan` fragment header definitions and adds `FirstFrag` and `NextFrag` nested types. The unit test `test_lowpan` is also updated to use the new types.
This commit is contained in:
committed by
Jonathan Hui
parent
e3f157402c
commit
c096c0e9ca
@@ -1532,7 +1532,7 @@ Error Headers::DecompressFrom(const Message & aMessage,
|
||||
const Mac::Address &aMacSource,
|
||||
const Mac::Address &aMacDest)
|
||||
{
|
||||
static constexpr uint16_t kReadLength = Lowpan::FragmentHeader::kSubsequentFragmentHeaderSize + sizeof(Headers);
|
||||
static constexpr uint16_t kReadLength = sizeof(Lowpan::FragmentHeader::NextFrag) + sizeof(Headers);
|
||||
|
||||
uint8_t frameBuffer[kReadLength];
|
||||
uint16_t frameLength;
|
||||
|
||||
+21
-48
@@ -45,7 +45,6 @@
|
||||
|
||||
using ot::Encoding::BigEndian::HostSwap16;
|
||||
using ot::Encoding::BigEndian::ReadUint16;
|
||||
using ot::Encoding::BigEndian::WriteUint16;
|
||||
|
||||
namespace ot {
|
||||
namespace Lowpan {
|
||||
@@ -1232,50 +1231,43 @@ void MeshHeader::DecrementHopsLeft(void)
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t MeshHeader::WriteTo(uint8_t *aFrame) const
|
||||
Error MeshHeader::AppendTo(FrameBuilder &aFrameBuilder) const
|
||||
{
|
||||
uint8_t *cur = aFrame;
|
||||
uint8_t dispatch = (kDispatch | kSourceShort | kDestShort);
|
||||
Error error;
|
||||
uint8_t dispatch = (kDispatch | kSourceShort | kDestShort);
|
||||
|
||||
if (mHopsLeft < kDeepHopsLeft)
|
||||
{
|
||||
*cur++ = (dispatch | mHopsLeft);
|
||||
SuccessOrExit(error = aFrameBuilder.AppendUint8(dispatch | mHopsLeft));
|
||||
}
|
||||
else
|
||||
{
|
||||
*cur++ = (dispatch | kDeepHopsLeft);
|
||||
*cur++ = mHopsLeft;
|
||||
SuccessOrExit(error = aFrameBuilder.AppendUint8(dispatch | kDeepHopsLeft));
|
||||
SuccessOrExit(error = aFrameBuilder.AppendUint8(mHopsLeft));
|
||||
}
|
||||
|
||||
WriteUint16(mSource, cur);
|
||||
cur += sizeof(uint16_t);
|
||||
SuccessOrExit(error = aFrameBuilder.AppendBigEndianUint16(mSource));
|
||||
SuccessOrExit(error = aFrameBuilder.AppendBigEndianUint16(mDestination));
|
||||
|
||||
WriteUint16(mDestination, cur);
|
||||
cur += sizeof(uint16_t);
|
||||
|
||||
return static_cast<uint16_t>(cur - aFrame);
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error MeshHeader::AppendTo(Message &aMessage) const
|
||||
{
|
||||
uint8_t frame[kDeepHopsHeaderLength];
|
||||
uint16_t headerLength;
|
||||
uint8_t frame[kDeepHopsHeaderLength];
|
||||
FrameBuilder frameBuilder;
|
||||
|
||||
headerLength = WriteTo(frame);
|
||||
frameBuilder.Init(frame, sizeof(frame));
|
||||
|
||||
return aMessage.AppendBytes(frame, headerLength);
|
||||
IgnoreError(AppendTo(frameBuilder));
|
||||
|
||||
return aMessage.AppendBytes(frameBuilder.GetBytes(), frameBuilder.GetLength());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
// FragmentHeader
|
||||
|
||||
void FragmentHeader::Init(uint16_t aSize, uint16_t aTag, uint16_t aOffset)
|
||||
{
|
||||
mSize = (aSize & kSizeMask);
|
||||
mTag = aTag;
|
||||
mOffset = (aOffset & kOffsetMask);
|
||||
}
|
||||
|
||||
bool FragmentHeader::IsFragmentHeader(const FrameData &aFrameData)
|
||||
{
|
||||
return IsFragmentHeader(aFrameData.GetBytes(), aFrameData.GetLength());
|
||||
@@ -1283,7 +1275,7 @@ bool FragmentHeader::IsFragmentHeader(const FrameData &aFrameData)
|
||||
|
||||
bool FragmentHeader::IsFragmentHeader(const uint8_t *aFrame, uint16_t aFrameLength)
|
||||
{
|
||||
return (aFrameLength >= kFirstFragmentHeaderSize) && ((*aFrame & kDispatchMask) == kDispatch);
|
||||
return (aFrameLength >= sizeof(FirstFrag)) && ((*aFrame & kDispatchMask) == kDispatch);
|
||||
}
|
||||
|
||||
Error FragmentHeader::ParseFrom(FrameData &aFrameData)
|
||||
@@ -1309,14 +1301,14 @@ Error FragmentHeader::ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, ui
|
||||
|
||||
if ((*aFrame & kOffsetFlag) == kOffsetFlag)
|
||||
{
|
||||
VerifyOrExit(aFrameLength >= kSubsequentFragmentHeaderSize);
|
||||
VerifyOrExit(aFrameLength >= sizeof(NextFrag));
|
||||
mOffset = aFrame[kOffsetIndex] * 8;
|
||||
aHeaderLength = kSubsequentFragmentHeaderSize;
|
||||
aHeaderLength = sizeof(NextFrag);
|
||||
}
|
||||
else
|
||||
{
|
||||
mOffset = 0;
|
||||
aHeaderLength = kFirstFragmentHeaderSize;
|
||||
aHeaderLength = sizeof(FirstFrag);
|
||||
}
|
||||
|
||||
error = kErrorNone;
|
||||
@@ -1327,7 +1319,7 @@ exit:
|
||||
|
||||
Error FragmentHeader::ParseFrom(const Message &aMessage, uint16_t aOffset, uint16_t &aHeaderLength)
|
||||
{
|
||||
uint8_t frame[kSubsequentFragmentHeaderSize];
|
||||
uint8_t frame[sizeof(NextFrag)];
|
||||
uint16_t frameLength;
|
||||
|
||||
frameLength = aMessage.ReadBytes(aOffset, frame, sizeof(frame));
|
||||
@@ -1335,24 +1327,5 @@ Error FragmentHeader::ParseFrom(const Message &aMessage, uint16_t aOffset, uint1
|
||||
return ParseFrom(frame, frameLength, aHeaderLength);
|
||||
}
|
||||
|
||||
uint16_t FragmentHeader::WriteTo(uint8_t *aFrame) const
|
||||
{
|
||||
uint8_t *cur = aFrame;
|
||||
|
||||
WriteUint16((static_cast<uint16_t>(kDispatch) << 8) + mSize, cur);
|
||||
cur += sizeof(uint16_t);
|
||||
|
||||
WriteUint16(mTag, cur);
|
||||
cur += sizeof(uint16_t);
|
||||
|
||||
if (mOffset != 0)
|
||||
{
|
||||
*aFrame |= kOffsetFlag;
|
||||
*cur++ = static_cast<uint8_t>(mOffset >> 3);
|
||||
}
|
||||
|
||||
return static_cast<uint16_t>(cur - aFrame);
|
||||
}
|
||||
|
||||
} // namespace Lowpan
|
||||
} // namespace ot
|
||||
|
||||
+69
-54
@@ -428,16 +428,15 @@ public:
|
||||
uint16_t GetDestination(void) const { return mDestination; }
|
||||
|
||||
/**
|
||||
* This method writes the Mesh Header into a given frame.
|
||||
* This method appends the Mesh Header into a given frame.
|
||||
*
|
||||
* @note This method expects the frame buffer to have enough space for the entire Mesh Header.
|
||||
* @param[out] aFrameBuilder The `FrameBuidler` to append to.
|
||||
*
|
||||
* @param[out] aFrame The pointer to the frame buffer to write to.
|
||||
*
|
||||
* @returns The header length (number of bytes written).
|
||||
* @retval kErrorNone Successfully appended the MeshHeader to @p aFrameBuildr.
|
||||
* @retval kErrorNoBufs Insufficient available buffers.
|
||||
*
|
||||
*/
|
||||
uint16_t WriteTo(uint8_t *aFrame) const;
|
||||
Error AppendTo(FrameBuilder &aFrameBuilder) const;
|
||||
|
||||
/**
|
||||
* This method appends the Mesh Header to a given message.
|
||||
@@ -475,31 +474,70 @@ private:
|
||||
class FragmentHeader
|
||||
{
|
||||
public:
|
||||
static constexpr uint16_t kFirstFragmentHeaderSize = 4; ///< First fragment header size in octets.
|
||||
static constexpr uint16_t kSubsequentFragmentHeaderSize = 5; ///< Subsequent fragment header size in octets.
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class FirstFrag
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method initializes the `FirstFrag`.
|
||||
*
|
||||
* @param[in] aSize The Datagram Size value.
|
||||
* @param[in] aTag The Datagram Tag value.
|
||||
*
|
||||
*/
|
||||
void Init(uint16_t aSize, uint16_t aTag)
|
||||
{
|
||||
mDispatchSize = HostSwap16(kFirstDispatch | (aSize & kSizeMask));
|
||||
mTag = HostSwap16(aTag);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method initializes the Fragment Header as a first fragment.
|
||||
*
|
||||
* A first fragment header starts at offset zero.
|
||||
*
|
||||
* @param[in] aSize The Datagram Size value.
|
||||
* @param[in] aTag The Datagram Tag value.
|
||||
*
|
||||
*/
|
||||
void InitFirstFragment(uint16_t aSize, uint16_t aTag) { Init(aSize, aTag, 0); }
|
||||
private:
|
||||
// 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |1 1 0 0 0| datagram_size | datagram_tag |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
/**
|
||||
* This method initializes the Fragment Header.
|
||||
*
|
||||
* The @p aOffset value will be truncated to become a multiple of 8.
|
||||
*
|
||||
* @param[in] aSize The Datagram Size value.
|
||||
* @param[in] aTag The Datagram Tag value.
|
||||
* @param[in] aOffset The Datagram Offset value.
|
||||
*
|
||||
*/
|
||||
void Init(uint16_t aSize, uint16_t aTag, uint16_t aOffset);
|
||||
static constexpr uint16_t kFirstDispatch = 0xc000; // 0b11000_0000_0000_0000
|
||||
|
||||
uint16_t mDispatchSize;
|
||||
uint16_t mTag;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
class NextFrag
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method initializes the `NextFrag`.
|
||||
*
|
||||
* @param[in] aSize The Datagram Size value.
|
||||
* @param[in] aTag The Datagram Tag value.
|
||||
* @param[in] aOffset The Datagram Offset value.
|
||||
*
|
||||
*/
|
||||
void Init(uint16_t aSize, uint16_t aTag, uint16_t aOffset)
|
||||
{
|
||||
mDispatchSize = HostSwap16(kNextDispatch | (aSize & kSizeMask));
|
||||
mTag = HostSwap16(aTag);
|
||||
mOffset = static_cast<uint8_t>(aOffset >> 3);
|
||||
}
|
||||
|
||||
private:
|
||||
// 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |1 1 1 0 0| datagram_size | datagram_tag |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |datagram_offset|
|
||||
// +-+-+-+-+-+-+-+-+
|
||||
|
||||
static constexpr uint16_t kNextDispatch = 0xe000; // 0b11100_0000_0000_0000
|
||||
|
||||
uint16_t mDispatchSize;
|
||||
uint16_t mTag;
|
||||
uint8_t mOffset;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
* This static method indicates whether or not the header (in a given frame) is a Fragment Header.
|
||||
@@ -516,19 +554,6 @@ public:
|
||||
*/
|
||||
static bool IsFragmentHeader(const FrameData &aFrameData);
|
||||
|
||||
/**
|
||||
* This method parses the Fragment Header from a frame @p aFrame.
|
||||
*
|
||||
* @param[in] aFrame The pointer to the frame.
|
||||
* @param[in] aFrameLength The length of the frame.
|
||||
* @param[out] aHeaderLength A reference to a variable to output the parsed header length (on success).
|
||||
*
|
||||
* @retval kErrorNone Fragment Header parsed successfully.
|
||||
* @retval kErrorParse Fragment header could not be parsed from @p aFrame.
|
||||
*
|
||||
*/
|
||||
Error ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength); //~~~ REMOVE OR MAKE PRIVATE
|
||||
|
||||
/**
|
||||
* This method parses the Fragment Header from a given frame data.
|
||||
*
|
||||
@@ -581,18 +606,6 @@ public:
|
||||
*/
|
||||
uint16_t GetDatagramOffset(void) const { return mOffset; }
|
||||
|
||||
/**
|
||||
* This method writes the Fragment Header into a given frame.
|
||||
*
|
||||
* @note This method expects the frame buffer to have enough space for the entire Fragment Header
|
||||
*
|
||||
* @param[out] aFrame The pointer to the frame buffer to write to.
|
||||
*
|
||||
* @returns The header length (number of bytes written).
|
||||
*
|
||||
*/
|
||||
uint16_t WriteTo(uint8_t *aFrame) const;
|
||||
|
||||
private:
|
||||
static constexpr uint8_t kDispatch = 0xc0; // 0b1100_0000
|
||||
static constexpr uint8_t kDispatchMask = 0xd8; // 0b1101_1000 accepts first (0b1100_0xxx) and next (0b1110_0xxx).
|
||||
@@ -607,6 +620,8 @@ private:
|
||||
|
||||
static bool IsFragmentHeader(const uint8_t *aFrame, uint16_t aFrameLength);
|
||||
|
||||
Error ParseFrom(const uint8_t *aFrame, uint16_t aFrameLength, uint16_t &aHeaderLength);
|
||||
|
||||
uint16_t mSize;
|
||||
uint16_t mTag;
|
||||
uint16_t mOffset;
|
||||
|
||||
@@ -852,16 +852,14 @@ uint16_t MeshForwarder::PrepareDataFrame(Mac::TxFrame & aFrame,
|
||||
uint16_t aMeshDest,
|
||||
bool aAddFragHeader)
|
||||
{
|
||||
uint16_t fcf;
|
||||
uint8_t *payload;
|
||||
uint8_t headerLength;
|
||||
uint16_t maxPayloadLength;
|
||||
uint16_t payloadLength;
|
||||
uint16_t fragmentLength;
|
||||
uint16_t dstpan;
|
||||
uint8_t secCtl;
|
||||
uint16_t nextOffset;
|
||||
bool iePresent = CalcIePresent(&aMessage);
|
||||
uint16_t fcf;
|
||||
uint16_t payloadLength;
|
||||
uint16_t dstpan;
|
||||
uint8_t secCtl;
|
||||
uint16_t origMsgOffset;
|
||||
uint16_t nextOffset;
|
||||
FrameBuilder frameBuilder;
|
||||
bool iePresent = CalcIePresent(&aMessage);
|
||||
|
||||
start:
|
||||
|
||||
@@ -974,10 +972,7 @@ start:
|
||||
}
|
||||
#endif
|
||||
|
||||
payload = aFrame.GetPayload();
|
||||
maxPayloadLength = aFrame.GetMaxPayloadLength();
|
||||
|
||||
headerLength = 0;
|
||||
frameBuilder.Init(aFrame.GetPayload(), aFrame.GetMaxPayloadLength());
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
|
||||
@@ -986,8 +981,8 @@ start:
|
||||
{
|
||||
Mle::MleRouter & mle = Get<Mle::MleRouter>();
|
||||
Lowpan::MeshHeader meshHeader;
|
||||
uint16_t meshHeaderLength;
|
||||
uint8_t hopsLeft;
|
||||
uint16_t maxPayloadLength;
|
||||
|
||||
// Mesh Header frames are forwarded by routers over multiple
|
||||
// hops to reach a final destination. The forwarding path can
|
||||
@@ -1007,6 +1002,8 @@ start:
|
||||
maxPayloadLength = kMeshHeaderFrameMtu - aFrame.GetHeaderLength() -
|
||||
(aFrame.GetFooterLength() - aFrame.GetFcsSize() + kMeshHeaderFrameFcsSize);
|
||||
|
||||
frameBuilder.Init(aFrame.GetPayload(), maxPayloadLength);
|
||||
|
||||
if (mle.IsChild())
|
||||
{
|
||||
// REED sets hopsLeft to max (16) + 1. It does not know the route cost.
|
||||
@@ -1036,21 +1033,37 @@ start:
|
||||
}
|
||||
|
||||
meshHeader.Init(aMeshSource, aMeshDest, hopsLeft + Lowpan::MeshHeader::kAdditionalHopsLeft);
|
||||
meshHeaderLength = meshHeader.WriteTo(payload);
|
||||
payload += meshHeaderLength;
|
||||
headerLength += meshHeaderLength;
|
||||
|
||||
IgnoreError(meshHeader.AppendTo(frameBuilder));
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // OPENTHREAD_FTD
|
||||
|
||||
// While performing lowpan compression, the message offset may be
|
||||
// changed to skip over the compressed IPv6 headers, we save the
|
||||
// original offset and set it back on `aMessage` at the end
|
||||
// before returning.
|
||||
|
||||
origMsgOffset = aMessage.GetOffset();
|
||||
|
||||
// Compress IPv6 Header
|
||||
if (aMessage.GetOffset() == 0)
|
||||
{
|
||||
FrameBuilder frameBuilder;
|
||||
uint8_t hcLength;
|
||||
Mac::Address meshSource, meshDest;
|
||||
uint16_t fragHeaderOffset;
|
||||
uint16_t maxFrameLength;
|
||||
Mac::Address meshSource;
|
||||
Mac::Address meshDest;
|
||||
|
||||
frameBuilder.Init(payload, maxPayloadLength - headerLength - Lowpan::FragmentHeader::kFirstFragmentHeaderSize);
|
||||
// Before performing lowpan header compression, we reduce the
|
||||
// max length on `frameBuilder` to reserve bytes for first
|
||||
// fragment header. This ensures that lowpan compression will
|
||||
// leave room for a first fragment header. After the lowpan
|
||||
// header compression is done, we reclaim the reserved bytes
|
||||
// by setting the max length back to its original value.
|
||||
|
||||
fragHeaderOffset = frameBuilder.GetLength();
|
||||
maxFrameLength = frameBuilder.GetMaxLength();
|
||||
frameBuilder.SetMaxLength(maxFrameLength - sizeof(Lowpan::FragmentHeader::FirstFrag));
|
||||
|
||||
if (aAddMeshHeader)
|
||||
{
|
||||
@@ -1065,24 +1078,26 @@ start:
|
||||
|
||||
SuccessOrAssert(Get<Lowpan::Lowpan>().Compress(aMessage, meshSource, meshDest, frameBuilder));
|
||||
|
||||
hcLength = static_cast<uint8_t>(frameBuilder.GetLength());
|
||||
headerLength += hcLength;
|
||||
payloadLength = aMessage.GetLength() - aMessage.GetOffset();
|
||||
fragmentLength = maxPayloadLength - headerLength;
|
||||
frameBuilder.SetMaxLength(maxFrameLength);
|
||||
|
||||
if ((payloadLength > fragmentLength) || aAddFragHeader)
|
||||
payloadLength = aMessage.GetLength() - aMessage.GetOffset();
|
||||
|
||||
if (aAddFragHeader || (payloadLength > frameBuilder.GetRemainingLength()))
|
||||
{
|
||||
Lowpan::FragmentHeader fragmentHeader;
|
||||
Lowpan::FragmentHeader::FirstFrag firstFragHeader;
|
||||
|
||||
if ((!aMessage.IsLinkSecurityEnabled()) && aMessage.IsSubTypeMle())
|
||||
{
|
||||
// Enable security and try again.
|
||||
// MLE messages that require fragmentation MUST use
|
||||
// link-layer security. We enable security and try
|
||||
// constructing the frame again.
|
||||
|
||||
aMessage.SetOffset(0);
|
||||
aMessage.SetLinkSecurityEnabled(true);
|
||||
goto start;
|
||||
}
|
||||
|
||||
// Write Fragment header
|
||||
// Insert Fragment header
|
||||
if (aMessage.GetDatagramTag() == 0)
|
||||
{
|
||||
// Avoid using datagram tag value 0, which indicates the tag has not been set
|
||||
@@ -1094,60 +1109,32 @@ start:
|
||||
aMessage.SetDatagramTag(mFragTag++);
|
||||
}
|
||||
|
||||
memmove(payload + Lowpan::FragmentHeader::kFirstFragmentHeaderSize, payload, hcLength);
|
||||
|
||||
fragmentHeader.InitFirstFragment(aMessage.GetLength(), static_cast<uint16_t>(aMessage.GetDatagramTag()));
|
||||
fragmentHeader.WriteTo(payload);
|
||||
|
||||
payload += Lowpan::FragmentHeader::kFirstFragmentHeaderSize;
|
||||
headerLength += Lowpan::FragmentHeader::kFirstFragmentHeaderSize;
|
||||
|
||||
fragmentLength = maxPayloadLength - headerLength;
|
||||
|
||||
if (payloadLength > fragmentLength)
|
||||
{
|
||||
payloadLength = fragmentLength & ~0x7;
|
||||
}
|
||||
firstFragHeader.Init(aMessage.GetLength(), static_cast<uint16_t>(aMessage.GetDatagramTag()));
|
||||
SuccessOrAssert(frameBuilder.Insert(fragHeaderOffset, firstFragHeader));
|
||||
}
|
||||
|
||||
payload += hcLength;
|
||||
|
||||
// copy IPv6 Payload
|
||||
aMessage.ReadBytes(aMessage.GetOffset(), payload, payloadLength);
|
||||
aFrame.SetPayloadLength(headerLength + payloadLength);
|
||||
|
||||
nextOffset = aMessage.GetOffset() + payloadLength;
|
||||
aMessage.SetOffset(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Lowpan::FragmentHeader fragmentHeader;
|
||||
uint16_t fragmentHeaderLength;
|
||||
Lowpan::FragmentHeader::NextFrag nextFragHeader;
|
||||
|
||||
nextFragHeader.Init(aMessage.GetLength(), static_cast<uint16_t>(aMessage.GetDatagramTag()),
|
||||
aMessage.GetOffset());
|
||||
SuccessOrAssert(frameBuilder.Append(nextFragHeader));
|
||||
|
||||
payloadLength = aMessage.GetLength() - aMessage.GetOffset();
|
||||
|
||||
// Write Fragment header
|
||||
fragmentHeader.Init(aMessage.GetLength(), static_cast<uint16_t>(aMessage.GetDatagramTag()),
|
||||
aMessage.GetOffset());
|
||||
fragmentHeaderLength = fragmentHeader.WriteTo(payload);
|
||||
|
||||
payload += fragmentHeaderLength;
|
||||
headerLength += fragmentHeaderLength;
|
||||
|
||||
fragmentLength = maxPayloadLength - headerLength;
|
||||
|
||||
if (payloadLength > fragmentLength)
|
||||
{
|
||||
payloadLength = (fragmentLength & ~0x7);
|
||||
}
|
||||
|
||||
// Copy IPv6 Payload
|
||||
aMessage.ReadBytes(aMessage.GetOffset(), payload, payloadLength);
|
||||
aFrame.SetPayloadLength(headerLength + payloadLength);
|
||||
|
||||
nextOffset = aMessage.GetOffset() + payloadLength;
|
||||
}
|
||||
|
||||
if (payloadLength > frameBuilder.GetRemainingLength())
|
||||
{
|
||||
payloadLength = (frameBuilder.GetRemainingLength() & ~0x7);
|
||||
}
|
||||
|
||||
// Copy IPv6 Payload
|
||||
SuccessOrAssert(frameBuilder.AppendBytesFromMessage(aMessage, aMessage.GetOffset(), payloadLength));
|
||||
aFrame.SetPayloadLength(frameBuilder.GetLength());
|
||||
|
||||
nextOffset = aMessage.GetOffset() + payloadLength;
|
||||
|
||||
if (nextOffset < aMessage.GetLength())
|
||||
{
|
||||
aFrame.SetFramePending(true);
|
||||
@@ -1156,6 +1143,8 @@ start:
|
||||
#endif
|
||||
}
|
||||
|
||||
aMessage.SetOffset(origMsgOffset);
|
||||
|
||||
return nextOffset;
|
||||
}
|
||||
|
||||
|
||||
+50
-40
@@ -1870,6 +1870,7 @@ void TestLowpanMeshHeader(void)
|
||||
uint8_t frame[kMaxFrameSize];
|
||||
uint16_t length;
|
||||
FrameData frameData;
|
||||
FrameBuilder frameBuilder;
|
||||
Lowpan::MeshHeader meshHeader;
|
||||
|
||||
meshHeader.Init(kSourceAddr, kDestAddr, 1);
|
||||
@@ -1877,10 +1878,12 @@ void TestLowpanMeshHeader(void)
|
||||
VerifyOrQuit(meshHeader.GetDestination() == kDestAddr, "failed after Init()");
|
||||
VerifyOrQuit(meshHeader.GetHopsLeft() == 1, "failed after Init()");
|
||||
|
||||
length = meshHeader.WriteTo(frame);
|
||||
frameBuilder.Init(frame, sizeof(frame));
|
||||
SuccessOrQuit(meshHeader.AppendTo(frameBuilder));
|
||||
length = frameBuilder.GetLength();
|
||||
VerifyOrQuit(length == meshHeader.GetHeaderLength());
|
||||
VerifyOrQuit(length == sizeof(kMeshHeader1), "MeshHeader::WriteTo() returned length is incorrect");
|
||||
VerifyOrQuit(memcmp(frame, kMeshHeader1, length) == 0, "MeshHeader::WriteTo() failed");
|
||||
VerifyOrQuit(length == sizeof(kMeshHeader1), "MeshHeader::AppendTo() returned length is incorrect");
|
||||
VerifyOrQuit(memcmp(frame, kMeshHeader1, length) == 0, "MeshHeader::AppendTo() failed");
|
||||
|
||||
memset(&meshHeader, 0, sizeof(meshHeader));
|
||||
frameData.Init(frame, length);
|
||||
@@ -1903,10 +1906,12 @@ void TestLowpanMeshHeader(void)
|
||||
VerifyOrQuit(meshHeader.GetDestination() == kDestAddr, "failed after Init()");
|
||||
VerifyOrQuit(meshHeader.GetHopsLeft() == 0x20, "failed after Init()");
|
||||
|
||||
length = meshHeader.WriteTo(frame);
|
||||
VerifyOrQuit(length == sizeof(kMeshHeader2), "MeshHeader::WriteTo() returned length is incorrect");
|
||||
frameBuilder.Init(frame, sizeof(frame));
|
||||
SuccessOrQuit(meshHeader.AppendTo(frameBuilder));
|
||||
length = frameBuilder.GetLength();
|
||||
VerifyOrQuit(length == sizeof(kMeshHeader2), "MeshHeader::AppendTo() returned length is incorrect");
|
||||
VerifyOrQuit(length == meshHeader.GetHeaderLength());
|
||||
VerifyOrQuit(memcmp(frame, kMeshHeader2, length) == 0, "MeshHeader::WriteTo() failed");
|
||||
VerifyOrQuit(memcmp(frame, kMeshHeader2, length) == 0, "MeshHeader::AppendTo() failed");
|
||||
|
||||
memset(&meshHeader, 0, sizeof(meshHeader));
|
||||
frameData.Init(frame, length);
|
||||
@@ -1933,7 +1938,9 @@ void TestLowpanMeshHeader(void)
|
||||
VerifyOrQuit(meshHeader.GetDestination() == kDestAddr, "failed after ParseFrom()");
|
||||
VerifyOrQuit(meshHeader.GetHopsLeft() == 1, "failed after ParseFrom()");
|
||||
|
||||
VerifyOrQuit(meshHeader.WriteTo(frame) == sizeof(kMeshHeader1));
|
||||
frameBuilder.Init(frame, sizeof(frame));
|
||||
SuccessOrQuit(meshHeader.AppendTo(frameBuilder));
|
||||
VerifyOrQuit(frameBuilder.GetLength() == sizeof(kMeshHeader1));
|
||||
|
||||
frameData.Init(kMeshHeader3, sizeof(kMeshHeader3) - 1);
|
||||
VerifyOrQuit(meshHeader.ParseFrom(frameData) == kErrorParse,
|
||||
@@ -1942,13 +1949,10 @@ void TestLowpanMeshHeader(void)
|
||||
|
||||
void TestLowpanFragmentHeader(void)
|
||||
{
|
||||
enum
|
||||
{
|
||||
kMaxFrameSize = 127,
|
||||
kSize = 0x7ef,
|
||||
kTag = 0x1234,
|
||||
kOffset = (100 * 8),
|
||||
};
|
||||
static constexpr uint16_t kMaxFrameSize = 127;
|
||||
static constexpr uint16_t kSize = 0x7ef;
|
||||
static constexpr uint16_t kTag = 0x1234;
|
||||
static constexpr uint16_t kOffset = (100 * 8);
|
||||
|
||||
const uint8_t kFragHeader1[] = {0xc7, 0xef, 0x12, 0x34}; // size:0x7ef, tag:0x1234, offset:0 (first frag)
|
||||
const uint8_t kFragHeader2[] = {0xe7, 0xef, 0x12, 0x34, 0x64}; // size:0x7ef, tag:0x1234, offset:100 (next frag)
|
||||
@@ -1958,21 +1962,22 @@ void TestLowpanFragmentHeader(void)
|
||||
const uint8_t kInvalidFragHeader2[] = {0xd0, 0xef, 0x12, 0x34, 0x64};
|
||||
const uint8_t kInvalidFragHeader3[] = {0x90, 0xef, 0x12, 0x34, 0x64};
|
||||
|
||||
uint8_t frame[kMaxFrameSize];
|
||||
uint16_t length;
|
||||
FrameData frameData;
|
||||
Lowpan::FragmentHeader fragHeader;
|
||||
uint8_t frame[kMaxFrameSize];
|
||||
uint16_t length;
|
||||
FrameData frameData;
|
||||
FrameBuilder frameBuilder;
|
||||
Lowpan::FragmentHeader fragHeader;
|
||||
Lowpan::FragmentHeader::FirstFrag firstFragHeader;
|
||||
Lowpan::FragmentHeader::NextFrag nextFragHeader;
|
||||
|
||||
fragHeader.InitFirstFragment(kSize, kTag);
|
||||
VerifyOrQuit(fragHeader.GetDatagramSize() == kSize, "failed after Init");
|
||||
VerifyOrQuit(fragHeader.GetDatagramTag() == kTag, "failed after Init()");
|
||||
VerifyOrQuit(fragHeader.GetDatagramOffset() == 0, "failed after Init()");
|
||||
frameBuilder.Init(frame, sizeof(frame));
|
||||
|
||||
length = fragHeader.WriteTo(frame);
|
||||
VerifyOrQuit(length == Lowpan::FragmentHeader::kFirstFragmentHeaderSize,
|
||||
"FragmentHeader::WriteTo() returned length is incorrect");
|
||||
VerifyOrQuit(length == sizeof(kFragHeader1), "FragmentHeader::WriteTo() returned length is incorrect");
|
||||
VerifyOrQuit(memcmp(frame, kFragHeader1, length) == 0, "FragmentHeader::WriteTo() failed");
|
||||
firstFragHeader.Init(kSize, kTag);
|
||||
SuccessOrQuit(frameBuilder.Append(firstFragHeader));
|
||||
|
||||
length = frameBuilder.GetLength();
|
||||
VerifyOrQuit(length == sizeof(Lowpan::FragmentHeader::FirstFrag));
|
||||
VerifyOrQuit(memcmp(frame, kFragHeader1, length) == 0);
|
||||
|
||||
memset(&fragHeader, 0, sizeof(fragHeader));
|
||||
|
||||
@@ -1993,22 +1998,27 @@ void TestLowpanFragmentHeader(void)
|
||||
|
||||
//- - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
fragHeader.Init(kSize, kTag, kOffset);
|
||||
VerifyOrQuit(fragHeader.GetDatagramSize() == kSize, "failed after Init");
|
||||
VerifyOrQuit(fragHeader.GetDatagramTag() == kTag, "failed after Init()");
|
||||
VerifyOrQuit(fragHeader.GetDatagramOffset() == kOffset, "failed after Init()");
|
||||
frameBuilder.Init(frame, sizeof(frame));
|
||||
nextFragHeader.Init(kSize, kTag, kOffset);
|
||||
SuccessOrQuit(frameBuilder.Append(nextFragHeader));
|
||||
length = frameBuilder.GetLength();
|
||||
VerifyOrQuit(length == sizeof(kFragHeader2));
|
||||
VerifyOrQuit(memcmp(frame, kFragHeader2, length) == 0);
|
||||
|
||||
// Check the truncation of offset (to be multiple of 8).
|
||||
fragHeader.Init(kSize, kTag, kOffset + 1);
|
||||
VerifyOrQuit(fragHeader.GetDatagramOffset() == kOffset, "FragmentHeader::GetDatagramOffset() did not truncate");
|
||||
fragHeader.Init(kSize, kTag, kOffset + 7);
|
||||
VerifyOrQuit(fragHeader.GetDatagramOffset() == kOffset, "FragmentHeader::GetDatagramOffset() did not truncate");
|
||||
frameBuilder.Init(frame, sizeof(frame));
|
||||
nextFragHeader.Init(kSize, kTag, kOffset + 1);
|
||||
SuccessOrQuit(frameBuilder.Append(nextFragHeader));
|
||||
length = frameBuilder.GetLength();
|
||||
VerifyOrQuit(length == sizeof(kFragHeader2));
|
||||
VerifyOrQuit(memcmp(frame, kFragHeader2, length) == 0);
|
||||
|
||||
length = fragHeader.WriteTo(frame);
|
||||
VerifyOrQuit(length == Lowpan::FragmentHeader::kSubsequentFragmentHeaderSize,
|
||||
"FragmentHeader::WriteTo() returned length is incorrect");
|
||||
VerifyOrQuit(length == sizeof(kFragHeader2), "FragmentHeader::WriteTo() returned length is incorrect");
|
||||
VerifyOrQuit(memcmp(frame, kFragHeader2, length) == 0, "FragmentHeader::WriteTo() failed");
|
||||
frameBuilder.Init(frame, sizeof(frame));
|
||||
nextFragHeader.Init(kSize, kTag, kOffset + 7);
|
||||
SuccessOrQuit(frameBuilder.Append(nextFragHeader));
|
||||
length = frameBuilder.GetLength();
|
||||
VerifyOrQuit(length == sizeof(kFragHeader2));
|
||||
VerifyOrQuit(memcmp(frame, kFragHeader2, length) == 0);
|
||||
|
||||
memset(&fragHeader, 0, sizeof(fragHeader));
|
||||
frameData.Init(frame, length);
|
||||
|
||||
Reference in New Issue
Block a user