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 * The file implements the Thread Backbone agent.
32 */
33
34 #define OTBR_LOG_TAG "BBA"
35
36 #include "backbone_router/backbone_agent.hpp"
37
38 #if OTBR_ENABLE_BACKBONE_ROUTER
39
40 #include <assert.h>
41 #include <net/if.h>
42
43 #include <openthread/backbone_router_ftd.h>
44
45 #include "common/code_utils.hpp"
46
47 namespace otbr {
48 namespace BackboneRouter {
49
BackboneAgent(otbr::Ncp::ControllerOpenThread & aNcp,std::string aInterfaceName,std::string aBackboneInterfaceName)50 BackboneAgent::BackboneAgent(otbr::Ncp::ControllerOpenThread &aNcp,
51 std::string aInterfaceName,
52 std::string aBackboneInterfaceName)
53 : mNcp(aNcp)
54 , mBackboneRouterState(OT_BACKBONE_ROUTER_STATE_DISABLED)
55 #if OTBR_ENABLE_DUA_ROUTING
56 , mNdProxyManager(aNcp, aBackboneInterfaceName)
57 , mDuaRoutingManager(aInterfaceName, aBackboneInterfaceName)
58 #endif
59 {
60 OTBR_UNUSED_VARIABLE(aInterfaceName);
61 OTBR_UNUSED_VARIABLE(aBackboneInterfaceName);
62 }
63
Init(void)64 void BackboneAgent::Init(void)
65 {
66 mNcp.AddThreadStateChangedCallback([this](otChangedFlags aFlags) { HandleThreadStateChanged(aFlags); });
67 otBackboneRouterSetDomainPrefixCallback(mNcp.GetInstance(), &BackboneAgent::HandleBackboneRouterDomainPrefixEvent,
68 this);
69 #if OTBR_ENABLE_DUA_ROUTING
70 otBackboneRouterSetNdProxyCallback(mNcp.GetInstance(), &BackboneAgent::HandleBackboneRouterNdProxyEvent, this);
71 mNdProxyManager.Init();
72 #endif
73
74 otBackboneRouterSetEnabled(mNcp.GetInstance(), /* aEnabled */ true);
75 }
76
HandleThreadStateChanged(otChangedFlags aFlags)77 void BackboneAgent::HandleThreadStateChanged(otChangedFlags aFlags)
78 {
79 if (aFlags & OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE)
80 {
81 HandleBackboneRouterState();
82 }
83 }
84
HandleBackboneRouterState(void)85 void BackboneAgent::HandleBackboneRouterState(void)
86 {
87 otBackboneRouterState state = otBackboneRouterGetState(mNcp.GetInstance());
88 bool wasPrimary = (mBackboneRouterState == OT_BACKBONE_ROUTER_STATE_PRIMARY);
89
90 otbrLogDebug("BackboneAgent: HandleBackboneRouterState: state=%d, mBackboneRouterState=%d", state,
91 mBackboneRouterState);
92 VerifyOrExit(mBackboneRouterState != state);
93
94 mBackboneRouterState = state;
95
96 if (IsPrimary())
97 {
98 OnBecomePrimary();
99 }
100 else if (wasPrimary)
101 {
102 OnResignPrimary();
103 }
104
105 exit:
106 return;
107 }
108
OnBecomePrimary(void)109 void BackboneAgent::OnBecomePrimary(void)
110 {
111 otbrLogNotice("BackboneAgent: Backbone Router becomes Primary!");
112
113 #if OTBR_ENABLE_DUA_ROUTING
114 if (mDomainPrefix.IsValid())
115 {
116 mDuaRoutingManager.Enable(mDomainPrefix);
117 mNdProxyManager.Enable(mDomainPrefix);
118 }
119 #endif
120 }
121
OnResignPrimary(void)122 void BackboneAgent::OnResignPrimary(void)
123 {
124 otbrLogNotice("BackboneAgent: Backbone Router resigns Primary to %s!", StateToString(mBackboneRouterState));
125
126 #if OTBR_ENABLE_DUA_ROUTING
127 mDuaRoutingManager.Disable();
128 mNdProxyManager.Disable();
129 #endif
130 }
131
StateToString(otBackboneRouterState aState)132 const char *BackboneAgent::StateToString(otBackboneRouterState aState)
133 {
134 const char *ret = "Unknown";
135
136 switch (aState)
137 {
138 case OT_BACKBONE_ROUTER_STATE_DISABLED:
139 ret = "Disabled";
140 break;
141 case OT_BACKBONE_ROUTER_STATE_SECONDARY:
142 ret = "Secondary";
143 break;
144 case OT_BACKBONE_ROUTER_STATE_PRIMARY:
145 ret = "Primary";
146 break;
147 }
148
149 return ret;
150 }
151
HandleBackboneRouterDomainPrefixEvent(void * aContext,otBackboneRouterDomainPrefixEvent aEvent,const otIp6Prefix * aDomainPrefix)152 void BackboneAgent::HandleBackboneRouterDomainPrefixEvent(void * aContext,
153 otBackboneRouterDomainPrefixEvent aEvent,
154 const otIp6Prefix * aDomainPrefix)
155 {
156 static_cast<BackboneAgent *>(aContext)->HandleBackboneRouterDomainPrefixEvent(aEvent, aDomainPrefix);
157 }
158
HandleBackboneRouterDomainPrefixEvent(otBackboneRouterDomainPrefixEvent aEvent,const otIp6Prefix * aDomainPrefix)159 void BackboneAgent::HandleBackboneRouterDomainPrefixEvent(otBackboneRouterDomainPrefixEvent aEvent,
160 const otIp6Prefix * aDomainPrefix)
161 {
162 if (aEvent == OT_BACKBONE_ROUTER_DOMAIN_PREFIX_REMOVED)
163 {
164 mDomainPrefix.Clear();
165 }
166 else
167 {
168 assert(aDomainPrefix != nullptr);
169 mDomainPrefix.Set(*aDomainPrefix);
170 assert(mDomainPrefix.IsValid());
171 }
172
173 VerifyOrExit(IsPrimary() && aEvent != OT_BACKBONE_ROUTER_DOMAIN_PREFIX_REMOVED);
174
175 #if OTBR_ENABLE_DUA_ROUTING
176 mDuaRoutingManager.Disable();
177 mNdProxyManager.Disable();
178
179 mDuaRoutingManager.Enable(mDomainPrefix);
180 mNdProxyManager.Enable(mDomainPrefix);
181 #endif
182
183 exit:
184 return;
185 }
186
187 #if OTBR_ENABLE_DUA_ROUTING
HandleBackboneRouterNdProxyEvent(void * aContext,otBackboneRouterNdProxyEvent aEvent,const otIp6Address * aAddress)188 void BackboneAgent::HandleBackboneRouterNdProxyEvent(void * aContext,
189 otBackboneRouterNdProxyEvent aEvent,
190 const otIp6Address * aAddress)
191 {
192 static_cast<BackboneAgent *>(aContext)->HandleBackboneRouterNdProxyEvent(aEvent, aAddress);
193 }
194
HandleBackboneRouterNdProxyEvent(otBackboneRouterNdProxyEvent aEvent,const otIp6Address * aDua)195 void BackboneAgent::HandleBackboneRouterNdProxyEvent(otBackboneRouterNdProxyEvent aEvent, const otIp6Address *aDua)
196 {
197 mNdProxyManager.HandleBackboneRouterNdProxyEvent(aEvent, aDua);
198 }
199 #endif
200
201 } // namespace BackboneRouter
202 } // namespace otbr
203
204 #endif // OTBR_ENABLE_BACKBONE_ROUTER
205