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