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/locator.hpp" 48 #include "common/non_copyable.hpp" 49 #include "common/notifier.hpp" 50 #include "common/time_ticker.hpp" 51 #include "common/timer.hpp" 52 #include "net/netif.hpp" 53 #include "thread/thread_tlvs.hpp" 54 #include "thread/topology.hpp" 55 56 namespace ot { 57 58 /** 59 * @addtogroup core-mlr 60 * 61 * @brief 62 * This module includes definitions for Multicast Listener Registration. 63 * 64 * @{ 65 * 66 * @defgroup core-mlr Mlr 67 * 68 * @} 69 * 70 */ 71 72 /** 73 * This class implements MLR management. 74 * 75 */ 76 class MlrManager : public InstanceLocator, private NonCopyable 77 { 78 friend class ot::Notifier; 79 friend class ot::TimeTicker; 80 81 public: 82 /** 83 * This constructor initializes the object. 84 * 85 * @param[in] aInstance A reference to the OpenThread instance. 86 * 87 */ 88 explicit MlrManager(Instance &aInstance); 89 90 /** 91 * This method notifies Primary Backbone Router status. 92 * 93 * @param[in] aState The state or state change of Primary Backbone Router. 94 * @param[in] aConfig The Primary Backbone Router service. 95 * 96 */ 97 void HandleBackboneRouterPrimaryUpdate(BackboneRouter::Leader::State aState, 98 const BackboneRouter::BackboneRouterConfig &aConfig); 99 100 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE 101 /** 102 * This method updates the Multicast Subscription Table according to the Child information. 103 * 104 * @param[in] aChild A reference to the child information. 105 * @param[in] aOldMlrRegisteredAddresses Pointer to an array of the Child's previously registered IPv6 addresses. 106 * @param[in] aOldMlrRegisteredAddressNum The number of previously registered IPv6 addresses. 107 * 108 */ 109 void UpdateProxiedSubscriptions(Child & aChild, 110 const Ip6::Address *aOldMlrRegisteredAddresses, 111 uint16_t aOldMlrRegisteredAddressNum); 112 #endif 113 114 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 115 /** 116 * This method registers Multicast Listeners to Primary Backbone Router. 117 * 118 * Note: only available when both `(OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE)` and 119 * `OPENTHREAD_CONFIG_COMMISSIONER_ENABLE` are enabled) 120 * 121 * @param aAddresses A pointer to IPv6 multicast addresses to register. 122 * @param aAddressNum The number of IPv6 multicast addresses. 123 * @param aTimeout A pointer to the timeout (in seconds), or nullptr to use the default MLR timeout. 124 * A timeout of 0 seconds removes the Multicast Listener addresses. 125 * @param aCallback A callback function. 126 * @param aContext A user context pointer. 127 * 128 * @retval kErrorNone Successfully sent MLR.req. The @p aCallback will be called iff this method 129 * returns kErrorNone. 130 * @retval kErrorBusy If a previous registration was ongoing. 131 * @retval kErrorInvalidArgs If one or more arguments are invalid. 132 * @retval kErrorInvalidState If the device was not in a valid state to send MLR.req (e.g. Commissioner not 133 * started, Primary Backbone Router not found). 134 * @retval kErrorNoBufs If insufficient message buffers available. 135 * 136 */ 137 Error RegisterMulticastListeners(const otIp6Address * aAddresses, 138 uint8_t aAddressNum, 139 const uint32_t * aTimeout, 140 otIp6RegisterMulticastListenersCallback aCallback, 141 void * aContext); 142 #endif 143 144 private: 145 void HandleNotifierEvents(Events aEvents); 146 147 void SendMulticastListenerRegistration(void); 148 Error SendMulticastListenerRegistrationMessage(const otIp6Address * aAddresses, 149 uint8_t aAddressNum, 150 const uint32_t * aTimeout, 151 Coap::ResponseHandler aResponseHandler, 152 void * aResponseContext); 153 154 static void HandleMulticastListenerRegistrationResponse(void * aContext, 155 otMessage * aMessage, 156 const otMessageInfo *aMessageInfo, 157 Error aResult); 158 void HandleMulticastListenerRegistrationResponse(Coap::Message * aMessage, 159 const Ip6::MessageInfo *aMessageInfo, 160 Error aResult); 161 static Error ParseMulticastListenerRegistrationResponse(Error aResult, 162 Coap::Message *aMessage, 163 uint8_t & aStatus, 164 Ip6::Address * aFailedAddresses, 165 uint8_t & aFailedAddressNum); 166 167 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 168 static void HandleRegisterMulticastListenersResponse(void * aContext, 169 otMessage * aMessage, 170 const otMessageInfo *aMessageInfo, 171 Error aResult); 172 void HandleRegisterMulticastListenersResponse(otMessage * aMessage, 173 const otMessageInfo *aMessageInfo, 174 Error 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 FinishMulticastListenerRegistration(bool aSuccess, 192 const Ip6::Address *aFailedAddresses, 193 uint8_t aFailedAddressNum); 194 195 void AppendToUniqueAddressList(Ip6::Address (&aAddresses)[kIp6AddressesNumMax], 196 uint8_t & aAddressNum, 197 const Ip6::Address &aAddress); 198 static bool AddressListContains(const Ip6::Address *aAddressList, 199 uint8_t aAddressListSize, 200 const Ip6::Address &aAddress); 201 202 void ScheduleSend(uint16_t aDelay); 203 void UpdateTimeTickerRegistration(void); 204 void UpdateReregistrationDelay(bool aRereg); 205 void Reregister(void); 206 void HandleTimeTick(void); 207 208 void LogMulticastAddresses(void); 209 void CheckInvariants(void) const; 210 static void LogMlrResponse(Error aResult, 211 Error aError, 212 uint8_t aStatus, 213 const Ip6::Address *aFailedAddresses, 214 uint8_t aFailedAddressNum); 215 216 #if (OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE) && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 217 otIp6RegisterMulticastListenersCallback mRegisterMulticastListenersCallback; 218 void * mRegisterMulticastListenersContext; 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