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