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