1 /* 2 * Copyright (c) 2016-2018, 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 Thread child table. 32 */ 33 34 #ifndef CHILD_TABLE_HPP_ 35 #define CHILD_TABLE_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #if OPENTHREAD_FTD 40 41 #include "common/const_cast.hpp" 42 #include "common/iterator_utils.hpp" 43 #include "common/locator.hpp" 44 #include "common/non_copyable.hpp" 45 #include "thread/child.hpp" 46 47 namespace ot { 48 49 /** 50 * Represents the Thread child table. 51 */ 52 class ChildTable : public InstanceLocator, private NonCopyable 53 { 54 friend class NeighborTable; 55 class IteratorBuilder; 56 57 public: 58 /** 59 * Represents an iterator for iterating through the child entries in the child table. 60 */ 61 class Iterator : public InstanceLocator, public ItemPtrIterator<Child, Iterator> 62 { 63 friend class ItemPtrIterator<Child, Iterator>; 64 friend class IteratorBuilder; 65 66 public: 67 /** 68 * Initializes an `Iterator` instance. 69 * 70 * @param[in] aInstance A reference to the OpenThread instance. 71 * @param[in] aFilter A child state filter. 72 */ 73 Iterator(Instance &aInstance, Child::StateFilter aFilter); 74 75 /** 76 * Resets the iterator to start over. 77 */ 78 void Reset(void); 79 80 /** 81 * Gets the `Child` entry to which the iterator is currently pointing. 82 * 83 * @returns A pointer to the `Child` entry, or `nullptr` if the iterator is done and/or empty. 84 */ GetChild(void)85 Child *GetChild(void) { return mItem; } 86 87 private: Iterator(Instance & aInstance)88 explicit Iterator(Instance &aInstance) 89 : InstanceLocator(aInstance) 90 , mFilter(Child::StateFilter::kInStateValid) 91 { 92 } 93 94 void Advance(void); 95 96 Child::StateFilter mFilter; 97 }; 98 99 /** 100 * Initializes a `ChildTable` instance. 101 * 102 * @param[in] aInstance A reference to the OpenThread instance. 103 */ 104 explicit ChildTable(Instance &aInstance); 105 106 /** 107 * Clears the child table. 108 */ 109 void Clear(void); 110 111 /** 112 * Returns the child table index for a given `Child` instance. 113 * 114 * @param[in] aChild A reference to a `Child` 115 * 116 * @returns The index corresponding to @p aChild. 117 */ GetChildIndex(const Child & aChild) const118 uint16_t GetChildIndex(const Child &aChild) const { return static_cast<uint16_t>(&aChild - mChildren); } 119 120 /** 121 * Returns a pointer to a `Child` entry at a given index, or `nullptr` if the index is out of bounds, 122 * i.e., index is larger or equal to maximum number of children allowed (@sa GetMaxChildrenAllowed()). 123 * 124 * @param[in] aChildIndex A child index. 125 * 126 * @returns A pointer to the `Child` corresponding to the given index, or `nullptr` if the index is out of bounds. 127 */ 128 Child *GetChildAtIndex(uint16_t aChildIndex); 129 130 /** 131 * Gets a new/unused `Child` entry from the child table. 132 * 133 * @note The returned child entry will be cleared (`memset` to zero). 134 * 135 * @returns A pointer to a new `Child` entry, or `nullptr` if all `Child` entries are in use. 136 */ 137 Child *GetNewChild(void); 138 139 /** 140 * Searches the child table for a `Child` with a given RLOC16 also matching a given state filter. 141 * 142 * @param[in] aRloc16 A RLOC16 address. 143 * @param[in] aFilter A child state filter. 144 * 145 * @returns A pointer to the `Child` entry if one is found, or `nullptr` otherwise. 146 */ 147 Child *FindChild(uint16_t aRloc16, Child::StateFilter aFilter); 148 149 /** 150 * Searches the child table for a `Child` with a given extended address also matching a given state 151 * filter. 152 * 153 * @param[in] aExtAddress A reference to an extended address. 154 * @param[in] aFilter A child state filter. 155 * 156 * @returns A pointer to the `Child` entry if one is found, or `nullptr` otherwise. 157 */ 158 Child *FindChild(const Mac::ExtAddress &aExtAddress, Child::StateFilter aFilter); 159 160 /** 161 * Searches the child table for a `Child` with a given address also matching a given state filter. 162 * 163 * @param[in] aMacAddress A reference to a MAC address. 164 * @param[in] aFilter A child state filter. 165 * 166 * @returns A pointer to the `Child` entry if one is found, or `nullptr` otherwise. 167 */ 168 Child *FindChild(const Mac::Address &aMacAddress, Child::StateFilter aFilter); 169 170 /** 171 * Indicates whether the child table contains any child matching a given state filter. 172 * 173 * @param[in] aFilter A child state filter. 174 * 175 * @returns TRUE if the table contains at least one child table matching the given filter, FALSE otherwise. 176 */ 177 bool HasChildren(Child::StateFilter aFilter) const; 178 179 /** 180 * Returns the number of children in the child table matching a given state filter. 181 * 182 * @param[in] aFilter A child state filter. 183 * 184 * @returns Number of children matching the given state filer. 185 */ 186 uint16_t GetNumChildren(Child::StateFilter aFilter) const; 187 188 /** 189 * Returns the maximum number of children that can be supported (build-time constant). 190 * 191 * @note Number of children allowed (from `GetMaxChildrenAllowed()`) can be less than maximum number of supported 192 * children. 193 * 194 * @returns The maximum number of children supported 195 */ GetMaxChildren(void) const196 uint16_t GetMaxChildren(void) const { return kMaxChildren; } 197 198 /** 199 * Get the maximum number of children allowed. 200 * 201 * @returns The maximum number of children allowed. 202 */ GetMaxChildrenAllowed(void) const203 uint16_t GetMaxChildrenAllowed(void) const { return mMaxChildrenAllowed; } 204 205 /** 206 * Sets the maximum number of children allowed. 207 * 208 * The number of children allowed must be at least one and at most same as maximum supported children (@sa 209 * GetMaxChildren()). It can be changed only if the child table is empty. 210 * 211 * @param[in] aMaxChildren Maximum number of children allowed. 212 * 213 * @retval kErrorNone The number of allowed children changed successfully. 214 * @retval kErrorInvalidArgs If @p aMaxChildren is not in the range [1, Max supported children]. 215 * @retval kErrorInvalidState The child table is not empty. 216 */ 217 Error SetMaxChildrenAllowed(uint16_t aMaxChildren); 218 219 /** 220 * Enables range-based `for` loop iteration over all child entries in the child table matching a given 221 * state filter. 222 * 223 * Should be used as follows: 224 * 225 * for (Child &child : aChildTable.Iterate(aFilter)) { ... } 226 * 227 * @param[in] aFilter A child state filter. 228 * 229 * @returns An IteratorBuilder instance. 230 */ Iterate(Child::StateFilter aFilter)231 IteratorBuilder Iterate(Child::StateFilter aFilter) { return IteratorBuilder(GetInstance(), aFilter); } 232 233 /** 234 * Retains diagnostic information for an attached child by Child ID or RLOC16. 235 * 236 * @param[in] aChildId The Child ID or RLOC16 for an attached child. 237 * @param[out] aChildInfo A reference to a `Child::Info` to populate with the child information. 238 */ 239 Error GetChildInfoById(uint16_t aChildId, Child::Info &aChildInfo); 240 241 /** 242 * Retains diagnostic information for an attached child by the internal table index. 243 * 244 * @param[in] aChildIndex The table index. 245 * @param[out] aChildInfo A reference to a `Child::Info` to populate with the child information. 246 */ 247 Error GetChildInfoByIndex(uint16_t aChildIndex, Child::Info &aChildInfo); 248 249 /** 250 * Restores child table from non-volatile memory. 251 */ 252 void Restore(void); 253 254 /** 255 * Removes a stored child information from non-volatile memory. 256 * 257 * @param[in] aChild A reference to the child to remove from non-volatile memory. 258 */ 259 void RemoveStoredChild(const Child &aChild); 260 261 /** 262 * Store a child information into non-volatile memory. 263 * 264 * @param[in] aChild A reference to the child to store. 265 * 266 * @retval kErrorNone Successfully store child. 267 * @retval kErrorNoBufs Insufficient available buffers to store child. 268 */ 269 Error StoreChild(const Child &aChild); 270 271 /** 272 * Indicates whether or not the child table contains an MTD child with a given @p aRloc16. 273 * 274 * Only children in `kInStateValidOrRestoring` are considered. 275 * 276 * @param[in] aRloc16 The RLOC16 to check. 277 * 278 * @retval TRUE If the child table contains an MTD child with @p aRloc16. 279 * @retval FALSE If the child table does not contain an MTD child with @p aRloc16. 280 */ 281 bool HasMinimalChild(uint16_t aRloc16) const; 282 283 /** 284 * Indicates whether the child table contains any sleepy child (in states valid or restoring) with a 285 * given IPv6 address. 286 * 287 * @param[in] aIp6Address An IPv6 address. 288 * 289 * @retval TRUE If the child table contains any sleepy child with @p aIp6Address. 290 * @retval FALSE If the child table does not contain any sleepy child with @p aIp6Address. 291 */ 292 bool HasSleepyChildWithAddress(const Ip6::Address &aIp6Address) const; 293 294 /** 295 * Indicates whether the child table contains a given `Neighbor` instance. 296 * 297 * @param[in] aNeighbor A reference to a `Neighbor`. 298 * 299 * @retval TRUE if @p aNeighbor is a `Child` in the child table. 300 * @retval FALSE if @p aNeighbor is not a `Child` in the child table. 301 */ Contains(const Neighbor & aNeighbor) const302 bool Contains(const Neighbor &aNeighbor) const 303 { 304 const Child *child = static_cast<const Child *>(&aNeighbor); 305 306 return (mChildren <= child) && (child < GetArrayEnd(mChildren)); 307 } 308 309 private: 310 static constexpr uint16_t kMaxChildren = OPENTHREAD_CONFIG_MLE_MAX_CHILDREN; 311 312 class IteratorBuilder : public InstanceLocator 313 { 314 public: IteratorBuilder(Instance & aInstance,Child::StateFilter aFilter)315 IteratorBuilder(Instance &aInstance, Child::StateFilter aFilter) 316 : InstanceLocator(aInstance) 317 , mFilter(aFilter) 318 { 319 } 320 begin(void)321 Iterator begin(void) { return Iterator(GetInstance(), mFilter); } end(void)322 Iterator end(void) { return Iterator(GetInstance()); } 323 324 private: 325 Child::StateFilter mFilter; 326 }; 327 FindChild(const Child::AddressMatcher & aMatcher)328 Child *FindChild(const Child::AddressMatcher &aMatcher) { return AsNonConst(AsConst(this)->FindChild(aMatcher)); } 329 330 const Child *FindChild(const Child::AddressMatcher &aMatcher) const; 331 void RefreshStoredChildren(void); 332 333 uint16_t mMaxChildrenAllowed; 334 Child mChildren[kMaxChildren]; 335 }; 336 337 } // namespace ot 338 339 #endif // OPENTHREAD_FTD 340 341 #endif // CHILD_TABLE_HPP_ 342