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 /** 75 * Implements MLR management. 76 * 77 */ 78 class MlrManager : public InstanceLocator, private NonCopyable 79 { 80 friend class ot::Notifier; 81 friend class ot::TimeTicker; 82 83 public: 84 typedef otIp6RegisterMulticastListenersCallback MlrCallback; 85 86 /** 87 * Initializes the object. 88 * 89 * @param[in] aInstance A reference to the OpenThread instance. 90 * 91 */ 92 explicit MlrManager(Instance &aInstance); 93 94 /** 95 * Notifies Primary Backbone Router status. 96 * 97 * @param[in] aState The state or state change of Primary Backbone Router. 98 * @param[in] aConfig The Primary Backbone Router service. 99 * 100 */ 101 void HandleBackboneRouterPrimaryUpdate(BackboneRouter::Leader::State aState, const BackboneRouter::Config &aConfig); 102 103 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE 104 static constexpr uint16_t kMaxMlrAddresses = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD - 1; ///< Max MLR addresses 105 106 typedef Array<Ip6::Address, kMaxMlrAddresses> MlrAddressArray; ///< Registered MLR addresses array. 107 108 /** 109 * Updates the Multicast Subscription Table according to the Child information. 110 * 111 * @param[in] aChild A reference to the child information. 112 * @param[in] aOldMlrRegisteredAddresses Array of the Child's previously registered IPv6 addresses. 113 * 114 */ 115 void UpdateProxiedSubscriptions(Child &aChild, const MlrAddressArray &aOldMlrRegisteredAddresses); 116 #endif 117 118 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 119 /** 120 * Registers Multicast Listeners to Primary Backbone Router. 121 * 122 * Note: only available when both `(OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)` and 123 * `OPENTHREAD_CONFIG_COMMISSIONER_ENABLE` are enabled) 124 * 125 * @param aAddresses A pointer to IPv6 multicast addresses to register. 126 * @param aAddressNum The number of IPv6 multicast addresses. 127 * @param aTimeout A pointer to the timeout (in seconds), or `nullptr` to use the default MLR timeout. 128 * A timeout of 0 seconds removes the Multicast Listener addresses. 129 * @param aCallback A callback function. 130 * @param aContext A user context pointer. 131 * 132 * @retval kErrorNone Successfully sent MLR.req. The @p aCallback will be called iff this method 133 * returns kErrorNone. 134 * @retval kErrorBusy If a previous registration was ongoing. 135 * @retval kErrorInvalidArgs If one or more arguments are invalid. 136 * @retval kErrorInvalidState If the device was not in a valid state to send MLR.req (e.g. Commissioner not 137 * started, Primary Backbone Router not found). 138 * @retval kErrorNoBufs If insufficient message buffers available. 139 * 140 */ 141 Error RegisterMulticastListeners(const Ip6::Address *aAddresses, 142 uint8_t aAddressNum, 143 const uint32_t *aTimeout, 144 MlrCallback aCallback, 145 void *aContext); 146 #endif 147 148 private: 149 class AddressArray : public Array<Ip6::Address, Ip6AddressesTlv::kMaxAddresses> 150 { 151 public: IsEmptyOrContains(const Ip6::Address & aAddress) const152 bool IsEmptyOrContains(const Ip6::Address &aAddress) const { return IsEmpty() || Contains(aAddress); } 153 void AddUnique(const Ip6::Address &aAddress); 154 }; 155 156 void HandleNotifierEvents(Events aEvents); 157 158 void SendMlr(void); 159 Error SendMlrMessage(const Ip6::Address *aAddresses, 160 uint8_t aAddressNum, 161 const uint32_t *aTimeout, 162 Coap::ResponseHandler aResponseHandler, 163 void *aResponseContext); 164 165 static void HandleMlrResponse(void *aContext, 166 otMessage *aMessage, 167 const otMessageInfo *aMessageInfo, 168 Error aResult); 169 void HandleMlrResponse(Coap::Message *aMessage, const Ip6::MessageInfo *aMessageInfo, Error aResult); 170 static Error ParseMlrResponse(Error aResult, 171 Coap::Message *aMessage, 172 uint8_t &aStatus, 173 AddressArray &aFailedAddresses); 174 175 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 176 static void HandleRegisterResponse(void *aContext, 177 otMessage *aMessage, 178 const otMessageInfo *aMessageInfo, 179 Error aResult); 180 void HandleRegisterResponse(otMessage *aMessage, const otMessageInfo *aMessageInfo, Error aResult); 181 #endif 182 183 #if OPENTHREAD_CONFIG_MLR_ENABLE 184 void UpdateLocalSubscriptions(void); 185 bool IsAddressMlrRegisteredByNetif(const Ip6::Address &aAddress) const; 186 #endif 187 188 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE IsAddressMlrRegisteredByAnyChild(const Ip6::Address & aAddress) const189 bool IsAddressMlrRegisteredByAnyChild(const Ip6::Address &aAddress) const 190 { 191 return IsAddressMlrRegisteredByAnyChildExcept(aAddress, nullptr); 192 } 193 bool IsAddressMlrRegisteredByAnyChildExcept(const Ip6::Address &aAddress, const Child *aExceptChild) const; 194 #endif 195 196 void SetMulticastAddressMlrState(MlrState aFromState, MlrState aToState); 197 void FinishMlr(bool aSuccess, const AddressArray &aFailedAddresses); 198 199 void ScheduleSend(uint16_t aDelay); 200 void UpdateTimeTickerRegistration(void); 201 void UpdateReregistrationDelay(bool aRereg); 202 void Reregister(void); 203 void HandleTimeTick(void); 204 205 void LogMulticastAddresses(void); 206 void CheckInvariants(void) const; 207 static void LogMlrResponse(Error aResult, Error aError, uint8_t aStatus, const AddressArray &aFailedAddresses); 208 209 #if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 210 Callback<MlrCallback> mRegisterCallback; 211 #endif 212 213 uint32_t mReregistrationDelay; 214 uint16_t mSendDelay; 215 216 bool mMlrPending : 1; 217 #if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 218 bool mRegisterPending : 1; 219 #endif 220 }; 221 222 } // namespace ot 223 224 #endif // OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) 225 #endif // MLR_MANAGER_HPP_ 226