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 Primary Backbone Router service management in the Thread Network.
32 */
33
34 #include "bbr_leader.hpp"
35
36 #if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
37
38 #include "common/instance.hpp"
39 #include "common/locator_getters.hpp"
40
41 namespace ot {
42 namespace BackboneRouter {
43
44 RegisterLogModule("BbrLeader");
45
Leader(Instance & aInstance)46 Leader::Leader(Instance &aInstance)
47 : InstanceLocator(aInstance)
48 {
49 Reset();
50 }
51
Reset(void)52 void Leader::Reset(void)
53 {
54 // Invalid server short address indicates no available Backbone Router service in the Thread Network.
55 mConfig.mServer16 = Mac::kShortAddrInvalid;
56
57 // Domain Prefix Length 0 indicates no available Domain Prefix in the Thread network.
58 mDomainPrefix.SetLength(0);
59 }
60
GetConfig(BackboneRouterConfig & aConfig) const61 Error Leader::GetConfig(BackboneRouterConfig &aConfig) const
62 {
63 Error error = kErrorNone;
64
65 VerifyOrExit(HasPrimary(), error = kErrorNotFound);
66
67 aConfig = mConfig;
68
69 exit:
70 return error;
71 }
72
GetServiceId(uint8_t & aServiceId) const73 Error Leader::GetServiceId(uint8_t &aServiceId) const
74 {
75 Error error = kErrorNone;
76
77 VerifyOrExit(HasPrimary(), error = kErrorNotFound);
78 error = Get<NetworkData::Service::Manager>().GetServiceId<NetworkData::Service::BackboneRouter>(
79 /* aServerStable */ true, aServiceId);
80
81 exit:
82 return error;
83 }
84
85 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
86
LogBackboneRouterPrimary(State aState,const BackboneRouterConfig & aConfig) const87 void Leader::LogBackboneRouterPrimary(State aState, const BackboneRouterConfig &aConfig) const
88 {
89 OT_UNUSED_VARIABLE(aConfig);
90
91 LogInfo("PBBR state: %s", StateToString(aState));
92
93 if (aState != kStateRemoved && aState != kStateNone)
94 {
95 LogInfo("Rloc16: 0x%4X, seqno: %d, delay: %d, timeout %d", aConfig.mServer16, aConfig.mSequenceNumber,
96 aConfig.mReregistrationDelay, aConfig.mMlrTimeout);
97 }
98 }
99
LogDomainPrefix(DomainPrefixState aState,const Ip6::Prefix & aPrefix) const100 void Leader::LogDomainPrefix(DomainPrefixState aState, const Ip6::Prefix &aPrefix) const
101 {
102 LogInfo("Domain Prefix: %s, state: %s", aPrefix.ToString().AsCString(), DomainPrefixStateToString(aState));
103 }
104
StateToString(State aState)105 const char *Leader::StateToString(State aState)
106 {
107 static const char *const kStateStrings[] = {
108 "None", // (0) kStateNone
109 "Added", // (1) kStateAdded
110 "Removed", // (2) kStateRemoved
111 "Rereg triggered", // (3) kStateToTriggerRereg
112 "Refreshed", // (4) kStateRefreshed
113 "Unchanged", // (5) kStateUnchanged
114 };
115
116 static_assert(0 == kStateNone, "kStateNone value is incorrect");
117 static_assert(1 == kStateAdded, "kStateAdded value is incorrect");
118 static_assert(2 == kStateRemoved, "kStateRemoved value is incorrect");
119 static_assert(3 == kStateToTriggerRereg, "kStateToTriggerRereg value is incorrect");
120 static_assert(4 == kStateRefreshed, "kStateRefreshed value is incorrect");
121 static_assert(5 == kStateUnchanged, "kStateUnchanged value is incorrect");
122
123 return kStateStrings[aState];
124 }
125
DomainPrefixStateToString(DomainPrefixState aState)126 const char *Leader::DomainPrefixStateToString(DomainPrefixState aState)
127 {
128 static const char *const kPrefixStateStrings[] = {
129 "None", // (0) kDomainPrefixNone
130 "Added", // (1) kDomainPrefixAdded
131 "Removed", // (2) kDomainPrefixRemoved
132 "Refreshed", // (3) kDomainPrefixRefreshed
133 "Unchanged", // (4) kDomainPrefixUnchanged
134 };
135
136 static_assert(0 == kDomainPrefixNone, "kDomainPrefixNone value is incorrect");
137 static_assert(1 == kDomainPrefixAdded, "kDomainPrefixAdded value is incorrect");
138 static_assert(2 == kDomainPrefixRemoved, "kDomainPrefixRemoved value is incorrect");
139 static_assert(3 == kDomainPrefixRefreshed, "kDomainPrefixRefreshed value is incorrect");
140 static_assert(4 == kDomainPrefixUnchanged, "kDomainPrefixUnchanged value is incorrect");
141
142 return kPrefixStateStrings[aState];
143 }
144
145 #endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
146
Update(void)147 void Leader::Update(void)
148 {
149 UpdateBackboneRouterPrimary();
150 UpdateDomainPrefixConfig();
151 }
152
UpdateBackboneRouterPrimary(void)153 void Leader::UpdateBackboneRouterPrimary(void)
154 {
155 BackboneRouterConfig config;
156 State state;
157 uint32_t origMlrTimeout;
158
159 Get<NetworkData::Service::Manager>().GetBackboneRouterPrimary(config);
160
161 if (config.mServer16 != mConfig.mServer16)
162 {
163 if (config.mServer16 == Mac::kShortAddrInvalid)
164 {
165 state = kStateRemoved;
166 }
167 else if (mConfig.mServer16 == Mac::kShortAddrInvalid)
168 {
169 state = kStateAdded;
170 }
171 else
172 {
173 // Short Address of PBBR changes.
174 state = kStateToTriggerRereg;
175 }
176 }
177 else if (config.mServer16 == Mac::kShortAddrInvalid)
178 {
179 // If no Primary all the time.
180 state = kStateNone;
181 }
182 else if (config.mSequenceNumber != mConfig.mSequenceNumber)
183 {
184 state = kStateToTriggerRereg;
185 }
186 else if (config.mReregistrationDelay != mConfig.mReregistrationDelay || config.mMlrTimeout != mConfig.mMlrTimeout)
187 {
188 state = kStateRefreshed;
189 }
190 else
191 {
192 state = kStateUnchanged;
193 }
194
195 // Restrain the range of MLR timeout to be always valid
196 if (config.mServer16 != Mac::kShortAddrInvalid)
197 {
198 origMlrTimeout = config.mMlrTimeout;
199 config.mMlrTimeout = config.mMlrTimeout < static_cast<uint32_t>(Mle::kMlrTimeoutMin)
200 ? static_cast<uint32_t>(Mle::kMlrTimeoutMin)
201 : config.mMlrTimeout;
202 config.mMlrTimeout = config.mMlrTimeout > static_cast<uint32_t>(Mle::kMlrTimeoutMax)
203 ? static_cast<uint32_t>(Mle::kMlrTimeoutMax)
204 : config.mMlrTimeout;
205
206 if (config.mMlrTimeout != origMlrTimeout)
207 {
208 LogNote("Leader MLR Timeout is normalized from %u to %u", origMlrTimeout, config.mMlrTimeout);
209 }
210 }
211
212 mConfig = config;
213 LogBackboneRouterPrimary(state, mConfig);
214
215 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
216 Get<BackboneRouter::Local>().HandleBackboneRouterPrimaryUpdate(state, mConfig);
217 #endif
218
219 #if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)
220 Get<MlrManager>().HandleBackboneRouterPrimaryUpdate(state, mConfig);
221 #endif
222
223 #if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
224 Get<DuaManager>().HandleBackboneRouterPrimaryUpdate(state, mConfig);
225 #endif
226 }
227
UpdateDomainPrefixConfig(void)228 void Leader::UpdateDomainPrefixConfig(void)
229 {
230 NetworkData::Iterator iterator = NetworkData::kIteratorInit;
231 NetworkData::OnMeshPrefixConfig config;
232 DomainPrefixState state;
233 bool found = false;
234
235 while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == kErrorNone)
236 {
237 if (config.mDp)
238 {
239 found = true;
240 break;
241 }
242 }
243
244 if (!found)
245 {
246 if (mDomainPrefix.GetLength() != 0)
247 {
248 // Domain Prefix does not exist any more.
249 mDomainPrefix.SetLength(0);
250 state = kDomainPrefixRemoved;
251 }
252 else
253 {
254 state = kDomainPrefixNone;
255 }
256 }
257 else if (config.GetPrefix() == mDomainPrefix)
258 {
259 state = kDomainPrefixUnchanged;
260 }
261 else
262 {
263 if (mDomainPrefix.mLength == 0)
264 {
265 state = kDomainPrefixAdded;
266 }
267 else
268 {
269 state = kDomainPrefixRefreshed;
270 }
271
272 mDomainPrefix = config.GetPrefix();
273 }
274
275 LogDomainPrefix(state, mDomainPrefix);
276
277 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
278 Get<Local>().HandleDomainPrefixUpdate(state);
279 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
280 Get<NdProxyTable>().HandleDomainPrefixUpdate(state);
281 #endif
282 #endif
283
284 #if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
285 Get<DuaManager>().HandleDomainPrefixUpdate(state);
286 #endif
287 }
288
IsDomainUnicast(const Ip6::Address & aAddress) const289 bool Leader::IsDomainUnicast(const Ip6::Address &aAddress) const
290 {
291 return HasDomainPrefix() && aAddress.MatchesPrefix(mDomainPrefix);
292 }
293
294 } // namespace BackboneRouter
295 } // namespace ot
296
297 #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
298