1 /*
2  *  Copyright (c) 2016, 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 /**
30  * @file
31  *   This file includes definitions for manipulating Thread Network Data managed by the Thread Leader.
32  */
33 
34 #ifndef NETWORK_DATA_LEADER_FTD_HPP_
35 #define NETWORK_DATA_LEADER_FTD_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #if OPENTHREAD_FTD
40 
41 #include <stdint.h>
42 
43 #include "common/non_copyable.hpp"
44 #include "common/numeric_limits.hpp"
45 #include "common/timer.hpp"
46 #include "net/ip6_address.hpp"
47 #include "thread/mle_router.hpp"
48 #include "thread/network_data.hpp"
49 #include "thread/tmf.hpp"
50 
51 namespace ot {
52 
53 namespace NetworkData {
54 
55 /**
56  * @addtogroup core-netdata-leader
57  *
58  * @brief
59  *   This module includes definitions for manipulating Thread Network Data managed by the Thread Leader.
60  *
61  * @{
62  *
63  */
64 
65 /**
66  * This class implements the Thread Network Data maintained by the Leader.
67  *
68  */
69 class Leader : public LeaderBase, private NonCopyable
70 {
71     friend class Tmf::Agent;
72 
73 public:
74     /**
75      * This enumeration defines the match mode constants to compare two RLOC16 values.
76      *
77      */
78     enum MatchMode : uint8_t
79     {
80         kMatchModeRloc16,   ///< Perform exact RLOC16 match.
81         kMatchModeRouterId, ///< Perform Router ID match (match the router and any of its children).
82     };
83 
84     /**
85      * This constructor initializes the object.
86      *
87      * @param[in]  aInstance     A reference to the OpenThread instance.
88      *
89      */
90     explicit Leader(Instance &aInstance);
91 
92     /**
93      * This method reset the Thread Network Data.
94      *
95      */
96     void Reset(void);
97 
98     /**
99      * This method starts the Leader services.
100      *
101      * The start mode indicates whether device is starting normally as leader or restoring its role as leader after
102      * reset. In the latter case, we do not accept any new registrations (`HandleServerData()`) and wait for
103      * `HandleNetworkDataRestoredAfterReset()` to indicate that the leader has successfully recovered the Network Data
104      * before allowing new Network Data registrations.
105      *
106      * @param[in] aStartMode   The start mode.
107      *
108      */
109     void Start(Mle::LeaderStartMode aStartMode);
110 
111     /**
112      * This method increments the Thread Network Data version.
113      *
114      */
115     void IncrementVersion(void);
116 
117     /**
118      * This method increments both the Thread Network Data version and stable version.
119      *
120      */
121     void IncrementVersionAndStableVersion(void);
122 
123     /**
124      * This method returns CONTEXT_ID_RESUSE_DELAY value.
125      *
126      * @returns The CONTEXT_ID_REUSE_DELAY value (in seconds).
127      *
128      */
GetContextIdReuseDelay(void) const129     uint32_t GetContextIdReuseDelay(void) const { return mContextIds.GetReuseDelay(); }
130 
131     /**
132      * This method sets CONTEXT_ID_RESUSE_DELAY value.
133      *
134      * @warning This method should only be used for testing.
135      *
136      * @param[in]  aDelay  The CONTEXT_ID_REUSE_DELAY value (in seconds).
137      *
138      */
SetContextIdReuseDelay(uint32_t aDelay)139     void SetContextIdReuseDelay(uint32_t aDelay) { mContextIds.SetReuseDelay(aDelay); }
140 
141     /**
142      * This method removes Network Data entries matching with a given RLOC16.
143      *
144      * @param[in]  aRloc16    A RLOC16 value.
145      * @param[in]  aMatchMode A match mode (@sa MatchMode).
146      *
147      */
148     void RemoveBorderRouter(uint16_t aRloc16, MatchMode aMatchMode);
149 
150     /**
151      * This method synchronizes internal 6LoWPAN Context ID Set with recently obtained Thread Network Data.
152      *
153      * Note that this method should be called only by the Leader once after reset.
154      *
155      */
156     void HandleNetworkDataRestoredAfterReset(void);
157 
158     /**
159      * This method scans network data for given Service ID and returns pointer to the respective TLV, if present.
160      *
161      * @param aServiceId Service ID to look for.
162      * @return Pointer to the Service TLV for given Service ID, or nullptr if not present.
163      *
164      */
165     const ServiceTlv *FindServiceById(uint8_t aServiceId) const;
166 
167 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
168     /**
169      * This method indicates whether a given Prefix can act as a valid OMR prefix and exists in the network data.
170      *
171      * @param[in]  aPrefix   The OMR prefix to check.
172      *
173      * @retval TRUE  If @p aPrefix is a valid OMR prefix and Network Data contains @p aPrefix.
174      * @retval FALSE Otherwise.
175      *
176      */
177     bool ContainsOmrPrefix(const Ip6::Prefix &aPrefix);
178 #endif
179 
180 private:
181     static constexpr uint32_t kMaxNetDataSyncWait = 60 * 1000; // Maximum time to wait for netdata sync in msec.
182 
183     class ChangedFlags
184     {
185     public:
ChangedFlags(void)186         ChangedFlags(void)
187             : mChanged(false)
188             , mStableChanged(false)
189         {
190         }
191 
Update(const NetworkDataTlv & aTlv)192         void Update(const NetworkDataTlv &aTlv)
193         {
194             mChanged       = true;
195             mStableChanged = (mStableChanged || aTlv.IsStable());
196         }
197 
DidChange(void) const198         bool DidChange(void) const { return mChanged; }
DidStableChange(void) const199         bool DidStableChange(void) const { return mStableChanged; }
200 
201     private:
202         bool mChanged;       // Any (stable or not) network data change (add/remove).
203         bool mStableChanged; // Stable network data change (add/remove).
204     };
205 
206     enum UpdateStatus : uint8_t
207     {
208         kTlvRemoved, // TLV contained no sub TLVs and therefore is removed.
209         kTlvUpdated, // TLV stable flag is updated based on its sub TLVs.
210     };
211 
212     class ContextIds : public InstanceLocator
213     {
214     public:
215         // This class tracks Context IDs. A Context ID can be in one
216         // of the 3 states: It is unallocated, or it is allocated
217         // and in-use, or it scheduled to be removed (after reuse delay
218         // interval is passed).
219 
220         static constexpr uint8_t kInvalidId = NumericLimits<uint8_t>::kMax;
221 
ContextIds(Instance & aInstance)222         explicit ContextIds(Instance &aInstance)
223             : InstanceLocator(aInstance)
224             , mReuseDelay(kReuseDelay)
225         {
226         }
227 
228         void     Clear(void);
229         Error    GetUnallocatedId(uint8_t &aId);
MarkAsInUse(uint8_t aId)230         void     MarkAsInUse(uint8_t aId) { mRemoveTimes[aId - kMinId].SetValue(kInUse); }
231         void     ScheduleToRemove(uint8_t aId);
GetReuseDelay(void) const232         uint32_t GetReuseDelay(void) const { return mReuseDelay; }
SetReuseDelay(uint32_t aDelay)233         void     SetReuseDelay(uint32_t aDelay) { mReuseDelay = aDelay; }
234         void     HandleTimer(void);
235 
236     private:
237         static constexpr uint32_t kReuseDelay = 5 * 60; // 5 minutes (in seconds).
238 
239         static constexpr uint8_t kMinId = 1;
240         static constexpr uint8_t kMaxId = 15;
241 
242         // The `mRemoveTimes[id]` is used to track the state of a
243         // Context ID and its remove time. Two specific values
244         // `kUnallocated` and `kInUse` are used to indicate ID is in
245         // unallocated or in-use states. Other values indicate we
246         // are in remove state waiting to remove it at `mRemoveTime`.
247 
248         static constexpr uint32_t kUnallocated = 0;
249         static constexpr uint32_t kInUse       = 1;
250 
IsUnallocated(uint8_t aId) const251         bool      IsUnallocated(uint8_t aId) const { return mRemoveTimes[aId - kMinId].GetValue() == kUnallocated; }
IsInUse(uint8_t aId) const252         bool      IsInUse(uint8_t aId) const { return mRemoveTimes[aId - kMinId].GetValue() == kInUse; }
GetRemoveTime(uint8_t aId) const253         TimeMilli GetRemoveTime(uint8_t aId) const { return mRemoveTimes[aId - kMinId]; }
254         void      SetRemoveTime(uint8_t aId, TimeMilli aTime);
MarkAsUnallocated(uint8_t aId)255         void      MarkAsUnallocated(uint8_t aId) { mRemoveTimes[aId - kMinId].SetValue(kUnallocated); }
256 
257         TimeMilli mRemoveTimes[kMaxId - kMinId + 1];
258         uint32_t  mReuseDelay;
259     };
260 
261     template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
262 
263     void HandleTimer(void);
264 
265     void RegisterNetworkData(uint16_t aRloc16, const NetworkData &aNetworkData);
266 
267     Error AddPrefix(const PrefixTlv &aPrefix, ChangedFlags &aChangedFlags);
268     Error AddHasRoute(const HasRouteTlv &aHasRoute, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags);
269     Error AddBorderRouter(const BorderRouterTlv &aBorderRouter, PrefixTlv &aDstPrefix, ChangedFlags &aChangedFlags);
270     Error AddService(const ServiceTlv &aService, ChangedFlags &aChangedFlags);
271     Error AddServer(const ServerTlv &aServer, ServiceTlv &aDstService, ChangedFlags &aChangedFlags);
272 
273     Error AllocateServiceId(uint8_t &aServiceId) const;
274 
275     void RemoveContext(uint8_t aContextId);
276     void RemoveContext(PrefixTlv &aPrefix, uint8_t aContextId);
277 
278     void RemoveCommissioningData(void);
279 
280     void RemoveRloc(uint16_t aRloc16, MatchMode aMatchMode, ChangedFlags &aChangedFlags);
281     void RemoveRloc(uint16_t           aRloc16,
282                     MatchMode          aMatchMode,
283                     const NetworkData &aExcludeNetworkData,
284                     ChangedFlags      &aChangedFlags);
285     void RemoveRlocInPrefix(PrefixTlv       &aPrefix,
286                             uint16_t         aRloc16,
287                             MatchMode        aMatchMode,
288                             const PrefixTlv *aExcludePrefix,
289                             ChangedFlags    &aChangedFlags);
290     void RemoveRlocInService(ServiceTlv       &aService,
291                              uint16_t          aRloc16,
292                              MatchMode         aMatchMode,
293                              const ServiceTlv *aExcludeService,
294                              ChangedFlags     &aChangedFlags);
295     void RemoveRlocInHasRoute(PrefixTlv       &aPrefix,
296                               HasRouteTlv     &aHasRoute,
297                               uint16_t         aRloc16,
298                               MatchMode        aMatchMode,
299                               const PrefixTlv *aExcludePrefix,
300                               ChangedFlags    &aChangedFlags);
301     void RemoveRlocInBorderRouter(PrefixTlv       &aPrefix,
302                                   BorderRouterTlv &aBorderRouter,
303                                   uint16_t         aRloc16,
304                                   MatchMode        aMatchMode,
305                                   const PrefixTlv *aExcludePrefix,
306                                   ChangedFlags    &aChangedFlags);
307 
308     static bool RlocMatch(uint16_t aFirstRloc16, uint16_t aSecondRloc16, MatchMode aMatchMode);
309 
310     static Error Validate(const NetworkData &aNetworkData, uint16_t aRloc16);
311     static Error ValidatePrefix(const PrefixTlv &aPrefix, uint16_t aRloc16);
312     static Error ValidateService(const ServiceTlv &aService, uint16_t aRloc16);
313 
314     static bool ContainsMatchingEntry(const PrefixTlv *aPrefix, bool aStable, const HasRouteEntry &aEntry);
315     static bool ContainsMatchingEntry(const HasRouteTlv *aHasRoute, const HasRouteEntry &aEntry);
316     static bool ContainsMatchingEntry(const PrefixTlv *aPrefix, bool aStable, const BorderRouterEntry &aEntry);
317     static bool ContainsMatchingEntry(const BorderRouterTlv *aBorderRouter, const BorderRouterEntry &aEntry);
318     static bool ContainsMatchingServer(const ServiceTlv *aService, const ServerTlv &aServer);
319 
320     UpdateStatus UpdatePrefix(PrefixTlv &aPrefix);
321     UpdateStatus UpdateService(ServiceTlv &aService);
322     UpdateStatus UpdateTlv(NetworkDataTlv &aTlv, const NetworkDataTlv *aSubTlvs);
323 
324     void SendCommissioningGetResponse(const Coap::Message    &aRequest,
325                                       uint16_t                aLength,
326                                       const Ip6::MessageInfo &aMessageInfo);
327     void SendCommissioningSetResponse(const Coap::Message     &aRequest,
328                                       const Ip6::MessageInfo  &aMessageInfo,
329                                       MeshCoP::StateTlv::State aState);
330     void IncrementVersions(bool aIncludeStable);
331     void IncrementVersions(const ChangedFlags &aFlags);
332 
333     using UpdateTimer = TimerMilliIn<Leader, &Leader::HandleTimer>;
334 
335     bool        mWaitingForNetDataSync;
336     ContextIds  mContextIds;
337     UpdateTimer mTimer;
338 };
339 
340 DeclareTmfHandler(Leader, kUriServerData);
341 DeclareTmfHandler(Leader, kUriCommissionerGet);
342 DeclareTmfHandler(Leader, kUriCommissionerSet);
343 
344 /**
345  * @}
346  */
347 
348 } // namespace NetworkData
349 } // namespace ot
350 
351 #endif // OPENTHREAD_FTD
352 
353 #endif // NETWORK_DATA_LEADER_FTD_HPP_
354