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 Backbone Router management.
32  */
33 
34 #ifndef BACKBONE_ROUTER_MANAGER_HPP_
35 #define BACKBONE_ROUTER_MANAGER_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
40 
41 #include <openthread/backbone_router.h>
42 #include <openthread/backbone_router_ftd.h>
43 
44 #include "backbone_router/backbone_tmf.hpp"
45 #include "backbone_router/bbr_leader.hpp"
46 #include "backbone_router/multicast_listeners_table.hpp"
47 #include "backbone_router/ndproxy_table.hpp"
48 #include "common/locator.hpp"
49 #include "common/non_copyable.hpp"
50 #include "net/netif.hpp"
51 #include "thread/network_data.hpp"
52 
53 namespace ot {
54 
55 namespace BackboneRouter {
56 
57 /**
58  * This class implements the definitions for Backbone Router management.
59  *
60  */
61 class Manager : public InstanceLocator, private NonCopyable
62 {
63     friend class ot::Notifier;
64 
65 public:
66     /**
67      * This constructor initializes the Backbone Router manager.
68      *
69      * @param[in] aInstance  A reference to the OpenThread instance.
70      *
71      */
72     explicit Manager(Instance &aInstance);
73 
74 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
75     /**
76      * This method returns the NdProxy Table.
77      *
78      * @returns The NdProxy Table.
79      *
80      */
81     NdProxyTable &GetNdProxyTable(void);
82 #endif
83 
84 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
85     /**
86      * This method configures response status for next DUA registration.
87      *
88      * Note: available only when `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is enabled.
89      *       Only used for test and certification.
90      *
91      * @param[in] aMlIid    A pointer to the Mesh Local IID. If nullptr, respond with @p aStatus for any
92      *                      coming DUA.req, otherwise only respond the one with matching @p aMlIid.
93      * @param[in] aStatus   The status to respond.
94      *
95      */
96     void ConfigNextDuaRegistrationResponse(const Ip6::InterfaceIdentifier *aMlIid, uint8_t aStatus);
97 
98 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
99     /**
100      * This method configures response status for next Multicast Listener Registration.
101      *
102      * Note: available only when `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` is enabled.
103      *       Only used for test and certification.
104      *
105      * @param[in] aStatus  The status to respond.
106      *
107      */
108     void ConfigNextMulticastListenerRegistrationResponse(ThreadStatusTlv::MlrStatus aStatus);
109 #endif
110 #endif
111 
112 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
113     /**
114      * This method gets the Multicast Listeners Table.
115      *
116      * @returns The Multicast Listeners Table.
117      *
118      */
GetMulticastListenersTable(void)119     MulticastListenersTable &GetMulticastListenersTable(void) { return mMulticastListenersTable; }
120 #endif
121 
122     /**
123      * This method returns if messages destined to a given Domain Unicast Address should be forwarded to the Backbone
124      * link.
125      *
126      * @param aAddress The Domain Unicast Address.
127      *
128      * @retval TRUE   If messages destined to the Domain Unicast Address should be forwarded to the Backbone link.
129      * @retval FALSE  If messages destined to the Domain Unicast Address should not be forwarded to the Backbone link.
130      *
131      */
132     bool ShouldForwardDuaToBackbone(const Ip6::Address &aAddress);
133 
134     /**
135      * This method returns a reference to the Backbone TMF agent.
136      *
137      * @returns A reference to the Backbone TMF agent.
138      *
139      */
GetBackboneTmfAgent(void)140     BackboneTmfAgent &GetBackboneTmfAgent(void) { return mBackboneTmfAgent; }
141 
142     /**
143      * This method sends BB.qry on the Backbone link.
144      *
145      * @param[in]  aDua     The Domain Unicast Address to query.
146      * @param[in]  aRloc16  The short address of the address resolution initiator or `Mac::kShortAddrInvalid` for
147      *                      DUA DAD.
148      *
149      * @retval kErrorNone          Successfully sent BB.qry on backbone link.
150      * @retval kErrorInvalidState  If the Backbone Router is not primary, or not enabled.
151      * @retval kErrorNoBufs        If insufficient message buffers available.
152      *
153      */
154     Error SendBackboneQuery(const Ip6::Address &aDua, uint16_t aRloc16 = Mac::kShortAddrInvalid);
155 
156     /**
157      * This method send a Proactive Backbone Notification (PRO_BB.ntf) on the Backbone link.
158      *
159      * @param[in] aDua                          The Domain Unicast Address to notify.
160      * @param[in] aMeshLocalIid                 The Mesh-Local IID to notify.
161      * @param[in] aTimeSinceLastTransaction     Time since last transaction (in seconds).
162      *
163      * @retval kErrorNone          Successfully sent PRO_BB.ntf on backbone link.
164      * @retval kErrorNoBufs        If insufficient message buffers available.
165      *
166      */
167     Error SendProactiveBackboneNotification(const Ip6::Address &            aDua,
168                                             const Ip6::InterfaceIdentifier &aMeshLocalIid,
169                                             uint32_t                        aTimeSinceLastTransaction);
170 
171 private:
172     static constexpr uint32_t kTimerInterval = 1000;
173 
174 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
HandleMulticastListenerRegistration(void * aContext,otMessage * aMessage,const otMessageInfo * aMessageInfo)175     static void HandleMulticastListenerRegistration(void *               aContext,
176                                                     otMessage *          aMessage,
177                                                     const otMessageInfo *aMessageInfo)
178     {
179         static_cast<Manager *>(aContext)->HandleMulticastListenerRegistration(
180             *static_cast<const Coap::Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
181     }
182     void HandleMulticastListenerRegistration(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
183 
184     void SendMulticastListenerRegistrationResponse(const Coap::Message &      aMessage,
185                                                    const Ip6::MessageInfo &   aMessageInfo,
186                                                    ThreadStatusTlv::MlrStatus aStatus,
187                                                    Ip6::Address *             aFailedAddresses,
188                                                    uint8_t                    aFailedAddressNum);
189     void SendBackboneMulticastListenerRegistration(const Ip6::Address *aAddresses,
190                                                    uint8_t             aAddressNum,
191                                                    uint32_t            aTimeout);
192 #endif
193 
194 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
HandleDuaRegistration(void * aContext,otMessage * aMessage,const otMessageInfo * aMessageInfo)195     static void HandleDuaRegistration(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo)
196     {
197         static_cast<Manager *>(aContext)->HandleDuaRegistration(*static_cast<const Coap::Message *>(aMessage),
198                                                                 *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
199     }
200     void        HandleDuaRegistration(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
201     static void HandleBackboneQuery(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
202     void        HandleBackboneQuery(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
203     static void HandleBackboneAnswer(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
204     void        HandleBackboneAnswer(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
205     Error       SendBackboneAnswer(const Ip6::MessageInfo &     aQueryMessageInfo,
206                                    const Ip6::Address &         aDua,
207                                    uint16_t                     aSrcRloc16,
208                                    const NdProxyTable::NdProxy &aNdProxy);
209     Error       SendBackboneAnswer(const Ip6::Address &            aDstAddr,
210                                    uint16_t                        aDstPort,
211                                    const Ip6::Address &            aDua,
212                                    const Ip6::InterfaceIdentifier &aMeshLocalIid,
213                                    uint32_t                        aTimeSinceLastTransaction,
214                                    uint16_t                        aSrcRloc16);
215     void        HandleDadBackboneAnswer(const Ip6::Address &aDua, const Ip6::InterfaceIdentifier &aMeshLocalIid);
216     void        HandleExtendedBackboneAnswer(const Ip6::Address &            aDua,
217                                              const Ip6::InterfaceIdentifier &aMeshLocalIid,
218                                              uint32_t                        aTimeSinceLastTransaction,
219                                              uint16_t                        aSrcRloc16);
220     void        HandleProactiveBackboneNotification(const Ip6::Address &            aDua,
221                                                     const Ip6::InterfaceIdentifier &aMeshLocalIid,
222                                                     uint32_t                        aTimeSinceLastTransaction);
223     void        SendDuaRegistrationResponse(const Coap::Message &      aMessage,
224                                             const Ip6::MessageInfo &   aMessageInfo,
225                                             const Ip6::Address &       aTarget,
226                                             ThreadStatusTlv::DuaStatus aStatus);
227 #endif
228     void HandleNotifierEvents(Events aEvents);
229 
230     static void HandleTimer(Timer &aTimer);
231     void        HandleTimer(void);
232 
233 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
234     Coap::Resource mMulticastListenerRegistration;
235 #endif
236 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
237     Coap::Resource mDuaRegistration;
238     Coap::Resource mBackboneQuery;
239     Coap::Resource mBackboneAnswer;
240     NdProxyTable   mNdProxyTable;
241 #endif
242 
243 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
244     MulticastListenersTable mMulticastListenersTable;
245 #endif
246     TimerMilli mTimer;
247 
248     BackboneTmfAgent mBackboneTmfAgent;
249 
250 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
251 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
252     Ip6::InterfaceIdentifier mDuaResponseTargetMlIid;
253     uint8_t                  mDuaResponseStatus;
254 #endif
255 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
256     ThreadStatusTlv::MlrStatus mMlrResponseStatus;
257 #endif
258 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_DUA_NDPROXYING_ENABLE
259     bool mDuaResponseIsSpecified : 1;
260 #endif
261 #if OPENTHREAD_CONFIG_BACKBONE_ROUTER_MULTICAST_ROUTING_ENABLE
262     bool mMlrResponseIsSpecified : 1;
263 #endif
264 #endif
265 };
266 
267 } // namespace BackboneRouter
268 
269 /**
270  * @}
271  */
272 
273 } // namespace ot
274 
275 #endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
276 
277 #endif // BACKBONE_ROUTER_MANAGER_HPP_
278