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