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 /**
30  * @file
31  *   This file includes definitions for transmitting SVR_DATA.ntf messages.
32  */
33 
34 #ifndef NETWORK_DATA_NOTIFIER_HPP_
35 #define NETWORK_DATA_NOTIFIER_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #if OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
40 
41 #include <openthread/border_router.h>
42 
43 #include "coap/coap.hpp"
44 #include "common/message.hpp"
45 #include "common/non_copyable.hpp"
46 #include "common/notifier.hpp"
47 #include "common/tasklet.hpp"
48 #include "common/time_ticker.hpp"
49 
50 namespace ot {
51 namespace NetworkData {
52 
53 class NetworkData;
54 
55 /**
56  * Implements the SVR_DATA.ntf transmission logic.
57  *
58  */
59 class Notifier : public InstanceLocator, private NonCopyable
60 {
61     friend class ot::Notifier;
62     friend class ot::TimeTicker;
63 
64 public:
65     /**
66      * Constructor.
67      *
68      * @param[in] aInstance  The OpenThread instance.
69      *
70      */
71     explicit Notifier(Instance &aInstance);
72 
73     /**
74      * Call this method to inform the notifier that new server data is available.
75      *
76      * Posts a tasklet to sync new server data with leader so if there are multiple changes within the same
77      * flow of execution (multiple calls to this method) they are all synchronized together and included in the same
78      * message to the leader.
79      *
80      */
81     void HandleServerDataUpdated(void);
82 
83 #if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL
84     typedef otBorderRouterNetDataFullCallback NetDataCallback; ///< Network Data full callback.
85 
86     /**
87      * Sets the callback to indicate when Network Data gets full.
88      *
89      * @param[in] aCallback   The callback.
90      * @param[in] aContext    The context to use with @p aCallback.
91      *
92      */
93     void SetNetDataFullCallback(NetDataCallback aCallback, void *aContext);
94 
95     /**
96      * Signals that network data (local or leader) is getting full.
97      *
98      */
SignalNetworkDataFull(void)99     void SignalNetworkDataFull(void) { mNetDataFullTask.Post(); }
100 #endif
101 
102 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
103     /**
104      * Indicates whether the device as border router is eligible for router role upgrade request using the
105      * status reason `kBorderRouterRequest`.
106      *
107      * Checks whether device is providing IP connectivity and that there are fewer than two border routers
108      * in network data acting as router.  Device is considered to provide external IP connectivity if at least one of
109      * the below conditions hold:
110      *
111      * - It has added at least one external route entry.
112      * - It has added at least one prefix entry with default-route and on-mesh flags set.
113      * - It has added at least one domain prefix (domain and on-mesh flags set).
114      *
115      * Does not check the current role of device.
116      *
117      * @retval TRUE    Device is eligible to request router role upgrade as a border router.
118      * @retval FALSE   Device is not eligible to request router role upgrade as a border router.
119      *
120      */
121     bool IsEligibleForRouterRoleUpgradeAsBorderRouter(void) const;
122 #endif
123 
124 private:
125     static constexpr uint32_t kDelayNoBufs                 = 1000;   // in msec
126     static constexpr uint32_t kDelayRemoveStaleChildren    = 5000;   // in msec
127     static constexpr uint32_t kDelaySynchronizeServerData  = 300000; // in msec
128     static constexpr uint8_t  kRouterRoleUpgradeMaxTimeout = 10;     // in sec
129 
130     void  SynchronizeServerData(void);
131     Error SendServerDataNotification(uint16_t aOldRloc16, const NetworkData *aNetworkData = nullptr);
132 #if OPENTHREAD_FTD
133     Error RemoveStaleChildEntries(void);
134 #endif
135 #if OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
136     Error UpdateInconsistentData(void);
137 #endif
138 
139     void        HandleNotifierEvents(Events aEvents);
140     void        HandleTimer(void);
141     static void HandleCoapResponse(void                *aContext,
142                                    otMessage           *aMessage,
143                                    const otMessageInfo *aMessageInfo,
144                                    Error                aResult);
145     void        HandleCoapResponse(Error aResult);
146 
147 #if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL
148     void HandleNetDataFull(void);
149 #endif
150 
151 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
152     void ScheduleRouterRoleUpgradeIfEligible(void);
153     void HandleTimeTick(void);
154 #endif
155 
156     using SynchronizeDataTask = TaskletIn<Notifier, &Notifier::SynchronizeServerData>;
157     using DelayTimer          = TimerMilliIn<Notifier, &Notifier::HandleTimer>;
158 #if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL
159     using NetDataFullTask = TaskletIn<Notifier, &Notifier::HandleNetDataFull>;
160 #endif
161 
162     DelayTimer          mTimer;
163     SynchronizeDataTask mSynchronizeDataTask;
164 #if OPENTHREAD_CONFIG_BORDER_ROUTER_SIGNAL_NETWORK_DATA_FULL
165     NetDataFullTask           mNetDataFullTask;
166     Callback<NetDataCallback> mNetDataFullCallback;
167 #endif
168     uint32_t mNextDelay;
169     uint16_t mOldRloc;
170     bool     mWaitingForResponse : 1;
171 
172 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE && OPENTHREAD_CONFIG_BORDER_ROUTER_REQUEST_ROUTER_ROLE
173     bool    mDidRequestRouterRoleUpgrade : 1;
174     uint8_t mRouterRoleUpgradeTimeout;
175 #endif
176 };
177 
178 } // namespace NetworkData
179 } // namespace ot
180 
181 #endif // OPENTHREAD_FTD || OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE || OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
182 
183 #endif // NETWORK_DATA_NOTIFIER_HPP_
184