From c5108df3e3a4537b7b54602fb6f8182c74306693 Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Fri, 27 Mar 2026 16:42:01 -0500 Subject: [PATCH] [bbr] fix primary BBR registration flakiness on leader (#12783) This commit fixes an intermittent failure in the Nexus test 1_2_BBR_TC_2 by ensuring that the Backbone Router (BBR) service is registered immediately when a node assumes the Leader role and no primary BBR is active. Previously, BbrLeader only tracked network data changes, and BbrLocal applied a mandatory jitter delay before registration. This created a race condition where another node could register its BBR service before the new Leader, causing the Leader to incorrectly skip its own registration. Changes: - Update BbrLeader to monitor role changes (kEventThreadRoleChanged). - Modify BbrLocal to bypass registration jitter if the node is the Leader and there is no existing primary BBR. --- src/core/backbone_router/bbr_leader.cpp | 2 +- src/core/backbone_router/bbr_local.cpp | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/core/backbone_router/bbr_leader.cpp b/src/core/backbone_router/bbr_leader.cpp index 3dfa4fb20..46b80eb0a 100644 --- a/src/core/backbone_router/bbr_leader.cpp +++ b/src/core/backbone_router/bbr_leader.cpp @@ -127,7 +127,7 @@ const char *Leader::DomainPrefixEventToString(DomainPrefixEvent aEvent) void Leader::HandleNotifierEvents(Events aEvents) { - if (aEvents.Contains(kEventThreadNetdataChanged)) + if (aEvents.ContainsAny(kEventThreadNetdataChanged | kEventThreadRoleChanged)) { UpdateBackboneRouterPrimary(); UpdateDomainPrefixConfig(); diff --git a/src/core/backbone_router/bbr_local.cpp b/src/core/backbone_router/bbr_local.cpp index bb21ede56..0b317677c 100644 --- a/src/core/backbone_router/bbr_local.cpp +++ b/src/core/backbone_router/bbr_local.cpp @@ -246,15 +246,18 @@ void Local::HandleBackboneRouterPrimaryUpdate(Leader::State aState, const Config // Wait some jitter before trying to Register. if (aConfig.mServer16 == Mle::kInvalidRloc16) { - mRegistrationTimeout = 1; - - if (!Get().IsLeader()) + if (Get().IsLeader()) { - mRegistrationTimeout += - Random::NonCrypto::GetUint16InRange(0, static_cast(mRegistrationJitter) + 1); + mRegistrationTimeout = 0; + Get().UnregisterReceiver(TimeTicker::kBbrLocal); + IgnoreError(AddService(kDecideBasedOnState)); + } + else + { + mRegistrationTimeout = + 1 + Random::NonCrypto::GetUint16InRange(0, static_cast(mRegistrationJitter)); + Get().RegisterReceiver(TimeTicker::kBbrLocal); } - - Get().RegisterReceiver(TimeTicker::kBbrLocal); } else if (aConfig.mServer16 != Get().GetRloc16()) {