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