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