[mesh-forwarder] simplify GetFramePriority() (#5282)

This commit simplifies the `GetFramePriority()` implementation
mainly avoiding copying of ICMP6/UDP header when possible.

It also updates unit test `test-toolchain` to verify alignment
behavior of packed structure.
This commit is contained in:
Abtin Keshavarzian
2020-07-23 12:54:44 -07:00
committed by GitHub
parent 2efe99c507
commit c89fd9a8f5
2 changed files with 92 additions and 31 deletions
+35 -25
View File
@@ -1242,12 +1242,11 @@ otError MeshForwarder::GetFramePriority(const uint8_t * aFrame,
const Mac::Address &aMacDest,
Message::Priority & aPriority)
{
otError error = OT_ERROR_NONE;
Ip6::Header ip6Header;
Ip6::Udp::Header udpHeader;
Ip6::Icmp::Header icmpHeader;
uint8_t headerLength;
bool nextHeaderCompressed;
otError error = OT_ERROR_NONE;
Ip6::Header ip6Header;
uint16_t dstPort;
uint8_t headerLength;
bool nextHeaderCompressed;
SuccessOrExit(error = DecompressIp6Header(aFrame, aFrameLength, aMacSource, aMacDest, ip6Header, headerLength,
nextHeaderCompressed));
@@ -1256,35 +1255,46 @@ otError MeshForwarder::GetFramePriority(const uint8_t * aFrame,
aFrame += headerLength;
aFrameLength -= headerLength;
if (ip6Header.GetNextHeader() == Ip6::kProtoIcmp6 && aFrameLength)
switch (ip6Header.GetNextHeader())
{
// Just check the first byte which is an ICMPv6 type.
memcpy(&icmpHeader, aFrame, sizeof(icmpHeader.mType));
case Ip6::kProtoIcmp6:
VerifyOrExit(aFrameLength >= sizeof(Ip6::Icmp::Header), error = OT_ERROR_PARSE);
// Only ICMPv6 error messages are prioritized.
if (icmpHeader.IsError())
if (reinterpret_cast<const Ip6::Icmp::Header *>(aFrame)->IsError())
{
aPriority = Message::kPriorityNet;
}
ExitNow();
}
break;
VerifyOrExit(ip6Header.GetNextHeader() == Ip6::kProtoUdp, OT_NOOP);
case Ip6::kProtoUdp:
if (nextHeaderCompressed)
{
VerifyOrExit(Get<Lowpan::Lowpan>().DecompressUdpHeader(udpHeader, aFrame, aFrameLength) >= 0, OT_NOOP);
}
else
{
VerifyOrExit(aFrameLength >= sizeof(Ip6::Udp::Header), error = OT_ERROR_PARSE);
memcpy(&udpHeader, aFrame, sizeof(Ip6::Udp::Header));
}
if (nextHeaderCompressed)
{
Ip6::Udp::Header udpHeader;
if (udpHeader.GetDestinationPort() == Mle::kUdpPort || udpHeader.GetDestinationPort() == kCoapUdpPort)
{
aPriority = Message::kPriorityNet;
VerifyOrExit(Get<Lowpan::Lowpan>().DecompressUdpHeader(udpHeader, aFrame, aFrameLength) >= 0,
error = OT_ERROR_PARSE);
dstPort = udpHeader.GetDestinationPort();
}
else
{
VerifyOrExit(aFrameLength >= sizeof(Ip6::Udp::Header), error = OT_ERROR_PARSE);
dstPort = reinterpret_cast<const Ip6::Udp::Header *>(aFrame)->GetDestinationPort();
}
if ((dstPort == Mle::kUdpPort) || (dstPort == kCoapUdpPort))
{
aPriority = Message::kPriorityNet;
}
break;
default:
break;
}
exit:
+57 -6
View File
@@ -41,7 +41,7 @@ uint32_t otNetifAddress_offset_mNext_c();
otNetifAddress CreateNetif_c();
}
void test_packed1()
void test_packed1(void)
{
OT_TOOL_PACKED_BEGIN
struct packed_t
@@ -56,7 +56,7 @@ void test_packed1()
VerifyOrQuit(sizeof(packed_t) == 7, "Toolchain::OT_TOOL_PACKED failed 1");
}
void test_packed2()
void test_packed2(void)
{
OT_TOOL_PACKED_BEGIN
struct packed_t
@@ -70,7 +70,7 @@ void test_packed2()
VerifyOrQuit(sizeof(packed_t) == 4, "Toolchain::OT_TOOL_PACKED failed 2");
}
void test_packed_union()
void test_packed_union(void)
{
typedef struct
{
@@ -93,7 +93,7 @@ void test_packed_union()
VerifyOrQuit(sizeof(packed_t) == 5, "Toolchain::OT_TOOL_PACKED failed 3");
}
void test_packed_enum()
void test_packed_enum(void)
{
ot::Neighbor neighbor;
neighbor.SetState(ot::Neighbor::kStateValid);
@@ -102,18 +102,68 @@ void test_packed_enum()
VerifyOrQuit(neighbor.GetState() == ot::Neighbor::kStateValid, "Toolchain::OT_TOOL_PACKED failed 4");
}
void test_addr_sizes()
void test_addr_sizes(void)
{
VerifyOrQuit(offsetof(otNetifAddress, mNext) == otNetifAddress_offset_mNext_c(),
"mNext should offset the same in C & C++");
VerifyOrQuit(sizeof(otNetifAddress) == otNetifAddress_Size_c(), "otNetifAddress should the same in C & C++");
}
void test_addr_bitfield()
void test_addr_bitfield(void)
{
VerifyOrQuit(CreateNetif_c().mScopeOverrideValid == true, "Toolchain::test_addr_size_cpp");
}
void test_packed_alignment(void)
{
OT_TOOL_PACKED_BEGIN
struct PackedStruct
{
uint32_t mUint32;
uint8_t mByte;
uint16_t mUint16;
} OT_TOOL_PACKED_END;
PackedStruct packedStruct;
PackedStruct packedStructCopy;
const uint8_t *packedStructBytes = reinterpret_cast<const uint8_t *>(&packedStruct);
uint8_t buffer[sizeof(PackedStruct) * 2 + 1];
VerifyOrQuit(sizeof(PackedStruct) == 7, "Toolchain::OT_TOOL_PACKED failed");
packedStruct.mUint32 = 0x12345678;
packedStruct.mByte = 0xfe;
packedStruct.mUint16 = 0xabcd;
for (uint16_t start = 0; start < sizeof(PackedStruct); start++)
{
uint8_t *ptr = &buffer[start];
memset(buffer, 0, sizeof(buffer));
*reinterpret_cast<PackedStruct *>(ptr) = packedStruct;
for (uint16_t i = 0; i < start; i++)
{
VerifyOrQuit(buffer[i] == 0, "Toolchain::OT_TOOL_PACKED alignment failed - pre-size write");
}
VerifyOrQuit(memcmp(ptr, packedStructBytes, sizeof(PackedStruct)) == 0,
"Toolchain::OT_TOOL_PACKED alignment failed");
for (uint16_t i = start + sizeof(packedStruct); i < sizeof(buffer); i++)
{
VerifyOrQuit(buffer[i] == 0, "Toolchain::OT_TOOL_PACKED alignment failed - post-size write");
}
memset(&packedStructCopy, 0, sizeof(PackedStruct));
packedStructCopy = *reinterpret_cast<PackedStruct *>(ptr);
VerifyOrQuit(memcmp(&packedStructCopy, &packedStruct, sizeof(PackedStruct)) == 0,
"Toolchain::OT_TOOL_PACKED failed - read error");
}
}
void TestToolchain(void)
{
test_packed1();
@@ -122,6 +172,7 @@ void TestToolchain(void)
test_packed_enum();
test_addr_sizes();
test_addr_bitfield();
test_packed_alignment();
}
int main(void)