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 * Returns the destination for a supervision message. 107 * 108 * @param[in] aMessage The message for which to get the destination. 109 * 110 * @returns A pointer to the destination child of the message, or `nullptr` if @p aMessage is not of supervision 111 * type. 112 * 113 */ 114 Child *GetDestination(const Message &aMessage) const; 115 116 /** 117 * Updates the supervision state for a child. It informs the child supervisor that a message was 118 * successfully sent to the child. 119 * 120 * @param[in] aChild The child to which a message was successfully sent. 121 * 122 */ 123 void UpdateOnSend(Child &aChild); 124 125 private: 126 static constexpr uint16_t kDefaultSupervisionInterval = OPENTHREAD_CONFIG_CHILD_SUPERVISION_INTERVAL; // (seconds) 127 128 void SendMessage(Child &aChild); 129 void CheckState(void); 130 void HandleTimeTick(void); 131 void HandleNotifierEvents(Events aEvents); 132 }; 133 134 #endif // #if OPENTHREAD_FTD 135 136 /** 137 * Implements a child supervision listener. 138 * 139 */ 140 class SupervisionListener : public InstanceLocator, private NonCopyable 141 { 142 public: 143 /** 144 * Initializes the object. 145 * 146 * @param[in] aInstance A reference to the OpenThread instance. 147 * 148 */ 149 explicit SupervisionListener(Instance &aInstance); 150 151 /** 152 * Starts the supervision listener operation. 153 * 154 */ 155 void Start(void); 156 157 /** 158 * Stops the supervision listener operation. 159 * 160 */ 161 void Stop(void); 162 163 /** 164 * Sets the supervision interval. 165 * 166 * @param[in] aInterval If non-zero, the desired supervision interval (in seconds), zero to disable supervision. 167 * 168 */ 169 void SetInterval(uint16_t aInterval); 170 171 /** 172 * Returns the supervision interval. 173 * 174 * @returns The current supervision interval (seconds), or zero if supervision is disabled. 175 * 176 */ GetInterval(void) const177 uint16_t GetInterval(void) const { return mInterval; } 178 179 /** 180 * Sets the supervision check timeout (in seconds). 181 * 182 * If the child does not hear from its parent within the given check timeout interval, it initiates the re-attach 183 * process (MLE Child Update Request/Response exchange with its parent). Setting the timeout to zero, disables the 184 * supervision check on the child. 185 * 186 * It is recommended to select a supervision check timeout value larger than the parent's child supervision 187 * interval plus the maximum time between the child's data poll transmissions. 188 * 189 * @param[in] aTimeout The timeout interval (in seconds), zero to disable the supervision check on the child. 190 * 191 */ 192 void SetTimeout(uint16_t aTimeout); 193 194 /** 195 * Returns the supervision check timeout interval (in seconds). 196 * 197 * @returns The check timeout interval (in seconds) or zero if the supervision check on the child is disabled. 198 * 199 */ GetTimeout(void) const200 uint16_t GetTimeout(void) const { return mTimeout; } 201 202 /** 203 * Returns the value of supervision check timeout failure counter. 204 * 205 * The counter tracks the number of supervision check failures on the child. It is incremented when the child does 206 * not hear from its parent within the specified check timeout interval. 207 * 208 */ GetCounter(void) const209 uint16_t GetCounter(void) const { return mCounter; } 210 211 /** 212 * Reset the supervision check timeout failure counter. 213 * 214 */ ResetCounter(void)215 void ResetCounter(void) { mCounter = 0; } 216 217 /** 218 * Updates the supervision listener state. It informs the listener of a received frame. 219 * 220 * @param[in] aSourceAddress The source MAC address of the received frame 221 * @param[in] aIsSecure TRUE to indicate that the received frame is secure, FALSE otherwise. 222 * 223 */ 224 void UpdateOnReceive(const Mac::Address &aSourceAddress, bool aIsSecure); 225 226 private: 227 static constexpr uint16_t kDefaultTimeout = OPENTHREAD_CONFIG_CHILD_SUPERVISION_CHECK_TIMEOUT; // (seconds) 228 static constexpr uint16_t kDefaultInterval = OPENTHREAD_CONFIG_CHILD_SUPERVISION_INTERVAL; // (seconds) 229 230 void RestartTimer(void); 231 void HandleTimer(void); 232 233 using ListenerTimer = TimerMilliIn<SupervisionListener, &SupervisionListener::HandleTimer>; 234 235 uint16_t mTimeout; 236 uint16_t mInterval; 237 uint16_t mCounter; 238 ListenerTimer mTimer; 239 }; 240 241 } // namespace ot 242 243 #endif // CHILD_SUPERVISION_HPP_ 244