/* * 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_