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