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