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