• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016-2020, 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 Thread neighbor table.
32  */
33 
34 #include "neighbor_table.hpp"
35 
36 #include "instance/instance.hpp"
37 
38 namespace ot {
39 
NeighborTable(Instance & aInstance)40 NeighborTable::NeighborTable(Instance &aInstance)
41     : InstanceLocator(aInstance)
42     , mCallback(nullptr)
43 {
44 }
45 
FindParent(const Neighbor::AddressMatcher & aMatcher)46 Neighbor *NeighborTable::FindParent(const Neighbor::AddressMatcher &aMatcher)
47 {
48     Neighbor *neighbor = nullptr;
49     Mle::Mle &mle      = Get<Mle::Mle>();
50 
51     if (mle.GetParent().Matches(aMatcher))
52     {
53         neighbor = &mle.GetParent();
54     }
55     else if (mle.GetParentCandidate().Matches(aMatcher))
56     {
57         neighbor = &mle.GetParentCandidate();
58     }
59 
60     return neighbor;
61 }
62 
FindParent(Mac::ShortAddress aShortAddress,Neighbor::StateFilter aFilter)63 Neighbor *NeighborTable::FindParent(Mac::ShortAddress aShortAddress, Neighbor::StateFilter aFilter)
64 {
65     return FindParent(Neighbor::AddressMatcher(aShortAddress, aFilter));
66 }
67 
FindParent(const Mac::ExtAddress & aExtAddress,Neighbor::StateFilter aFilter)68 Neighbor *NeighborTable::FindParent(const Mac::ExtAddress &aExtAddress, Neighbor::StateFilter aFilter)
69 {
70     return FindParent(Neighbor::AddressMatcher(aExtAddress, aFilter));
71 }
72 
FindParent(const Mac::Address & aMacAddress,Neighbor::StateFilter aFilter)73 Neighbor *NeighborTable::FindParent(const Mac::Address &aMacAddress, Neighbor::StateFilter aFilter)
74 {
75     return FindParent(Neighbor::AddressMatcher(aMacAddress, aFilter));
76 }
77 
FindNeighbor(const Neighbor::AddressMatcher & aMatcher)78 Neighbor *NeighborTable::FindNeighbor(const Neighbor::AddressMatcher &aMatcher)
79 {
80     Neighbor *neighbor = nullptr;
81 
82 #if OPENTHREAD_FTD
83     if (Get<Mle::Mle>().IsRouterOrLeader())
84     {
85         neighbor = FindChildOrRouter(aMatcher);
86     }
87 
88     if (neighbor == nullptr)
89 #endif
90     {
91         neighbor = FindParent(aMatcher);
92     }
93 
94     return neighbor;
95 }
96 
FindNeighbor(Mac::ShortAddress aShortAddress,Neighbor::StateFilter aFilter)97 Neighbor *NeighborTable::FindNeighbor(Mac::ShortAddress aShortAddress, Neighbor::StateFilter aFilter)
98 {
99     Neighbor *neighbor = nullptr;
100 
101     VerifyOrExit((aShortAddress != Mac::kShortAddrBroadcast) && (aShortAddress != Mac::kShortAddrInvalid));
102     neighbor = FindNeighbor(Neighbor::AddressMatcher(aShortAddress, aFilter));
103 
104 exit:
105     return neighbor;
106 }
107 
FindNeighbor(const Mac::ExtAddress & aExtAddress,Neighbor::StateFilter aFilter)108 Neighbor *NeighborTable::FindNeighbor(const Mac::ExtAddress &aExtAddress, Neighbor::StateFilter aFilter)
109 {
110     return FindNeighbor(Neighbor::AddressMatcher(aExtAddress, aFilter));
111 }
112 
FindNeighbor(const Mac::Address & aMacAddress,Neighbor::StateFilter aFilter)113 Neighbor *NeighborTable::FindNeighbor(const Mac::Address &aMacAddress, Neighbor::StateFilter aFilter)
114 {
115     return FindNeighbor(Neighbor::AddressMatcher(aMacAddress, aFilter));
116 }
117 
118 #if OPENTHREAD_FTD
119 
FindChildOrRouter(const Neighbor::AddressMatcher & aMatcher)120 Neighbor *NeighborTable::FindChildOrRouter(const Neighbor::AddressMatcher &aMatcher)
121 {
122     Neighbor *neighbor;
123 
124     neighbor = Get<ChildTable>().FindChild(aMatcher);
125 
126     if (neighbor == nullptr)
127     {
128         neighbor = Get<RouterTable>().FindRouter(aMatcher);
129     }
130 
131     return neighbor;
132 }
133 
FindNeighbor(const Ip6::Address & aIp6Address,Neighbor::StateFilter aFilter)134 Neighbor *NeighborTable::FindNeighbor(const Ip6::Address &aIp6Address, Neighbor::StateFilter aFilter)
135 {
136     Neighbor    *neighbor = nullptr;
137     Mac::Address macAddress;
138 
139     if (aIp6Address.IsLinkLocalUnicast())
140     {
141         aIp6Address.GetIid().ConvertToMacAddress(macAddress);
142     }
143 
144     if (Get<Mle::Mle>().IsRoutingLocator(aIp6Address))
145     {
146         macAddress.SetShort(aIp6Address.GetIid().GetLocator());
147     }
148 
149     if (!macAddress.IsNone())
150     {
151         neighbor = FindNeighbor(Neighbor::AddressMatcher(macAddress, aFilter));
152         ExitNow();
153     }
154 
155     for (Child &child : Get<ChildTable>().Iterate(aFilter))
156     {
157         if (child.HasIp6Address(aIp6Address))
158         {
159             ExitNow(neighbor = &child);
160         }
161     }
162 
163 exit:
164     return neighbor;
165 }
166 
FindRxOnlyNeighborRouter(const Mac::ExtAddress & aExtAddress)167 Neighbor *NeighborTable::FindRxOnlyNeighborRouter(const Mac::ExtAddress &aExtAddress)
168 {
169     Mac::Address macAddress;
170 
171     macAddress.SetExtended(aExtAddress);
172 
173     return FindRxOnlyNeighborRouter(macAddress);
174 }
175 
FindRxOnlyNeighborRouter(const Mac::Address & aMacAddress)176 Neighbor *NeighborTable::FindRxOnlyNeighborRouter(const Mac::Address &aMacAddress)
177 {
178     Neighbor *neighbor = nullptr;
179 
180     VerifyOrExit(Get<Mle::Mle>().IsChild());
181     neighbor = Get<RouterTable>().FindNeighbor(aMacAddress);
182 
183 exit:
184     return neighbor;
185 }
186 
GetNextNeighborInfo(otNeighborInfoIterator & aIterator,Neighbor::Info & aNeighInfo)187 Error NeighborTable::GetNextNeighborInfo(otNeighborInfoIterator &aIterator, Neighbor::Info &aNeighInfo)
188 {
189     Error   error = kErrorNone;
190     int16_t index;
191 
192     // Non-negative iterator value gives the Child index into child table
193 
194     if (aIterator >= 0)
195     {
196         for (index = aIterator;; index++)
197         {
198             Child *child = Get<ChildTable>().GetChildAtIndex(static_cast<uint16_t>(index));
199 
200             if (child == nullptr)
201             {
202                 break;
203             }
204 
205             if (child->IsStateValid())
206             {
207                 aNeighInfo.SetFrom(*child);
208                 aNeighInfo.mIsChild = true;
209                 index++;
210                 aIterator = index;
211                 ExitNow();
212             }
213         }
214 
215         aIterator = 0;
216     }
217 
218     // Negative iterator value gives the current index into mRouters array
219 
220     for (index = -aIterator; index <= Mle::kMaxRouterId; index++)
221     {
222         Router *router = Get<RouterTable>().FindRouterById(static_cast<uint8_t>(index));
223 
224         if (router != nullptr && router->IsStateValid())
225         {
226             aNeighInfo.SetFrom(*router);
227             aNeighInfo.mIsChild = false;
228             index++;
229             aIterator = -index;
230             ExitNow();
231         }
232     }
233 
234     aIterator = -index;
235     error     = kErrorNotFound;
236 
237 exit:
238     return error;
239 }
240 
241 #endif // OPENTHREAD_FTD
242 
243 #if OPENTHREAD_MTD
244 
GetNextNeighborInfo(otNeighborInfoIterator & aIterator,Neighbor::Info & aNeighInfo)245 Error NeighborTable::GetNextNeighborInfo(otNeighborInfoIterator &aIterator, Neighbor::Info &aNeighInfo)
246 {
247     Error error = kErrorNotFound;
248 
249     VerifyOrExit(aIterator == OT_NEIGHBOR_INFO_ITERATOR_INIT);
250 
251     aIterator++;
252     VerifyOrExit(Get<Mle::Mle>().GetParent().IsStateValid());
253 
254     aNeighInfo.SetFrom(Get<Mle::Mle>().GetParent());
255     aNeighInfo.mIsChild = false;
256     error               = kErrorNone;
257 
258 exit:
259     return error;
260 }
261 
262 #endif
263 
Signal(Event aEvent,const Neighbor & aNeighbor)264 void NeighborTable::Signal(Event aEvent, const Neighbor &aNeighbor)
265 {
266 #if !OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
267     if (mCallback != nullptr)
268 #endif
269     {
270         EntryInfo info;
271 
272         info.mInstance = &GetInstance();
273 
274         switch (aEvent)
275         {
276         case kChildAdded:
277         case kChildRemoved:
278         case kChildModeChanged:
279 #if OPENTHREAD_FTD
280             OT_ASSERT(Get<ChildTable>().Contains(aNeighbor));
281             static_cast<Child::Info &>(info.mInfo.mChild).SetFrom(static_cast<const Child &>(aNeighbor));
282 #endif
283             break;
284 
285         case kRouterAdded:
286         case kRouterRemoved:
287             static_cast<Neighbor::Info &>(info.mInfo.mRouter).SetFrom(aNeighbor);
288             break;
289         }
290 
291 #if OPENTHREAD_CONFIG_HISTORY_TRACKER_ENABLE
292         Get<Utils::HistoryTracker>().RecordNeighborEvent(aEvent, info);
293 
294         if (mCallback != nullptr)
295 #endif
296         {
297             mCallback(static_cast<otNeighborTableEvent>(aEvent), &info);
298         }
299     }
300 
301 #if OPENTHREAD_CONFIG_OTNS_ENABLE
302     Get<Utils::Otns>().EmitNeighborChange(aEvent, aNeighbor);
303 #endif
304 
305     switch (aEvent)
306     {
307     case kChildAdded:
308         Get<Notifier>().Signal(kEventThreadChildAdded);
309         break;
310 
311     case kChildRemoved:
312         Get<Notifier>().Signal(kEventThreadChildRemoved);
313 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
314         Get<DuaManager>().HandleChildDuaAddressEvent(static_cast<const Child &>(aNeighbor),
315                                                      DuaManager::kAddressRemoved);
316 #endif
317         break;
318 
319 #if OPENTHREAD_FTD
320     case kRouterAdded:
321     case kRouterRemoved:
322         Get<RouterTable>().SignalTableChanged();
323         break;
324 #endif
325 
326     default:
327         break;
328     }
329 }
330 
331 } // namespace ot
332