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