• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016, 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 EID-to-RLOC mapping and caching.
32  */
33 
34 #ifndef ADDRESS_RESOLVER_HPP_
35 #define ADDRESS_RESOLVER_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include "coap/coap.hpp"
40 #include "common/linked_list.hpp"
41 #include "common/locator.hpp"
42 #include "common/non_copyable.hpp"
43 #include "common/time_ticker.hpp"
44 #include "common/timer.hpp"
45 #include "mac/mac.hpp"
46 #include "net/icmp6.hpp"
47 #include "net/udp6.hpp"
48 #include "thread/thread_tlvs.hpp"
49 
50 namespace ot {
51 
52 /**
53  * @addtogroup core-arp
54  *
55  * @brief
56  *   This module includes definitions for Thread EID-to-RLOC mapping and caching.
57  *
58  * @{
59  */
60 
61 /**
62  * This class implements the EID-to-RLOC mapping and caching.
63  *
64  */
65 class AddressResolver : public InstanceLocator, private NonCopyable
66 {
67     friend class TimeTicker;
68 
69 public:
70     /**
71      * This type represents an iterator used for iterating through the EID cache table entries.
72      *
73      */
74     typedef otCacheEntryIterator Iterator;
75 
76     /**
77      * This type represents an EID cache entry.
78      *
79      */
80     typedef otCacheEntryInfo EntryInfo;
81 
82     /**
83      * This constructor initializes the object.
84      *
85      */
86     explicit AddressResolver(Instance &aInstance);
87 
88 #if OPENTHREAD_FTD
89     /**
90      * This method clears the EID-to-RLOC cache.
91      *
92      */
93     void Clear(void);
94 
95     /**
96      * This method gets the information about the next EID cache entry (using an iterator).
97      *
98      * @param[out]    aInfo      An `EntryInfo` where the EID cache entry information is placed.
99      * @param[in,out] aIterator  An iterator. It will be updated to point to the next entry on success.
100      *                           To get the first entry, initialize the iterator by setting all its fields to zero.
101      *                           e.g., `memset` the the iterator structure to zero.
102      *
103      * @retval kErrorNone      Successfully populated @p aInfo with the info for the next EID cache entry.
104      * @retval kErrorNotFound  No more entries in the address cache table.
105      *
106      */
107     Error GetNextCacheEntry(EntryInfo &aInfo, Iterator &aIterator) const;
108 
109     /**
110      * This method removes the EID-to-RLOC cache entries corresponding to an RLOC16.
111      *
112      * @param[in]  aRloc16  The RLOC16 address.
113      *
114      */
115     void Remove(Mac::ShortAddress aRloc16);
116 
117     /**
118      * This method removes all EID-to-RLOC cache entries associated with a Router ID.
119      *
120      * @param[in]  aRouterId  The Router ID.
121      *
122      */
123     void Remove(uint8_t aRouterId);
124 
125     /**
126      * This method removes the cache entry for the EID.
127      *
128      * @param[in]  aEid               A reference to the EID.
129      *
130      */
131     void Remove(const Ip6::Address &aEid);
132 
133     /**
134      * This method updates an existing entry or adds a snooped cache entry for a given EID.
135      *
136      * The method is intended to add an entry for snoop optimization (inspection of a received message to create a
137      * cache entry mapping an EID to a RLOC).
138      *
139      * @param[in] aEid             A reference to the EID.
140      * @param[in] aRloc16          The RLOC16 corresponding to @p aEid.
141      * @param[in] aDest            The short MAC address destination of the received snooped message.
142      *
143      */
144     void UpdateSnoopedCacheEntry(const Ip6::Address &aEid, Mac::ShortAddress aRloc16, Mac::ShortAddress aDest);
145 
146     /**
147      * This method returns the RLOC16 for a given EID, initiates an Address Query if the mapping is not known.
148      *
149      * @param[in]   aEid                A reference to the EID.
150      * @param[out]  aRloc16             The RLOC16 corresponding to @p aEid.
151      *
152      * @retval kErrorNone           Successfully provided the RLOC16.
153      * @retval kErrorAddressQuery   Initiated an Address Query if allowed.
154      * @retval kErrorDrop           Earlier Address Query for the EID timed out. In retry timeout interval.
155      * @retval kErrorNoBufs         Insufficient buffer space available to send Address Query.
156      *
157      */
Resolve(const Ip6::Address & aEid,Mac::ShortAddress & aRloc16)158     Error Resolve(const Ip6::Address &aEid, Mac::ShortAddress &aRloc16)
159     {
160         return Resolve(aEid, aRloc16, /* aAllowAddressQuery */ true);
161     }
162 
163     /**
164      * This method looks up the RLOC16 for a given EID in the address cache.
165      *
166      * @param[in]   aEid                A reference to the EID.
167      *
168      * @returns The RLOC16 mapping to @p aEid or `Mac::kShortAddrInvalid` if it is not found in the address cache.
169      *
170      */
171     Mac::ShortAddress LookUp(const Ip6::Address &aEid);
172 
173     /**
174      * This method restarts any ongoing address queries.
175      *
176      * Any existing address queries will be restarted as if they are being sent for the first time.
177      *
178      */
179     void RestartAddressQueries(void);
180 
181     /**
182      * This method sends an Address Notification (ADDR_NTF.ans) message.
183      *
184      * @param[in]  aTarget                  The target address of the ADDR_NTF.ans message.
185      * @param[in]  aMeshLocalIid            The ML-IID of the ADDR_NTF.ans message.
186      * @param[in]  aLastTransactionTimeTlv  A pointer to the Last Transaction Time if the ADDR_NTF.ans message contains
187      *                                      a Last Transaction Time TLV.
188      * @param[in]  aDestination             The destination to send the ADDR_NTF.ans message.
189      *
190      */
191     void SendAddressQueryResponse(const Ip6::Address &            aTarget,
192                                   const Ip6::InterfaceIdentifier &aMeshLocalIid,
193                                   const uint32_t *                aLastTransactionTimeTlv,
194                                   const Ip6::Address &            aDestination);
195 
196     /**
197      * This method sends an Address Error Notification (ADDR_ERR.ntf) message.
198      *
199      * @param aTarget        The target address of the ADDR_ERR.ntf message.
200      * @param aMeshLocalIid  The ML-IID of the ADDR_ERR.ntf message.
201      * @param aDestination   The destination to send the ADDR_ERR.ntf message.
202      *
203      */
204     void SendAddressError(const Ip6::Address &            aTarget,
205                           const Ip6::InterfaceIdentifier &aMeshLocalIid,
206                           const Ip6::Address *            aDestination);
207 
208 private:
209     static constexpr uint16_t kCacheEntries                  = OPENTHREAD_CONFIG_TMF_ADDRESS_CACHE_ENTRIES;
210     static constexpr uint16_t kMaxNonEvictableSnoopedEntries = OPENTHREAD_CONFIG_TMF_ADDRESS_CACHE_MAX_SNOOP_ENTRIES;
211 
212     // All time/delay values are in seconds
213     static constexpr uint16_t kAddressQueryTimeout           = OPENTHREAD_CONFIG_TMF_ADDRESS_QUERY_TIMEOUT;
214     static constexpr uint16_t kAddressQueryInitialRetryDelay = OPENTHREAD_CONFIG_TMF_ADDRESS_QUERY_INITIAL_RETRY_DELAY;
215     static constexpr uint16_t kAddressQueryMaxRetryDelay     = OPENTHREAD_CONFIG_TMF_ADDRESS_QUERY_MAX_RETRY_DELAY;
216     static constexpr uint16_t kSnoopBlockEvictionTimeout     = OPENTHREAD_CONFIG_TMF_SNOOP_CACHE_ENTRY_TIMEOUT;
217 
218     static constexpr uint8_t kIteratorListIndex  = 0;
219     static constexpr uint8_t kIteratorEntryIndex = 1;
220 
221     class CacheEntry : public InstanceLocatorInit
222     {
223     public:
224         void Init(Instance &aInstance);
225 
226         CacheEntry *      GetNext(void);
227         const CacheEntry *GetNext(void) const;
228         void              SetNext(CacheEntry *aEntry);
229 
GetTarget(void) const230         const Ip6::Address &GetTarget(void) const { return mTarget; }
SetTarget(const Ip6::Address & aTarget)231         void                SetTarget(const Ip6::Address &aTarget) { mTarget = aTarget; }
232 
GetRloc16(void) const233         Mac::ShortAddress GetRloc16(void) const { return mRloc16; }
SetRloc16(Mac::ShortAddress aRloc16)234         void              SetRloc16(Mac::ShortAddress aRloc16) { mRloc16 = aRloc16; }
235 
GetMeshLocalIid(void) const236         const Ip6::InterfaceIdentifier &GetMeshLocalIid(void) const { return mInfo.mCached.mMeshLocalIid; }
SetMeshLocalIid(const Ip6::InterfaceIdentifier & aIid)237         void SetMeshLocalIid(const Ip6::InterfaceIdentifier &aIid) { mInfo.mCached.mMeshLocalIid = aIid; }
238 
GetLastTransactionTime(void) const239         uint32_t GetLastTransactionTime(void) const { return mInfo.mCached.mLastTransactionTime; }
SetLastTransactionTime(uint32_t aTime)240         void     SetLastTransactionTime(uint32_t aTime) { mInfo.mCached.mLastTransactionTime = aTime; }
IsLastTransactionTimeValid(void) const241         bool     IsLastTransactionTimeValid(void) const { return GetLastTransactionTime() != kInvalidLastTransTime; }
MarkLastTransactionTimeAsInvalid(void)242         void     MarkLastTransactionTimeAsInvalid(void) { SetLastTransactionTime(kInvalidLastTransTime); }
243 
DecrementTimeout(void)244         void     DecrementTimeout(void) { mInfo.mOther.mTimeout--; }
IsTimeoutZero(void) const245         bool     IsTimeoutZero(void) const { return mInfo.mOther.mTimeout == 0; }
GetTimeout(void) const246         uint16_t GetTimeout(void) const { return mInfo.mOther.mTimeout; }
SetTimeout(uint16_t aTimeout)247         void     SetTimeout(uint16_t aTimeout) { mInfo.mOther.mTimeout = aTimeout; }
248 
GetRetryDelay(void) const249         uint16_t GetRetryDelay(void) const { return mInfo.mOther.mRetryDelay; }
SetRetryDelay(uint16_t aDelay)250         void     SetRetryDelay(uint16_t aDelay) { mInfo.mOther.mRetryDelay = aDelay; }
251 
CanEvict(void) const252         bool CanEvict(void) const { return mInfo.mOther.mCanEvict; }
SetCanEvict(bool aCanEvict)253         void SetCanEvict(bool aCanEvict) { mInfo.mOther.mCanEvict = aCanEvict; }
254 
Matches(const Ip6::Address & aEid) const255         bool Matches(const Ip6::Address &aEid) const { return GetTarget() == aEid; }
256 
257     private:
258         static constexpr uint16_t kNoNextIndex          = 0xffff;     // `mNextIndex` value when at end of list.
259         static constexpr uint32_t kInvalidLastTransTime = 0xffffffff; // Value when `mLastTransactionTime` is invalid.
260 
261         Ip6::Address      mTarget;
262         Mac::ShortAddress mRloc16;
263         uint16_t          mNextIndex;
264 
265         union
266         {
267             struct
268             {
269                 uint32_t                 mLastTransactionTime;
270                 Ip6::InterfaceIdentifier mMeshLocalIid;
271             } mCached;
272 
273             struct
274             {
275                 uint16_t mTimeout;
276                 uint16_t mRetryDelay;
277                 bool     mCanEvict;
278             } mOther;
279 
280         } mInfo;
281     };
282 
283     typedef Pool<CacheEntry, kCacheEntries> CacheEntryPool;
284     typedef LinkedList<CacheEntry>          CacheEntryList;
285 
286     enum EntryChange : uint8_t
287     {
288         kEntryAdded,
289         kEntryUpdated,
290         kEntryRemoved,
291     };
292 
293     enum Reason : uint8_t
294     {
295         kReasonQueryRequest,
296         kReasonSnoop,
297         kReasonReceivedNotification,
298         kReasonRemovingRouterId,
299         kReasonRemovingRloc16,
300         kReasonReceivedIcmpDstUnreachNoRoute,
301         kReasonEvictingForNewEntry,
302         kReasonRemovingEid,
303     };
304 
GetCacheEntryPool(void)305     CacheEntryPool &GetCacheEntryPool(void) { return mCacheEntryPool; }
306 
307     Error       Resolve(const Ip6::Address &aEid, Mac::ShortAddress &aRloc16, bool aAllowAddressQuery);
308     void        Remove(Mac::ShortAddress aRloc16, bool aMatchRouterId);
309     void        Remove(const Ip6::Address &aEid, Reason aReason);
310     CacheEntry *FindCacheEntry(const Ip6::Address &aEid, CacheEntryList *&aList, CacheEntry *&aPrevEntry);
311     CacheEntry *NewCacheEntry(bool aSnoopedEntry);
312     void        RemoveCacheEntry(CacheEntry &aEntry, CacheEntryList &aList, CacheEntry *aPrevEntry, Reason aReason);
313     Error       UpdateCacheEntry(const Ip6::Address &aEid, Mac::ShortAddress aRloc16);
314 
315     Error SendAddressQuery(const Ip6::Address &aEid);
316 
317     static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
318 
319 #endif // OPENTHREAD_FTD
320 
321     static void HandleAddressError(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
322     void        HandleAddressError(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
323 
324 #if OPENTHREAD_FTD
325     static void HandleAddressQuery(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
326     void        HandleAddressQuery(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
327 
328     static void HandleAddressNotification(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
329     void        HandleAddressNotification(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
330 
331     static void HandleIcmpReceive(void *               aContext,
332                                   otMessage *          aMessage,
333                                   const otMessageInfo *aMessageInfo,
334                                   const otIcmp6Header *aIcmpHeader);
335     void        HandleIcmpReceive(Message &                aMessage,
336                                   const Ip6::MessageInfo & aMessageInfo,
337                                   const Ip6::Icmp::Header &aIcmpHeader);
338 
339     void HandleTimeTick(void);
340 
341     void LogCacheEntryChange(EntryChange       aChange,
342                              Reason            aReason,
343                              const CacheEntry &aEntry,
344                              CacheEntryList *  aList = nullptr);
345 
346     const char *ListToString(const CacheEntryList *aList) const;
347 
348     static AddressResolver::CacheEntry *GetEntryAfter(CacheEntry *aPrev, CacheEntryList &aList);
349 
350 #endif // OPENTHREAD_FTD
351     Coap::Resource mAddressError;
352 #if OPENTHREAD_FTD
353     Coap::Resource mAddressQuery;
354     Coap::Resource mAddressNotification;
355 
356     CacheEntryPool mCacheEntryPool;
357     CacheEntryList mCachedList;
358     CacheEntryList mSnoopedList;
359     CacheEntryList mQueryList;
360     CacheEntryList mQueryRetryList;
361 
362     Ip6::Icmp::Handler mIcmpHandler;
363 #endif //  OPENTHREAD_FTD
364 };
365 
366 /**
367  * @}
368  */
369 
370 } // namespace ot
371 
372 #endif // ADDRESS_RESOLVER_HPP_
373