3 * Copyright (c) 2020 Project CHIP Authors
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
22 #include "platform/internal/CHIPDeviceLayerInternal.h"
23 #include "platform/internal/DeviceNetworkInfo.h"
25 #include "platform/PlatformManager.h"
26 #include "platform/ThreadStackManager.h"
27 #include "support/CodeUtils.h"
28 #include "support/logging/CHIPLogging.h"
30 #include "dbus/client/thread_api_dbus.hpp"
32 using chip::DeviceLayer::Internal::DeviceNetworkInfo;
33 using otbr::DBus::ClientError;
34 using otbr::DBus::DeviceRole;
35 using otbr::DBus::LinkModeConfig;
36 using otbr::DBus::NeighborInfo;
38 #ifndef CHIP_CONFIG_OTBR_CLIENT_ERROR_MIN
39 #define CHIP_CONFIG_OTBR_CLIENT_ERROR_MIN 8000000
42 #define OTBR_TO_CHIP_ERROR(x) \
43 (x == ClientError::ERROR_NONE ? CHIP_NO_ERROR : _CHIP_ERROR(CHIP_CONFIG_OTBR_CLIENT_ERROR_MIN + static_cast<int>(x)))
45 #define LogClientError(error) \
48 if (error != ClientError::ERROR_NONE) \
50 ChipLogError(DeviceLayer, __FILE__ " %d: Otbr ClientError %d", __LINE__, static_cast<int>(error)); \
55 namespace DeviceLayer {
57 ThreadStackManagerImpl ThreadStackManagerImpl::sInstance;
59 ThreadStackManagerImpl::ThreadStackManagerImpl() : mThreadApi(nullptr), mConnection(nullptr), mNetworkInfo(), mAttached(false) {}
61 CHIP_ERROR ThreadStackManagerImpl::_InitThreadStack()
66 DBusConnection * dispatchConnection;
68 dbus_error_init(&dbusError);
69 mConnection = UniqueDBusConnection(dbus_bus_get(DBUS_BUS_SYSTEM, &dbusError));
70 VerifyOrExit(dbus_bus_register(mConnection.get(), &dbusError), error = ClientError::ERROR_DBUS);
72 VerifyOrExit(mConnection != nullptr, error = ClientError::ERROR_DBUS);
73 mThreadApi = std::unique_ptr<otbr::DBus::ThreadApiDBus>(new otbr::DBus::ThreadApiDBus(mConnection.get()));
74 mThreadApi->AddDeviceRoleHandler([this](DeviceRole newRole) { this->_ThreadDevcieRoleChangedHandler(newRole); });
76 SuccessOrExit(error = mThreadApi->GetDeviceRole(role));
77 _ThreadDevcieRoleChangedHandler(role);
78 mAttached = (role != DeviceRole::OTBR_DEVICE_ROLE_DETACHED && role != DeviceRole::OTBR_DEVICE_ROLE_DISABLED);
80 dispatchConnection = mConnection.get();
81 mDBusEventLoop = std::thread([dispatchConnection]() {
84 dbus_connection_read_write_dispatch(dispatchConnection, -1);
87 mDBusEventLoop.detach();
89 dbus_error_free(&dbusError);
90 LogClientError(error);
91 return OTBR_TO_CHIP_ERROR(error);
94 void ThreadStackManagerImpl::_ThreadDevcieRoleChangedHandler(DeviceRole role)
96 bool attached = (role != DeviceRole::OTBR_DEVICE_ROLE_DETACHED && role != DeviceRole::OTBR_DEVICE_ROLE_DISABLED);
97 ChipDeviceEvent event = ChipDeviceEvent{};
99 if (attached != mAttached)
101 event.Type = DeviceEventType::kThreadConnectivityChange;
102 event.ThreadConnectivityChange.Result =
103 attached ? ConnectivityChange::kConnectivity_Established : ConnectivityChange::kConnectivity_Lost;
104 PlatformMgr().PostEvent(&event);
107 event.Type = DeviceEventType::kThreadStateChange;
108 event.ThreadStateChange.RoleChanged = true;
109 PlatformMgr().PostEvent(&event);
112 void ThreadStackManagerImpl::_ProcessThreadActivity() {}
114 static bool RouteMatch(const otbr::DBus::Ip6Prefix & prefix, const Inet::IPAddress & addr)
117 const uint8_t * prefixBuffer;
118 const uint8_t * addrBuffer;
119 uint8_t wholeBytes = prefix.mLength / CHAR_BIT;
120 uint8_t pendingBits = prefix.mLength % CHAR_BIT;
122 VerifyOrExit(addr.IsIPv6(), match = false);
123 VerifyOrExit(prefix.mLength > 0, match = false);
125 prefixBuffer = static_cast<const uint8_t *>(&prefix.mPrefix[0]);
126 addrBuffer = reinterpret_cast<const uint8_t *>(&addr.Addr);
127 VerifyOrExit(memcmp(addrBuffer, prefixBuffer, wholeBytes) == 0, match = false);
130 uint8_t mask = static_cast<uint8_t>(((UINT8_MAX >> pendingBits) << (CHAR_BIT - pendingBits)));
132 VerifyOrExit((addrBuffer[wholeBytes] & mask) == (addrBuffer[wholeBytes] & mask), match = false);
134 VerifyOrExit(memcmp(addrBuffer, prefixBuffer, wholeBytes) == 0, match = false);
140 bool ThreadStackManagerImpl::_HaveRouteToAddress(const Inet::IPAddress & destAddr)
142 std::vector<otbr::DBus::ExternalRoute> routes;
145 VerifyOrExit(mThreadApi->GetExternalRoutes(routes) == ClientError::ERROR_NONE, match = false);
146 VerifyOrExit(_IsThreadAttached(), match = false);
147 VerifyOrExit(destAddr.IsIPv6LinkLocal(), match = true);
148 for (const auto & route : routes)
150 VerifyOrExit(!(match = RouteMatch(route.mPrefix, destAddr)), );
157 void ThreadStackManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
160 // The otbr-agent processes the Thread state handling by itself so there
161 // isn't much to do in the Chip stack.
164 CHIP_ERROR ThreadStackManagerImpl::_SetThreadProvision(const Internal::DeviceNetworkInfo & netInfo)
166 mNetworkInfo = netInfo;
168 // post an event alerting other subsystems about change in provisioning state
169 ChipDeviceEvent event;
170 event.Type = DeviceEventType::kServiceProvisioningChange;
171 event.ServiceProvisioningChange.IsServiceProvisioned = true;
172 PlatformMgr().PostEvent(&event);
174 return CHIP_NO_ERROR;
177 CHIP_ERROR ThreadStackManagerImpl::_SetThreadProvision(const uint8_t * operationalDataset, size_t operationalDatasetLen)
179 mOperationalDatasetTlv = std::vector<uint8_t>(operationalDataset, operationalDataset + operationalDatasetLen);
181 // post an event alerting other subsystems about change in provisioning state
182 ChipDeviceEvent event;
183 event.Type = DeviceEventType::kServiceProvisioningChange;
184 event.ServiceProvisioningChange.IsServiceProvisioned = true;
185 PlatformMgr().PostEvent(&event);
187 return CHIP_NO_ERROR;
190 CHIP_ERROR ThreadStackManagerImpl::_GetThreadProvision(Internal::DeviceNetworkInfo & netInfo, bool includeCredentials)
192 netInfo = mNetworkInfo;
194 if (!includeCredentials)
196 memset(&netInfo.ThreadMasterKey, 0, sizeof(netInfo.ThreadMasterKey));
197 memset(&netInfo.ThreadPSKc, 0, sizeof(netInfo.ThreadPSKc));
198 netInfo.FieldPresent.ThreadPSKc = false;
201 return CHIP_NO_ERROR;
204 bool ThreadStackManagerImpl::_IsThreadProvisioned()
206 return mNetworkInfo.ThreadNetworkName[0] != '\0';
209 void ThreadStackManagerImpl::_ErasePersistentInfo()
211 mNetworkInfo = Internal::DeviceNetworkInfo{};
214 bool ThreadStackManagerImpl::_IsThreadEnabled()
216 bool enabled = false;
220 SuccessOrExit(error = mThreadApi->GetDeviceRole(role));
221 enabled = (role != DeviceRole::OTBR_DEVICE_ROLE_DISABLED);
223 LogClientError(error);
227 bool ThreadStackManagerImpl::_IsThreadAttached()
232 CHIP_ERROR ThreadStackManagerImpl::_SetThreadEnabled(bool val)
234 ClientError error = ClientError::ERROR_NONE;
238 if (mOperationalDatasetTlv.size() > 0)
240 SuccessOrExit(error = mThreadApi->SetActiveDatasetTlvs(mOperationalDatasetTlv));
241 SuccessOrExit(error = mThreadApi->Attach([](ClientError result) {
242 // ThreadDevcieRoleChangedHandler should take care of this, so we don't emit another event.
243 ChipLogProgress(DeviceLayer, "Thread attach result %d", result);
248 std::vector<uint8_t> masterkey(std::begin(mNetworkInfo.ThreadMasterKey), std::end(mNetworkInfo.ThreadMasterKey));
249 std::vector<uint8_t> pskc;
250 uint64_t extPanId = UINT64_MAX;
251 uint32_t channelMask = UINT32_MAX;
253 if (mNetworkInfo.FieldPresent.ThreadExtendedPANId)
256 for (size_t i = 0; i < extPanId; i++)
258 extPanId <<= CHAR_BIT;
259 extPanId |= mNetworkInfo.ThreadExtendedPANId[i];
262 if (mNetworkInfo.FieldPresent.ThreadPSKc)
264 pskc = std::vector<uint8_t>(std::begin(mNetworkInfo.ThreadPSKc), std::end(mNetworkInfo.ThreadPSKc));
266 if (mNetworkInfo.ThreadChannel != Internal::kThreadChannel_NotSpecified)
268 channelMask = 1 << mNetworkInfo.ThreadChannel;
271 if (mNetworkInfo.FieldPresent.ThreadMeshPrefix)
273 std::array<uint8_t, Internal::kThreadMeshPrefixLength> prefix;
275 std::copy(std::begin(mNetworkInfo.ThreadMeshPrefix), std::end(mNetworkInfo.ThreadMeshPrefix), std::begin(prefix));
276 SuccessOrExit(error = mThreadApi->SetMeshLocalPrefix(prefix));
279 mThreadApi->Attach(mNetworkInfo.ThreadNetworkName, mNetworkInfo.ThreadPANId, extPanId, masterkey, pskc, channelMask,
280 [](ClientError result) { ChipLogProgress(DeviceLayer, "Thread attach result %d", result); });
288 LogClientError(error);
289 return OTBR_TO_CHIP_ERROR(error);
292 ConnectivityManager::ThreadDeviceType ThreadStackManagerImpl::_GetThreadDeviceType()
296 LinkModeConfig linkMode;
297 ConnectivityManager::ThreadDeviceType type = ConnectivityManager::ThreadDeviceType::kThreadDeviceType_NotSupported;
299 SuccessOrExit(error = mThreadApi->GetDeviceRole(role));
303 case DeviceRole::OTBR_DEVICE_ROLE_DISABLED:
304 case DeviceRole::OTBR_DEVICE_ROLE_DETACHED:
306 case DeviceRole::OTBR_DEVICE_ROLE_CHILD:
307 SuccessOrExit(error = mThreadApi->GetLinkMode(linkMode));
308 if (!linkMode.mRxOnWhenIdle)
310 type = ConnectivityManager::ThreadDeviceType::kThreadDeviceType_SleepyEndDevice;
314 type = linkMode.mDeviceType ? ConnectivityManager::ThreadDeviceType::kThreadDeviceType_FullEndDevice
315 : ConnectivityManager::ThreadDeviceType::kThreadDeviceType_MinimalEndDevice;
318 case DeviceRole::OTBR_DEVICE_ROLE_ROUTER:
319 case DeviceRole::OTBR_DEVICE_ROLE_LEADER:
320 type = ConnectivityManager::ThreadDeviceType::kThreadDeviceType_Router;
323 ChipLogError(DeviceLayer, "Unknown Thread role: %d", static_cast<int>(role));
328 LogClientError(error);
332 CHIP_ERROR ThreadStackManagerImpl::_SetThreadDeviceType(ConnectivityManager::ThreadDeviceType deviceType)
334 LinkModeConfig linkMode{ true, true, true };
335 ClientError error = ClientError::ERROR_NONE;
337 if (deviceType == ConnectivityManager::ThreadDeviceType::kThreadDeviceType_MinimalEndDevice)
339 linkMode.mNetworkData = false;
341 else if (deviceType == ConnectivityManager::ThreadDeviceType::kThreadDeviceType_SleepyEndDevice)
343 linkMode.mRxOnWhenIdle = false;
344 linkMode.mNetworkData = false;
347 if (!linkMode.mNetworkData)
349 error = mThreadApi->SetLinkMode(linkMode);
352 LogClientError(error);
353 return OTBR_TO_CHIP_ERROR(error);
356 void ThreadStackManagerImpl::_GetThreadPollingConfig(ConnectivityManager::ThreadPollingConfig & pollingConfig)
358 (void) pollingConfig;
360 ChipLogError(DeviceLayer, "Polling config is not supported on linux");
363 CHIP_ERROR ThreadStackManagerImpl::_SetThreadPollingConfig(const ConnectivityManager::ThreadPollingConfig & pollingConfig)
365 (void) pollingConfig;
367 ChipLogError(DeviceLayer, "Polling config is not supported on linux");
368 return CHIP_ERROR_NOT_IMPLEMENTED;
371 bool ThreadStackManagerImpl::_HaveMeshConnectivity()
375 bool hasConnectivity = false;
376 std::vector<NeighborInfo> neighbors;
378 SuccessOrExit(error = mThreadApi->GetDeviceRole(role));
379 VerifyOrExit(role != DeviceRole::OTBR_DEVICE_ROLE_DETACHED && role != DeviceRole::OTBR_DEVICE_ROLE_DISABLED, );
380 if (role == DeviceRole::OTBR_DEVICE_ROLE_CHILD || role == DeviceRole::OTBR_DEVICE_ROLE_ROUTER)
382 hasConnectivity = true;
385 SuccessOrExit(error = mThreadApi->GetNeighborTable(neighbors));
386 for (const auto & neighbor : neighbors)
388 if (!neighbor.mIsChild)
390 hasConnectivity = true;
396 LogClientError(error);
397 return hasConnectivity;
400 void ThreadStackManagerImpl::_OnMessageLayerActivityChanged(bool messageLayerIsActive)
402 (void) messageLayerIsActive;
405 void ThreadStackManagerImpl::_OnCHIPoBLEAdvertisingStart() {}
407 void ThreadStackManagerImpl::_OnCHIPoBLEAdvertisingStop() {}
409 CHIP_ERROR ThreadStackManagerImpl::_GetAndLogThreadStatsCounters()
411 // TODO: implement after we decide on the profiling protocol
412 return CHIP_ERROR_NOT_IMPLEMENTED;
415 CHIP_ERROR ThreadStackManagerImpl::_GetAndLogThreadTopologyMinimal()
417 // TODO: implement after we decide on the profiling protocol
418 return CHIP_ERROR_NOT_IMPLEMENTED;
421 CHIP_ERROR ThreadStackManagerImpl::_GetAndLogThreadTopologyFull()
423 // TODO: implement after we decide on the profiling protocol
424 return CHIP_ERROR_NOT_IMPLEMENTED;
427 CHIP_ERROR ThreadStackManagerImpl::_GetPrimary802154MACAddress(uint8_t * buf)
431 SuccessOrExit(error = mThreadApi->GetExtendedAddress(extAddr));
433 for (size_t i = 0; i < sizeof(extAddr); i++)
435 buf[sizeof(uint64_t) - i - 1] = (extAddr & UINT8_MAX);
436 extAddr >>= CHAR_BIT;
440 LogClientError(error);
441 return OTBR_TO_CHIP_ERROR(error);
444 CHIP_ERROR ThreadStackManagerImpl::_GetExternalIPv6Address(chip::Inet::IPAddress & addr)
446 return CHIP_ERROR_NOT_IMPLEMENTED;
449 CHIP_ERROR ThreadStackManagerImpl::_JoinerStart()
451 return CHIP_ERROR_NOT_IMPLEMENTED;
454 ThreadStackManager & ThreadStackMgr()
456 return chip::DeviceLayer::ThreadStackManagerImpl::sInstance;
459 ThreadStackManagerImpl & ThreadStackMgrImpl()
461 return chip::DeviceLayer::ThreadStackManagerImpl::sInstance;
464 } // namespace DeviceLayer