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