• 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/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