• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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