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/callback.hpp" 48 #include "common/locator.hpp" 49 #include "common/non_copyable.hpp" 50 #include "common/notifier.hpp" 51 #include "common/time_ticker.hpp" 52 #include "common/timer.hpp" 53 #include "net/netif.hpp" 54 #include "thread/child.hpp" 55 #include "thread/thread_tlvs.hpp" 56 57 namespace ot { 58 59 /** 60 * @addtogroup core-mlr 61 * 62 * @brief 63 * This module includes definitions for Multicast Listener Registration. 64 * 65 * @{ 66 * 67 * @defgroup core-mlr Mlr 68 * 69 * @} 70 * 71 */ 72 73 /** 74 * Implements MLR management. 75 * 76 */ 77 class MlrManager : public InstanceLocator, private NonCopyable 78 { 79 friend class ot::Notifier; 80 friend class ot::TimeTicker; 81 82 public: 83 /** 84 * Initializes the object. 85 * 86 * @param[in] aInstance A reference to the OpenThread instance. 87 * 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 */ 98 void HandleBackboneRouterPrimaryUpdate(BackboneRouter::Leader::State aState, const BackboneRouter::Config &aConfig); 99 100 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE 101 static constexpr uint16_t kMaxMlrAddresses = OPENTHREAD_CONFIG_MLE_IP_ADDRS_PER_CHILD - 1; ///< Max MLR addresses 102 103 typedef Array<Ip6::Address, kMaxMlrAddresses> MlrAddressArray; ///< Registered MLR addresses array. 104 105 /** 106 * Updates the Multicast Subscription Table according to the Child information. 107 * 108 * @param[in] aChild A reference to the child information. 109 * @param[in] aOldMlrRegisteredAddresses Array of the Child's previously registered IPv6 addresses. 110 * 111 */ 112 void UpdateProxiedSubscriptions(Child &aChild, const MlrAddressArray &aOldMlrRegisteredAddresses); 113 #endif 114 115 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 116 /** 117 * Registers Multicast Listeners to Primary Backbone Router. 118 * 119 * Note: only available when both `(OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)` and 120 * `OPENTHREAD_CONFIG_COMMISSIONER_ENABLE` are enabled) 121 * 122 * @param aAddresses A pointer to IPv6 multicast addresses to register. 123 * @param aAddressNum The number of IPv6 multicast addresses. 124 * @param aTimeout A pointer to the timeout (in seconds), or `nullptr` to use the default MLR timeout. 125 * A timeout of 0 seconds removes the Multicast Listener addresses. 126 * @param aCallback A callback function. 127 * @param aContext A user context pointer. 128 * 129 * @retval kErrorNone Successfully sent MLR.req. The @p aCallback will be called iff this method 130 * returns kErrorNone. 131 * @retval kErrorBusy If a previous registration was ongoing. 132 * @retval kErrorInvalidArgs If one or more arguments are invalid. 133 * @retval kErrorInvalidState If the device was not in a valid state to send MLR.req (e.g. Commissioner not 134 * started, Primary Backbone Router not found). 135 * @retval kErrorNoBufs If insufficient message buffers available. 136 * 137 */ 138 Error RegisterMulticastListeners(const otIp6Address *aAddresses, 139 uint8_t aAddressNum, 140 const uint32_t *aTimeout, 141 otIp6RegisterMulticastListenersCallback aCallback, 142 void *aContext); 143 #endif 144 145 private: 146 void HandleNotifierEvents(Events aEvents); 147 148 void SendMulticastListenerRegistration(void); 149 Error SendMulticastListenerRegistrationMessage(const otIp6Address *aAddresses, 150 uint8_t aAddressNum, 151 const uint32_t *aTimeout, 152 Coap::ResponseHandler aResponseHandler, 153 void *aResponseContext); 154 155 static void HandleMulticastListenerRegistrationResponse(void *aContext, 156 otMessage *aMessage, 157 const otMessageInfo *aMessageInfo, 158 Error aResult); 159 void HandleMulticastListenerRegistrationResponse(Coap::Message *aMessage, 160 const Ip6::MessageInfo *aMessageInfo, 161 Error aResult); 162 static Error ParseMulticastListenerRegistrationResponse(Error aResult, 163 Coap::Message *aMessage, 164 uint8_t &aStatus, 165 Ip6::Address *aFailedAddresses, 166 uint8_t &aFailedAddressNum); 167 168 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 169 static void HandleRegisterMulticastListenersResponse(void *aContext, 170 otMessage *aMessage, 171 const otMessageInfo *aMessageInfo, 172 Error aResult); 173 void HandleRegisterMulticastListenersResponse(otMessage *aMessage, 174 const otMessageInfo *aMessageInfo, 175 Error aResult); 176 #endif 177 178 #if OPENTHREAD_CONFIG_MLR_ENABLE 179 void UpdateLocalSubscriptions(void); 180 bool IsAddressMlrRegisteredByNetif(const Ip6::Address &aAddress) const; 181 #endif 182 183 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE IsAddressMlrRegisteredByAnyChild(const Ip6::Address & aAddress) const184 bool IsAddressMlrRegisteredByAnyChild(const Ip6::Address &aAddress) const 185 { 186 return IsAddressMlrRegisteredByAnyChildExcept(aAddress, nullptr); 187 } 188 bool IsAddressMlrRegisteredByAnyChildExcept(const Ip6::Address &aAddress, const Child *aExceptChild) const; 189 #endif 190 191 void SetMulticastAddressMlrState(MlrState aFromState, MlrState aToState); 192 void FinishMulticastListenerRegistration(bool aSuccess, 193 const Ip6::Address *aFailedAddresses, 194 uint8_t aFailedAddressNum); 195 196 void AppendToUniqueAddressList(Ip6::Address (&aAddresses)[Ip6AddressesTlv::kMaxAddresses], 197 uint8_t &aAddressNum, 198 const Ip6::Address &aAddress); 199 static bool AddressListContains(const Ip6::Address *aAddressList, 200 uint8_t aAddressListSize, 201 const Ip6::Address &aAddress); 202 203 void ScheduleSend(uint16_t aDelay); 204 void UpdateTimeTickerRegistration(void); 205 void UpdateReregistrationDelay(bool aRereg); 206 void Reregister(void); 207 void HandleTimeTick(void); 208 209 void LogMulticastAddresses(void); 210 void CheckInvariants(void) const; 211 static void LogMlrResponse(Error aResult, 212 Error aError, 213 uint8_t aStatus, 214 const Ip6::Address *aFailedAddresses, 215 uint8_t aFailedAddressNum); 216 217 #if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 218 Callback<otIp6RegisterMulticastListenersCallback> mRegisterMulticastListenersCallback; 219 #endif 220 221 uint32_t mReregistrationDelay; 222 uint16_t mSendDelay; 223 224 bool mMlrPending : 1; 225 #if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 226 bool mRegisterMulticastListenersPending : 1; 227 #endif 228 }; 229 230 } // namespace ot 231 232 #endif // OPENTHREAD_CONFIG_MLR_ENABLE || (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) 233 #endif // MLR_MANAGER_HPP_ 234