blob: 6eda998ed47400ee1f05b67d192af54052ec0e6c [file] [log] [blame]
/*
* Copyright (c) 2020, 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 managing Multicast Listener Registration feature defined in Thread 1.2.
*/
#ifndef MLR_MANAGER_HPP_
#define MLR_MANAGER_HPP_
#include "openthread-core-config.h"
#if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)
#if OPENTHREAD_CONFIG_MLR_ENABLE && (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2)
#error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MLR_ENABLE"
#endif
#include "backbone_router/bbr_leader.hpp"
#include "coap/coap_message.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "common/notifier.hpp"
#include "common/time_ticker.hpp"
#include "common/timer.hpp"
#include "net/netif.hpp"
#include "thread/thread_tlvs.hpp"
#include "thread/topology.hpp"
namespace ot {
/**
* @addtogroup core-mlr
*
* @brief
* This module includes definitions for Multicast Listener Registration.
*
* @{
*
* @defgroup core-mlr Mlr
*
* @}
*
*/
/**
* This class implements MLR management.
*
*/
class MlrManager : public InstanceLocator, private NonCopyable
{
friend class ot::Notifier;
friend class ot::TimeTicker;
public:
/**
* This constructor initializes the object.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit MlrManager(Instance &aInstance);
/**
* This method notifies Primary Backbone Router status.
*
* @param[in] aState The state or state change of Primary Backbone Router.
* @param[in] aConfig The Primary Backbone Router service.
*
*/
void HandleBackboneRouterPrimaryUpdate(BackboneRouter::Leader::State aState,
const BackboneRouter::BackboneRouterConfig &aConfig);
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
/**
* This method updates the Multicast Subscription Table according to the Child information.
*
* @param[in] aChild A reference to the child information.
* @param[in] aOldMlrRegisteredAddresses Pointer to an array of the Child's previously registered IPv6 addresses.
* @param[in] aOldMlrRegisteredAddressNum The number of previously registered IPv6 addresses.
*
*/
void UpdateProxiedSubscriptions(Child & aChild,
const Ip6::Address *aOldMlrRegisteredAddresses,
uint16_t aOldMlrRegisteredAddressNum);
#endif
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
/**
* This method registers Multicast Listeners to Primary Backbone Router.
*
* Note: only available when both `(OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)` and
* `OPENTHREAD_CONFIG_COMMISSIONER_ENABLE` are enabled)
*
* @param aAddresses A pointer to IPv6 multicast addresses to register.
* @param aAddressNum The number of IPv6 multicast addresses.
* @param aTimeout A pointer to the timeout (in seconds), or `nullptr` to use the default MLR timeout.
* A timeout of 0 seconds removes the Multicast Listener addresses.
* @param aCallback A callback function.
* @param aContext A user context pointer.
*
* @retval kErrorNone Successfully sent MLR.req. The @p aCallback will be called iff this method
* returns kErrorNone.
* @retval kErrorBusy If a previous registration was ongoing.
* @retval kErrorInvalidArgs If one or more arguments are invalid.
* @retval kErrorInvalidState If the device was not in a valid state to send MLR.req (e.g. Commissioner not
* started, Primary Backbone Router not found).
* @retval kErrorNoBufs If insufficient message buffers available.
*
*/
Error RegisterMulticastListeners(const otIp6Address * aAddresses,
uint8_t aAddressNum,
const uint32_t * aTimeout,
otIp6RegisterMulticastListenersCallback aCallback,
void * aContext);
#endif
private:
void HandleNotifierEvents(Events aEvents);
void SendMulticastListenerRegistration(void);
Error SendMulticastListenerRegistrationMessage(const otIp6Address * aAddresses,
uint8_t aAddressNum,
const uint32_t * aTimeout,
Coap::ResponseHandler aResponseHandler,
void * aResponseContext);
static void HandleMulticastListenerRegistrationResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
Error aResult);
void HandleMulticastListenerRegistrationResponse(Coap::Message * aMessage,
const Ip6::MessageInfo *aMessageInfo,
Error aResult);
static Error ParseMulticastListenerRegistrationResponse(Error aResult,
Coap::Message *aMessage,
uint8_t & aStatus,
Ip6::Address * aFailedAddresses,
uint8_t & aFailedAddressNum);
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
static void HandleRegisterMulticastListenersResponse(void * aContext,
otMessage * aMessage,
const otMessageInfo *aMessageInfo,
Error aResult);
void HandleRegisterMulticastListenersResponse(otMessage * aMessage,
const otMessageInfo *aMessageInfo,
Error aResult);
#endif
#if OPENTHREAD_CONFIG_MLR_ENABLE
void UpdateLocalSubscriptions(void);
bool IsAddressMlrRegisteredByNetif(const Ip6::Address &aAddress) const;
#endif
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE
bool IsAddressMlrRegisteredByAnyChild(const Ip6::Address &aAddress) const
{
return IsAddressMlrRegisteredByAnyChildExcept(aAddress, nullptr);
}
bool IsAddressMlrRegisteredByAnyChildExcept(const Ip6::Address &aAddress, const Child *aExceptChild) const;
#endif
void SetMulticastAddressMlrState(MlrState aFromState, MlrState aToState);
void FinishMulticastListenerRegistration(bool aSuccess,
const Ip6::Address *aFailedAddresses,
uint8_t aFailedAddressNum);
void AppendToUniqueAddressList(Ip6::Address (&aAddresses)[Ip6AddressesTlv::kMaxAddresses],
uint8_t & aAddressNum,
const Ip6::Address &aAddress);
static bool AddressListContains(const Ip6::Address *aAddressList,
uint8_t aAddressListSize,
const Ip6::Address &aAddress);
void ScheduleSend(uint16_t aDelay);
void UpdateTimeTickerRegistration(void);
void UpdateReregistrationDelay(bool aRereg);
void Reregister(void);
void HandleTimeTick(void);
void LogMulticastAddresses(void);
void CheckInvariants(void) const;
static void LogMlrResponse(Error aResult,
Error aError,
uint8_t aStatus,
const Ip6::Address *aFailedAddresses,
uint8_t aFailedAddressNum);
#if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
otIp6RegisterMulticastListenersCallback mRegisterMulticastListenersCallback;
void * mRegisterMulticastListenersContext;
#endif
uint32_t mReregistrationDelay;
uint16_t mSendDelay;
bool mMlrPending : 1;
#if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
bool mRegisterMulticastListenersPending : 1;
#endif
};
} // namespace ot
#endif // OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)
#endif // MLR_MANAGER_HPP_