[core] adding FrameData class for parsing frames (#7892)

This commit adds a new class `FrameData` which is a sub-class of
`Data` (acts as a wrapper over a buffer pointer and a length). It is
used in `MeshForwarder` and `Lowpan` to simplify the method calls
(can pass `FrameData` instance instead of pointer and length). It
also provides helper methods for parsing the frame content (e.g.,
reading `uint16/32` value assuming big or little endian encoding).
When read successfully, the `FrameData` is updated to skip over the
read content. These methods help simplify `Lowpan` parsing and
decompression code. In particular the `Lowpan` methods now directly
update the passed-in `FrameData` to skip over the parsed header
portion (instead of returning the parsed header length).
This commit is contained in:
Abtin Keshavarzian
2022-07-14 17:04:47 -07:00
committed by GitHub
parent 366786dbed
commit 13416b15fb
15 changed files with 736 additions and 411 deletions
+82 -44
View File
@@ -145,12 +145,14 @@ static void Init(void)
*/
static void Test(TestIphcVector &aVector, bool aCompress, bool aDecompress)
{
Message *message = nullptr;
uint8_t result[512];
uint8_t iphc[512];
uint8_t ip6[512];
uint16_t iphcLength;
uint16_t ip6Length;
Message * message = nullptr;
uint8_t result[512];
uint8_t iphc[512];
uint8_t ip6[512];
uint16_t iphcLength;
uint16_t ip6Length;
FrameData frameData;
Error error;
aVector.GetCompressedStream(iphc, iphcLength);
aVector.GetUncompressedStream(ip6, ip6Length);
@@ -223,28 +225,29 @@ static void Test(TestIphcVector &aVector, bool aCompress, bool aDecompress)
{
VerifyOrQuit((message = sInstance->Get<MessagePool>().Allocate(Message::kTypeIp6)) != nullptr);
int decompressedBytes =
sLowpan->Decompress(*message, aVector.mMacSource, aVector.mMacDestination, iphc, iphcLength, 0);
frameData.Init(iphc, iphcLength);
error = sLowpan->Decompress(*message, aVector.mMacSource, aVector.mMacDestination, frameData, 0);
message->ReadBytes(0, result, message->GetLength());
if (aVector.mError == kErrorNone)
{
SuccessOrQuit(error, "Lowpan::Decompress failed");
// Append payload to the IPv6 Packet.
memcpy(result + message->GetLength(), iphc + decompressedBytes,
iphcLength - static_cast<uint16_t>(decompressedBytes));
memcpy(result + message->GetLength(), frameData.GetBytes(), frameData.GetLength());
DumpBuffer("Resulted IPv6 uncompressed packet", result,
message->GetLength() + iphcLength - static_cast<uint16_t>(decompressedBytes));
DumpBuffer("Resulted IPv6 uncompressed packet", result, message->GetLength() + frameData.GetLength());
VerifyOrQuit(decompressedBytes == aVector.mIphcHeader.mLength, "Lowpan::Decompress failed");
VerifyOrQuit((frameData.GetBytes() - iphc) == aVector.mIphcHeader.mLength, "Lowpan::Decompress failed");
VerifyOrQuit(message->GetOffset() == aVector.mPayloadOffset, "Lowpan::Decompress failed");
VerifyOrQuit(message->GetOffset() == message->GetLength(), "Lowpan::Decompress failed");
VerifyOrQuit(memcmp(ip6, result, ip6Length) == 0, "Lowpan::Decompress failed");
}
else
{
VerifyOrQuit(decompressedBytes < 0, "Lowpan::Decompress failed");
VerifyOrQuit(error == kErrorParse, "Lowpan::Decompress failed");
}
message->Free();
@@ -1864,7 +1867,7 @@ void TestLowpanMeshHeader(void)
uint8_t frame[kMaxFrameSize];
uint16_t length;
uint16_t headerLength;
FrameData frameData;
Lowpan::MeshHeader meshHeader;
meshHeader.Init(kSourceAddr, kDestAddr, 1);
@@ -1878,14 +1881,17 @@ void TestLowpanMeshHeader(void)
VerifyOrQuit(memcmp(frame, kMeshHeader1, length) == 0, "MeshHeader::WriteTo() failed");
memset(&meshHeader, 0, sizeof(meshHeader));
VerifyOrQuit(Lowpan::MeshHeader::IsMeshHeader(frame, length));
SuccessOrQuit(meshHeader.ParseFrom(frame, length, headerLength));
VerifyOrQuit(headerLength == length, "MeshHeader::ParseFrom() returned length is incorrect");
frameData.Init(frame, length);
VerifyOrQuit(Lowpan::MeshHeader::IsMeshHeader(frameData));
SuccessOrQuit(meshHeader.ParseFrom(frameData));
VerifyOrQuit(frameData.GetLength() == 0, "ParseFrom() did not skip over parsed content");
VerifyOrQuit(frameData.GetBytes() - frame == length, "ParseFrom() did not skip over parsed content");
VerifyOrQuit(meshHeader.GetSource() == kSourceAddr, "failed after ParseFrom()");
VerifyOrQuit(meshHeader.GetDestination() == kDestAddr, "failed after ParseFrom()");
VerifyOrQuit(meshHeader.GetHopsLeft() == 1, "failed after ParseFrom()");
VerifyOrQuit(meshHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
frameData.Init(frame, length - 1);
VerifyOrQuit(meshHeader.ParseFrom(frameData) == kErrorParse,
"MeshHeader::ParseFrom() did not fail with incorrect length");
//- - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1901,27 +1907,34 @@ void TestLowpanMeshHeader(void)
VerifyOrQuit(memcmp(frame, kMeshHeader2, length) == 0, "MeshHeader::WriteTo() failed");
memset(&meshHeader, 0, sizeof(meshHeader));
VerifyOrQuit(Lowpan::MeshHeader::IsMeshHeader(frame, length));
SuccessOrQuit(meshHeader.ParseFrom(frame, length, headerLength));
VerifyOrQuit(headerLength == length, "MeshHeader::ParseFrom() returned length is incorrect");
frameData.Init(frame, length);
VerifyOrQuit(Lowpan::MeshHeader::IsMeshHeader(frameData));
SuccessOrQuit(meshHeader.ParseFrom(frameData));
VerifyOrQuit(frameData.GetLength() == 0, "ParseFrom() did not skip over parsed content");
VerifyOrQuit(frameData.GetBytes() - frame == length, "ParseFrom() did not skip over parsed content");
VerifyOrQuit(meshHeader.GetSource() == kSourceAddr, "failed after ParseFrom()");
VerifyOrQuit(meshHeader.GetDestination() == kDestAddr, "failed after ParseFrom()");
VerifyOrQuit(meshHeader.GetHopsLeft() == 0x20, "failed after ParseFrom()");
VerifyOrQuit(meshHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
frameData.Init(frame, length - 1);
VerifyOrQuit(meshHeader.ParseFrom(frameData) == kErrorParse,
"MeshHeader::ParseFrom() did not fail with incorrect length");
//- - - - - - - - - - - - - - - - - - - - - - - - - -
SuccessOrQuit(meshHeader.ParseFrom(kMeshHeader3, sizeof(kMeshHeader3), headerLength));
VerifyOrQuit(headerLength == sizeof(kMeshHeader3), "MeshHeader::ParseFrom() returned length is incorrect");
length = sizeof(kMeshHeader3);
frameData.Init(kMeshHeader3, sizeof(kMeshHeader3));
SuccessOrQuit(meshHeader.ParseFrom(frameData));
VerifyOrQuit(frameData.GetLength() == 0, "ParseFrom() did not skip over parsed content");
VerifyOrQuit(frameData.GetBytes() - kMeshHeader3 == length, "ParseFrom() did not skip over parsed content");
VerifyOrQuit(meshHeader.GetSource() == kSourceAddr, "failed after ParseFrom()");
VerifyOrQuit(meshHeader.GetDestination() == kDestAddr, "failed after ParseFrom()");
VerifyOrQuit(meshHeader.GetHopsLeft() == 1, "failed after ParseFrom()");
VerifyOrQuit(meshHeader.WriteTo(frame) == sizeof(kMeshHeader1));
VerifyOrQuit(meshHeader.ParseFrom(kMeshHeader3, sizeof(kMeshHeader3) - 1, headerLength) == kErrorParse,
frameData.Init(kMeshHeader3, sizeof(kMeshHeader3) - 1);
VerifyOrQuit(meshHeader.ParseFrom(frameData) == kErrorParse,
"MeshHeader::ParseFrom() did not fail with incorrect length");
}
@@ -1945,7 +1958,7 @@ void TestLowpanFragmentHeader(void)
uint8_t frame[kMaxFrameSize];
uint16_t length;
uint16_t headerLength;
FrameData frameData;
Lowpan::FragmentHeader fragHeader;
fragHeader.InitFirstFragment(kSize, kTag);
@@ -1960,15 +1973,21 @@ void TestLowpanFragmentHeader(void)
VerifyOrQuit(memcmp(frame, kFragHeader1, length) == 0, "FragmentHeader::WriteTo() failed");
memset(&fragHeader, 0, sizeof(fragHeader));
VerifyOrQuit(Lowpan::FragmentHeader::IsFragmentHeader(frame, length));
SuccessOrQuit(fragHeader.ParseFrom(frame, length, headerLength));
VerifyOrQuit(headerLength == length, "FragmentHeader::ParseFrom() returned length is incorrect");
frameData.Init(frame, length);
VerifyOrQuit(Lowpan::FragmentHeader::IsFragmentHeader(frameData));
SuccessOrQuit(fragHeader.ParseFrom(frameData));
VerifyOrQuit(frameData.GetLength() == 0, "ParseFrom() did not skip over parsed content");
VerifyOrQuit(frameData.GetBytes() - frame == length, "ParseFrom() did not skip over parsed content");
VerifyOrQuit(fragHeader.GetDatagramSize() == kSize, "failed after ParseFrom()");
VerifyOrQuit(fragHeader.GetDatagramTag() == kTag, "failed after ParseFrom()");
VerifyOrQuit(fragHeader.GetDatagramOffset() == 0, "failed after ParseFrom()");
VerifyOrQuit(fragHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
frameData.Init(frame, length - 1);
VerifyOrQuit(fragHeader.ParseFrom(frameData) == kErrorParse,
"FragmentHeader::ParseFrom() did not fail with incorrect length");
VerifyOrQuit(frameData.GetLength() == length - 1);
VerifyOrQuit(frameData.GetBytes() == frame);
//- - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1990,51 +2009,70 @@ void TestLowpanFragmentHeader(void)
VerifyOrQuit(memcmp(frame, kFragHeader2, length) == 0, "FragmentHeader::WriteTo() failed");
memset(&fragHeader, 0, sizeof(fragHeader));
VerifyOrQuit(Lowpan::FragmentHeader::IsFragmentHeader(frame, length));
SuccessOrQuit(fragHeader.ParseFrom(frame, length, headerLength));
VerifyOrQuit(headerLength == length, "FragmentHeader::ParseFrom() returned length is incorrect");
frameData.Init(frame, length);
VerifyOrQuit(Lowpan::FragmentHeader::IsFragmentHeader(frameData));
SuccessOrQuit(fragHeader.ParseFrom(frameData));
VerifyOrQuit(frameData.GetLength() == 0, "ParseFrom() did not skip over parsed content");
VerifyOrQuit(frameData.GetBytes() - frame == length, "ParseFrom() did not skip over parsed content");
VerifyOrQuit(fragHeader.GetDatagramSize() == kSize, "failed after ParseFrom()");
VerifyOrQuit(fragHeader.GetDatagramTag() == kTag, "failed after ParseFrom()");
VerifyOrQuit(fragHeader.GetDatagramOffset() == kOffset, "failed after ParseFrom()");
VerifyOrQuit(fragHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
frameData.Init(frame, length - 1);
VerifyOrQuit(fragHeader.ParseFrom(frameData) == kErrorParse,
"FragmentHeader::ParseFrom() did not fail with incorrect length");
VerifyOrQuit(frameData.GetLength() == length - 1);
VerifyOrQuit(frameData.GetBytes() == frame);
//- - - - - - - - - - - - - - - - - - - - - - - - - -
length = sizeof(kFragHeader3);
memcpy(frame, kFragHeader3, length);
SuccessOrQuit(fragHeader.ParseFrom(frame, length, headerLength));
VerifyOrQuit(headerLength == length, "FragmentHeader::ParseFrom() returned length is incorrect");
frameData.Init(frame, length);
SuccessOrQuit(fragHeader.ParseFrom(frameData));
VerifyOrQuit(frameData.GetLength() == 0, "ParseFrom() did not skip over parsed content");
VerifyOrQuit(frameData.GetBytes() - frame == length, "ParseFrom() did not skip over parsed content");
VerifyOrQuit(fragHeader.GetDatagramSize() == kSize, "failed after ParseFrom()");
VerifyOrQuit(fragHeader.GetDatagramTag() == kTag, "failed after ParseFrom()");
VerifyOrQuit(fragHeader.GetDatagramOffset() == 0, "failed after ParseFrom()");
VerifyOrQuit(fragHeader.ParseFrom(frame, length - 1, headerLength) == kErrorParse,
frameData.Init(frame, length - 1);
VerifyOrQuit(fragHeader.ParseFrom(frameData) == kErrorParse,
"FragmentHeader::ParseFrom() did not fail with incorrect length");
VerifyOrQuit(frameData.GetLength() == length - 1);
VerifyOrQuit(frameData.GetBytes() == frame);
//- - - - - - - - - - - - - - - - - - - - - - - - - -
length = sizeof(kInvalidFragHeader1);
memcpy(frame, kInvalidFragHeader1, length);
VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frame, length),
frameData.Init(frame, length);
VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frameData),
"IsFragmentHeader() did not detect invalid header");
VerifyOrQuit(fragHeader.ParseFrom(frame, length, headerLength) != kErrorNone,
VerifyOrQuit(fragHeader.ParseFrom(frameData) != kErrorNone,
"FragmentHeader::ParseFrom() did not fail with invalid header");
VerifyOrQuit(frameData.GetLength() == length);
VerifyOrQuit(frameData.GetBytes() == frame);
length = sizeof(kInvalidFragHeader2);
memcpy(frame, kInvalidFragHeader2, length);
VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frame, length),
frameData.Init(frame, length);
VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frameData),
"IsFragmentHeader() did not detect invalid header");
VerifyOrQuit(fragHeader.ParseFrom(frame, length, headerLength) != kErrorNone,
VerifyOrQuit(fragHeader.ParseFrom(frameData) != kErrorNone,
"FragmentHeader::ParseFrom() did not fail with invalid header");
VerifyOrQuit(frameData.GetLength() == length);
VerifyOrQuit(frameData.GetBytes() == frame);
length = sizeof(kInvalidFragHeader3);
memcpy(frame, kInvalidFragHeader3, length);
VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frame, length),
frameData.Init(frame, length);
VerifyOrQuit(!Lowpan::FragmentHeader::IsFragmentHeader(frameData),
"IsFragmentHeader() did not detect invalid header");
VerifyOrQuit(fragHeader.ParseFrom(frame, length, headerLength) != kErrorNone,
VerifyOrQuit(fragHeader.ParseFrom(frameData) != kErrorNone,
"FragmentHeader::ParseFrom() did not fail with invalid header");
VerifyOrQuit(frameData.GetLength() == length);
VerifyOrQuit(frameData.GetBytes() == frame);
}
} // namespace ot