[routing-manager] track origin of received RA messages (#10229)

This commit adds `RouterAdvOrigin` enumeration to track the origin of
a received RA message, whether it is from another router on the
infrastructure, or self-generated by either the `RoutingManager`
module or another software entity running on the device.

This is used to exclude prefixes from self-generated `RoutingManager`
RAs in the prefix table and simplifies learning and adopting of RA
headers from other software entities on the same device.

The origin is now logged when a new RA is received for improved
debugging.

This commit also updates `test_routing_manager` to pass back any sent
RA messages to the OT stack. This validates the mechanism for
identifying self-generated RA messages.
This commit is contained in:
Abtin Keshavarzian
2024-05-14 11:04:56 -07:00
committed by GitHub
parent e47973a753
commit e27885ecb4
3 changed files with 59 additions and 26 deletions
+45 -24
View File
@@ -699,7 +699,7 @@ void RoutingManager::HandleRsSenderFinished(TimeMilli aStartTime)
if (mRaInfo.mHeaderUpdateTime <= aStartTime)
{
UpdateRouterAdvertHeader(/* aRouterAdvertMessage */ nullptr);
UpdateRouterAdvertHeader(/* aRouterAdvertMessage */ nullptr, kThisBrOtherEntity);
}
ScheduleRoutingPolicyEvaluation(kImmediately);
@@ -737,26 +737,29 @@ exit:
void RoutingManager::HandleRouterAdvertisement(const InfraIf::Icmp6Packet &aPacket, const Ip6::Address &aSrcAddress)
{
RouterAdvert::RxMessage routerAdvMessage(aPacket);
RouterAdvert::RxMessage raMsg(aPacket);
RouterAdvOrigin raOrigin = kAnotherRouter;
OT_ASSERT(mIsRunning);
VerifyOrExit(routerAdvMessage.IsValid());
VerifyOrExit(raMsg.IsValid());
Get<Ip6::Ip6>().GetBorderRoutingCounters().mRaRx++;
LogInfo("Received RA from %s on %s", aSrcAddress.ToString().AsCString(), mInfraIf.ToString().AsCString());
DumpDebg("[BR-CERT] direction=recv | type=RA |", aPacket.GetBytes(), aPacket.GetLength());
mDiscoveredPrefixTable.ProcessRouterAdvertMessage(routerAdvMessage, aSrcAddress);
// Remember the header and parameters of RA messages which are
// initiated from the infra interface.
if (mInfraIf.HasAddress(aSrcAddress))
{
UpdateRouterAdvertHeader(&routerAdvMessage);
raOrigin = mRaInfo.IsRaFromManager(raMsg) ? kThisBrRoutingManager : kThisBrOtherEntity;
}
LogInfo("Received RA from %s on %s %s", aSrcAddress.ToString().AsCString(), mInfraIf.ToString().AsCString(),
RouterAdvOriginToString(raOrigin));
DumpDebg("[BR-CERT] direction=recv | type=RA |", aPacket.GetBytes(), aPacket.GetLength());
mDiscoveredPrefixTable.ProcessRouterAdvertMessage(raMsg, aSrcAddress, raOrigin);
UpdateRouterAdvertHeader(&raMsg, raOrigin);
exit:
return;
}
@@ -885,24 +888,18 @@ bool RoutingManager::NetworkDataContainsUlaRoute(void) const
return contains;
}
void RoutingManager::UpdateRouterAdvertHeader(const RouterAdvert::RxMessage *aRouterAdvertMessage)
void RoutingManager::UpdateRouterAdvertHeader(const RouterAdvert::RxMessage *aRaMsg, RouterAdvOrigin aRaOrigin)
{
// Updates the `mRaInfo` from the given RA message.
RouterAdvert::Header oldHeader;
if (aRouterAdvertMessage != nullptr)
{
// We skip and do not update RA header if the received RA message
// was not prepared and sent by `RoutingManager` itself.
VerifyOrExit(!mRaInfo.IsRaFromManager(*aRouterAdvertMessage));
}
VerifyOrExit(aRaOrigin == kThisBrOtherEntity);
oldHeader = mRaInfo.mHeader;
mRaInfo.mHeaderUpdateTime = TimerMilli::GetNow();
if (aRouterAdvertMessage == nullptr || aRouterAdvertMessage->GetHeader().GetRouterLifetime() == 0)
if (aRaMsg == nullptr || aRaMsg->GetHeader().GetRouterLifetime() == 0)
{
mRaInfo.mHeader.SetToDefault();
mRaInfo.mIsHeaderFromHost = false;
@@ -913,7 +910,7 @@ void RoutingManager::UpdateRouterAdvertHeader(const RouterAdvert::RxMessage *aRo
// which indicates to platform that it needs to do the
// calculation and update it.
mRaInfo.mHeader = aRouterAdvertMessage->GetHeader();
mRaInfo.mHeader = aRaMsg->GetHeader();
mRaInfo.mHeader.SetChecksum(0);
mRaInfo.mIsHeaderFromHost = true;
}
@@ -970,6 +967,7 @@ void RoutingManager::ResetDiscoveredPrefixStaleTimer(void)
}
#if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
void RoutingManager::LogPrefixInfoOption(const Ip6::Prefix &aPrefix,
uint32_t aValidLifetime,
uint32_t aPreferredLifetime)
@@ -983,10 +981,28 @@ void RoutingManager::LogRouteInfoOption(const Ip6::Prefix &aPrefix, uint32_t aLi
LogInfo("- RIO %s (lifetime:%lu, prf:%s)", aPrefix.ToString().AsCString(), ToUlong(aLifetime),
RoutePreferenceToString(aPreference));
}
const char *RoutingManager::RouterAdvOriginToString(RouterAdvOrigin aRaOrigin)
{
static const char *const kOriginStrings[] = {
"", // (0) kAnotherRouter
"(this BR routing-manager)", // (1) kThisBrRoutingManager
"(this BR other sw entity)", // (2) kThisBrOtherEntity
};
static_assert(0 == kAnotherRouter, "kAnotherRouter value is incorrect");
static_assert(1 == kThisBrRoutingManager, "kThisBrRoutingManager value is incorrect");
static_assert(2 == kThisBrOtherEntity, "kThisBrOtherEntity value is incorrect");
return kOriginStrings[aRaOrigin];
}
#else
void RoutingManager::LogPrefixInfoOption(const Ip6::Prefix &, uint32_t, uint32_t) {}
void RoutingManager::LogRouteInfoOption(const Ip6::Prefix &, uint32_t, RoutePreference) {}
#endif
#endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
//---------------------------------------------------------------------------------------------------------------------
// LifetimedPrefix
@@ -1118,11 +1134,16 @@ RoutingManager::DiscoveredPrefixTable::DiscoveredPrefixTable(Instance &aInstance
}
void RoutingManager::DiscoveredPrefixTable::ProcessRouterAdvertMessage(const RouterAdvert::RxMessage &aRaMessage,
const Ip6::Address &aSrcAddress)
const Ip6::Address &aSrcAddress,
RouterAdvOrigin aRaOrigin)
{
// Process a received RA message and update the prefix table.
Router *router = mRouters.FindMatching(aSrcAddress);
Router *router;
VerifyOrExit(aRaOrigin != kThisBrRoutingManager);
router = mRouters.FindMatching(aSrcAddress);
if (router == nullptr)
{
+13 -2
View File
@@ -629,6 +629,13 @@ private:
kAdvPrefixesFromNetData,
};
enum RouterAdvOrigin : uint8_t // Origin of a received Router Advert message.
{
kAnotherRouter, // From another router on infra-if.
kThisBrRoutingManager, // From this BR generated by `RoutingManager` itself.
kThisBrOtherEntity, // From this BR generated by another sw entity.
};
enum ScheduleMode : uint8_t // Used in `ScheduleRoutingPolicyEvaluation()`
{
kImmediately,
@@ -738,7 +745,9 @@ private:
public:
explicit DiscoveredPrefixTable(Instance &aInstance);
void ProcessRouterAdvertMessage(const RouterAdvert::RxMessage &aRaMessage, const Ip6::Address &aSrcAddress);
void ProcessRouterAdvertMessage(const RouterAdvert::RxMessage &aRaMessage,
const Ip6::Address &aSrcAddress,
RouterAdvOrigin aRaOrigin);
void ProcessNeighborAdvertMessage(const NeighborAdvertMessage &aNaMessage);
bool ContainsDefaultOrNonUlaRoutePrefix(void) const;
@@ -1392,7 +1401,7 @@ private:
void UpdateDiscoveredPrefixTableOnNetDataChange(void);
bool NetworkDataContainsOmrPrefix(const Ip6::Prefix &aPrefix) const;
bool NetworkDataContainsUlaRoute(void) const;
void UpdateRouterAdvertHeader(const RouterAdvert::RxMessage *aRouterAdvertMessage);
void UpdateRouterAdvertHeader(const RouterAdvert::RxMessage *aRaMsg, RouterAdvOrigin aRaOrigin);
void ResetDiscoveredPrefixStaleTimer(void);
static bool IsValidBrUlaPrefix(const Ip6::Prefix &aBrUlaPrefix);
@@ -1402,6 +1411,8 @@ private:
static void LogPrefixInfoOption(const Ip6::Prefix &aPrefix, uint32_t aValidLifetime, uint32_t aPreferredLifetime);
static void LogRouteInfoOption(const Ip6::Prefix &aPrefix, uint32_t aLifetime, RoutePreference aPreference);
static const char *RouterAdvOriginToString(RouterAdvOrigin aRaOrigin);
//------------------------------------------------------------------------------------------------------------------
// Variables
+1
View File
@@ -317,6 +317,7 @@ otError otPlatInfraIfSendIcmp6Nd(uint32_t aInfraIfIndex,
Log(" Router Advertisement message");
LogRouterAdvert(packet);
ValidateRouterAdvert(packet);
otPlatInfraIfRecvIcmp6Nd(sInstance, kInfraIfIndex, &sInfraIfAddress, aBuffer, aBufferLength);
break;
case Ip6::Icmp::Header::kTypeNeighborSolicit: