blob: 7df7dee3472abe5575ecd21e31f62539fc919f7f [file] [log] [blame]
/*
* Copyright (c) 2016-2018, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes definitions for Thread child table.
*/
#ifndef CHILD_TABLE_HPP_
#define CHILD_TABLE_HPP_
#include "openthread-core-config.h"
#if OPENTHREAD_FTD
#include "common/const_cast.hpp"
#include "common/iterator_utils.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "thread/topology.hpp"
namespace ot {
/**
* This class represents the Thread child table.
*
*/
class ChildTable : public InstanceLocator, private NonCopyable
{
friend class NeighborTable;
class IteratorBuilder;
public:
/**
* This class represents an iterator for iterating through the child entries in the child table.
*
*/
class Iterator : public InstanceLocator, public ItemPtrIterator<Child, Iterator>
{
friend class ItemPtrIterator<Child, Iterator>;
friend class IteratorBuilder;
public:
/**
* This constructor initializes an `Iterator` instance.
*
* @param[in] aInstance A reference to the OpenThread instance.
* @param[in] aFilter A child state filter.
*
*/
Iterator(Instance &aInstance, Child::StateFilter aFilter);
/**
* This method resets the iterator to start over.
*
*/
void Reset(void);
/**
* This method gets the `Child` entry to which the iterator is currently pointing.
*
* @returns A pointer to the `Child` entry, or `nullptr` if the iterator is done and/or empty.
*
*/
Child *GetChild(void) { return mItem; }
private:
explicit Iterator(Instance &aInstance)
: InstanceLocator(aInstance)
, mFilter(Child::StateFilter::kInStateValid)
{
}
void Advance(void);
Child::StateFilter mFilter;
};
/**
* This constructor initializes a `ChildTable` instance.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit ChildTable(Instance &aInstance);
/**
* This method clears the child table.
*
*/
void Clear(void);
/**
* This method returns the child table index for a given `Child` instance.
*
* @param[in] aChild A reference to a `Child`
*
* @returns The index corresponding to @p aChild.
*
*/
uint16_t GetChildIndex(const Child &aChild) const { return static_cast<uint16_t>(&aChild - mChildren); }
/**
* This method returns a pointer to a `Child` entry at a given index, or `nullptr` if the index is out of bounds,
* i.e., index is larger or equal to maximum number of children allowed (@sa GetMaxChildrenAllowed()).
*
* @param[in] aChildIndex A child index.
*
* @returns A pointer to the `Child` corresponding to the given index, or `nullptr` if the index is out of bounds.
*
*/
Child *GetChildAtIndex(uint16_t aChildIndex);
/**
* This method gets a new/unused `Child` entry from the child table.
*
* @note The returned child entry will be cleared (`memset` to zero).
*
* @returns A pointer to a new `Child` entry, or `nullptr` if all `Child` entries are in use.
*
*/
Child *GetNewChild(void);
/**
* This method searches the child table for a `Child` with a given RLOC16 also matching a given state filter.
*
* @param[in] aRloc16 A RLOC16 address.
* @param[in] aFilter A child state filter.
*
* @returns A pointer to the `Child` entry if one is found, or `nullptr` otherwise.
*
*/
Child *FindChild(uint16_t aRloc16, Child::StateFilter aFilter);
/**
* This method searches the child table for a `Child` with a given extended address also matching a given state
* filter.
*
* @param[in] aExtAddress A reference to an extended address.
* @param[in] aFilter A child state filter.
*
* @returns A pointer to the `Child` entry if one is found, or `nullptr` otherwise.
*
*/
Child *FindChild(const Mac::ExtAddress &aExtAddress, Child::StateFilter aFilter);
/**
* This method searches the child table for a `Child` with a given address also matching a given state filter.
*
* @param[in] aMacAddress A reference to a MAC address.
* @param[in] aFilter A child state filter.
*
* @returns A pointer to the `Child` entry if one is found, or `nullptr` otherwise.
*
*/
Child *FindChild(const Mac::Address &aMacAddress, Child::StateFilter aFilter);
/**
* This method indicates whether the child table contains any child matching a given state filter.
*
* @param[in] aFilter A child state filter.
*
* @returns TRUE if the table contains at least one child table matching the given filter, FALSE otherwise.
*
*/
bool HasChildren(Child::StateFilter aFilter) const;
/**
* This method returns the number of children in the child table matching a given state filter.
*
* @param[in] aFilter A child state filter.
*
* @returns Number of children matching the given state filer.
*
*/
uint16_t GetNumChildren(Child::StateFilter aFilter) const;
/**
* This method returns the maximum number of children that can be supported (build-time constant).
*
* @note Number of children allowed (from `GetMaxChildrenAllowed()`) can be less than maximum number of supported
* children.
*
* @returns The maximum number of children supported
*
*/
uint16_t GetMaxChildren(void) const { return kMaxChildren; }
/**
* This method get the maximum number of children allowed.
*
* @returns The maximum number of children allowed.
*
*/
uint16_t GetMaxChildrenAllowed(void) const { return mMaxChildrenAllowed; }
/**
* This method sets the maximum number of children allowed.
*
* The number of children allowed must be at least one and at most same as maximum supported children (@sa
* GetMaxChildren()). It can be changed only if the child table is empty.
*
* @param[in] aMaxChildren Maximum number of children allowed.
*
* @retval kErrorNone The number of allowed children changed successfully.
* @retval kErrorInvalidArgs If @p aMaxChildren is not in the range [1, Max supported children].
* @retval kErrorInvalidState The child table is not empty.
*
*/
Error SetMaxChildrenAllowed(uint16_t aMaxChildren);
/**
* This method enables range-based `for` loop iteration over all child entries in the child table matching a given
* state filter.
*
* This method should be used as follows:
*
* for (Child &child : aChildTable.Iterate(aFilter)) { ... }
*
* @param[in] aFilter A child state filter.
*
* @returns An IteratorBuilder instance.
*
*/
IteratorBuilder Iterate(Child::StateFilter aFilter) { return IteratorBuilder(GetInstance(), aFilter); }
/**
* This method retains diagnostic information for an attached child by Child ID or RLOC16.
*
* @param[in] aChildId The Child ID or RLOC16 for an attached child.
* @param[out] aChildInfo A reference to a `Child::Info` to populate with the child information.
*
*/
Error GetChildInfoById(uint16_t aChildId, Child::Info &aChildInfo);
/**
* This method retains diagnostic information for an attached child by the internal table index.
*
* @param[in] aChildIndex The table index.
* @param[out] aChildInfo A reference to a `Child::Info` to populate with the child information.
*
*/
Error GetChildInfoByIndex(uint16_t aChildIndex, Child::Info &aChildInfo);
/**
* This method restores child table from non-volatile memory.
*
*/
void Restore(void);
/**
* This method removes a stored child information from non-volatile memory.
*
* @param[in] aChild A reference to the child to remove from non-volatile memory.
*
*/
void RemoveStoredChild(const Child &aChild);
/**
* This method store a child information into non-volatile memory.
*
* @param[in] aChild A reference to the child to store.
*
* @retval kErrorNone Successfully store child.
* @retval kErrorNoBufs Insufficient available buffers to store child.
*
*/
Error StoreChild(const Child &aChild);
/**
* This method indicates whether the child table contains any sleepy child (in states valid or restoring) with a
* given IPv6 address.
*
* @param[in] aIp6Address An IPv6 address.
*
* @retval TRUE If the child table contains any sleepy child with @p aIp6Address.
* @retval FALSE If the child table does not contain any sleepy child with @p aIp6Address.
*
*/
bool HasSleepyChildWithAddress(const Ip6::Address &aIp6Address) const;
/**
* This method indicates whether the child table contains a given `Neighbor` instance.
*
* @param[in] aNeighbor A reference to a `Neighbor`.
*
* @retval TRUE if @p aNeighbor is a `Child` in the child table.
* @retval FALSE if @p aNeighbor is not a `Child` in the child table.
*
*/
bool Contains(const Neighbor &aNeighbor) const
{
const Child *child = static_cast<const Child *>(&aNeighbor);
return (mChildren <= child) && (child < GetArrayEnd(mChildren));
}
private:
static constexpr uint16_t kMaxChildren = OPENTHREAD_CONFIG_MLE_MAX_CHILDREN;
class IteratorBuilder : public InstanceLocator
{
public:
IteratorBuilder(Instance &aInstance, Child::StateFilter aFilter)
: InstanceLocator(aInstance)
, mFilter(aFilter)
{
}
Iterator begin(void) { return Iterator(GetInstance(), mFilter); }
Iterator end(void) { return Iterator(GetInstance()); }
private:
Child::StateFilter mFilter;
};
Child *FindChild(const Child::AddressMatcher &aMatcher) { return AsNonConst(AsConst(this)->FindChild(aMatcher)); }
const Child *FindChild(const Child::AddressMatcher &aMatcher) const;
void RefreshStoredChildren(void);
uint16_t mMaxChildrenAllowed;
Child mChildren[kMaxChildren];
};
} // namespace ot
#endif // OPENTHREAD_FTD
#endif // CHILD_TABLE_HPP_