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