mirror of
https://github.com/espressif/openthread.git
synced 2026-08-03 01:17:46 +00:00
[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:
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()))
|
||||
|
||||
Reference in New Issue
Block a user