Skip to content

Commit

Permalink
[dhcp6-pd] stop PrefixManager when RoutingManager is stopped (ope…
Browse files Browse the repository at this point in the history
…nthread#9608)

When InfraIf is down and we received a RA from the host interface, we
may trigger the EvaluateRoutingPolicy unexpectly.

This might happen when infra if and uplink are separate interfaces.

This commit fixes this by adding Start and Stop to `PdPrefixManager`
to start / stop handling RA messages.
  • Loading branch information
erjiaqing authored Nov 28, 2023
1 parent 4b593f9 commit dc616d6
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 18 deletions.
81 changes: 72 additions & 9 deletions src/core/border_router/routing_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,9 @@ void RoutingManager::Start(void)
mOmrPrefixManager.Start();
mRoutePublisher.Start();
mRsSender.Start();
#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
mPdPrefixManager.Start();
#endif
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
mNat64PrefixManager.Start();
#endif
Expand All @@ -354,7 +357,9 @@ void RoutingManager::Stop(void)

mOmrPrefixManager.Stop();
mOnLinkPrefixManager.Stop();

#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
mPdPrefixManager.Stop();
#endif
#if OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE
mNat64PrefixManager.Stop();
#endif
Expand Down Expand Up @@ -3429,14 +3434,76 @@ void RoutingManager::RsSender::HandleTimer(void)
}

#if OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
const char *RoutingManager::PdPrefixManager::StateToString(Dhcp6PdState aState)
{
static const char *const kStateStrings[] = {
"Disabled", // (0) kDisabled
"Stopped", // (1) kStopped
"Running", // (2) kRunning
};

static_assert(0 == kDhcp6PdStateDisabled, "kDhcp6PdStateDisabled value is incorrect");
static_assert(1 == kDhcp6PdStateStopped, "kDhcp6PdStateStopped value is incorrect");
static_assert(2 == kDhcp6PdStateRunning, "kDhcp6PdStateRunning value is incorrect");

return kStateStrings[aState];
}

RoutingManager::PdPrefixManager::PdPrefixManager(Instance &aInstance)
: InstanceLocator(aInstance)
, mEnabled(false)
, mIsRunning(false)
, mTimer(aInstance)
{
mPrefix.Clear();
}

void RoutingManager::PdPrefixManager::StartStop(bool aStart)
{
Dhcp6PdState oldState = GetState();

VerifyOrExit(aStart != mIsRunning);
mIsRunning = aStart;
EvaluateStateChange(oldState);

exit:
return;
}

RoutingManager::Dhcp6PdState RoutingManager::PdPrefixManager::GetState(void) const
{
Dhcp6PdState state = kDhcp6PdStateDisabled;

if (mEnabled)
{
state = mIsRunning ? kDhcp6PdStateRunning : kDhcp6PdStateStopped;
}

return state;
}

void RoutingManager::PdPrefixManager::EvaluateStateChange(Dhcp6PdState aOldState)
{
Dhcp6PdState newState = GetState();

VerifyOrExit(aOldState != newState);
LogInfo("PdPrefixManager: %s -> %s", StateToString(aOldState), StateToString(newState));

// TODO: We may also want to inform the platform that PD is stopped.
switch (newState)
{
case kDhcp6PdStateDisabled:
case kDhcp6PdStateStopped:
WithdrawPrefix();
break;
case kDhcp6PdStateRunning:
break;
}

exit:
return;
}

Error RoutingManager::PdPrefixManager::GetPrefixInfo(PrefixTableEntry &aInfo) const
{
Error error = kErrorNone;
Expand Down Expand Up @@ -3472,7 +3539,7 @@ void RoutingManager::PdPrefixManager::ProcessPlatformGeneratedRa(const uint8_t *
Error error = kErrorNone;
Ip6::Nd::RouterAdvertMessage::Icmp6Packet packet;

VerifyOrExit(mEnabled, LogWarn("Ignore platform generated RA since PD is disabled."));
VerifyOrExit(IsRunning(), LogWarn("Ignore platform generated RA since PD is disabled or not running."));
packet.Init(aRouterAdvert, aLength);
error = Process(Ip6::Nd::RouterAdvertMessage(packet));

Expand Down Expand Up @@ -3563,15 +3630,11 @@ Error RoutingManager::PdPrefixManager::Process(const Ip6::Nd::RouterAdvertMessag

void RoutingManager::PdPrefixManager::SetEnabled(bool aEnabled)
{
VerifyOrExit(mEnabled != aEnabled);
Dhcp6PdState oldState = GetState();

VerifyOrExit(mEnabled != aEnabled);
mEnabled = aEnabled;
if (!aEnabled)
{
WithdrawPrefix();
}

LogInfo("PdPrefixManager is %s", aEnabled ? "enabled" : "disabled");
EvaluateStateChange(oldState);

exit:
return;
Expand Down
20 changes: 11 additions & 9 deletions src/core/border_router/routing_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ class RoutingManager : public InstanceLocator
*/
enum Dhcp6PdState : uint8_t
{
kDhcp6PdStateDisabled = OT_BORDER_ROUTING_STATE_DISABLED, ///< Disabled.
kDhcp6PdStateStopped = OT_BORDER_ROUTING_STATE_STOPPED, ///< Enabled, but currently stopped.
kDhcp6PdStateRunning = OT_BORDER_ROUTING_STATE_RUNNING, ///< Enabled, and running.
kDhcp6PdStateDisabled = OT_BORDER_ROUTING_DHCP6_PD_STATE_DISABLED, ///< Disabled.
kDhcp6PdStateStopped = OT_BORDER_ROUTING_DHCP6_PD_STATE_STOPPED, ///< Enabled, but currently stopped.
kDhcp6PdStateRunning = OT_BORDER_ROUTING_DHCP6_PD_STATE_RUNNING, ///< Enabled, and running.
};

/**
Expand Down Expand Up @@ -1169,20 +1169,19 @@ class RoutingManager : public InstanceLocator
explicit PdPrefixManager(Instance &aInstance);

void SetEnabled(bool aEnabled);
void Start(void) { StartStop(/* aStart= */ true); }
void Stop(void) { StartStop(/* aStart= */ false); }
bool IsRunning(void) const { return GetState() == Dhcp6PdState::kDhcp6PdStateRunning; }
bool HasPrefix(void) const { return IsValidOmrPrefix(mPrefix.GetPrefix()); }
const Ip6::Prefix &GetPrefix(void) const { return mPrefix.GetPrefix(); }
Dhcp6PdState GetState(void) const
{
// TODO: We need to stop and inform the platform when there is already a GUA prefix advertised in the
// network.
return mEnabled ? kDhcp6PdStateRunning : kDhcp6PdStateDisabled;
}
Dhcp6PdState GetState(void) const;

void ProcessPlatformGeneratedRa(const uint8_t *aRouterAdvert, uint16_t aLength);
Error GetPrefixInfo(PrefixTableEntry &aInfo) const;
void HandleTimer(void) { WithdrawPrefix(); }

static const char *StateToString(Dhcp6PdState aState);

static bool IsValidPdPrefix(const Ip6::Prefix &aPrefix)
{
// We should accept ULA prefix since it could be used by the internet infrastructure like NAT64.
Expand All @@ -1192,11 +1191,14 @@ class RoutingManager : public InstanceLocator

private:
Error Process(const Ip6::Nd::RouterAdvertMessage &aMessage);
void EvaluateStateChange(Dhcp6PdState aOldState);
void WithdrawPrefix(void);
void StartStop(bool aStart);

using PlatformOmrPrefixTimer = TimerMilliIn<RoutingManager, &RoutingManager::HandlePdPrefixManagerTimer>;

bool mEnabled;
bool mIsRunning;
PlatformOmrPrefixTimer mTimer;
DiscoveredPrefixTable::Entry mPrefix;
};
Expand Down

0 comments on commit dc616d6

Please sign in to comment.