• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016-2017, 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 includes definitions for a Thread `Child`.
32  */
33 
34 #include "child.hpp"
35 
36 #include "instance/instance.hpp"
37 
38 namespace ot {
39 
40 #if OPENTHREAD_FTD
41 
42 //---------------------------------------------------------------------------------------------------------------------
43 // Child::Info
44 
SetFrom(const Child & aChild)45 void Child::Info::SetFrom(const Child &aChild)
46 {
47     Clear();
48     mExtAddress          = aChild.GetExtAddress();
49     mTimeout             = aChild.GetTimeout();
50     mRloc16              = aChild.GetRloc16();
51     mChildId             = Mle::ChildIdFromRloc16(aChild.GetRloc16());
52     mNetworkDataVersion  = aChild.GetNetworkDataVersion();
53     mAge                 = Time::MsecToSec(TimerMilli::GetNow() - aChild.GetLastHeard());
54     mLinkQualityIn       = aChild.GetLinkQualityIn();
55     mAverageRssi         = aChild.GetLinkInfo().GetAverageRss();
56     mLastRssi            = aChild.GetLinkInfo().GetLastRss();
57     mFrameErrorRate      = aChild.GetLinkInfo().GetFrameErrorRate();
58     mMessageErrorRate    = aChild.GetLinkInfo().GetMessageErrorRate();
59     mQueuedMessageCnt    = aChild.GetIndirectMessageCount();
60     mVersion             = ClampToUint8(aChild.GetVersion());
61     mRxOnWhenIdle        = aChild.IsRxOnWhenIdle();
62     mFullThreadDevice    = aChild.IsFullThreadDevice();
63     mFullNetworkData     = (aChild.GetNetworkDataType() == NetworkData::kFullSet);
64     mIsStateRestoring    = aChild.IsStateRestoring();
65     mSupervisionInterval = aChild.GetSupervisionInterval();
66 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE
67     mIsCslSynced = aChild.IsCslSynchronized();
68 #else
69     mIsCslSynced = false;
70 #endif
71 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
72     mConnectionTime = aChild.GetConnectionTime();
73 #endif
74 }
75 
76 //---------------------------------------------------------------------------------------------------------------------
77 // Child::Ip6AddrEntry
78 
79 #if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
80 
GetMlrState(const Child & aChild) const81 MlrState Child::Ip6AddrEntry::GetMlrState(const Child &aChild) const
82 {
83     MlrState                   state = kMlrStateRegistering;
84     Ip6AddressArray::IndexType index;
85 
86     OT_ASSERT(aChild.mIp6Addresses.IsInArrayBuffer(this));
87 
88     index = aChild.mIp6Addresses.IndexOf(*this);
89 
90     if (aChild.mMlrToRegisterSet.Has(index))
91     {
92         state = kMlrStateToRegister;
93     }
94     else if (aChild.mMlrRegisteredSet.Has(index))
95     {
96         state = kMlrStateRegistered;
97     }
98 
99     return state;
100 }
101 
102 // NOLINTNEXTLINE(readability-make-member-function-const)
SetMlrState(MlrState aState,Child & aChild)103 void Child::Ip6AddrEntry::SetMlrState(MlrState aState, Child &aChild)
104 {
105     Ip6AddressArray::IndexType index;
106 
107     OT_ASSERT(aChild.mIp6Addresses.IsInArrayBuffer(this));
108 
109     index = aChild.mIp6Addresses.IndexOf(*this);
110 
111     aChild.mMlrToRegisterSet.Update(index, aState == kMlrStateToRegister);
112     aChild.mMlrRegisteredSet.Update(index, aState == kMlrStateRegistered);
113 }
114 
115 #endif // OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
116 
117 //---------------------------------------------------------------------------------------------------------------------
118 // Child
119 
Clear(void)120 void Child::Clear(void)
121 {
122     Instance &instance = GetInstance();
123 
124     ClearAllBytes(*this);
125     Init(instance);
126 }
127 
ClearIp6Addresses(void)128 void Child::ClearIp6Addresses(void)
129 {
130     mMeshLocalIid.Clear();
131     mIp6Addresses.Clear();
132 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
133     mMlrToRegisterSet.Clear();
134     mMlrRegisteredSet.Clear();
135 #endif
136 }
137 
SetDeviceMode(Mle::DeviceMode aMode)138 void Child::SetDeviceMode(Mle::DeviceMode aMode)
139 {
140     VerifyOrExit(aMode != GetDeviceMode());
141 
142     Neighbor::SetDeviceMode(aMode);
143 
144     VerifyOrExit(IsStateValid());
145     Get<NeighborTable>().Signal(NeighborTable::kChildModeChanged, *this);
146 
147 exit:
148     return;
149 }
150 
GetMeshLocalIp6Address(Ip6::Address & aAddress) const151 Error Child::GetMeshLocalIp6Address(Ip6::Address &aAddress) const
152 {
153     Error error = kErrorNone;
154 
155     VerifyOrExit(!mMeshLocalIid.IsUnspecified(), error = kErrorNotFound);
156 
157     aAddress.SetPrefix(Get<Mle::MleRouter>().GetMeshLocalPrefix());
158     aAddress.SetIid(mMeshLocalIid);
159 
160 exit:
161     return error;
162 }
163 
GetNextIp6Address(AddressIterator & aIterator,Ip6::Address & aAddress) const164 Error Child::GetNextIp6Address(AddressIterator &aIterator, Ip6::Address &aAddress) const
165 {
166     Error error = kErrorNone;
167 
168     if (aIterator == 0)
169     {
170         aIterator++;
171 
172         if (GetMeshLocalIp6Address(aAddress) == kErrorNone)
173         {
174             ExitNow();
175         }
176     }
177 
178     VerifyOrExit(aIterator - 1 < mIp6Addresses.GetLength(), error = kErrorNotFound);
179 
180     aAddress = mIp6Addresses[static_cast<Ip6AddressArray::IndexType>(aIterator - 1)];
181     aIterator++;
182 
183 exit:
184     return error;
185 }
186 
AddIp6Address(const Ip6::Address & aAddress)187 Error Child::AddIp6Address(const Ip6::Address &aAddress)
188 {
189     Error error = kErrorNone;
190 
191     VerifyOrExit(!aAddress.IsUnspecified(), error = kErrorInvalidArgs);
192 
193     if (Get<Mle::MleRouter>().IsMeshLocalAddress(aAddress))
194     {
195         VerifyOrExit(mMeshLocalIid.IsUnspecified(), error = kErrorAlready);
196         mMeshLocalIid = aAddress.GetIid();
197         ExitNow();
198     }
199 
200     VerifyOrExit(!mIp6Addresses.ContainsMatching(aAddress), error = kErrorAlready);
201     error = mIp6Addresses.PushBack(static_cast<const Ip6AddrEntry &>(aAddress));
202 
203 exit:
204     return error;
205 }
206 
RemoveIp6Address(const Ip6::Address & aAddress)207 Error Child::RemoveIp6Address(const Ip6::Address &aAddress)
208 {
209     Error         error = kErrorNotFound;
210     Ip6AddrEntry *entry;
211 
212     if (Get<Mle::MleRouter>().IsMeshLocalAddress(aAddress))
213     {
214         if (aAddress.GetIid() == mMeshLocalIid)
215         {
216             mMeshLocalIid.Clear();
217             error = kErrorNone;
218         }
219 
220         ExitNow();
221     }
222 
223     entry = mIp6Addresses.FindMatching(aAddress);
224     VerifyOrExit(entry != nullptr);
225 
226 #if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
227     {
228         // `Array::Remove()` will replace the removed entry with the
229         // last one in the array. We also update the MLR bit vectors
230         // to reflect this change.
231 
232         uint16_t entryIndex = mIp6Addresses.IndexOf(*entry);
233         uint16_t lastIndex  = mIp6Addresses.GetLength() - 1;
234 
235         mMlrToRegisterSet.Update(entryIndex, mMlrToRegisterSet.Has(lastIndex));
236         mMlrToRegisterSet.Remove(lastIndex);
237 
238         mMlrRegisteredSet.Update(entryIndex, mMlrRegisteredSet.Has(lastIndex));
239         mMlrRegisteredSet.Remove(lastIndex);
240     }
241 #endif
242 
243     mIp6Addresses.Remove(*entry);
244     error = kErrorNone;
245 
246 exit:
247     return error;
248 }
249 
HasIp6Address(const Ip6::Address & aAddress) const250 bool Child::HasIp6Address(const Ip6::Address &aAddress) const
251 {
252     bool hasAddress = false;
253 
254     VerifyOrExit(!aAddress.IsUnspecified());
255 
256     if (Get<Mle::MleRouter>().IsMeshLocalAddress(aAddress))
257     {
258         hasAddress = (aAddress.GetIid() == mMeshLocalIid);
259         ExitNow();
260     }
261 
262     hasAddress = mIp6Addresses.ContainsMatching(aAddress);
263 
264 exit:
265     return hasAddress;
266 }
267 
268 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
GetDomainUnicastAddress(Ip6::Address & aAddress) const269 Error Child::GetDomainUnicastAddress(Ip6::Address &aAddress) const
270 {
271     Error error = kErrorNotFound;
272 
273     for (const Ip6::Address &ip6Address : mIp6Addresses)
274     {
275         if (Get<BackboneRouter::Leader>().IsDomainUnicast(ip6Address))
276         {
277             aAddress = ip6Address;
278             error    = kErrorNone;
279             ExitNow();
280         }
281     }
282 
283 exit:
284     return error;
285 }
286 #endif
287 
288 #if OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
289 
HasMlrRegisteredAddress(const Ip6::Address & aAddress) const290 bool Child::HasMlrRegisteredAddress(const Ip6::Address &aAddress) const
291 {
292     bool                hasAddress = false;
293     const Ip6AddrEntry *entry;
294 
295     entry = mIp6Addresses.FindMatching(aAddress);
296     VerifyOrExit(entry != nullptr);
297     hasAddress = entry->GetMlrState(*this) == kMlrStateRegistered;
298 
299 exit:
300     return hasAddress;
301 }
302 
303 #endif
304 
305 #endif // OPENTHREAD_FTD
306 
307 } // namespace ot
308