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 #if OTBR_ENABLE_BACKBONE_ROUTER_ON_INIT
75 otBackboneRouterSetEnabled(mNcp.GetInstance(), /* aEnabled */ true);
76 #endif
77 }
78
HandleThreadStateChanged(otChangedFlags aFlags)79 void BackboneAgent::HandleThreadStateChanged(otChangedFlags aFlags)
80 {
81 if (aFlags & OT_CHANGED_THREAD_BACKBONE_ROUTER_STATE)
82 {
83 HandleBackboneRouterState();
84 }
85 }
86
HandleBackboneRouterState(void)87 void BackboneAgent::HandleBackboneRouterState(void)
88 {
89 otBackboneRouterState state = otBackboneRouterGetState(mNcp.GetInstance());
90 bool wasPrimary = (mBackboneRouterState == OT_BACKBONE_ROUTER_STATE_PRIMARY);
91
92 otbrLogDebug("BackboneAgent: HandleBackboneRouterState: state=%d, mBackboneRouterState=%d", state,
93 mBackboneRouterState);
94 VerifyOrExit(mBackboneRouterState != state);
95
96 mBackboneRouterState = state;
97
98 if (IsPrimary())
99 {
100 OnBecomePrimary();
101 }
102 else if (wasPrimary)
103 {
104 OnResignPrimary();
105 }
106
107 exit:
108 return;
109 }
110
OnBecomePrimary(void)111 void BackboneAgent::OnBecomePrimary(void)
112 {
113 otbrLogNotice("BackboneAgent: Backbone Router becomes Primary!");
114
115 #if OTBR_ENABLE_DUA_ROUTING
116 if (mDomainPrefix.IsValid())
117 {
118 mDuaRoutingManager.Enable(mDomainPrefix);
119 mNdProxyManager.Enable(mDomainPrefix);
120 }
121 #endif
122 }
123
OnResignPrimary(void)124 void BackboneAgent::OnResignPrimary(void)
125 {
126 otbrLogNotice("BackboneAgent: Backbone Router resigns Primary to %s!", StateToString(mBackboneRouterState));
127
128 #if OTBR_ENABLE_DUA_ROUTING
129 mDuaRoutingManager.Disable();
130 mNdProxyManager.Disable();
131 #endif
132 }
133
StateToString(otBackboneRouterState aState)134 const char *BackboneAgent::StateToString(otBackboneRouterState aState)
135 {
136 const char *ret = "Unknown";
137
138 switch (aState)
139 {
140 case OT_BACKBONE_ROUTER_STATE_DISABLED:
141 ret = "Disabled";
142 break;
143 case OT_BACKBONE_ROUTER_STATE_SECONDARY:
144 ret = "Secondary";
145 break;
146 case OT_BACKBONE_ROUTER_STATE_PRIMARY:
147 ret = "Primary";
148 break;
149 }
150
151 return ret;
152 }
153
HandleBackboneRouterDomainPrefixEvent(void * aContext,otBackboneRouterDomainPrefixEvent aEvent,const otIp6Prefix * aDomainPrefix)154 void BackboneAgent::HandleBackboneRouterDomainPrefixEvent(void *aContext,
155 otBackboneRouterDomainPrefixEvent aEvent,
156 const otIp6Prefix *aDomainPrefix)
157 {
158 static_cast<BackboneAgent *>(aContext)->HandleBackboneRouterDomainPrefixEvent(aEvent, aDomainPrefix);
159 }
160
HandleBackboneRouterDomainPrefixEvent(otBackboneRouterDomainPrefixEvent aEvent,const otIp6Prefix * aDomainPrefix)161 void BackboneAgent::HandleBackboneRouterDomainPrefixEvent(otBackboneRouterDomainPrefixEvent aEvent,
162 const otIp6Prefix *aDomainPrefix)
163 {
164 if (aEvent == OT_BACKBONE_ROUTER_DOMAIN_PREFIX_REMOVED)
165 {
166 mDomainPrefix.Clear();
167 }
168 else
169 {
170 assert(aDomainPrefix != nullptr);
171 mDomainPrefix.Set(*aDomainPrefix);
172 assert(mDomainPrefix.IsValid());
173 }
174
175 VerifyOrExit(IsPrimary() && aEvent != OT_BACKBONE_ROUTER_DOMAIN_PREFIX_REMOVED);
176
177 #if OTBR_ENABLE_DUA_ROUTING
178 mDuaRoutingManager.Disable();
179 mNdProxyManager.Disable();
180
181 mDuaRoutingManager.Enable(mDomainPrefix);
182 mNdProxyManager.Enable(mDomainPrefix);
183 #endif
184
185 exit:
186 return;
187 }
188
189 #if OTBR_ENABLE_DUA_ROUTING
HandleBackboneRouterNdProxyEvent(void * aContext,otBackboneRouterNdProxyEvent aEvent,const otIp6Address * aAddress)190 void BackboneAgent::HandleBackboneRouterNdProxyEvent(void *aContext,
191 otBackboneRouterNdProxyEvent aEvent,
192 const otIp6Address *aAddress)
193 {
194 static_cast<BackboneAgent *>(aContext)->HandleBackboneRouterNdProxyEvent(aEvent, aAddress);
195 }
196
HandleBackboneRouterNdProxyEvent(otBackboneRouterNdProxyEvent aEvent,const otIp6Address * aDua)197 void BackboneAgent::HandleBackboneRouterNdProxyEvent(otBackboneRouterNdProxyEvent aEvent, const otIp6Address *aDua)
198 {
199 mNdProxyManager.HandleBackboneRouterNdProxyEvent(aEvent, aDua);
200 }
201 #endif
202
203 } // namespace BackboneRouter
204 } // namespace otbr
205
206 #endif // OTBR_ENABLE_BACKBONE_ROUTER
207