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