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