[mesh-forwarder] track parsed IPv6 header in RxInfo (#10467)

This commit adds an `Ip6::Header` field to `RxInfo`, along with the
`ParseIp6Headers()` method to decompress and parse the IPv6 headers
from the received frame. `RxInfo` now tracks whether the headers have
been parsed before.

The IPv6 headers may be parsed from different code paths as the
received frame is processed. For example, `UpdateRoutes()`,
`GetFramePriority()`, and `CheckReachability()` may parse the IPv6
headers. By having `RxInfo` cache the parsed IPv6 headers,
duplicate parsing is avoided.
This commit is contained in:
Abtin Keshavarzian
2024-07-08 15:04:37 -07:00
committed by GitHub
parent 528784caa5
commit 9ac67520f2
3 changed files with 53 additions and 34 deletions
+25 -13
View File
@@ -1371,10 +1371,22 @@ exit:
return didRemove;
}
Error MeshForwarder::RxInfo::ParseIp6Headers(void)
{
Error error = kErrorNone;
VerifyOrExit(!mParsedIp6Headers);
SuccessOrExit(error = mIp6Headers.DecompressFrom(mFrameData, mMacAddrs, GetInstance()));
mParsedIp6Headers = true;
exit:
return error;
}
void MeshForwarder::HandleReceivedFrame(Mac::RxFrame &aFrame)
{
Error error = kErrorNone;
RxInfo rxInfo;
RxInfo rxInfo(GetInstance());
VerifyOrExit(mEnabled, error = kErrorInvalidState);
@@ -1610,7 +1622,7 @@ bool MeshForwarder::UpdateReassemblyList(void)
return mReassemblyList.GetHead() != nullptr;
}
Error MeshForwarder::FrameToMessage(const RxInfo &aRxInfo, uint16_t aDatagramSize, Message *&aMessage)
Error MeshForwarder::FrameToMessage(RxInfo &aRxInfo, uint16_t aDatagramSize, Message *&aMessage)
{
Error error = kErrorNone;
FrameData frameData = aRxInfo.mFrameData;
@@ -1630,7 +1642,7 @@ exit:
return error;
}
void MeshForwarder::HandleLowpanHc(const RxInfo &aRxInfo)
void MeshForwarder::HandleLowpanHc(RxInfo &aRxInfo)
{
Error error = kErrorNone;
Message *message = nullptr;
@@ -1681,32 +1693,32 @@ Error MeshForwarder::HandleDatagram(Message &aMessage, const Mac::Address &aMacS
return Get<Ip6::Ip6>().HandleDatagram(OwnedPtr<Message>(&aMessage));
}
Error MeshForwarder::GetFramePriority(const RxInfo &aRxInfo, Message::Priority &aPriority)
Error MeshForwarder::GetFramePriority(RxInfo &aRxInfo, Message::Priority &aPriority)
{
Error error = kErrorNone;
Ip6::Headers headers;
Error error = kErrorNone;
SuccessOrExit(error = headers.DecompressFrom(aRxInfo.mFrameData, aRxInfo.mMacAddrs, GetInstance()));
SuccessOrExit(error = aRxInfo.ParseIp6Headers());
aPriority = Ip6::Ip6::DscpToPriority(headers.GetIp6Header().GetDscp());
aPriority = Ip6::Ip6::DscpToPriority(aRxInfo.mIp6Headers.GetIp6Header().GetDscp());
// Only ICMPv6 error messages are prioritized.
if (headers.IsIcmp6() && headers.GetIcmpHeader().IsError())
if (aRxInfo.mIp6Headers.IsIcmp6() && aRxInfo.mIp6Headers.GetIcmpHeader().IsError())
{
aPriority = Message::kPriorityNet;
}
if (headers.IsUdp())
if (aRxInfo.mIp6Headers.IsUdp())
{
uint16_t destPort = headers.GetUdpHeader().GetDestinationPort();
uint16_t destPort = aRxInfo.mIp6Headers.GetUdpHeader().GetDestinationPort();
if (destPort == Mle::kUdpPort)
{
aPriority = Message::kPriorityNet;
}
else if (Get<Tmf::Agent>().IsTmfMessage(headers.GetSourceAddress(), headers.GetDestinationAddress(), destPort))
else if (Get<Tmf::Agent>().IsTmfMessage(aRxInfo.mIp6Headers.GetSourceAddress(),
aRxInfo.mIp6Headers.GetDestinationAddress(), destPort))
{
aPriority = Tmf::Agent::DscpToPriority(headers.GetIp6Header().GetDscp());
aPriority = Tmf::Agent::DscpToPriority(aRxInfo.mIp6Headers.GetIp6Header().GetDscp());
}
}
+15 -6
View File
@@ -411,20 +411,29 @@ private:
kAnycastService,
};
struct RxInfo
struct RxInfo : public InstanceLocator
{
static constexpr uint16_t kInfoStringSize = 70;
typedef String<kInfoStringSize> InfoString;
explicit RxInfo(Instance &aInstance)
: InstanceLocator(aInstance)
, mParsedIp6Headers(false)
{
}
const Mac::Address &GetSrcAddr(void) const { return mMacAddrs.mSource; }
const Mac::Address &GetDstAddr(void) const { return mMacAddrs.mDestination; }
bool IsLinkSecurityEnabled(void) const { return mLinkInfo.IsLinkSecurityEnabled(); }
Error ParseIp6Headers(void);
InfoString ToString(void) const;
FrameData mFrameData;
ThreadLinkInfo mLinkInfo;
Mac::Addresses mMacAddrs;
Ip6::Headers mIp6Headers;
bool mParsedIp6Headers;
};
#if OPENTHREAD_FTD
@@ -507,17 +516,17 @@ private:
#endif
void SendIcmpErrorIfDstUnreach(const Message &aMessage, const Mac::Addresses &aMacAddrs);
Error CheckReachability(const RxInfo &aRxInfo);
Error CheckReachability(RxInfo &aRxInfo);
Error CheckReachability(uint16_t aMeshDest, const Ip6::Header &aIp6Header);
void UpdateRoutes(const RxInfo &aRxInfo);
Error FrameToMessage(const RxInfo &aRxInfo, uint16_t aDatagramSize, Message *&aMessage);
void UpdateRoutes(RxInfo &aRxInfo);
Error FrameToMessage(RxInfo &aRxInfo, uint16_t aDatagramSize, Message *&aMessage);
void GetMacDestinationAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr);
void GetMacSourceAddress(const Ip6::Address &aIp6Addr, Mac::Address &aMacAddr);
Message *PrepareNextDirectTransmission(void);
void HandleMesh(RxInfo &aRxInfo);
void ResolveRoutingLoops(uint16_t aSourceRloc16, uint16_t aDestRloc16);
void HandleFragment(RxInfo &aRxInfo);
void HandleLowpanHc(const RxInfo &aRxInfo);
void HandleLowpanHc(RxInfo &aRxInfo);
void PrepareMacHeaders(Mac::TxFrame &aFrame,
Mac::Frame::Type aFrameType,
@@ -576,7 +585,7 @@ private:
void HandleTimeTick(void);
void ScheduleTransmissionTask(void);
Error GetFramePriority(const RxInfo &aRxInfo, Message::Priority &aPriority);
Error GetFramePriority(RxInfo &aRxInfo, Message::Priority &aPriority);
Error GetFragmentPriority(Lowpan::FragmentHeader &aFragmentHeader,
uint16_t aSrcRloc16,
Message::Priority &aPriority);
+13 -15
View File
@@ -641,12 +641,11 @@ exit:
return;
}
Error MeshForwarder::CheckReachability(const RxInfo &aRxInfo)
Error MeshForwarder::CheckReachability(RxInfo &aRxInfo)
{
Error error;
Ip6::Headers ip6Headers;
Error error;
error = ip6Headers.DecompressFrom(aRxInfo.mFrameData, aRxInfo.mMacAddrs, GetInstance());
error = aRxInfo.ParseIp6Headers();
switch (error)
{
@@ -660,11 +659,11 @@ Error MeshForwarder::CheckReachability(const RxInfo &aRxInfo)
ExitNow();
}
error = CheckReachability(aRxInfo.GetDstAddr().GetShort(), ip6Headers.GetIp6Header());
error = CheckReachability(aRxInfo.GetDstAddr().GetShort(), aRxInfo.mIp6Headers.GetIp6Header());
if (error == kErrorNoRoute)
{
SendDestinationUnreachable(aRxInfo.GetSrcAddr().GetShort(), ip6Headers);
SendDestinationUnreachable(aRxInfo.GetSrcAddr().GetShort(), aRxInfo.mIp6Headers);
}
exit:
@@ -819,27 +818,26 @@ exit:
return;
}
void MeshForwarder::UpdateRoutes(const RxInfo &aRxInfo)
void MeshForwarder::UpdateRoutes(RxInfo &aRxInfo)
{
Ip6::Headers ip6Headers;
Neighbor *neighbor;
Neighbor *neighbor;
VerifyOrExit(!aRxInfo.GetDstAddr().IsBroadcast() && aRxInfo.GetSrcAddr().IsShort());
SuccessOrExit(ip6Headers.DecompressFrom(aRxInfo.mFrameData, aRxInfo.mMacAddrs, GetInstance()));
SuccessOrExit(aRxInfo.ParseIp6Headers());
if (!ip6Headers.GetSourceAddress().GetIid().IsLocator() &&
Get<NetworkData::Leader>().IsOnMesh(ip6Headers.GetSourceAddress()))
if (!aRxInfo.mIp6Headers.GetSourceAddress().GetIid().IsLocator() &&
Get<NetworkData::Leader>().IsOnMesh(aRxInfo.mIp6Headers.GetSourceAddress()))
{
// FTDs MAY add/update EID-to-RLOC Map Cache entries by
// inspecting packets being received only for on mesh
// addresses.
Get<AddressResolver>().UpdateSnoopedCacheEntry(ip6Headers.GetSourceAddress(), aRxInfo.GetSrcAddr().GetShort(),
aRxInfo.GetDstAddr().GetShort());
Get<AddressResolver>().UpdateSnoopedCacheEntry(
aRxInfo.mIp6Headers.GetSourceAddress(), aRxInfo.GetSrcAddr().GetShort(), aRxInfo.GetDstAddr().GetShort());
}
neighbor = Get<NeighborTable>().FindNeighbor(ip6Headers.GetSourceAddress());
neighbor = Get<NeighborTable>().FindNeighbor(aRxInfo.mIp6Headers.GetSourceAddress());
VerifyOrExit(neighbor != nullptr && !neighbor->IsFullThreadDevice());
if (!Get<Mle::Mle>().HasMatchingRouterIdWith(aRxInfo.GetSrcAddr().GetShort()))