1 /*
2  *  Copyright (c) 2017, 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 child supervision feature.
32  *
33  */
34 
35 #ifndef CHILD_SUPERVISION_HPP_
36 #define CHILD_SUPERVISION_HPP_
37 
38 #include "openthread-core-config.h"
39 
40 #include <stdint.h>
41 
42 #include "common/locator.hpp"
43 #include "common/message.hpp"
44 #include "common/non_copyable.hpp"
45 #include "common/notifier.hpp"
46 #include "common/time_ticker.hpp"
47 #include "common/timer.hpp"
48 #include "mac/mac_types.hpp"
49 #include "thread/topology.hpp"
50 
51 namespace ot {
52 
53 class ThreadNetif;
54 class Child;
55 
56 namespace Utils {
57 
58 /**
59  *
60  * Child supervision feature provides a mechanism for parent
61  * to ensure that a message is sent to each sleepy child within
62  * a fixed interval, namely the supervision interval. If there
63  * is no transmission to the child within the supervision
64  * interval, child supervisor enqueues and sends a supervision
65  * message (a data message with empty payload) to the child.
66  *
67  * On the child side, this is used to check the connectivity
68  * to the parent. If the child does not hear from its parent
69  * for a pre-specified timeout interval it assumes that it may
70  * be disconnected and tries to re-attach to the parent.
71  *
72  * The child supervision provides an alternative, more
73  * energy-efficient solution compared to requiring the sleepy child
74  * to periodically perform an MLE Child Update Request/Response
75  * exchange with the parent (as a way of verifying that it
76  * is still connected to the parent). The child supervision
77  * solution puts the burden of message transmissions on the
78  * parent instead of the typically more energy-constrained child.
79  *
80  * Note that most radios generate an auto-ack in hardware in
81  * response to a received frame, so the child cannot solely rely
82  * on the 15.4 acknowledgments it receives from parent as an
83  * indicator that it is still connected and is in parent's
84  * child table.
85  *
86  */
87 
88 #if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
89 
90 #if OPENTHREAD_FTD
91 
92 /**
93  * This class implements a child supervisor.
94  *
95  */
96 class ChildSupervisor : public InstanceLocator, private NonCopyable
97 {
98     friend class ot::Notifier;
99     friend class ot::TimeTicker;
100 
101 public:
102     /**
103      * This constructor initializes the object.
104      *
105      * @param[in]  aInstance     A reference to the OpenThread instance.
106      *
107      */
108     explicit ChildSupervisor(Instance &aInstance);
109 
110     /**
111      * This method starts the child supervision process on parent.
112      *
113      */
114     void Start(void);
115 
116     /**
117      * This method stops the child supervision process on parent.
118      *
119      */
120     void Stop(void);
121 
122     /**
123      * This method sets the supervision interval.
124      *
125      * Setting the supervision interval to a non-zero value will ensure to start the supervision process (if not
126      * already started).
127      *
128      * @param[in] aInterval If non-zero, the desired supervision interval (in seconds), zero to disable supervision.
129      *
130      */
131     void SetSupervisionInterval(uint16_t aInterval);
132 
133     /**
134      * This method returns the supervision interval.
135      *
136      * @returns  The current supervision interval (seconds), or zero if supervision is disabled.
137      *
138      */
GetSupervisionInterval(void) const139     uint16_t GetSupervisionInterval(void) const { return mSupervisionInterval; }
140 
141     /**
142      * This method returns the destination for a supervision message.
143      *
144      * @param[in] aMessage The message for which to get the destination.
145      *
146      * @returns  A pointer to the destination child of the message, or nullptr if @p aMessage is not of supervision
147      * type.
148      *
149      */
150     Child *GetDestination(const Message &aMessage) const;
151 
152     /**
153      * This method updates the supervision state for a child. It informs the child supervisor that a message was
154      * successfully sent to the child.
155      *
156      * @param[in] aChild     The child to which a message was successfully sent.
157      *
158      */
159     void UpdateOnSend(Child &aChild);
160 
161 private:
162     static constexpr uint16_t kDefaultSupervisionInterval = OPENTHREAD_CONFIG_CHILD_SUPERVISION_INTERVAL; // (seconds)
163 
164     void SendMessage(Child &aChild);
165     void CheckState(void);
166     void HandleTimeTick(void);
167     void HandleNotifierEvents(Events aEvents);
168 
169     uint16_t mSupervisionInterval;
170 };
171 
172 #endif // #if OPENTHREAD_FTD
173 
174 /**
175  * This class implements a child supervision listener.
176  *
177  */
178 class SupervisionListener : public InstanceLocator, private NonCopyable
179 {
180 public:
181     /**
182      * This constructor initializes the object.
183      *
184      * @param[in]  aInstance     A reference to the OpenThread instance.
185      *
186      */
187     explicit SupervisionListener(Instance &aInstance);
188 
189     /**
190      * This method starts the supervision listener operation.
191      *
192      */
193     void Start(void);
194 
195     /**
196      * This method stops the supervision listener operation.
197      *
198      */
199     void Stop(void);
200 
201     /**
202      * This method sets the supervision check timeout (in seconds).
203      *
204      * If the child does not hear from its parent within the given check timeout interval, it initiates the re-attach
205      * process (MLE Child Update Request/Response exchange with its parent). Setting the timeout to zero, disables the
206      * supervision check on the child.
207      *
208      * It is recommended to select a supervision check timeout value larger than the parent's child supervision
209      * interval plus the maximum time between the child's data poll transmissions.
210      *
211      * @param[in]  aTimeout   The timeout interval (in seconds), zero to disable the supervision check on the child.
212      *
213      */
214     void SetTimeout(uint16_t aTimeout);
215 
216     /**
217      * This method returns the supervision check timeout interval (in seconds).
218      *
219      * @returns   The check timeout interval (in seconds) or zero if the supervision check on the child is disabled.
220      *
221      */
GetTimeout(void) const222     uint16_t GetTimeout(void) const { return mTimeout; }
223 
224     /**
225      * This method updates the supervision listener state. It informs the listener of a received frame.
226      *
227      * @param[in]   aSourceAddress    The source MAC address of the received frame
228      * @param[in]   aIsSecure         TRUE to indicate that the received frame is secure, FALSE otherwise.
229      *
230      */
231     void UpdateOnReceive(const Mac::Address &aSourceAddress, bool aIsSecure);
232 
233 private:
234     static constexpr uint16_t kDefaultTimeout = OPENTHREAD_CONFIG_CHILD_SUPERVISION_CHECK_TIMEOUT; // (seconds)
235 
236     void        RestartTimer(void);
237     static void HandleTimer(Timer &aTimer);
238     void        HandleTimer(void);
239 
240     uint16_t   mTimeout;
241     TimerMilli mTimer;
242 };
243 
244 #endif // #if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE
245 
246 /**
247  * @}
248  *
249  */
250 
251 } // namespace Utils
252 } // namespace ot
253 
254 #endif // CHILD_SUPERVISION_HPP_
255