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 "common/code_utils.hpp"
39 #include "common/locator_getters.hpp"
40 #include "common/log.hpp"
41 #include "common/random.hpp"
42 #include "instance/instance.hpp"
43 #include "thread/mle_types.hpp"
44 #include "thread/thread_netif.hpp"
45 
46 namespace ot {
47 
48 namespace BackboneRouter {
49 
50 RegisterLogModule("BbrLocal");
51 
Local(Instance & aInstance)52 Local::Local(Instance &aInstance)
53     : InstanceLocator(aInstance)
54     , mIsServiceAdded(false)
55     , mState(kStateDisabled)
56     , mSequenceNumber(Random::NonCrypto::GetUint8() % 127)
57     , mRegistrationJitter(kDefaultRegistrationJitter)
58     , mReregistrationDelay(kDefaultRegistrationDelay)
59     , mRegistrationTimeout(0)
60     , mMlrTimeout(kDefaultMlrTimeout)
61 {
62     mDomainPrefixConfig.GetPrefix().SetLength(0);
63 
64     // Primary Backbone Router Aloc
65     mBbrPrimaryAloc.InitAsThreadOriginMeshLocal();
66     mBbrPrimaryAloc.GetAddress().GetIid().SetToLocator(Mle::kAloc16BackboneRouterPrimary);
67 
68     // All Network Backbone Routers Multicast Address.
69     mAllNetworkBackboneRouters.Clear();
70 
71     mAllNetworkBackboneRouters.mFields.m8[0]  = 0xff; // Multicast
72     mAllNetworkBackboneRouters.mFields.m8[1]  = 0x32; // Flags = 3, Scope = 2
73     mAllNetworkBackboneRouters.mFields.m8[15] = 3;    // Group ID = 3
74 
75     // All Domain Backbone Routers Multicast Address.
76     mAllDomainBackboneRouters.Clear();
77 
78     mAllDomainBackboneRouters.mFields.m8[0]  = 0xff; // Multicast
79     mAllDomainBackboneRouters.mFields.m8[1]  = 0x32; // Flags = 3, Scope = 2
80     mAllDomainBackboneRouters.mFields.m8[15] = 3;    // Group ID = 3
81 }
82 
SetEnabled(bool aEnable)83 void Local::SetEnabled(bool aEnable)
84 {
85     VerifyOrExit(aEnable != IsEnabled());
86 
87     if (aEnable)
88     {
89         SetState(kStateSecondary);
90         AddDomainPrefixToNetworkData();
91         IgnoreError(AddService(kDecideBasedOnState));
92     }
93     else
94     {
95         RemoveDomainPrefixFromNetworkData();
96         RemoveService();
97         SetState(kStateDisabled);
98     }
99 
100 exit:
101     return;
102 }
103 
Reset(void)104 void Local::Reset(void)
105 {
106     VerifyOrExit(mState != kStateDisabled);
107 
108     RemoveService();
109 
110     if (mState == kStatePrimary)
111     {
112         // Increase sequence number when changing from Primary to Secondary.
113         IncrementSequenceNumber();
114         Get<Notifier>().Signal(kEventThreadBackboneRouterLocalChanged);
115         SetState(kStateSecondary);
116     }
117 
118 exit:
119     return;
120 }
121 
GetConfig(Config & aConfig) const122 void Local::GetConfig(Config &aConfig) const
123 {
124     aConfig.mSequenceNumber      = mSequenceNumber;
125     aConfig.mReregistrationDelay = mReregistrationDelay;
126     aConfig.mMlrTimeout          = mMlrTimeout;
127 }
128 
SetConfig(const Config & aConfig)129 Error Local::SetConfig(const Config &aConfig)
130 {
131     Error error  = kErrorNone;
132     bool  update = false;
133 
134 #if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
135     VerifyOrExit(aConfig.mMlrTimeout >= kMinMlrTimeout && aConfig.mMlrTimeout <= kMaxMlrTimeout,
136                  error = kErrorInvalidArgs);
137 #endif
138     // Validate configuration according to Thread 1.2.1 Specification 5.21.3.3:
139     // "The Reregistration Delay in seconds MUST be lower than (0.5 * MLR Timeout). It MUST be at least 1."
140     VerifyOrExit(aConfig.mReregistrationDelay >= 1, error = kErrorInvalidArgs);
141     static_assert(sizeof(aConfig.mReregistrationDelay) < sizeof(aConfig.mMlrTimeout),
142                   "the calculation below might overflow");
143     VerifyOrExit(aConfig.mReregistrationDelay * 2 < aConfig.mMlrTimeout, error = kErrorInvalidArgs);
144 
145     if (aConfig.mReregistrationDelay != mReregistrationDelay)
146     {
147         mReregistrationDelay = aConfig.mReregistrationDelay;
148         update               = true;
149     }
150 
151     if (aConfig.mMlrTimeout != mMlrTimeout)
152     {
153         mMlrTimeout = aConfig.mMlrTimeout;
154         update      = true;
155     }
156 
157     if (aConfig.mSequenceNumber != mSequenceNumber)
158     {
159         mSequenceNumber = aConfig.mSequenceNumber;
160         update          = true;
161     }
162 
163     if (update)
164     {
165         Get<Notifier>().Signal(kEventThreadBackboneRouterLocalChanged);
166 
167         IgnoreError(AddService(kDecideBasedOnState));
168     }
169 
170 exit:
171     LogService(kActionSet, error);
172     return error;
173 }
174 
AddService(RegisterMode aMode)175 Error Local::AddService(RegisterMode aMode)
176 {
177     Error                                            error = kErrorInvalidState;
178     NetworkData::Service::BackboneRouter::ServerData serverData;
179 
180     VerifyOrExit(mState != kStateDisabled && Get<Mle::Mle>().IsAttached());
181 
182     switch (aMode)
183     {
184     case kDecideBasedOnState:
185         VerifyOrExit(!Get<BackboneRouter::Leader>().HasPrimary() ||
186                      Get<BackboneRouter::Leader>().GetServer16() == Get<Mle::MleRouter>().GetRloc16());
187         break;
188     case kForceRegistration:
189         break;
190     }
191 
192     serverData.SetSequenceNumber(mSequenceNumber);
193     serverData.SetReregistrationDelay(mReregistrationDelay);
194     serverData.SetMlrTimeout(mMlrTimeout);
195 
196     SuccessOrExit(error = Get<NetworkData::Service::Manager>().Add<NetworkData::Service::BackboneRouter>(serverData));
197     Get<NetworkData::Notifier>().HandleServerDataUpdated();
198 
199     mIsServiceAdded = true;
200 
201 exit:
202     LogService(kActionAdd, error);
203     return error;
204 }
205 
RemoveService(void)206 void Local::RemoveService(void)
207 {
208     Error error;
209 
210     SuccessOrExit(error = Get<NetworkData::Service::Manager>().Remove<NetworkData::Service::BackboneRouter>());
211     Get<NetworkData::Notifier>().HandleServerDataUpdated();
212     mIsServiceAdded = false;
213 
214 exit:
215     LogService(kActionRemove, error);
216 }
217 
SetState(State aState)218 void Local::SetState(State aState)
219 {
220     VerifyOrExit(mState != aState);
221 
222     switch (mState)
223     {
224     case kStateDisabled:
225         // Update All Network Backbone Routers Multicast Address for both Secondary and Primary state.
226         mAllNetworkBackboneRouters.SetMulticastNetworkPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
227         break;
228     case kStateSecondary:
229         break;
230     case kStatePrimary:
231         Get<ThreadNetif>().RemoveUnicastAddress(mBbrPrimaryAloc);
232         break;
233     }
234 
235     if (aState == kStatePrimary)
236     {
237         // Add Primary Backbone Router ALOC for Primary Backbone Router.
238         mBbrPrimaryAloc.GetAddress().SetPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
239         Get<ThreadNetif>().AddUnicastAddress(mBbrPrimaryAloc);
240     }
241 
242     mState = aState;
243 
244     Get<Notifier>().Signal(kEventThreadBackboneRouterStateChanged);
245 
246 exit:
247     return;
248 }
249 
HandleBackboneRouterPrimaryUpdate(Leader::State aState,const Config & aConfig)250 void Local::HandleBackboneRouterPrimaryUpdate(Leader::State aState, const Config &aConfig)
251 {
252     OT_UNUSED_VARIABLE(aState);
253 
254     VerifyOrExit(IsEnabled() && Get<Mle::MleRouter>().IsAttached());
255 
256     // Wait some jitter before trying to Register.
257     if (aConfig.mServer16 == Mac::kShortAddrInvalid)
258     {
259         mRegistrationTimeout = 1;
260 
261         if (!Get<Mle::MleRouter>().IsLeader())
262         {
263             mRegistrationTimeout +=
264                 Random::NonCrypto::GetUint16InRange(0, static_cast<uint16_t>(mRegistrationJitter) + 1);
265         }
266 
267         Get<TimeTicker>().RegisterReceiver(TimeTicker::kBbrLocal);
268     }
269     else if (aConfig.mServer16 != Get<Mle::MleRouter>().GetRloc16())
270     {
271         Reset();
272     }
273     else if (!mIsServiceAdded)
274     {
275         // Here original PBBR restores its Backbone Router Service from Thread Network,
276         // Intentionally skips the state update as PBBR will refresh its service.
277         mSequenceNumber      = aConfig.mSequenceNumber;
278         mReregistrationDelay = aConfig.mReregistrationDelay;
279         mMlrTimeout          = aConfig.mMlrTimeout;
280         IncrementSequenceNumber();
281         Get<Notifier>().Signal(kEventThreadBackboneRouterLocalChanged);
282         IgnoreError(AddService(kForceRegistration));
283     }
284     else
285     {
286         SetState(kStatePrimary);
287     }
288 
289 exit:
290     return;
291 }
292 
HandleTimeTick(void)293 void Local::HandleTimeTick(void)
294 {
295     // Delay registration while router role transition is pending
296     // (i.e., device may soon switch from REED to router role).
297 
298     VerifyOrExit(!Get<Mle::MleRouter>().IsRouterRoleTransitionPending());
299 
300     if (mRegistrationTimeout > 0)
301     {
302         mRegistrationTimeout--;
303 
304         if (mRegistrationTimeout == 0)
305         {
306             IgnoreError(AddService(kDecideBasedOnState));
307         }
308     }
309 
310 exit:
311     if (mRegistrationTimeout == 0)
312     {
313         Get<TimeTicker>().UnregisterReceiver(TimeTicker::kBbrLocal);
314     }
315 }
316 
GetDomainPrefix(NetworkData::OnMeshPrefixConfig & aConfig)317 Error Local::GetDomainPrefix(NetworkData::OnMeshPrefixConfig &aConfig)
318 {
319     Error error = kErrorNone;
320 
321     VerifyOrExit(mDomainPrefixConfig.GetPrefix().GetLength() > 0, error = kErrorNotFound);
322 
323     aConfig = mDomainPrefixConfig;
324 
325 exit:
326     return error;
327 }
328 
RemoveDomainPrefix(const Ip6::Prefix & aPrefix)329 Error Local::RemoveDomainPrefix(const Ip6::Prefix &aPrefix)
330 {
331     Error error = kErrorNone;
332 
333     VerifyOrExit(aPrefix.GetLength() > 0, error = kErrorInvalidArgs);
334     VerifyOrExit(mDomainPrefixConfig.GetPrefix() == aPrefix, error = kErrorNotFound);
335 
336     if (IsEnabled())
337     {
338         RemoveDomainPrefixFromNetworkData();
339     }
340 
341     mDomainPrefixConfig.GetPrefix().SetLength(0);
342 
343 exit:
344     return error;
345 }
346 
SetDomainPrefix(const NetworkData::OnMeshPrefixConfig & aConfig)347 Error Local::SetDomainPrefix(const NetworkData::OnMeshPrefixConfig &aConfig)
348 {
349     Error error = kErrorNone;
350 
351     VerifyOrExit(aConfig.IsValid(GetInstance()), error = kErrorInvalidArgs);
352 
353     if (IsEnabled())
354     {
355         RemoveDomainPrefixFromNetworkData();
356     }
357 
358     mDomainPrefixConfig = aConfig;
359     LogDomainPrefix(kActionSet, kErrorNone);
360 
361     if (IsEnabled())
362     {
363         AddDomainPrefixToNetworkData();
364     }
365 
366 exit:
367     return error;
368 }
369 
ApplyNewMeshLocalPrefix(void)370 void Local::ApplyNewMeshLocalPrefix(void)
371 {
372     VerifyOrExit(IsEnabled());
373 
374     Get<BackboneTmfAgent>().UnsubscribeMulticast(mAllNetworkBackboneRouters);
375     mAllNetworkBackboneRouters.SetMulticastNetworkPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
376     Get<BackboneTmfAgent>().SubscribeMulticast(mAllNetworkBackboneRouters);
377 
378 exit:
379     return;
380 }
381 
HandleDomainPrefixUpdate(DomainPrefixEvent aEvent)382 void Local::HandleDomainPrefixUpdate(DomainPrefixEvent aEvent)
383 {
384     if (!IsEnabled())
385     {
386         ExitNow();
387     }
388 
389     if (aEvent == kDomainPrefixRemoved || aEvent == kDomainPrefixRefreshed)
390     {
391         Get<BackboneTmfAgent>().UnsubscribeMulticast(mAllDomainBackboneRouters);
392     }
393 
394     if (aEvent == kDomainPrefixAdded || aEvent == kDomainPrefixRefreshed)
395     {
396         mAllDomainBackboneRouters.SetMulticastNetworkPrefix(*Get<Leader>().GetDomainPrefix());
397         Get<BackboneTmfAgent>().SubscribeMulticast(mAllDomainBackboneRouters);
398     }
399 
400     if (aEvent != kDomainPrefixUnchanged)
401     {
402         mDomainPrefixCallback.InvokeIfSet(static_cast<otBackboneRouterDomainPrefixEvent>(aEvent),
403                                           Get<Leader>().GetDomainPrefix());
404     }
405 
406 exit:
407     return;
408 }
409 
RemoveDomainPrefixFromNetworkData(void)410 void Local::RemoveDomainPrefixFromNetworkData(void)
411 {
412     Error error = kErrorNotFound; // only used for logging.
413 
414     if (mDomainPrefixConfig.mPrefix.mLength > 0)
415     {
416         error = Get<NetworkData::Local>().RemoveOnMeshPrefix(mDomainPrefixConfig.GetPrefix());
417     }
418 
419     LogDomainPrefix(kActionRemove, error);
420 }
421 
IncrementSequenceNumber(void)422 void Local::IncrementSequenceNumber(void)
423 {
424     switch (mSequenceNumber)
425     {
426     case 126:
427     case 127:
428         mSequenceNumber = 0;
429         break;
430     case 254:
431     case 255:
432         mSequenceNumber = 128;
433         break;
434     default:
435         mSequenceNumber++;
436         break;
437     }
438 }
439 
AddDomainPrefixToNetworkData(void)440 void Local::AddDomainPrefixToNetworkData(void)
441 {
442     Error error = kErrorNotFound; // only used for logging.
443 
444     if (mDomainPrefixConfig.GetPrefix().GetLength() > 0)
445     {
446         error = Get<NetworkData::Local>().AddOnMeshPrefix(mDomainPrefixConfig);
447     }
448 
449     LogDomainPrefix(kActionAdd, error);
450 }
451 
452 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
453 
ActionToString(Action aAction)454 const char *Local::ActionToString(Action aAction)
455 {
456     static const char *const kActionStrings[] = {
457         "Set",    // (0) kActionSet
458         "Add",    // (1) kActionAdd
459         "Remove", // (2) kActionRemove
460     };
461 
462     static_assert(0 == kActionSet, "kActionSet value is incorrect");
463     static_assert(1 == kActionAdd, "kActionAdd value is incorrect");
464     static_assert(2 == kActionRemove, "kActionRemove value is incorrect");
465 
466     return kActionStrings[aAction];
467 }
468 
LogDomainPrefix(Action aAction,Error aError)469 void Local::LogDomainPrefix(Action aAction, Error aError)
470 {
471     LogInfo("%s Domain Prefix: %s, %s", ActionToString(aAction), mDomainPrefixConfig.GetPrefix().ToString().AsCString(),
472             ErrorToString(aError));
473 }
474 
LogService(Action aAction,Error aError)475 void Local::LogService(Action aAction, Error aError)
476 {
477     LogInfo("%s BBR Service: seqno (%u), delay (%us), timeout (%lus), %s", ActionToString(aAction), mSequenceNumber,
478             mReregistrationDelay, ToUlong(mMlrTimeout), ErrorToString(aError));
479 }
480 
481 #endif
482 
483 } // namespace BackboneRouter
484 
485 } // namespace ot
486 
487 #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
488