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