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