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