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/locator_getters.hpp"
39 #include "instance/instance.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 = Mle::kInvalidRloc16;
56
57 // Domain Prefix Length 0 indicates no available Domain Prefix in the Thread network.
58 mDomainPrefix.SetLength(0);
59 }
60
GetConfig(Config & aConfig) const61 Error Leader::GetConfig(Config &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>().GetBackboneRouterServiceId(aServiceId);
79
80 exit:
81 return error;
82 }
83
84 #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
85
LogBackboneRouterPrimary(State aState,const Config & aConfig) const86 void Leader::LogBackboneRouterPrimary(State aState, const Config &aConfig) const
87 {
88 OT_UNUSED_VARIABLE(aConfig);
89
90 LogInfo("PBBR state: %s", StateToString(aState));
91
92 if (aState != kStateRemoved && aState != kStateNone)
93 {
94 LogInfo("Rloc16:0x%4x, seqno:%u, delay:%u, timeout:%lu", aConfig.mServer16, aConfig.mSequenceNumber,
95 aConfig.mReregistrationDelay, ToUlong(aConfig.mMlrTimeout));
96 }
97 }
98
StateToString(State aState)99 const char *Leader::StateToString(State aState)
100 {
101 static const char *const kStateStrings[] = {
102 "None", // (0) kStateNone
103 "Added", // (1) kStateAdded
104 "Removed", // (2) kStateRemoved
105 "Rereg triggered", // (3) kStateToTriggerRereg
106 "Refreshed", // (4) kStateRefreshed
107 "Unchanged", // (5) kStateUnchanged
108 };
109
110 static_assert(0 == kStateNone, "kStateNone value is incorrect");
111 static_assert(1 == kStateAdded, "kStateAdded value is incorrect");
112 static_assert(2 == kStateRemoved, "kStateRemoved value is incorrect");
113 static_assert(3 == kStateToTriggerRereg, "kStateToTriggerRereg value is incorrect");
114 static_assert(4 == kStateRefreshed, "kStateRefreshed value is incorrect");
115 static_assert(5 == kStateUnchanged, "kStateUnchanged value is incorrect");
116
117 return kStateStrings[aState];
118 }
119
DomainPrefixEventToString(DomainPrefixEvent aEvent)120 const char *Leader::DomainPrefixEventToString(DomainPrefixEvent aEvent)
121 {
122 static const char *const kEventStrings[] = {
123 "Added", // (0) kDomainPrefixAdded
124 "Removed", // (1) kDomainPrefixRemoved
125 "Refreshed", // (2) kDomainPrefixRefreshed
126 "Unchanged", // (3) kDomainPrefixUnchanged
127 };
128
129 static_assert(0 == kDomainPrefixAdded, "kDomainPrefixAdded value is incorrect");
130 static_assert(1 == kDomainPrefixRemoved, "kDomainPrefixRemoved value is incorrect");
131 static_assert(2 == kDomainPrefixRefreshed, "kDomainPrefixRefreshed value is incorrect");
132 static_assert(3 == kDomainPrefixUnchanged, "kDomainPrefixUnchanged value is incorrect");
133
134 return kEventStrings[aEvent];
135 }
136
137 #endif // OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO)
138
Update(void)139 void Leader::Update(void)
140 {
141 UpdateBackboneRouterPrimary();
142 UpdateDomainPrefixConfig();
143 }
144
UpdateBackboneRouterPrimary(void)145 void Leader::UpdateBackboneRouterPrimary(void)
146 {
147 Config config;
148 State state;
149
150 Get<NetworkData::Service::Manager>().GetBackboneRouterPrimary(config);
151
152 if (config.mServer16 != mConfig.mServer16)
153 {
154 if (config.mServer16 == Mle::kInvalidRloc16)
155 {
156 state = kStateRemoved;
157 }
158 else if (mConfig.mServer16 == Mle::kInvalidRloc16)
159 {
160 state = kStateAdded;
161 }
162 else
163 {
164 // Short Address of PBBR changes.
165 state = kStateToTriggerRereg;
166 }
167 }
168 else if (config.mServer16 == Mle::kInvalidRloc16)
169 {
170 // If no Primary all the time.
171 state = kStateNone;
172 }
173 else if (config.mSequenceNumber != mConfig.mSequenceNumber)
174 {
175 state = kStateToTriggerRereg;
176 }
177 else if (config.mReregistrationDelay != mConfig.mReregistrationDelay || config.mMlrTimeout != mConfig.mMlrTimeout)
178 {
179 state = kStateRefreshed;
180 }
181 else
182 {
183 state = kStateUnchanged;
184 }
185
186 // Restrain the range of MLR timeout to be always valid
187 if (config.mServer16 != Mle::kInvalidRloc16)
188 {
189 uint32_t origTimeout = config.mMlrTimeout;
190
191 config.mMlrTimeout = Clamp(config.mMlrTimeout, kMinMlrTimeout, kMaxMlrTimeout);
192
193 if (config.mMlrTimeout != origTimeout)
194 {
195 LogNote("Leader MLR Timeout is normalized from %lu to %lu", ToUlong(origTimeout),
196 ToUlong(config.mMlrTimeout));
197 }
198 }
199
200 mConfig = config;
201 LogBackboneRouterPrimary(state, mConfig);
202
203 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
204 Get<BackboneRouter::Local>().HandleBackboneRouterPrimaryUpdate(state, mConfig);
205 #endif
206
207 #if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)
208 Get<MlrManager>().HandleBackboneRouterPrimaryUpdate(state, mConfig);
209 #endif
210
211 #if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
212 Get<DuaManager>().HandleBackboneRouterPrimaryUpdate(state, mConfig);
213 #endif
214 }
215
UpdateDomainPrefixConfig(void)216 void Leader::UpdateDomainPrefixConfig(void)
217 {
218 NetworkData::Iterator iterator = NetworkData::kIteratorInit;
219 NetworkData::OnMeshPrefixConfig config;
220 DomainPrefixEvent event;
221 bool found = false;
222
223 while (Get<NetworkData::Leader>().GetNextOnMeshPrefix(iterator, config) == kErrorNone)
224 {
225 if (config.mDp)
226 {
227 found = true;
228 break;
229 }
230 }
231
232 if (!found)
233 {
234 VerifyOrExit(HasDomainPrefix());
235
236 // Domain Prefix does not exist any more.
237 mDomainPrefix.Clear();
238 event = kDomainPrefixRemoved;
239 }
240 else if (config.GetPrefix() == mDomainPrefix)
241 {
242 event = kDomainPrefixUnchanged;
243 }
244 else
245 {
246 event = HasDomainPrefix() ? kDomainPrefixRefreshed : kDomainPrefixAdded;
247 mDomainPrefix = config.GetPrefix();
248 }
249
250 LogInfo("%s domain Prefix: %s", DomainPrefixEventToString(event), mDomainPrefix.ToString().AsCString());
251
252 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
253 Get<Local>().HandleDomainPrefixUpdate(event);
254 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
255 Get<NdProxyTable>().HandleDomainPrefixUpdate(event);
256 #endif
257 #endif
258
259 #if OPENTHREAD_CONFIG_DUA_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE)
260 Get<DuaManager>().HandleDomainPrefixUpdate(event);
261 #else
262 OT_UNUSED_VARIABLE(event);
263 #endif
264
265 exit:
266 return;
267 }
268
IsDomainUnicast(const Ip6::Address & aAddress) const269 bool Leader::IsDomainUnicast(const Ip6::Address &aAddress) const
270 {
271 return HasDomainPrefix() && aAddress.MatchesPrefix(mDomainPrefix);
272 }
273
274 } // namespace BackboneRouter
275 } // namespace ot
276
277 #endif // (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
278