1 /*
2  *  Copyright (c) 2019, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file implements local Backbone Router service.
32  */
33 
34 #include "bbr_local.hpp"
35 
36 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
37 
38 #include "instance/instance.hpp"
39 
40 namespace ot {
41 
42 namespace BackboneRouter {
43 
44 RegisterLogModule("BbrLocal");
45 
Local(Instance & aInstance)46 Local::Local(Instance &aInstance)
47     : InstanceLocator(aInstance)
48     , mIsServiceAdded(false)
49     , mState(kStateDisabled)
50     , mSequenceNumber(Random::NonCrypto::GetUint8() % 127)
51     , mRegistrationJitter(kDefaultRegistrationJitter)
52     , mReregistrationDelay(kDefaultRegistrationDelay)
53     , mRegistrationTimeout(0)
54     , mMlrTimeout(kDefaultMlrTimeout)
55 {
56     mDomainPrefixConfig.GetPrefix().SetLength(0);
57 
58     // Primary Backbone Router Aloc
59     mBbrPrimaryAloc.InitAsThreadOriginMeshLocal();
60     mBbrPrimaryAloc.GetAddress().GetIid().SetToLocator(Mle::kAloc16BackboneRouterPrimary);
61 
62     // All Network Backbone Routers Multicast Address.
63     mAllNetworkBackboneRouters.Clear();
64 
65     mAllNetworkBackboneRouters.mFields.m8[0]  = 0xff; // Multicast
66     mAllNetworkBackboneRouters.mFields.m8[1]  = 0x32; // Flags = 3, Scope = 2
67     mAllNetworkBackboneRouters.mFields.m8[15] = 3;    // Group ID = 3
68 
69     // All Domain Backbone Routers Multicast Address.
70     mAllDomainBackboneRouters.Clear();
71 
72     mAllDomainBackboneRouters.mFields.m8[0]  = 0xff; // Multicast
73     mAllDomainBackboneRouters.mFields.m8[1]  = 0x32; // Flags = 3, Scope = 2
74     mAllDomainBackboneRouters.mFields.m8[15] = 3;    // Group ID = 3
75 }
76 
SetEnabled(bool aEnable)77 void Local::SetEnabled(bool aEnable)
78 {
79     VerifyOrExit(aEnable != IsEnabled());
80 
81     if (aEnable)
82     {
83         SetState(kStateSecondary);
84         AddDomainPrefixToNetworkData();
85         IgnoreError(AddService(kDecideBasedOnState));
86     }
87     else
88     {
89         RemoveDomainPrefixFromNetworkData();
90         RemoveService();
91         SetState(kStateDisabled);
92     }
93 
94 exit:
95     return;
96 }
97 
Reset(void)98 void Local::Reset(void)
99 {
100     VerifyOrExit(mState != kStateDisabled);
101 
102     RemoveService();
103 
104     if (mState == kStatePrimary)
105     {
106         // Increase sequence number when changing from Primary to Secondary.
107         IncrementSequenceNumber();
108         Get<Notifier>().Signal(kEventThreadBackboneRouterLocalChanged);
109         SetState(kStateSecondary);
110     }
111 
112 exit:
113     return;
114 }
115 
GetConfig(Config & aConfig) const116 void Local::GetConfig(Config &aConfig) const
117 {
118     aConfig.mSequenceNumber      = mSequenceNumber;
119     aConfig.mReregistrationDelay = mReregistrationDelay;
120     aConfig.mMlrTimeout          = mMlrTimeout;
121 }
122 
SetConfig(const Config & aConfig)123 Error Local::SetConfig(const Config &aConfig)
124 {
125     Error error  = kErrorNone;
126     bool  update = false;
127 
128 #if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
129     VerifyOrExit(aConfig.mMlrTimeout >= kMinMlrTimeout && aConfig.mMlrTimeout <= kMaxMlrTimeout,
130                  error = kErrorInvalidArgs);
131 #endif
132     // Validate configuration according to Thread 1.2.1 Specification 5.21.3.3:
133     // "The Reregistration Delay in seconds MUST be lower than (0.5 * MLR Timeout). It MUST be at least 1."
134     VerifyOrExit(aConfig.mReregistrationDelay >= 1, error = kErrorInvalidArgs);
135     static_assert(sizeof(aConfig.mReregistrationDelay) < sizeof(aConfig.mMlrTimeout),
136                   "the calculation below might overflow");
137     VerifyOrExit(aConfig.mReregistrationDelay * 2 < aConfig.mMlrTimeout, error = kErrorInvalidArgs);
138 
139     if (aConfig.mReregistrationDelay != mReregistrationDelay)
140     {
141         mReregistrationDelay = aConfig.mReregistrationDelay;
142         update               = true;
143     }
144 
145     if (aConfig.mMlrTimeout != mMlrTimeout)
146     {
147         mMlrTimeout = aConfig.mMlrTimeout;
148         update      = true;
149     }
150 
151     if (aConfig.mSequenceNumber != mSequenceNumber)
152     {
153         mSequenceNumber = aConfig.mSequenceNumber;
154         update          = true;
155     }
156 
157     if (update)
158     {
159         Get<Notifier>().Signal(kEventThreadBackboneRouterLocalChanged);
160 
161         IgnoreError(AddService(kDecideBasedOnState));
162     }
163 
164 exit:
165     LogService(kActionSet, error);
166     return error;
167 }
168 
AddService(RegisterMode aMode)169 Error Local::AddService(RegisterMode aMode)
170 {
171     Error error = kErrorInvalidState;
172 
173     VerifyOrExit(mState != kStateDisabled && Get<Mle::Mle>().IsAttached());
174 
175     switch (aMode)
176     {
177     case kDecideBasedOnState:
178         VerifyOrExit(!Get<BackboneRouter::Leader>().HasPrimary() ||
179                      Get<BackboneRouter::Leader>().GetServer16() == Get<Mle::MleRouter>().GetRloc16());
180         break;
181     case kForceRegistration:
182         break;
183     }
184 
185     SuccessOrExit(error = Get<NetworkData::Service::Manager>().AddBackboneRouterService(
186                       mSequenceNumber, mReregistrationDelay, mMlrTimeout));
187     Get<NetworkData::Notifier>().HandleServerDataUpdated();
188 
189     mIsServiceAdded = true;
190 
191 exit:
192     LogService(kActionAdd, error);
193     return error;
194 }
195 
RemoveService(void)196 void Local::RemoveService(void)
197 {
198     Error error;
199 
200     SuccessOrExit(error = Get<NetworkData::Service::Manager>().RemoveBackboneRouterService());
201     Get<NetworkData::Notifier>().HandleServerDataUpdated();
202     mIsServiceAdded = false;
203 
204 exit:
205     LogService(kActionRemove, error);
206 }
207 
SetState(State aState)208 void Local::SetState(State aState)
209 {
210     VerifyOrExit(mState != aState);
211 
212     switch (mState)
213     {
214     case kStateDisabled:
215         // Update All Network Backbone Routers Multicast Address for both Secondary and Primary state.
216         mAllNetworkBackboneRouters.SetMulticastNetworkPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
217         break;
218     case kStateSecondary:
219         break;
220     case kStatePrimary:
221         Get<ThreadNetif>().RemoveUnicastAddress(mBbrPrimaryAloc);
222         break;
223     }
224 
225     if (aState == kStatePrimary)
226     {
227         // Add Primary Backbone Router ALOC for Primary Backbone Router.
228         mBbrPrimaryAloc.GetAddress().SetPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
229         Get<ThreadNetif>().AddUnicastAddress(mBbrPrimaryAloc);
230     }
231 
232     mState = aState;
233 
234     Get<Notifier>().Signal(kEventThreadBackboneRouterStateChanged);
235 
236 exit:
237     return;
238 }
239 
HandleBackboneRouterPrimaryUpdate(Leader::State aState,const Config & aConfig)240 void Local::HandleBackboneRouterPrimaryUpdate(Leader::State aState, const Config &aConfig)
241 {
242     OT_UNUSED_VARIABLE(aState);
243 
244     VerifyOrExit(IsEnabled() && Get<Mle::MleRouter>().IsAttached());
245 
246     // Wait some jitter before trying to Register.
247     if (aConfig.mServer16 == Mle::kInvalidRloc16)
248     {
249         mRegistrationTimeout = 1;
250 
251         if (!Get<Mle::MleRouter>().IsLeader())
252         {
253             mRegistrationTimeout +=
254                 Random::NonCrypto::GetUint16InRange(0, static_cast<uint16_t>(mRegistrationJitter) + 1);
255         }
256 
257         Get<TimeTicker>().RegisterReceiver(TimeTicker::kBbrLocal);
258     }
259     else if (aConfig.mServer16 != Get<Mle::MleRouter>().GetRloc16())
260     {
261         Reset();
262     }
263     else if (!mIsServiceAdded)
264     {
265         // Here original PBBR restores its Backbone Router Service from Thread Network,
266         // Intentionally skips the state update as PBBR will refresh its service.
267         mSequenceNumber      = aConfig.mSequenceNumber;
268         mReregistrationDelay = aConfig.mReregistrationDelay;
269         mMlrTimeout          = aConfig.mMlrTimeout;
270         IncrementSequenceNumber();
271         Get<Notifier>().Signal(kEventThreadBackboneRouterLocalChanged);
272         IgnoreError(AddService(kForceRegistration));
273     }
274     else
275     {
276         SetState(kStatePrimary);
277     }
278 
279 exit:
280     return;
281 }
282 
HandleTimeTick(void)283 void Local::HandleTimeTick(void)
284 {
285     // Delay registration while router role transition is pending
286     // (i.e., device may soon switch from REED to router role).
287 
288     VerifyOrExit(!Get<Mle::MleRouter>().IsRouterRoleTransitionPending());
289 
290     if (mRegistrationTimeout > 0)
291     {
292         mRegistrationTimeout--;
293 
294         if (mRegistrationTimeout == 0)
295         {
296             IgnoreError(AddService(kDecideBasedOnState));
297         }
298     }
299 
300 exit:
301     if (mRegistrationTimeout == 0)
302     {
303         Get<TimeTicker>().UnregisterReceiver(TimeTicker::kBbrLocal);
304     }
305 }
306 
GetDomainPrefix(NetworkData::OnMeshPrefixConfig & aConfig)307 Error Local::GetDomainPrefix(NetworkData::OnMeshPrefixConfig &aConfig)
308 {
309     Error error = kErrorNone;
310 
311     VerifyOrExit(mDomainPrefixConfig.GetPrefix().GetLength() > 0, error = kErrorNotFound);
312 
313     aConfig = mDomainPrefixConfig;
314 
315 exit:
316     return error;
317 }
318 
RemoveDomainPrefix(const Ip6::Prefix & aPrefix)319 Error Local::RemoveDomainPrefix(const Ip6::Prefix &aPrefix)
320 {
321     Error error = kErrorNone;
322 
323     VerifyOrExit(aPrefix.GetLength() > 0, error = kErrorInvalidArgs);
324     VerifyOrExit(mDomainPrefixConfig.GetPrefix() == aPrefix, error = kErrorNotFound);
325 
326     if (IsEnabled())
327     {
328         RemoveDomainPrefixFromNetworkData();
329     }
330 
331     mDomainPrefixConfig.GetPrefix().SetLength(0);
332 
333 exit:
334     return error;
335 }
336 
SetDomainPrefix(const NetworkData::OnMeshPrefixConfig & aConfig)337 Error Local::SetDomainPrefix(const NetworkData::OnMeshPrefixConfig &aConfig)
338 {
339     Error error = kErrorNone;
340 
341     VerifyOrExit(aConfig.IsValid(GetInstance()), error = kErrorInvalidArgs);
342 
343     if (IsEnabled())
344     {
345         RemoveDomainPrefixFromNetworkData();
346     }
347 
348     mDomainPrefixConfig = aConfig;
349     LogDomainPrefix(kActionSet, kErrorNone);
350 
351     if (IsEnabled())
352     {
353         AddDomainPrefixToNetworkData();
354     }
355 
356 exit:
357     return error;
358 }
359 
ApplyNewMeshLocalPrefix(void)360 void Local::ApplyNewMeshLocalPrefix(void)
361 {
362     VerifyOrExit(IsEnabled());
363 
364     Get<BackboneTmfAgent>().UnsubscribeMulticast(mAllNetworkBackboneRouters);
365     mAllNetworkBackboneRouters.SetMulticastNetworkPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
366     Get<BackboneTmfAgent>().SubscribeMulticast(mAllNetworkBackboneRouters);
367 
368 exit:
369     return;
370 }
371 
HandleDomainPrefixUpdate(DomainPrefixEvent aEvent)372 void Local::HandleDomainPrefixUpdate(DomainPrefixEvent aEvent)
373 {
374     if (!IsEnabled())
375     {
376         ExitNow();
377     }
378 
379     if (aEvent == kDomainPrefixRemoved || aEvent == kDomainPrefixRefreshed)
380     {
381         Get<BackboneTmfAgent>().UnsubscribeMulticast(mAllDomainBackboneRouters);
382     }
383 
384     if (aEvent == kDomainPrefixAdded || aEvent == kDomainPrefixRefreshed)
385     {
386         mAllDomainBackboneRouters.SetMulticastNetworkPrefix(*Get<Leader>().GetDomainPrefix());
387         Get<BackboneTmfAgent>().SubscribeMulticast(mAllDomainBackboneRouters);
388     }
389 
390     if (aEvent != kDomainPrefixUnchanged)
391     {
392         mDomainPrefixCallback.InvokeIfSet(static_cast<otBackboneRouterDomainPrefixEvent>(aEvent),
393                                           Get<Leader>().GetDomainPrefix());
394     }
395 
396 exit:
397     return;
398 }
399 
RemoveDomainPrefixFromNetworkData(void)400 void Local::RemoveDomainPrefixFromNetworkData(void)
401 {
402     Error error = kErrorNotFound; // only used for logging.
403 
404     if (mDomainPrefixConfig.mPrefix.mLength > 0)
405     {
406         error = Get<NetworkData::Local>().RemoveOnMeshPrefix(mDomainPrefixConfig.GetPrefix());
407     }
408 
409     LogDomainPrefix(kActionRemove, error);
410 }
411 
IncrementSequenceNumber(void)412 void Local::IncrementSequenceNumber(void)
413 {
414     switch (mSequenceNumber)
415     {
416     case 126:
417     case 127:
418         mSequenceNumber = 0;
419         break;
420     case 254:
421     case 255:
422         mSequenceNumber = 128;
423         break;
424     default:
425         mSequenceNumber++;
426         break;
427     }
428 }
429 
AddDomainPrefixToNetworkData(void)430 void Local::AddDomainPrefixToNetworkData(void)
431 {
432     Error error = kErrorNotFound; // only used for logging.
433 
434     if (mDomainPrefixConfig.GetPrefix().GetLength() > 0)
435     {
436         error = Get<NetworkData::Local>().AddOnMeshPrefix(mDomainPrefixConfig);
437     }
438 
439     LogDomainPrefix(kActionAdd, error);
440 }
441 
442 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
443 
ActionToString(Action aAction)444 const char *Local::ActionToString(Action aAction)
445 {
446     static const char *const kActionStrings[] = {
447         "Set",    // (0) kActionSet
448         "Add",    // (1) kActionAdd
449         "Remove", // (2) kActionRemove
450     };
451 
452     struct EnumCheck
453     {
454         InitEnumValidatorCounter();
455         ValidateNextEnum(kActionSet);
456         ValidateNextEnum(kActionAdd);
457         ValidateNextEnum(kActionRemove);
458     };
459 
460     return kActionStrings[aAction];
461 }
462 
LogDomainPrefix(Action aAction,Error aError)463 void Local::LogDomainPrefix(Action aAction, Error aError)
464 {
465     LogInfo("%s Domain Prefix: %s, %s", ActionToString(aAction), mDomainPrefixConfig.GetPrefix().ToString().AsCString(),
466             ErrorToString(aError));
467 }
468 
LogService(Action aAction,Error aError)469 void Local::LogService(Action aAction, Error aError)
470 {
471     LogInfo("%s BBR Service: seqno (%u), delay (%us), timeout (%lus), %s", ActionToString(aAction), mSequenceNumber,
472             mReregistrationDelay, ToUlong(mMlrTimeout), ErrorToString(aError));
473 }
474 
475 #endif
476 
477 } // namespace BackboneRouter
478 
479 } // namespace ot
480 
481 #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
482