1 /* 2 * Copyright (c) 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 * @file 30 * This file includes definitions for NdProxy Table on Thread Backbone Border Router. 31 */ 32 33 #ifndef NDPROXY_TABLE_HPP_ 34 #define NDPROXY_TABLE_HPP_ 35 36 #include "openthread-core-config.h" 37 38 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE 39 40 #include <openthread/backbone_router_ftd.h> 41 42 #include "backbone_router/bbr_leader.hpp" 43 #include "common/iterator_utils.hpp" 44 #include "common/locator.hpp" 45 #include "common/non_copyable.hpp" 46 #include "common/time.hpp" 47 #include "net/ip6_address.hpp" 48 #include "thread/mle_types.hpp" 49 50 namespace ot { 51 52 namespace BackboneRouter { 53 54 /** 55 * This class implements NdProxy Table maintenance on Primary Backbone Router. 56 * 57 */ 58 class NdProxyTable : public InstanceLocator, private NonCopyable 59 { 60 public: 61 /** 62 * This class represents a ND Proxy instance. 63 * 64 */ 65 class NdProxy : private Clearable<NdProxy> 66 { 67 friend class NdProxyTable; 68 69 public: 70 /** 71 * This method gets the Mesh-Local IID of the ND Proxy. 72 * 73 * @returns The Mesh-Local IID. 74 * 75 */ GetMeshLocalIid(void) const76 const Ip6::InterfaceIdentifier &GetMeshLocalIid(void) const { return mMeshLocalIid; } 77 78 /** 79 * This method gets the time since last transaction of the ND Proxy. 80 * 81 * @returns The time since last transaction in seconds. 82 * 83 */ GetTimeSinceLastTransaction(void) const84 uint32_t GetTimeSinceLastTransaction(void) const 85 { 86 return TimeMilli::MsecToSec(TimerMilli::GetNow() - mLastRegistrationTime); 87 } 88 89 /** 90 * This method gets the short address of the device who sends the DUA registration. 91 * 92 * @returns The RLOC16 value. 93 * 94 */ GetRloc16(void) const95 uint16_t GetRloc16(void) const { return mRloc16; } 96 97 /** 98 * This method gets the DAD flag of the ND Proxy. 99 * 100 * @returns The DAD flag. 101 * 102 */ GetDadFlag(void) const103 bool GetDadFlag(void) const { return mDadFlag; } 104 105 private: NdProxy(void)106 NdProxy(void) { Clear(); } 107 108 void Init(const Ip6::InterfaceIdentifier &aAddressIid, 109 const Ip6::InterfaceIdentifier &aMeshLocalIid, 110 uint16_t aRloc16, 111 uint32_t aTimeSinceLastTransaction); 112 113 void Update(uint16_t aRloc16, uint32_t aTimeSinceLastTransaction); IncreaseDadAttempts(void)114 void IncreaseDadAttempts(void) { mDadAttempts++; } IsDadAttemptsComplete() const115 bool IsDadAttemptsComplete() const { return mDadAttempts == Mle::kDuaDadRepeats; } 116 117 Ip6::InterfaceIdentifier mAddressIid; 118 Ip6::InterfaceIdentifier mMeshLocalIid; 119 TimeMilli mLastRegistrationTime; ///< in milliseconds 120 uint16_t mRloc16; 121 uint8_t mDadAttempts : 2; 122 bool mDadFlag : 1; 123 bool mValid : 1; 124 125 static_assert(Mle::kDuaDadRepeats < 4, "Mle::kDuaDadRepeats does not fit in mDadAttempts field as 2-bit value"); 126 }; 127 128 /** 129 * This constructor initializes the `NdProxyTable` object. 130 * 131 * @param[in] aInstance A reference to the OpenThread instance. 132 * 133 */ NdProxyTable(Instance & aInstance)134 explicit NdProxyTable(Instance &aInstance) 135 : InstanceLocator(aInstance) 136 , mCallback(nullptr) 137 , mCallbackContext(nullptr) 138 , mIsAnyDadInProcess(false) 139 { 140 } 141 142 /** 143 * This method registers a given IPv6 address IID with related information to the NdProxy table. 144 * 145 * @param[in] aAddressIid The IPv6 address IID. 146 * @param[in] aMeshLocalIid The Mesh-Local IID. 147 * @param[in] aRloc16 The RLOC16. 148 * @param[in] aTimeSinceLastTransaction Time since last transaction (in seconds). 149 * 150 * @retval kErrorNone If registered successfully. 151 * @retval kErrorDuplicated If the IPv6 address IID is a duplicate. 152 * @retval kErrorNoBufs Insufficient buffer space available to register. 153 * 154 */ 155 Error Register(const Ip6::InterfaceIdentifier &aAddressIid, 156 const Ip6::InterfaceIdentifier &aMeshLocalIid, 157 uint16_t aRloc16, 158 const uint32_t * aTimeSinceLastTransaction); 159 160 /** 161 * This method checks if a given IPv6 address IID was registered. 162 * 163 * @param[in] aAddressIid The IPv6 address IID. 164 * 165 * @retval TRUE If the IPv6 address IID was registered. 166 * @retval FALSE If the IPv6 address IID was not registered. 167 * 168 */ IsRegistered(const Ip6::InterfaceIdentifier & aAddressIid)169 bool IsRegistered(const Ip6::InterfaceIdentifier &aAddressIid) { return FindByAddressIid(aAddressIid) != nullptr; } 170 171 /** 172 * This method notifies Domain Prefix status. 173 * 174 * @param[in] aState The Domain Prefix state or state change. 175 * 176 */ 177 void HandleDomainPrefixUpdate(Leader::DomainPrefixState aState); 178 179 /** 180 * This method notifies ND Proxy table of the timer tick. 181 * 182 */ 183 void HandleTimer(void); 184 185 /** 186 * This method gets the ND Proxy info for a given Domain Unicast Address. 187 * 188 * @param[in] aDua The Domain Unicast Address. 189 * 190 * @returns The `NdProxy` instance matching the specified @p aDua, or nullptr if not found. 191 * 192 */ 193 NdProxy *ResolveDua(const Ip6::Address &aDua); 194 195 /** 196 * This method notifies DAD completed for a given ND Proxy. 197 * 198 * @param[in] aNdProxy The ND Proxy to notify of. 199 * @param[in] aDuplicated Whether duplicate was detected. 200 * 201 */ 202 static void NotifyDadComplete(NdProxy &aNdProxy, bool aDuplicated); 203 204 /** 205 * This method removes the ND Proxy. 206 * 207 * @param[in] aNdProxy The ND Proxy to remove. 208 * 209 */ 210 static void Erase(NdProxy &aNdProxy); 211 212 /* 213 * This method sets the ND Proxy callback. 214 * 215 * @param[in] aCallback The callback function. 216 * @param[in] aContext A user context pointer. 217 * 218 */ 219 void SetCallback(otBackboneRouterNdProxyCallback aCallback, void *aContext); 220 221 /** 222 * This method retrieves the ND Proxy info of the Domain Unicast Address. 223 * 224 * @param[in] aDua The Domain Unicast Address to get info. 225 * @param[in] aNdProxyInfo A pointer to the ND Proxy info. 226 * 227 * @retval kErrorNone Successfully retrieve the ND Proxy info. 228 * @retval kErrorNotFound Failed to find the Domain Unicast Address in the ND Proxy table. 229 * 230 */ 231 Error GetInfo(const Ip6::Address &aDua, otBackboneRouterNdProxyInfo &aNdProxyInfo); 232 233 private: 234 static constexpr uint16_t kMaxNdProxyNum = OPENTHREAD_CONFIG_NDPROXY_TABLE_ENTRY_NUM; 235 236 enum Filter : uint8_t 237 { 238 kFilterInvalid, 239 kFilterValid, 240 kFilterDadInProcess, 241 }; 242 243 /** 244 * This class represents an iterator for iterating through the NdProxy Table. 245 * 246 */ 247 class Iterator : public InstanceLocator, public ItemPtrIterator<NdProxy, Iterator> 248 { 249 friend class ItemPtrIterator<NdProxy, Iterator>; 250 friend class NdProxyTable; 251 friend class IteratorBuilder; 252 253 private: 254 enum IteratorType : uint8_t 255 { 256 kEndIterator, 257 }; 258 259 Iterator(Instance &aInstance, Filter aFilter); 260 Iterator(Instance &aInstance, IteratorType); 261 262 void Advance(void); 263 264 Filter mFilter; 265 }; 266 267 class IteratorBuilder : public InstanceLocator 268 { 269 friend class NdProxyTable; 270 271 private: IteratorBuilder(Instance & aInstance,Filter aFilter)272 IteratorBuilder(Instance &aInstance, Filter aFilter) 273 : InstanceLocator(aInstance) 274 , mFilter(aFilter) 275 { 276 } 277 begin(void)278 Iterator begin(void) { return Iterator(GetInstance(), mFilter); } end(void)279 Iterator end(void) { return Iterator(GetInstance(), Iterator::kEndIterator); } 280 281 Filter mFilter; 282 }; 283 Iterate(Filter aFilter)284 IteratorBuilder Iterate(Filter aFilter) { return IteratorBuilder(GetInstance(), aFilter); } 285 void Clear(void); 286 static bool MatchesFilter(const NdProxy &aProxy, Filter aFilter); 287 NdProxy * FindByAddressIid(const Ip6::InterfaceIdentifier &aAddressIid); 288 NdProxy * FindByMeshLocalIid(const Ip6::InterfaceIdentifier &aMeshLocalIid); 289 NdProxy * FindInvalid(void); 290 Ip6::Address GetDua(NdProxy &aNdProxy); 291 void NotifyDuaRegistrationOnBackboneLink(NdProxy &aNdProxy, bool aIsRenew); 292 void TriggerCallback(otBackboneRouterNdProxyEvent aEvent, const Ip6::InterfaceIdentifier &aAddressIid) const; 293 294 NdProxy mProxies[kMaxNdProxyNum]; 295 otBackboneRouterNdProxyCallback mCallback; 296 void * mCallbackContext; 297 bool mIsAnyDadInProcess : 1; 298 }; 299 300 } // namespace BackboneRouter 301 302 } // namespace ot 303 304 #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE 305 306 #endif // NDPROXY_TABLE_HPP_ 307