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 #ifndef CHILD_SUPERVISION_HPP_ 35 #define CHILD_SUPERVISION_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #include <stdint.h> 40 41 #include <openthread/child_supervision.h> 42 43 #include "common/locator.hpp" 44 #include "common/message.hpp" 45 #include "common/non_copyable.hpp" 46 #include "common/notifier.hpp" 47 #include "common/time_ticker.hpp" 48 #include "common/timer.hpp" 49 #include "mac/mac_types.hpp" 50 #include "thread/child.hpp" 51 52 namespace ot { 53 54 class ThreadNetif; 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 #if OPENTHREAD_FTD 86 87 /** 88 * Implements a child supervisor. 89 */ 90 class ChildSupervisor : public InstanceLocator, private NonCopyable 91 { 92 friend class ot::Notifier; 93 friend class ot::TimeTicker; 94 95 public: 96 /** 97 * Initializes the object. 98 * 99 * @param[in] aInstance A reference to the OpenThread instance. 100 */ 101 explicit ChildSupervisor(Instance &aInstance); 102 103 /** 104 * Returns the destination for a supervision message. 105 * 106 * @param[in] aMessage The message for which to get the destination. 107 * 108 * @returns A pointer to the destination child of the message, or `nullptr` if @p aMessage is not of supervision 109 * type. 110 */ 111 Child *GetDestination(const Message &aMessage) const; 112 113 /** 114 * Updates the supervision state for a child. It informs the child supervisor that a message was 115 * successfully sent to the child. 116 * 117 * @param[in] aChild The child to which a message was successfully sent. 118 */ 119 void UpdateOnSend(Child &aChild); 120 121 private: 122 static constexpr uint16_t kDefaultSupervisionInterval = OPENTHREAD_CONFIG_CHILD_SUPERVISION_INTERVAL; // (seconds) 123 124 void SendMessage(Child &aChild); 125 void CheckState(void); 126 void HandleTimeTick(void); 127 void HandleNotifierEvents(Events aEvents); 128 }; 129 130 #endif // #if OPENTHREAD_FTD 131 132 /** 133 * Implements a child supervision listener. 134 */ 135 class SupervisionListener : public InstanceLocator, private NonCopyable 136 { 137 public: 138 /** 139 * Initializes the object. 140 * 141 * @param[in] aInstance A reference to the OpenThread instance. 142 */ 143 explicit SupervisionListener(Instance &aInstance); 144 145 /** 146 * Starts the supervision listener operation. 147 */ 148 void Start(void); 149 150 /** 151 * Stops the supervision listener operation. 152 */ 153 void Stop(void); 154 155 /** 156 * Sets the supervision interval. 157 * 158 * @param[in] aInterval If non-zero, the desired supervision interval (in seconds), zero to disable supervision. 159 */ 160 void SetInterval(uint16_t aInterval); 161 162 /** 163 * Returns the supervision interval. 164 * 165 * @returns The current supervision interval (seconds), or zero if supervision is disabled. 166 */ GetInterval(void) const167 uint16_t GetInterval(void) const { return mInterval; } 168 169 /** 170 * Sets the supervision check timeout (in seconds). 171 * 172 * If the child does not hear from its parent within the given check timeout interval, it initiates the re-attach 173 * process (MLE Child Update Request/Response exchange with its parent). Setting the timeout to zero, disables the 174 * supervision check on the child. 175 * 176 * It is recommended to select a supervision check timeout value larger than the parent's child supervision 177 * interval plus the maximum time between the child's data poll transmissions. 178 * 179 * @param[in] aTimeout The timeout interval (in seconds), zero to disable the supervision check on the child. 180 */ 181 void SetTimeout(uint16_t aTimeout); 182 183 /** 184 * Returns the supervision check timeout interval (in seconds). 185 * 186 * @returns The check timeout interval (in seconds) or zero if the supervision check on the child is disabled. 187 */ GetTimeout(void) const188 uint16_t GetTimeout(void) const { return mTimeout; } 189 190 /** 191 * Returns the value of supervision check timeout failure counter. 192 * 193 * The counter tracks the number of supervision check failures on the child. It is incremented when the child does 194 * not hear from its parent within the specified check timeout interval. 195 */ GetCounter(void) const196 uint16_t GetCounter(void) const { return mCounter; } 197 198 /** 199 * Reset the supervision check timeout failure counter. 200 */ ResetCounter(void)201 void ResetCounter(void) { mCounter = 0; } 202 203 /** 204 * Updates the supervision listener state. It informs the listener of a received frame. 205 * 206 * @param[in] aSourceAddress The source MAC address of the received frame 207 * @param[in] aIsSecure TRUE to indicate that the received frame is secure, FALSE otherwise. 208 */ 209 void UpdateOnReceive(const Mac::Address &aSourceAddress, bool aIsSecure); 210 211 private: 212 static constexpr uint16_t kDefaultTimeout = OPENTHREAD_CONFIG_CHILD_SUPERVISION_CHECK_TIMEOUT; // (seconds) 213 static constexpr uint16_t kDefaultInterval = OPENTHREAD_CONFIG_CHILD_SUPERVISION_INTERVAL; // (seconds) 214 215 void RestartTimer(void); 216 void HandleTimer(void); 217 218 using ListenerTimer = TimerMilliIn<SupervisionListener, &SupervisionListener::HandleTimer>; 219 220 uint16_t mTimeout; 221 uint16_t mInterval; 222 uint16_t mCounter; 223 ListenerTimer mTimer; 224 }; 225 226 } // namespace ot 227 228 #endif // CHILD_SUPERVISION_HPP_ 229