1 /* 2 * Copyright (c) 2020, 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 managing Multicast Listener Registration feature defined in Thread 1.2. 32 */ 33 34 #ifndef MLR_MANAGER_HPP_ 35 #define MLR_MANAGER_HPP_ 36 37 #include "openthread-core-config.h" 38 39 #if OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) 40 41 #if OPENTHREAD_CONFIG_MLR_ENABLE && (OPENTHREAD_CONFIG_THREAD_VERSION < OT_THREAD_VERSION_1_2) 42 #error "Thread 1.2 or higher version is required for OPENTHREAD_CONFIG_MLR_ENABLE" 43 #endif 44 45 #include "backbone_router/bbr_leader.hpp" 46 #include "coap/coap_message.hpp" 47 #include "common/array.hpp" 48 #include "common/callback.hpp" 49 #include "common/locator.hpp" 50 #include "common/non_copyable.hpp" 51 #include "common/notifier.hpp" 52 #include "common/time_ticker.hpp" 53 #include "common/timer.hpp" 54 #include "net/netif.hpp" 55 #include "thread/child.hpp" 56 #include "thread/thread_tlvs.hpp" 57 58 namespace ot { 59 60 /** 61 * @addtogroup core-mlr 62 * 63 * @brief 64 * This module includes definitions for Multicast Listener Registration. 65 * 66 * @{ 67 * 68 * @defgroup core-mlr Mlr 69 * 70 * @} 71 */ 72 73 /** 74 * Implements MLR management. 75 */ 76 class MlrManager : public InstanceLocator, private NonCopyable 77 { 78 friend class ot::Notifier; 79 friend class ot::TimeTicker; 80 81 public: 82 typedef otIp6RegisterMulticastListenersCallback MlrCallback; 83 84 /** 85 * Initializes the object. 86 * 87 * @param[in] aInstance A reference to the OpenThread instance. 88 */ 89 explicit MlrManager(Instance &aInstance); 90 91 /** 92 * Notifies Primary Backbone Router status. 93 * 94 * @param[in] aState The state or state change of Primary Backbone Router. 95 * @param[in] aConfig The Primary Backbone Router service. 96 */ 97 void HandleBackboneRouterPrimaryUpdate(BackboneRouter::Leader::State aState, const BackboneRouter::Config &aConfig); 98 99 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE 100 static constexpr uint16_t kMaxMlrAddresses = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD - 1; ///< Max MLR addresses 101 102 typedef Array<Ip6::Address, kMaxMlrAddresses> MlrAddressArray; ///< Registered MLR addresses array. 103 104 /** 105 * Updates the Multicast Subscription Table according to the Child information. 106 * 107 * @param[in] aChild A reference to the child information. 108 * @param[in] aOldMlrRegisteredAddresses Array of the Child's previously registered IPv6 addresses. 109 */ 110 void UpdateProxiedSubscriptions(Child &aChild, const MlrAddressArray &aOldMlrRegisteredAddresses); 111 #endif 112 113 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 114 /** 115 * Registers Multicast Listeners to Primary Backbone Router. 116 * 117 * Note: only available when both `(OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)` and 118 * `OPENTHREAD_CONFIG_COMMISSIONER_ENABLE` are enabled) 119 * 120 * @param aAddresses A pointer to IPv6 multicast addresses to register. 121 * @param aAddressNum The number of IPv6 multicast addresses. 122 * @param aTimeout A pointer to the timeout (in seconds), or `nullptr` to use the default MLR timeout. 123 * A timeout of 0 seconds removes the Multicast Listener addresses. 124 * @param aCallback A callback function. 125 * @param aContext A user context pointer. 126 * 127 * @retval kErrorNone Successfully sent MLR.req. The @p aCallback will be called iff this method 128 * returns kErrorNone. 129 * @retval kErrorBusy If a previous registration was ongoing. 130 * @retval kErrorInvalidArgs If one or more arguments are invalid. 131 * @retval kErrorInvalidState If the device was not in a valid state to send MLR.req (e.g. Commissioner not 132 * started, Primary Backbone Router not found). 133 * @retval kErrorNoBufs If insufficient message buffers available. 134 */ 135 Error RegisterMulticastListeners(const Ip6::Address *aAddresses, 136 uint8_t aAddressNum, 137 const uint32_t *aTimeout, 138 MlrCallback aCallback, 139 void *aContext); 140 #endif 141 142 private: 143 class AddressArray : public Array<Ip6::Address, Ip6AddressesTlv::kMaxAddresses> 144 { 145 public: IsEmptyOrContains(const Ip6::Address & aAddress) const146 bool IsEmptyOrContains(const Ip6::Address &aAddress) const { return IsEmpty() || Contains(aAddress); } 147 void AddUnique(const Ip6::Address &aAddress); 148 }; 149 150 void HandleNotifierEvents(Events aEvents); 151 152 void SendMlr(void); 153 Error SendMlrMessage(const Ip6::Address *aAddresses, 154 uint8_t aAddressNum, 155 const uint32_t *aTimeout, 156 Coap::ResponseHandler aResponseHandler, 157 void *aResponseContext); 158 159 static void HandleMlrResponse(void *aContext, 160 otMessage *aMessage, 161 const otMessageInfo *aMessageInfo, 162 otError aResult); 163 void HandleMlrResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult); 164 static Error ParseMlrResponse(Error aResult, 165 Coap::Message *aMessage, 166 uint8_t &aStatus, 167 AddressArray &aFailedAddresses); 168 169 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 170 static void HandleRegisterResponse(void *aContext, 171 otMessage *aMessage, 172 const otMessageInfo *aMessageInfo, 173 otError aResult); 174 void HandleRegisterResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aResult); 175 #endif 176 177 #if OPENTHREAD_CONFIG_MLR_ENABLE 178 void UpdateLocalSubscriptions(void); 179 bool IsAddressMlrRegisteredByNetif(const Ip6::Address &aAddress) const; 180 #endif 181 182 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE IsAddressMlrRegisteredByAnyChild(const Ip6::Address & aAddress) const183 bool IsAddressMlrRegisteredByAnyChild(const Ip6::Address &aAddress) const 184 { 185 return IsAddressMlrRegisteredByAnyChildExcept(aAddress, nullptr); 186 } 187 bool IsAddressMlrRegisteredByAnyChildExcept(const Ip6::Address &aAddress, const Child *aExceptChild) const; 188 #endif 189 190 void SetMulticastAddressMlrState(MlrState aFromState, MlrState aToState); 191 void FinishMlr(bool aSuccess, const AddressArray &aFailedAddresses); 192 193 void ScheduleSend(uint16_t aDelay); 194 void UpdateTimeTickerRegistration(void); 195 void UpdateReregistrationDelay(bool aRereg); 196 void Reregister(void); 197 void HandleTimeTick(void); 198 199 void LogMulticastAddresses(void); 200 void CheckInvariants(void) const; 201 static void LogMlrResponse(Error aResult, Error aError, uint8_t aStatus, const AddressArray &aFailedAddresses); 202 203 #if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 204 Callback<MlrCallback> mRegisterCallback; 205 #endif 206 207 uint32_t mReregistrationDelay; 208 uint16_t mSendDelay; 209 210 bool mMlrPending : 1; 211 #if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 212 bool mRegisterPending : 1; 213 #endif 214 }; 215 216 } // namespace ot 217 218 #endif // OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) 219 #endif // MLR_MANAGER_HPP_ 220