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 #define OTBR_LOG_TAG "UTILS"
30
31 #include "utils/thread_helper.hpp"
32
33 #include <assert.h>
34 #include <limits.h>
35 #include <string.h>
36 #include <time.h>
37
38 #include <openthread/border_router.h>
39 #include <openthread/channel_manager.h>
40 #include <openthread/dataset_ftd.h>
41 #if OTBR_ENABLE_DNSSD_DISCOVERY_PROXY
42 #include <openthread/dnssd_server.h>
43 #endif
44 #include <openthread/jam_detection.h>
45 #include <openthread/joiner.h>
46 #if OTBR_ENABLE_NAT64
47 #include <openthread/crypto.h>
48 #include <openthread/nat64.h>
49 #include "utils/sha256.hpp"
50 #endif
51 #if OTBR_ENABLE_DHCP6_PD
52 #include "utils/sha256.hpp"
53 #endif
54 #if OTBR_ENABLE_LINK_METRICS_TELEMETRY
55 #include <openthread/link_metrics.h>
56 #endif
57 #if OTBR_ENABLE_SRP_ADVERTISING_PROXY
58 #include <openthread/srp_server.h>
59 #endif
60 #include <openthread/thread_ftd.h>
61 #if OTBR_ENABLE_TREL
62 #include <openthread/trel.h>
63 #endif
64 #include <openthread/platform/radio.h>
65
66 #include "common/byteswap.hpp"
67 #include "common/code_utils.hpp"
68 #include "common/logging.hpp"
69 #include "common/tlv.hpp"
70 #include "ncp/ncp_openthread.hpp"
71
72 namespace otbr {
73 namespace agent {
74 namespace {
FindTlv(uint8_t aTlvType,const uint8_t * aTlvs,int aTlvsSize)75 const Tlv *FindTlv(uint8_t aTlvType, const uint8_t *aTlvs, int aTlvsSize)
76 {
77 const Tlv *result = nullptr;
78
79 for (const Tlv *tlv = reinterpret_cast<const Tlv *>(aTlvs);
80 reinterpret_cast<const uint8_t *>(tlv) + sizeof(Tlv) < aTlvs + aTlvsSize; tlv = tlv->GetNext())
81 {
82 if (tlv->GetType() == aTlvType)
83 {
84 ExitNow(result = tlv);
85 }
86 }
87
88 exit:
89 return result;
90 }
91
92 #if OTBR_ENABLE_TELEMETRY_DATA_API
TelemetryNodeTypeFromRoleAndLinkMode(const otDeviceRole & aRole,const otLinkModeConfig & aLinkModeCfg)93 static uint32_t TelemetryNodeTypeFromRoleAndLinkMode(const otDeviceRole &aRole, const otLinkModeConfig &aLinkModeCfg)
94 {
95 uint32_t nodeType;
96
97 switch (aRole)
98 {
99 case OT_DEVICE_ROLE_DISABLED:
100 nodeType = threadnetwork::TelemetryData::NODE_TYPE_DISABLED;
101 break;
102 case OT_DEVICE_ROLE_DETACHED:
103 nodeType = threadnetwork::TelemetryData::NODE_TYPE_DETACHED;
104 break;
105 case OT_DEVICE_ROLE_ROUTER:
106 nodeType = threadnetwork::TelemetryData::NODE_TYPE_ROUTER;
107 break;
108 case OT_DEVICE_ROLE_LEADER:
109 nodeType = threadnetwork::TelemetryData::NODE_TYPE_LEADER;
110 break;
111 case OT_DEVICE_ROLE_CHILD:
112 if (!aLinkModeCfg.mRxOnWhenIdle)
113 {
114 nodeType = threadnetwork::TelemetryData::NODE_TYPE_SLEEPY_END;
115 }
116 else if (!aLinkModeCfg.mDeviceType)
117 {
118 // If it's not an FTD, return as minimal end device.
119 nodeType = threadnetwork::TelemetryData::NODE_TYPE_MINIMAL_END;
120 }
121 else
122 {
123 nodeType = threadnetwork::TelemetryData::NODE_TYPE_END;
124 }
125 break;
126 default:
127 nodeType = threadnetwork::TelemetryData::NODE_TYPE_UNSPECIFIED;
128 }
129
130 return nodeType;
131 }
132
133 #if OTBR_ENABLE_SRP_ADVERTISING_PROXY
SrpServerStateFromOtSrpServerState(otSrpServerState srpServerState)134 threadnetwork::TelemetryData_SrpServerState SrpServerStateFromOtSrpServerState(otSrpServerState srpServerState)
135 {
136 switch (srpServerState)
137 {
138 case OT_SRP_SERVER_STATE_DISABLED:
139 return threadnetwork::TelemetryData::SRP_SERVER_STATE_DISABLED;
140 case OT_SRP_SERVER_STATE_RUNNING:
141 return threadnetwork::TelemetryData::SRP_SERVER_STATE_RUNNING;
142 case OT_SRP_SERVER_STATE_STOPPED:
143 return threadnetwork::TelemetryData::SRP_SERVER_STATE_STOPPED;
144 default:
145 return threadnetwork::TelemetryData::SRP_SERVER_STATE_UNSPECIFIED;
146 }
147 }
148
SrpServerAddressModeFromOtSrpServerAddressMode(otSrpServerAddressMode srpServerAddressMode)149 threadnetwork::TelemetryData_SrpServerAddressMode SrpServerAddressModeFromOtSrpServerAddressMode(
150 otSrpServerAddressMode srpServerAddressMode)
151 {
152 switch (srpServerAddressMode)
153 {
154 case OT_SRP_SERVER_ADDRESS_MODE_ANYCAST:
155 return threadnetwork::TelemetryData::SRP_SERVER_ADDRESS_MODE_STATE_ANYCAST;
156 case OT_SRP_SERVER_ADDRESS_MODE_UNICAST:
157 return threadnetwork::TelemetryData::SRP_SERVER_ADDRESS_MODE_UNICAST;
158 default:
159 return threadnetwork::TelemetryData::SRP_SERVER_ADDRESS_MODE_UNSPECIFIED;
160 }
161 }
162 #endif // OTBR_ENABLE_SRP_ADVERTISING_PROXY
163
164 #if OTBR_ENABLE_NAT64
Nat64StateFromOtNat64State(otNat64State nat64State)165 threadnetwork::TelemetryData_Nat64State Nat64StateFromOtNat64State(otNat64State nat64State)
166 {
167 switch (nat64State)
168 {
169 case OT_NAT64_STATE_DISABLED:
170 return threadnetwork::TelemetryData::NAT64_STATE_DISABLED;
171 case OT_NAT64_STATE_NOT_RUNNING:
172 return threadnetwork::TelemetryData::NAT64_STATE_NOT_RUNNING;
173 case OT_NAT64_STATE_IDLE:
174 return threadnetwork::TelemetryData::NAT64_STATE_IDLE;
175 case OT_NAT64_STATE_ACTIVE:
176 return threadnetwork::TelemetryData::NAT64_STATE_ACTIVE;
177 default:
178 return threadnetwork::TelemetryData::NAT64_STATE_UNSPECIFIED;
179 }
180 }
181
CopyNat64TrafficCounters(const otNat64Counters & from,threadnetwork::TelemetryData_Nat64TrafficCounters * to)182 void CopyNat64TrafficCounters(const otNat64Counters &from, threadnetwork::TelemetryData_Nat64TrafficCounters *to)
183 {
184 to->set_ipv4_to_ipv6_packets(from.m4To6Packets);
185 to->set_ipv4_to_ipv6_bytes(from.m4To6Bytes);
186 to->set_ipv6_to_ipv4_packets(from.m6To4Packets);
187 to->set_ipv6_to_ipv4_bytes(from.m6To4Bytes);
188 }
189 #endif // OTBR_ENABLE_NAT64
190
191 #if OTBR_ENABLE_DHCP6_PD
Dhcp6PdStateFromOtDhcp6PdState(otBorderRoutingDhcp6PdState dhcp6PdState)192 threadnetwork::TelemetryData_Dhcp6PdState Dhcp6PdStateFromOtDhcp6PdState(otBorderRoutingDhcp6PdState dhcp6PdState)
193 {
194 threadnetwork::TelemetryData_Dhcp6PdState pdState = threadnetwork::TelemetryData::DHCP6_PD_STATE_UNSPECIFIED;
195
196 switch (dhcp6PdState)
197 {
198 case OT_BORDER_ROUTING_DHCP6_PD_STATE_DISABLED:
199 pdState = threadnetwork::TelemetryData::DHCP6_PD_STATE_DISABLED;
200 break;
201 case OT_BORDER_ROUTING_DHCP6_PD_STATE_STOPPED:
202 pdState = threadnetwork::TelemetryData::DHCP6_PD_STATE_STOPPED;
203 break;
204 case OT_BORDER_ROUTING_DHCP6_PD_STATE_RUNNING:
205 pdState = threadnetwork::TelemetryData::DHCP6_PD_STATE_RUNNING;
206 break;
207 default:
208 break;
209 }
210
211 return pdState;
212 }
213 #endif // OTBR_ENABLE_DHCP6_PD
214
CopyMdnsResponseCounters(const MdnsResponseCounters & from,threadnetwork::TelemetryData_MdnsResponseCounters * to)215 void CopyMdnsResponseCounters(const MdnsResponseCounters &from, threadnetwork::TelemetryData_MdnsResponseCounters *to)
216 {
217 to->set_success_count(from.mSuccess);
218 to->set_not_found_count(from.mNotFound);
219 to->set_invalid_args_count(from.mInvalidArgs);
220 to->set_duplicated_count(from.mDuplicated);
221 to->set_not_implemented_count(from.mNotImplemented);
222 to->set_unknown_error_count(from.mUnknownError);
223 to->set_aborted_count(from.mAborted);
224 to->set_invalid_state_count(from.mInvalidState);
225 }
226 #endif // OTBR_ENABLE_TELEMETRY_DATA_API
227 } // namespace
228
ThreadHelper(otInstance * aInstance,otbr::Ncp::ControllerOpenThread * aNcp)229 ThreadHelper::ThreadHelper(otInstance *aInstance, otbr::Ncp::ControllerOpenThread *aNcp)
230 : mInstance(aInstance)
231 , mNcp(aNcp)
232 {
233 #if OTBR_ENABLE_TELEMETRY_DATA_API && (OTBR_ENABLE_NAT64 || OTBR_ENABLE_DHCP6_PD)
234 otError error;
235
236 SuccessOrExit(error = otPlatCryptoRandomGet(mNat64PdCommonSalt, sizeof(mNat64PdCommonSalt)));
237
238 exit:
239 if (error != OT_ERROR_NONE)
240 {
241 otbrLogWarning("Error otPlatCryptoRandomGet: %s", otThreadErrorToString(error));
242 }
243 #endif
244 }
245
StateChangedCallback(otChangedFlags aFlags)246 void ThreadHelper::StateChangedCallback(otChangedFlags aFlags)
247 {
248 if (aFlags & OT_CHANGED_THREAD_ROLE)
249 {
250 otDeviceRole role = otThreadGetDeviceRole(mInstance);
251
252 for (const auto &handler : mDeviceRoleHandlers)
253 {
254 handler(role);
255 }
256
257 if (role != OT_DEVICE_ROLE_DISABLED && role != OT_DEVICE_ROLE_DETACHED)
258 {
259 if (mAttachHandler != nullptr)
260 {
261 if (mWaitingMgmtSetResponse)
262 {
263 otbrLogInfo("StateChangedCallback is called during waiting for Mgmt Set Response");
264 ExitNow();
265 }
266 if (mAttachPendingDatasetTlvs.mLength == 0)
267 {
268 AttachHandler handler = mAttachHandler;
269
270 mAttachHandler = nullptr;
271 handler(OT_ERROR_NONE, mAttachDelayMs);
272 }
273 else
274 {
275 otOperationalDataset emptyDataset = {};
276 otError error =
277 otDatasetSendMgmtPendingSet(mInstance, &emptyDataset, mAttachPendingDatasetTlvs.mTlvs,
278 mAttachPendingDatasetTlvs.mLength, MgmtSetResponseHandler, this);
279 if (error != OT_ERROR_NONE)
280 {
281 AttachHandler handler = mAttachHandler;
282
283 mAttachHandler = nullptr;
284 mAttachPendingDatasetTlvs = {};
285 mWaitingMgmtSetResponse = false;
286 handler(error, 0);
287 }
288 else
289 {
290 mWaitingMgmtSetResponse = true;
291 }
292 }
293 }
294 else if (mJoinerHandler != nullptr)
295 {
296 mJoinerHandler(OT_ERROR_NONE);
297 mJoinerHandler = nullptr;
298 }
299 }
300 }
301
302 if (aFlags & OT_CHANGED_ACTIVE_DATASET)
303 {
304 ActiveDatasetChangedCallback();
305 }
306
307 exit:
308 return;
309 }
310
ActiveDatasetChangedCallback()311 void ThreadHelper::ActiveDatasetChangedCallback()
312 {
313 otError error;
314 otOperationalDatasetTlvs datasetTlvs;
315
316 SuccessOrExit(error = otDatasetGetActiveTlvs(mInstance, &datasetTlvs));
317
318 for (const auto &handler : mActiveDatasetChangeHandlers)
319 {
320 handler(datasetTlvs);
321 }
322
323 exit:
324 if (error != OT_ERROR_NONE)
325 {
326 otbrLogWarning("Error handling active dataset change: %s", otThreadErrorToString(error));
327 }
328 }
329
330 #if OTBR_ENABLE_DBUS_SERVER
OnUpdateMeshCopTxt(std::map<std::string,std::vector<uint8_t>> aUpdate)331 void ThreadHelper::OnUpdateMeshCopTxt(std::map<std::string, std::vector<uint8_t>> aUpdate)
332 {
333 if (mUpdateMeshCopTxtHandler)
334 {
335 mUpdateMeshCopTxtHandler(std::move(aUpdate));
336 }
337 else
338 {
339 otbrLogErr("No UpdateMeshCopTxtHandler");
340 }
341 }
342 #endif
343
AddDeviceRoleHandler(DeviceRoleHandler aHandler)344 void ThreadHelper::AddDeviceRoleHandler(DeviceRoleHandler aHandler)
345 {
346 mDeviceRoleHandlers.emplace_back(aHandler);
347 }
348
Scan(ScanHandler aHandler)349 void ThreadHelper::Scan(ScanHandler aHandler)
350 {
351 otError error = OT_ERROR_NONE;
352
353 VerifyOrExit(aHandler != nullptr);
354 mScanHandler = aHandler;
355 mScanResults.clear();
356
357 error =
358 otLinkActiveScan(mInstance, /*scanChannels =*/0, /*scanDuration=*/0, &ThreadHelper::ActiveScanHandler, this);
359
360 exit:
361 if (error != OT_ERROR_NONE)
362 {
363 if (aHandler)
364 {
365 mScanHandler(error, {});
366 }
367 mScanHandler = nullptr;
368 }
369 }
370
EnergyScan(uint32_t aScanDuration,EnergyScanHandler aHandler)371 void ThreadHelper::EnergyScan(uint32_t aScanDuration, EnergyScanHandler aHandler)
372 {
373 otError error = OT_ERROR_NONE;
374 uint32_t preferredChannels = otPlatRadioGetPreferredChannelMask(mInstance);
375
376 VerifyOrExit(aHandler != nullptr, error = OT_ERROR_BUSY);
377 VerifyOrExit(aScanDuration < UINT16_MAX, error = OT_ERROR_INVALID_ARGS);
378 mEnergyScanHandler = aHandler;
379 mEnergyScanResults.clear();
380
381 error = otLinkEnergyScan(mInstance, preferredChannels, static_cast<uint16_t>(aScanDuration),
382 &ThreadHelper::EnergyScanCallback, this);
383
384 exit:
385 if (error != OT_ERROR_NONE)
386 {
387 if (aHandler)
388 {
389 mEnergyScanHandler(error, {});
390 }
391 mEnergyScanHandler = nullptr;
392 }
393 }
394
RandomFill(void * aBuf,size_t size)395 void ThreadHelper::RandomFill(void *aBuf, size_t size)
396 {
397 std::uniform_int_distribution<> dist(0, UINT8_MAX);
398 uint8_t *buf = static_cast<uint8_t *>(aBuf);
399
400 for (size_t i = 0; i < size; i++)
401 {
402 buf[i] = static_cast<uint8_t>(dist(mRandomDevice));
403 }
404 }
405
ActiveScanHandler(otActiveScanResult * aResult,void * aThreadHelper)406 void ThreadHelper::ActiveScanHandler(otActiveScanResult *aResult, void *aThreadHelper)
407 {
408 ThreadHelper *helper = static_cast<ThreadHelper *>(aThreadHelper);
409
410 helper->ActiveScanHandler(aResult);
411 }
412
ActiveScanHandler(otActiveScanResult * aResult)413 void ThreadHelper::ActiveScanHandler(otActiveScanResult *aResult)
414 {
415 if (aResult == nullptr)
416 {
417 if (mScanHandler != nullptr)
418 {
419 mScanHandler(OT_ERROR_NONE, mScanResults);
420 }
421 }
422 else
423 {
424 mScanResults.push_back(*aResult);
425 }
426 }
427
EnergyScanCallback(otEnergyScanResult * aResult,void * aThreadHelper)428 void ThreadHelper::EnergyScanCallback(otEnergyScanResult *aResult, void *aThreadHelper)
429 {
430 ThreadHelper *helper = static_cast<ThreadHelper *>(aThreadHelper);
431
432 helper->EnergyScanCallback(aResult);
433 }
434
EnergyScanCallback(otEnergyScanResult * aResult)435 void ThreadHelper::EnergyScanCallback(otEnergyScanResult *aResult)
436 {
437 if (aResult == nullptr)
438 {
439 if (mEnergyScanHandler != nullptr)
440 {
441 mEnergyScanHandler(OT_ERROR_NONE, mEnergyScanResults);
442 }
443 }
444 else
445 {
446 mEnergyScanResults.push_back(*aResult);
447 }
448 }
449
RandomChannelFromChannelMask(uint32_t aChannelMask)450 uint8_t ThreadHelper::RandomChannelFromChannelMask(uint32_t aChannelMask)
451 {
452 // 8 bit per byte
453 constexpr uint8_t kNumChannels = sizeof(aChannelMask) * 8;
454 uint8_t channels[kNumChannels];
455 uint8_t numValidChannels = 0;
456
457 for (uint8_t i = 0; i < kNumChannels; i++)
458 {
459 if (aChannelMask & (1 << i))
460 {
461 channels[numValidChannels++] = i;
462 }
463 }
464
465 return channels[std::uniform_int_distribution<unsigned int>(0, numValidChannels - 1)(mRandomDevice)];
466 }
467
ToOtExtendedPanId(uint64_t aExtPanId)468 static otExtendedPanId ToOtExtendedPanId(uint64_t aExtPanId)
469 {
470 otExtendedPanId extPanId;
471 uint64_t mask = UINT8_MAX;
472
473 for (size_t i = 0; i < sizeof(uint64_t); i++)
474 {
475 extPanId.m8[i] = static_cast<uint8_t>((aExtPanId >> ((sizeof(uint64_t) - i - 1) * 8)) & mask);
476 }
477
478 return extPanId;
479 }
480
Attach(const std::string & aNetworkName,uint16_t aPanId,uint64_t aExtPanId,const std::vector<uint8_t> & aNetworkKey,const std::vector<uint8_t> & aPSKc,uint32_t aChannelMask,AttachHandler aHandler)481 void ThreadHelper::Attach(const std::string &aNetworkName,
482 uint16_t aPanId,
483 uint64_t aExtPanId,
484 const std::vector<uint8_t> &aNetworkKey,
485 const std::vector<uint8_t> &aPSKc,
486 uint32_t aChannelMask,
487 AttachHandler aHandler)
488
489 {
490 otError error = OT_ERROR_NONE;
491 otOperationalDataset dataset = {};
492
493 VerifyOrExit(aHandler != nullptr, error = OT_ERROR_INVALID_ARGS);
494 VerifyOrExit(mAttachHandler == nullptr && mJoinerHandler == nullptr, error = OT_ERROR_INVALID_STATE);
495 VerifyOrExit(aNetworkKey.empty() || aNetworkKey.size() == sizeof(dataset.mNetworkKey.m8),
496 error = OT_ERROR_INVALID_ARGS);
497 VerifyOrExit(aPSKc.empty() || aPSKc.size() == sizeof(dataset.mPskc.m8), error = OT_ERROR_INVALID_ARGS);
498 VerifyOrExit(aChannelMask != 0, error = OT_ERROR_INVALID_ARGS);
499
500 SuccessOrExit(error = otDatasetCreateNewNetwork(mInstance, &dataset));
501
502 if (aExtPanId != UINT64_MAX)
503 {
504 dataset.mExtendedPanId = ToOtExtendedPanId(aExtPanId);
505 }
506
507 if (!aNetworkKey.empty())
508 {
509 memcpy(dataset.mNetworkKey.m8, &aNetworkKey[0], sizeof(dataset.mNetworkKey.m8));
510 }
511
512 if (aPanId != UINT16_MAX)
513 {
514 dataset.mPanId = aPanId;
515 }
516
517 if (!aPSKc.empty())
518 {
519 memcpy(dataset.mPskc.m8, &aPSKc[0], sizeof(dataset.mPskc.m8));
520 }
521
522 SuccessOrExit(error = otNetworkNameFromString(&dataset.mNetworkName, aNetworkName.c_str()));
523
524 dataset.mChannelMask &= aChannelMask;
525 VerifyOrExit(dataset.mChannelMask != 0, otbrLogWarning("Invalid channel mask"), error = OT_ERROR_INVALID_ARGS);
526
527 dataset.mChannel = RandomChannelFromChannelMask(dataset.mChannelMask);
528
529 SuccessOrExit(error = otDatasetSetActive(mInstance, &dataset));
530
531 if (!otIp6IsEnabled(mInstance))
532 {
533 SuccessOrExit(error = otIp6SetEnabled(mInstance, true));
534 }
535
536 SuccessOrExit(error = otThreadSetEnabled(mInstance, true));
537 mAttachDelayMs = 0;
538 mAttachHandler = aHandler;
539
540 exit:
541 if (error != OT_ERROR_NONE)
542 {
543 if (aHandler)
544 {
545 aHandler(error, 0);
546 }
547 }
548 }
549
Attach(AttachHandler aHandler)550 void ThreadHelper::Attach(AttachHandler aHandler)
551 {
552 otError error = OT_ERROR_NONE;
553
554 VerifyOrExit(mAttachHandler == nullptr && mJoinerHandler == nullptr, error = OT_ERROR_INVALID_STATE);
555
556 if (!otIp6IsEnabled(mInstance))
557 {
558 SuccessOrExit(error = otIp6SetEnabled(mInstance, true));
559 }
560 SuccessOrExit(error = otThreadSetEnabled(mInstance, true));
561 mAttachHandler = aHandler;
562
563 exit:
564 if (error != OT_ERROR_NONE)
565 {
566 if (aHandler)
567 {
568 aHandler(error, 0);
569 }
570 }
571 }
572
Detach(void)573 otError ThreadHelper::Detach(void)
574 {
575 otError error = OT_ERROR_NONE;
576
577 SuccessOrExit(error = otThreadSetEnabled(mInstance, false));
578 SuccessOrExit(error = otIp6SetEnabled(mInstance, false));
579
580 exit:
581 return error;
582 }
583
Reset(void)584 otError ThreadHelper::Reset(void)
585 {
586 mDeviceRoleHandlers.clear();
587 otInstanceReset(mInstance);
588
589 return OT_ERROR_NONE;
590 }
591
JoinerStart(const std::string & aPskd,const std::string & aProvisioningUrl,const std::string & aVendorName,const std::string & aVendorModel,const std::string & aVendorSwVersion,const std::string & aVendorData,ResultHandler aHandler)592 void ThreadHelper::JoinerStart(const std::string &aPskd,
593 const std::string &aProvisioningUrl,
594 const std::string &aVendorName,
595 const std::string &aVendorModel,
596 const std::string &aVendorSwVersion,
597 const std::string &aVendorData,
598 ResultHandler aHandler)
599 {
600 otError error = OT_ERROR_NONE;
601
602 VerifyOrExit(aHandler != nullptr, error = OT_ERROR_INVALID_ARGS);
603 VerifyOrExit(mAttachHandler == nullptr && mJoinerHandler == nullptr, error = OT_ERROR_INVALID_STATE);
604
605 if (!otIp6IsEnabled(mInstance))
606 {
607 SuccessOrExit(error = otIp6SetEnabled(mInstance, true));
608 }
609 SuccessOrExit(error = otJoinerStart(mInstance, aPskd.c_str(), aProvisioningUrl.c_str(), aVendorName.c_str(),
610 aVendorModel.c_str(), aVendorSwVersion.c_str(), aVendorData.c_str(),
611 JoinerCallback, this));
612 mJoinerHandler = aHandler;
613
614 exit:
615 if (error != OT_ERROR_NONE)
616 {
617 if (aHandler)
618 {
619 aHandler(error);
620 }
621 }
622 }
623
JoinerCallback(otError aError,void * aThreadHelper)624 void ThreadHelper::JoinerCallback(otError aError, void *aThreadHelper)
625 {
626 ThreadHelper *helper = static_cast<ThreadHelper *>(aThreadHelper);
627
628 helper->JoinerCallback(aError);
629 }
630
JoinerCallback(otError aError)631 void ThreadHelper::JoinerCallback(otError aError)
632 {
633 if (aError != OT_ERROR_NONE)
634 {
635 otbrLogWarning("Failed to join Thread network: %s", otThreadErrorToString(aError));
636 mJoinerHandler(aError);
637 mJoinerHandler = nullptr;
638 }
639 else
640 {
641 LogOpenThreadResult("Start Thread network", otThreadSetEnabled(mInstance, true));
642 }
643 }
644
TryResumeNetwork(void)645 otError ThreadHelper::TryResumeNetwork(void)
646 {
647 otError error = OT_ERROR_NONE;
648
649 if (otLinkGetPanId(mInstance) != UINT16_MAX && otThreadGetDeviceRole(mInstance) == OT_DEVICE_ROLE_DISABLED)
650 {
651 if (!otIp6IsEnabled(mInstance))
652 {
653 SuccessOrExit(error = otIp6SetEnabled(mInstance, true));
654 SuccessOrExit(error = otThreadSetEnabled(mInstance, true));
655 }
656 }
657
658 exit:
659 if (error != OT_ERROR_NONE)
660 {
661 (void)otIp6SetEnabled(mInstance, false);
662 }
663
664 return error;
665 }
666
LogOpenThreadResult(const char * aAction,otError aError)667 void ThreadHelper::LogOpenThreadResult(const char *aAction, otError aError)
668 {
669 if (aError == OT_ERROR_NONE)
670 {
671 otbrLogInfo("%s: %s", aAction, otThreadErrorToString(aError));
672 }
673 else
674 {
675 otbrLogWarning("%s: %s", aAction, otThreadErrorToString(aError));
676 }
677 }
678
AttachAllNodesTo(const std::vector<uint8_t> & aDatasetTlvs,AttachHandler aHandler)679 void ThreadHelper::AttachAllNodesTo(const std::vector<uint8_t> &aDatasetTlvs, AttachHandler aHandler)
680 {
681 constexpr uint32_t kDelayTimerMilliseconds = 300 * 1000;
682
683 otError error = OT_ERROR_NONE;
684 otOperationalDatasetTlvs datasetTlvs;
685 otOperationalDataset dataset;
686 otOperationalDataset emptyDataset{};
687 otDeviceRole role = otThreadGetDeviceRole(mInstance);
688 Tlv *tlv;
689 uint64_t pendingTimestamp = 0;
690 timespec currentTime;
691
692 if (aHandler == nullptr)
693 {
694 otbrLogWarning("Attach Handler is nullptr");
695 ExitNow(error = OT_ERROR_INVALID_ARGS);
696 }
697 VerifyOrExit(mAttachHandler == nullptr && mJoinerHandler == nullptr, error = OT_ERROR_BUSY);
698
699 VerifyOrExit(aDatasetTlvs.size() <= sizeof(datasetTlvs.mTlvs), error = OT_ERROR_INVALID_ARGS);
700 std::copy(aDatasetTlvs.begin(), aDatasetTlvs.end(), datasetTlvs.mTlvs);
701 datasetTlvs.mLength = aDatasetTlvs.size();
702
703 SuccessOrExit(error = otDatasetParseTlvs(&datasetTlvs, &dataset));
704 VerifyOrExit(dataset.mComponents.mIsActiveTimestampPresent, error = OT_ERROR_INVALID_ARGS);
705 VerifyOrExit(dataset.mComponents.mIsNetworkKeyPresent, error = OT_ERROR_INVALID_ARGS);
706 VerifyOrExit(dataset.mComponents.mIsNetworkNamePresent, error = OT_ERROR_INVALID_ARGS);
707 VerifyOrExit(dataset.mComponents.mIsExtendedPanIdPresent, error = OT_ERROR_INVALID_ARGS);
708 VerifyOrExit(dataset.mComponents.mIsMeshLocalPrefixPresent, error = OT_ERROR_INVALID_ARGS);
709 VerifyOrExit(dataset.mComponents.mIsPanIdPresent, error = OT_ERROR_INVALID_ARGS);
710 VerifyOrExit(dataset.mComponents.mIsChannelPresent, error = OT_ERROR_INVALID_ARGS);
711 VerifyOrExit(dataset.mComponents.mIsPskcPresent, error = OT_ERROR_INVALID_ARGS);
712 VerifyOrExit(dataset.mComponents.mIsSecurityPolicyPresent, error = OT_ERROR_INVALID_ARGS);
713 VerifyOrExit(dataset.mComponents.mIsChannelMaskPresent, error = OT_ERROR_INVALID_ARGS);
714
715 VerifyOrExit(FindTlv(OT_MESHCOP_TLV_PENDINGTIMESTAMP, datasetTlvs.mTlvs, datasetTlvs.mLength) == nullptr &&
716 FindTlv(OT_MESHCOP_TLV_DELAYTIMER, datasetTlvs.mTlvs, datasetTlvs.mLength) == nullptr,
717 error = OT_ERROR_INVALID_ARGS);
718
719 // There must be sufficient space for a Pending Timestamp TLV and a Delay Timer TLV.
720 VerifyOrExit(
721 static_cast<int>(datasetTlvs.mLength +
722 (sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint64_t)) // Pending Timestamp TLV (10 bytes)
723 + (sizeof(uint8_t) + sizeof(uint8_t) + sizeof(uint32_t))) // Delay Timer TLV (6 bytes)
724 <= int{sizeof(datasetTlvs.mTlvs)},
725 error = OT_ERROR_INVALID_ARGS);
726
727 tlv = reinterpret_cast<Tlv *>(datasetTlvs.mTlvs + datasetTlvs.mLength);
728 tlv->SetType(OT_MESHCOP_TLV_PENDINGTIMESTAMP);
729 clock_gettime(CLOCK_REALTIME, ¤tTime);
730 pendingTimestamp |= (static_cast<uint64_t>(currentTime.tv_sec) << 16);
731 pendingTimestamp |= (((static_cast<uint64_t>(currentTime.tv_nsec) * 32768 / 1000000000) & 0x7fff) << 1);
732 tlv->SetValue(pendingTimestamp);
733
734 tlv = tlv->GetNext();
735 tlv->SetType(OT_MESHCOP_TLV_DELAYTIMER);
736 tlv->SetValue(kDelayTimerMilliseconds);
737
738 datasetTlvs.mLength = reinterpret_cast<uint8_t *>(tlv->GetNext()) - datasetTlvs.mTlvs;
739
740 assert(datasetTlvs.mLength > 0);
741
742 if (role == OT_DEVICE_ROLE_DISABLED || role == OT_DEVICE_ROLE_DETACHED)
743 {
744 otOperationalDataset existingDataset;
745 bool hasActiveDataset;
746
747 error = otDatasetGetActive(mInstance, &existingDataset);
748 VerifyOrExit(error == OT_ERROR_NONE || error == OT_ERROR_NOT_FOUND);
749
750 hasActiveDataset = (error == OT_ERROR_NONE);
751
752 if (!hasActiveDataset)
753 {
754 SuccessOrExit(error = otDatasetSetActiveTlvs(mInstance, &datasetTlvs));
755 }
756
757 if (!otIp6IsEnabled(mInstance))
758 {
759 SuccessOrExit(error = otIp6SetEnabled(mInstance, true));
760 }
761 SuccessOrExit(error = otThreadSetEnabled(mInstance, true));
762
763 if (hasActiveDataset)
764 {
765 mAttachDelayMs = kDelayTimerMilliseconds;
766 mAttachPendingDatasetTlvs = datasetTlvs;
767 }
768 else
769 {
770 mAttachDelayMs = 0;
771 mAttachPendingDatasetTlvs = {};
772 }
773 mWaitingMgmtSetResponse = false;
774 mAttachHandler = aHandler;
775 ExitNow();
776 }
777
778 SuccessOrExit(error = otDatasetSendMgmtPendingSet(mInstance, &emptyDataset, datasetTlvs.mTlvs, datasetTlvs.mLength,
779 MgmtSetResponseHandler, this));
780 mAttachDelayMs = kDelayTimerMilliseconds;
781 mAttachHandler = aHandler;
782 mWaitingMgmtSetResponse = true;
783
784 exit:
785 if (error != OT_ERROR_NONE)
786 {
787 aHandler(error, 0);
788 }
789 }
790
MgmtSetResponseHandler(otError aResult,void * aContext)791 void ThreadHelper::MgmtSetResponseHandler(otError aResult, void *aContext)
792 {
793 static_cast<ThreadHelper *>(aContext)->MgmtSetResponseHandler(aResult);
794 }
795
MgmtSetResponseHandler(otError aResult)796 void ThreadHelper::MgmtSetResponseHandler(otError aResult)
797 {
798 AttachHandler handler;
799 int64_t attachDelayMs;
800
801 LogOpenThreadResult("MgmtSetResponseHandler()", aResult);
802 mWaitingMgmtSetResponse = false;
803
804 if (mAttachHandler == nullptr)
805 {
806 otbrLogWarning("mAttachHandler is nullptr");
807 mAttachDelayMs = 0;
808 mAttachPendingDatasetTlvs = {};
809 ExitNow();
810 }
811
812 switch (aResult)
813 {
814 case OT_ERROR_NONE:
815 case OT_ERROR_REJECTED:
816 break;
817 default:
818 aResult = OT_ERROR_FAILED;
819 break;
820 }
821
822 attachDelayMs = mAttachDelayMs;
823 handler = mAttachHandler;
824 mAttachDelayMs = 0;
825 mAttachHandler = nullptr;
826 mAttachPendingDatasetTlvs = {};
827 if (aResult == OT_ERROR_NONE)
828 {
829 handler(aResult, attachDelayMs);
830 }
831 else
832 {
833 handler(aResult, 0);
834 }
835
836 exit:
837 return;
838 }
839
840 #if OTBR_ENABLE_UNSECURE_JOIN
PermitUnsecureJoin(uint16_t aPort,uint32_t aSeconds)841 otError ThreadHelper::PermitUnsecureJoin(uint16_t aPort, uint32_t aSeconds)
842 {
843 otError error = OT_ERROR_NONE;
844 otExtAddress steeringData;
845
846 // 0xff to allow all devices to join
847 memset(&steeringData.m8, 0xff, sizeof(steeringData.m8));
848 SuccessOrExit(error = otIp6AddUnsecurePort(mInstance, aPort));
849 otThreadSetSteeringData(mInstance, &steeringData);
850
851 if (aSeconds > 0)
852 {
853 auto delay = Milliseconds(aSeconds * 1000);
854
855 ++mUnsecurePortRefCounter[aPort];
856
857 mNcp->PostTimerTask(delay, [this, aPort]() {
858 assert(mUnsecurePortRefCounter.find(aPort) != mUnsecurePortRefCounter.end());
859 assert(mUnsecurePortRefCounter[aPort] > 0);
860
861 if (--mUnsecurePortRefCounter[aPort] == 0)
862 {
863 otExtAddress noneAddress;
864
865 // 0 to clean steering data
866 memset(&noneAddress.m8, 0, sizeof(noneAddress.m8));
867 (void)otIp6RemoveUnsecurePort(mInstance, aPort);
868 otThreadSetSteeringData(mInstance, &noneAddress);
869 mUnsecurePortRefCounter.erase(aPort);
870 }
871 });
872 }
873 else
874 {
875 otExtAddress noneAddress;
876
877 memset(&noneAddress.m8, 0, sizeof(noneAddress.m8));
878 (void)otIp6RemoveUnsecurePort(mInstance, aPort);
879 otThreadSetSteeringData(mInstance, &noneAddress);
880 }
881
882 exit:
883 return error;
884 }
885 #endif
886
AddActiveDatasetChangeHandler(DatasetChangeHandler aHandler)887 void ThreadHelper::AddActiveDatasetChangeHandler(DatasetChangeHandler aHandler)
888 {
889 mActiveDatasetChangeHandlers.push_back(std::move(aHandler));
890 }
891
DetachGracefully(ResultHandler aHandler)892 void ThreadHelper::DetachGracefully(ResultHandler aHandler)
893 {
894 otError error = OT_ERROR_NONE;
895
896 VerifyOrExit(mDetachGracefullyHandler == nullptr, error = OT_ERROR_BUSY);
897
898 SuccessOrExit(error = otThreadDetachGracefully(mInstance, &ThreadHelper::DetachGracefullyCallback, this));
899 mDetachGracefullyHandler = aHandler;
900
901 exit:
902 if (error != OT_ERROR_NONE)
903 {
904 aHandler(error);
905 }
906 }
907
DetachGracefullyCallback(void * aContext)908 void ThreadHelper::DetachGracefullyCallback(void *aContext)
909 {
910 static_cast<ThreadHelper *>(aContext)->DetachGracefullyCallback();
911 }
912
DetachGracefullyCallback(void)913 void ThreadHelper::DetachGracefullyCallback(void)
914 {
915 if (mDetachGracefullyHandler != nullptr)
916 {
917 mDetachGracefullyHandler(OT_ERROR_NONE);
918 }
919 }
920
921 #if OTBR_ENABLE_TELEMETRY_DATA_API
RetrieveTelemetryData(Mdns::Publisher * aPublisher,threadnetwork::TelemetryData & telemetryData)922 otError ThreadHelper::RetrieveTelemetryData(Mdns::Publisher *aPublisher, threadnetwork::TelemetryData &telemetryData)
923 {
924 otError error = OT_ERROR_NONE;
925 std::vector<otNeighborInfo> neighborTable;
926
927 // Begin of WpanStats section.
928 auto wpanStats = telemetryData.mutable_wpan_stats();
929
930 {
931 otDeviceRole role = otThreadGetDeviceRole(mInstance);
932 otLinkModeConfig otCfg = otThreadGetLinkMode(mInstance);
933
934 wpanStats->set_node_type(TelemetryNodeTypeFromRoleAndLinkMode(role, otCfg));
935 }
936
937 wpanStats->set_channel(otLinkGetChannel(mInstance));
938
939 {
940 uint16_t ccaFailureRate = otLinkGetCcaFailureRate(mInstance);
941
942 wpanStats->set_mac_cca_fail_rate(static_cast<float>(ccaFailureRate) / 0xffff);
943 }
944
945 {
946 int8_t radioTxPower;
947
948 if (otPlatRadioGetTransmitPower(mInstance, &radioTxPower) == OT_ERROR_NONE)
949 {
950 wpanStats->set_radio_tx_power(radioTxPower);
951 }
952 else
953 {
954 error = OT_ERROR_FAILED;
955 }
956 }
957
958 {
959 const otMacCounters *linkCounters = otLinkGetCounters(mInstance);
960
961 wpanStats->set_phy_rx(linkCounters->mRxTotal);
962 wpanStats->set_phy_tx(linkCounters->mTxTotal);
963 wpanStats->set_mac_unicast_rx(linkCounters->mRxUnicast);
964 wpanStats->set_mac_unicast_tx(linkCounters->mTxUnicast);
965 wpanStats->set_mac_broadcast_rx(linkCounters->mRxBroadcast);
966 wpanStats->set_mac_broadcast_tx(linkCounters->mTxBroadcast);
967 wpanStats->set_mac_tx_ack_req(linkCounters->mTxAckRequested);
968 wpanStats->set_mac_tx_no_ack_req(linkCounters->mTxNoAckRequested);
969 wpanStats->set_mac_tx_acked(linkCounters->mTxAcked);
970 wpanStats->set_mac_tx_data(linkCounters->mTxData);
971 wpanStats->set_mac_tx_data_poll(linkCounters->mTxDataPoll);
972 wpanStats->set_mac_tx_beacon(linkCounters->mTxBeacon);
973 wpanStats->set_mac_tx_beacon_req(linkCounters->mTxBeaconRequest);
974 wpanStats->set_mac_tx_other_pkt(linkCounters->mTxOther);
975 wpanStats->set_mac_tx_retry(linkCounters->mTxRetry);
976 wpanStats->set_mac_rx_data(linkCounters->mRxData);
977 wpanStats->set_mac_rx_data_poll(linkCounters->mRxDataPoll);
978 wpanStats->set_mac_rx_beacon(linkCounters->mRxBeacon);
979 wpanStats->set_mac_rx_beacon_req(linkCounters->mRxBeaconRequest);
980 wpanStats->set_mac_rx_other_pkt(linkCounters->mRxOther);
981 wpanStats->set_mac_rx_filter_whitelist(linkCounters->mRxAddressFiltered);
982 wpanStats->set_mac_rx_filter_dest_addr(linkCounters->mRxDestAddrFiltered);
983 wpanStats->set_mac_tx_fail_cca(linkCounters->mTxErrCca);
984 wpanStats->set_mac_rx_fail_decrypt(linkCounters->mRxErrSec);
985 wpanStats->set_mac_rx_fail_no_frame(linkCounters->mRxErrNoFrame);
986 wpanStats->set_mac_rx_fail_unknown_neighbor(linkCounters->mRxErrUnknownNeighbor);
987 wpanStats->set_mac_rx_fail_invalid_src_addr(linkCounters->mRxErrInvalidSrcAddr);
988 wpanStats->set_mac_rx_fail_fcs(linkCounters->mRxErrFcs);
989 wpanStats->set_mac_rx_fail_other(linkCounters->mRxErrOther);
990 }
991
992 {
993 const otIpCounters *ipCounters = otThreadGetIp6Counters(mInstance);
994
995 wpanStats->set_ip_tx_success(ipCounters->mTxSuccess);
996 wpanStats->set_ip_rx_success(ipCounters->mRxSuccess);
997 wpanStats->set_ip_tx_failure(ipCounters->mTxFailure);
998 wpanStats->set_ip_rx_failure(ipCounters->mRxFailure);
999 }
1000 // End of WpanStats section.
1001
1002 {
1003 // Begin of WpanTopoFull section.
1004 auto wpanTopoFull = telemetryData.mutable_wpan_topo_full();
1005 uint16_t rloc16 = otThreadGetRloc16(mInstance);
1006
1007 wpanTopoFull->set_rloc16(rloc16);
1008
1009 {
1010 otRouterInfo info;
1011
1012 if (otThreadGetRouterInfo(mInstance, rloc16, &info) == OT_ERROR_NONE)
1013 {
1014 wpanTopoFull->set_router_id(info.mRouterId);
1015 }
1016 else
1017 {
1018 error = OT_ERROR_FAILED;
1019 }
1020 }
1021
1022 otNeighborInfoIterator iter = OT_NEIGHBOR_INFO_ITERATOR_INIT;
1023 otNeighborInfo neighborInfo;
1024
1025 while (otThreadGetNextNeighborInfo(mInstance, &iter, &neighborInfo) == OT_ERROR_NONE)
1026 {
1027 neighborTable.push_back(neighborInfo);
1028 }
1029 wpanTopoFull->set_neighbor_table_size(neighborTable.size());
1030
1031 uint16_t childIndex = 0;
1032 otChildInfo childInfo;
1033 std::vector<otChildInfo> childTable;
1034
1035 while (otThreadGetChildInfoByIndex(mInstance, childIndex, &childInfo) == OT_ERROR_NONE)
1036 {
1037 childTable.push_back(childInfo);
1038 childIndex++;
1039 }
1040 wpanTopoFull->set_child_table_size(childTable.size());
1041
1042 {
1043 struct otLeaderData leaderData;
1044
1045 if (otThreadGetLeaderData(mInstance, &leaderData) == OT_ERROR_NONE)
1046 {
1047 wpanTopoFull->set_leader_router_id(leaderData.mLeaderRouterId);
1048 wpanTopoFull->set_leader_weight(leaderData.mWeighting);
1049 wpanTopoFull->set_network_data_version(leaderData.mDataVersion);
1050 wpanTopoFull->set_stable_network_data_version(leaderData.mStableDataVersion);
1051 }
1052 else
1053 {
1054 error = OT_ERROR_FAILED;
1055 }
1056 }
1057
1058 uint8_t weight = otThreadGetLocalLeaderWeight(mInstance);
1059
1060 wpanTopoFull->set_leader_local_weight(weight);
1061
1062 uint32_t partitionId = otThreadGetPartitionId(mInstance);
1063
1064 wpanTopoFull->set_partition_id(partitionId);
1065
1066 static constexpr size_t kNetworkDataMaxSize = 255;
1067 {
1068 uint8_t data[kNetworkDataMaxSize];
1069 uint8_t len = sizeof(data);
1070 std::vector<uint8_t> networkData;
1071
1072 if (otNetDataGet(mInstance, /*stable=*/false, data, &len) == OT_ERROR_NONE)
1073 {
1074 networkData = std::vector<uint8_t>(&data[0], &data[len]);
1075 wpanTopoFull->set_network_data(std::string(networkData.begin(), networkData.end()));
1076 }
1077 else
1078 {
1079 error = OT_ERROR_FAILED;
1080 }
1081 }
1082
1083 {
1084 uint8_t data[kNetworkDataMaxSize];
1085 uint8_t len = sizeof(data);
1086 std::vector<uint8_t> networkData;
1087
1088 if (otNetDataGet(mInstance, /*stable=*/true, data, &len) == OT_ERROR_NONE)
1089 {
1090 networkData = std::vector<uint8_t>(&data[0], &data[len]);
1091 wpanTopoFull->set_stable_network_data(std::string(networkData.begin(), networkData.end()));
1092 }
1093 else
1094 {
1095 error = OT_ERROR_FAILED;
1096 }
1097 }
1098
1099 int8_t rssi = otPlatRadioGetRssi(mInstance);
1100
1101 wpanTopoFull->set_instant_rssi(rssi);
1102
1103 const otExtendedPanId *extPanId = otThreadGetExtendedPanId(mInstance);
1104 uint64_t extPanIdVal;
1105
1106 extPanIdVal = ConvertOpenThreadUint64(extPanId->m8);
1107 wpanTopoFull->set_extended_pan_id(extPanIdVal);
1108 // End of WpanTopoFull section.
1109
1110 // Begin of TopoEntry section.
1111 std::map<uint16_t, const otChildInfo *> childMap;
1112
1113 for (const otChildInfo &childInfo : childTable)
1114 {
1115 auto pair = childMap.insert({childInfo.mRloc16, &childInfo});
1116 if (!pair.second)
1117 {
1118 // This shouldn't happen, so log an error. It doesn't matter which
1119 // duplicate is kept.
1120 otbrLogErr("Children with duplicate RLOC16 found: 0x%04x", static_cast<int>(childInfo.mRloc16));
1121 }
1122 }
1123
1124 for (const otNeighborInfo &neighborInfo : neighborTable)
1125 {
1126 auto topoEntry = telemetryData.add_topo_entries();
1127 topoEntry->set_rloc16(neighborInfo.mRloc16);
1128 topoEntry->mutable_age()->set_seconds(neighborInfo.mAge);
1129 topoEntry->set_link_quality_in(neighborInfo.mLinkQualityIn);
1130 topoEntry->set_average_rssi(neighborInfo.mAverageRssi);
1131 topoEntry->set_last_rssi(neighborInfo.mLastRssi);
1132 topoEntry->set_link_frame_counter(neighborInfo.mLinkFrameCounter);
1133 topoEntry->set_mle_frame_counter(neighborInfo.mMleFrameCounter);
1134 topoEntry->set_rx_on_when_idle(neighborInfo.mRxOnWhenIdle);
1135 topoEntry->set_secure_data_request(true);
1136 topoEntry->set_full_function(neighborInfo.mFullThreadDevice);
1137 topoEntry->set_full_network_data(neighborInfo.mFullNetworkData);
1138 topoEntry->set_mac_frame_error_rate(static_cast<float>(neighborInfo.mFrameErrorRate) / 0xffff);
1139 topoEntry->set_ip_message_error_rate(static_cast<float>(neighborInfo.mMessageErrorRate) / 0xffff);
1140 topoEntry->set_version(neighborInfo.mVersion);
1141
1142 if (!neighborInfo.mIsChild)
1143 {
1144 continue;
1145 }
1146
1147 auto it = childMap.find(neighborInfo.mRloc16);
1148 if (it == childMap.end())
1149 {
1150 otbrLogErr("Neighbor 0x%04x not found in child table", static_cast<int>(neighborInfo.mRloc16));
1151 continue;
1152 }
1153 const otChildInfo *childInfo = it->second;
1154 topoEntry->set_is_child(true);
1155 topoEntry->mutable_timeout()->set_seconds(childInfo->mTimeout);
1156 topoEntry->set_network_data_version(childInfo->mNetworkDataVersion);
1157 }
1158 // End of TopoEntry section.
1159 }
1160
1161 {
1162 // Begin of WpanBorderRouter section.
1163 auto wpanBorderRouter = telemetryData.mutable_wpan_border_router();
1164 // Begin of BorderRoutingCounters section.
1165 auto borderRoutingCouters = wpanBorderRouter->mutable_border_routing_counters();
1166 const otBorderRoutingCounters *otBorderRoutingCounters = otIp6GetBorderRoutingCounters(mInstance);
1167
1168 borderRoutingCouters->mutable_inbound_unicast()->set_packet_count(
1169 otBorderRoutingCounters->mInboundUnicast.mPackets);
1170 borderRoutingCouters->mutable_inbound_unicast()->set_byte_count(
1171 otBorderRoutingCounters->mInboundUnicast.mBytes);
1172 borderRoutingCouters->mutable_inbound_multicast()->set_packet_count(
1173 otBorderRoutingCounters->mInboundMulticast.mPackets);
1174 borderRoutingCouters->mutable_inbound_multicast()->set_byte_count(
1175 otBorderRoutingCounters->mInboundMulticast.mBytes);
1176 borderRoutingCouters->mutable_outbound_unicast()->set_packet_count(
1177 otBorderRoutingCounters->mOutboundUnicast.mPackets);
1178 borderRoutingCouters->mutable_outbound_unicast()->set_byte_count(
1179 otBorderRoutingCounters->mOutboundUnicast.mBytes);
1180 borderRoutingCouters->mutable_outbound_multicast()->set_packet_count(
1181 otBorderRoutingCounters->mOutboundMulticast.mPackets);
1182 borderRoutingCouters->mutable_outbound_multicast()->set_byte_count(
1183 otBorderRoutingCounters->mOutboundMulticast.mBytes);
1184 borderRoutingCouters->set_ra_rx(otBorderRoutingCounters->mRaRx);
1185 borderRoutingCouters->set_ra_tx_success(otBorderRoutingCounters->mRaTxSuccess);
1186 borderRoutingCouters->set_ra_tx_failure(otBorderRoutingCounters->mRaTxFailure);
1187 borderRoutingCouters->set_rs_rx(otBorderRoutingCounters->mRsRx);
1188 borderRoutingCouters->set_rs_tx_success(otBorderRoutingCounters->mRsTxSuccess);
1189 borderRoutingCouters->set_rs_tx_failure(otBorderRoutingCounters->mRsTxFailure);
1190 borderRoutingCouters->mutable_inbound_internet()->set_packet_count(
1191 otBorderRoutingCounters->mInboundInternet.mPackets);
1192 borderRoutingCouters->mutable_inbound_internet()->set_byte_count(
1193 otBorderRoutingCounters->mInboundInternet.mBytes);
1194 borderRoutingCouters->mutable_outbound_internet()->set_packet_count(
1195 otBorderRoutingCounters->mOutboundInternet.mPackets);
1196 borderRoutingCouters->mutable_outbound_internet()->set_byte_count(
1197 otBorderRoutingCounters->mOutboundInternet.mBytes);
1198
1199 #if OTBR_ENABLE_NAT64
1200 {
1201 auto nat64IcmpCounters = borderRoutingCouters->mutable_nat64_protocol_counters()->mutable_icmp();
1202 auto nat64UdpCounters = borderRoutingCouters->mutable_nat64_protocol_counters()->mutable_udp();
1203 auto nat64TcpCounters = borderRoutingCouters->mutable_nat64_protocol_counters()->mutable_tcp();
1204 otNat64ProtocolCounters otCounters;
1205
1206 otNat64GetCounters(mInstance, &otCounters);
1207 nat64IcmpCounters->set_ipv4_to_ipv6_packets(otCounters.mIcmp.m4To6Packets);
1208 nat64IcmpCounters->set_ipv4_to_ipv6_bytes(otCounters.mIcmp.m4To6Bytes);
1209 nat64IcmpCounters->set_ipv6_to_ipv4_packets(otCounters.mIcmp.m6To4Packets);
1210 nat64IcmpCounters->set_ipv6_to_ipv4_bytes(otCounters.mIcmp.m6To4Bytes);
1211 nat64UdpCounters->set_ipv4_to_ipv6_packets(otCounters.mUdp.m4To6Packets);
1212 nat64UdpCounters->set_ipv4_to_ipv6_bytes(otCounters.mUdp.m4To6Bytes);
1213 nat64UdpCounters->set_ipv6_to_ipv4_packets(otCounters.mUdp.m6To4Packets);
1214 nat64UdpCounters->set_ipv6_to_ipv4_bytes(otCounters.mUdp.m6To4Bytes);
1215 nat64TcpCounters->set_ipv4_to_ipv6_packets(otCounters.mTcp.m4To6Packets);
1216 nat64TcpCounters->set_ipv4_to_ipv6_bytes(otCounters.mTcp.m4To6Bytes);
1217 nat64TcpCounters->set_ipv6_to_ipv4_packets(otCounters.mTcp.m6To4Packets);
1218 nat64TcpCounters->set_ipv6_to_ipv4_bytes(otCounters.mTcp.m6To4Bytes);
1219 }
1220
1221 {
1222 auto errorCounters = borderRoutingCouters->mutable_nat64_error_counters();
1223 otNat64ErrorCounters otCounters;
1224 otNat64GetErrorCounters(mInstance, &otCounters);
1225
1226 errorCounters->mutable_unknown()->set_ipv4_to_ipv6_packets(
1227 otCounters.mCount4To6[OT_NAT64_DROP_REASON_UNKNOWN]);
1228 errorCounters->mutable_unknown()->set_ipv6_to_ipv4_packets(
1229 otCounters.mCount6To4[OT_NAT64_DROP_REASON_UNKNOWN]);
1230 errorCounters->mutable_illegal_packet()->set_ipv4_to_ipv6_packets(
1231 otCounters.mCount4To6[OT_NAT64_DROP_REASON_ILLEGAL_PACKET]);
1232 errorCounters->mutable_illegal_packet()->set_ipv6_to_ipv4_packets(
1233 otCounters.mCount6To4[OT_NAT64_DROP_REASON_ILLEGAL_PACKET]);
1234 errorCounters->mutable_unsupported_protocol()->set_ipv4_to_ipv6_packets(
1235 otCounters.mCount4To6[OT_NAT64_DROP_REASON_UNSUPPORTED_PROTO]);
1236 errorCounters->mutable_unsupported_protocol()->set_ipv6_to_ipv4_packets(
1237 otCounters.mCount6To4[OT_NAT64_DROP_REASON_UNSUPPORTED_PROTO]);
1238 errorCounters->mutable_no_mapping()->set_ipv4_to_ipv6_packets(
1239 otCounters.mCount4To6[OT_NAT64_DROP_REASON_NO_MAPPING]);
1240 errorCounters->mutable_no_mapping()->set_ipv6_to_ipv4_packets(
1241 otCounters.mCount6To4[OT_NAT64_DROP_REASON_NO_MAPPING]);
1242 }
1243 #endif // OTBR_ENABLE_NAT64
1244 // End of BorderRoutingCounters section.
1245
1246 #if OTBR_ENABLE_TREL
1247 // Begin of TrelInfo section.
1248 {
1249 auto trelInfo = wpanBorderRouter->mutable_trel_info();
1250 auto otTrelCounters = otTrelGetCounters(mInstance);
1251 auto trelCounters = trelInfo->mutable_counters();
1252
1253 trelInfo->set_is_trel_enabled(otTrelIsEnabled(mInstance));
1254 trelInfo->set_num_trel_peers(otTrelGetNumberOfPeers(mInstance));
1255
1256 trelCounters->set_trel_tx_packets(otTrelCounters->mTxPackets);
1257 trelCounters->set_trel_tx_bytes(otTrelCounters->mTxBytes);
1258 trelCounters->set_trel_tx_packets_failed(otTrelCounters->mTxFailure);
1259 trelCounters->set_tre_rx_packets(otTrelCounters->mRxPackets);
1260 trelCounters->set_trel_rx_bytes(otTrelCounters->mRxBytes);
1261 }
1262 // End of TrelInfo section.
1263 #endif // OTBR_ENABLE_TREL
1264
1265 #if OTBR_ENABLE_SRP_ADVERTISING_PROXY
1266 // Begin of SrpServerInfo section.
1267 {
1268 auto srpServer = wpanBorderRouter->mutable_srp_server();
1269 otSrpServerLeaseInfo leaseInfo;
1270 const otSrpServerHost *host = nullptr;
1271 const otSrpServerResponseCounters *responseCounters = otSrpServerGetResponseCounters(mInstance);
1272
1273 srpServer->set_state(SrpServerStateFromOtSrpServerState(otSrpServerGetState(mInstance)));
1274 srpServer->set_port(otSrpServerGetPort(mInstance));
1275 srpServer->set_address_mode(
1276 SrpServerAddressModeFromOtSrpServerAddressMode(otSrpServerGetAddressMode(mInstance)));
1277
1278 auto srpServerHosts = srpServer->mutable_hosts();
1279 auto srpServerServices = srpServer->mutable_services();
1280 auto srpServerResponseCounters = srpServer->mutable_response_counters();
1281
1282 while ((host = otSrpServerGetNextHost(mInstance, host)))
1283 {
1284 const otSrpServerService *service = nullptr;
1285
1286 if (otSrpServerHostIsDeleted(host))
1287 {
1288 srpServerHosts->set_deleted_count(srpServerHosts->deleted_count() + 1);
1289 }
1290 else
1291 {
1292 srpServerHosts->set_fresh_count(srpServerHosts->fresh_count() + 1);
1293 otSrpServerHostGetLeaseInfo(host, &leaseInfo);
1294 srpServerHosts->set_lease_time_total_ms(srpServerHosts->lease_time_total_ms() + leaseInfo.mLease);
1295 srpServerHosts->set_key_lease_time_total_ms(srpServerHosts->key_lease_time_total_ms() +
1296 leaseInfo.mKeyLease);
1297 srpServerHosts->set_remaining_lease_time_total_ms(srpServerHosts->remaining_lease_time_total_ms() +
1298 leaseInfo.mRemainingLease);
1299 srpServerHosts->set_remaining_key_lease_time_total_ms(
1300 srpServerHosts->remaining_key_lease_time_total_ms() + leaseInfo.mRemainingKeyLease);
1301 }
1302
1303 while ((service = otSrpServerHostGetNextService(host, service)))
1304 {
1305 if (otSrpServerServiceIsDeleted(service))
1306 {
1307 srpServerServices->set_deleted_count(srpServerServices->deleted_count() + 1);
1308 }
1309 else
1310 {
1311 srpServerServices->set_fresh_count(srpServerServices->fresh_count() + 1);
1312 otSrpServerServiceGetLeaseInfo(service, &leaseInfo);
1313 srpServerServices->set_lease_time_total_ms(srpServerServices->lease_time_total_ms() +
1314 leaseInfo.mLease);
1315 srpServerServices->set_key_lease_time_total_ms(srpServerServices->key_lease_time_total_ms() +
1316 leaseInfo.mKeyLease);
1317 srpServerServices->set_remaining_lease_time_total_ms(
1318 srpServerServices->remaining_lease_time_total_ms() + leaseInfo.mRemainingLease);
1319 srpServerServices->set_remaining_key_lease_time_total_ms(
1320 srpServerServices->remaining_key_lease_time_total_ms() + leaseInfo.mRemainingKeyLease);
1321 }
1322 }
1323 }
1324
1325 srpServerResponseCounters->set_success_count(responseCounters->mSuccess);
1326 srpServerResponseCounters->set_server_failure_count(responseCounters->mServerFailure);
1327 srpServerResponseCounters->set_format_error_count(responseCounters->mFormatError);
1328 srpServerResponseCounters->set_name_exists_count(responseCounters->mNameExists);
1329 srpServerResponseCounters->set_refused_count(responseCounters->mRefused);
1330 srpServerResponseCounters->set_other_count(responseCounters->mOther);
1331 }
1332 // End of SrpServerInfo section.
1333 #endif // OTBR_ENABLE_SRP_ADVERTISING_PROXY
1334
1335 #if OTBR_ENABLE_DNSSD_DISCOVERY_PROXY
1336 // Begin of DnsServerInfo section.
1337 {
1338 auto dnsServer = wpanBorderRouter->mutable_dns_server();
1339 auto dnsServerResponseCounters = dnsServer->mutable_response_counters();
1340 otDnssdCounters otDnssdCounters = *otDnssdGetCounters(mInstance);
1341
1342 dnsServerResponseCounters->set_success_count(otDnssdCounters.mSuccessResponse);
1343 dnsServerResponseCounters->set_server_failure_count(otDnssdCounters.mServerFailureResponse);
1344 dnsServerResponseCounters->set_format_error_count(otDnssdCounters.mFormatErrorResponse);
1345 dnsServerResponseCounters->set_name_error_count(otDnssdCounters.mNameErrorResponse);
1346 dnsServerResponseCounters->set_not_implemented_count(otDnssdCounters.mNotImplementedResponse);
1347 dnsServerResponseCounters->set_other_count(otDnssdCounters.mOtherResponse);
1348 // The counters of queries, responses, failures handled by upstream DNS server.
1349 dnsServerResponseCounters->set_upstream_dns_queries(otDnssdCounters.mUpstreamDnsCounters.mQueries);
1350 dnsServerResponseCounters->set_upstream_dns_responses(otDnssdCounters.mUpstreamDnsCounters.mResponses);
1351 dnsServerResponseCounters->set_upstream_dns_failures(otDnssdCounters.mUpstreamDnsCounters.mFailures);
1352
1353 dnsServer->set_resolved_by_local_srp_count(otDnssdCounters.mResolvedBySrp);
1354
1355 #if OTBR_ENABLE_DNS_UPSTREAM_QUERY
1356 dnsServer->set_upstream_dns_query_state(
1357 otDnssdUpstreamQueryIsEnabled(mInstance)
1358 ? threadnetwork::TelemetryData::UPSTREAMDNS_QUERY_STATE_ENABLED
1359 : threadnetwork::TelemetryData::UPSTREAMDNS_QUERY_STATE_DISABLED);
1360 #endif // OTBR_ENABLE_DNS_UPSTREAM_QUERY
1361 }
1362 // End of DnsServerInfo section.
1363 #endif // OTBR_ENABLE_DNSSD_DISCOVERY_PROXY
1364
1365 // Start of MdnsInfo section.
1366 if (aPublisher != nullptr)
1367 {
1368 auto mdns = wpanBorderRouter->mutable_mdns();
1369 const MdnsTelemetryInfo &mdnsInfo = aPublisher->GetMdnsTelemetryInfo();
1370
1371 CopyMdnsResponseCounters(mdnsInfo.mHostRegistrations, mdns->mutable_host_registration_responses());
1372 CopyMdnsResponseCounters(mdnsInfo.mServiceRegistrations, mdns->mutable_service_registration_responses());
1373 CopyMdnsResponseCounters(mdnsInfo.mHostResolutions, mdns->mutable_host_resolution_responses());
1374 CopyMdnsResponseCounters(mdnsInfo.mServiceResolutions, mdns->mutable_service_resolution_responses());
1375
1376 mdns->set_host_registration_ema_latency_ms(mdnsInfo.mHostRegistrationEmaLatency);
1377 mdns->set_service_registration_ema_latency_ms(mdnsInfo.mServiceRegistrationEmaLatency);
1378 mdns->set_host_resolution_ema_latency_ms(mdnsInfo.mHostResolutionEmaLatency);
1379 mdns->set_service_resolution_ema_latency_ms(mdnsInfo.mServiceResolutionEmaLatency);
1380 }
1381 // End of MdnsInfo section.
1382
1383 #if OTBR_ENABLE_NAT64
1384 // Start of BorderRoutingNat64State section.
1385 {
1386 auto nat64State = wpanBorderRouter->mutable_nat64_state();
1387
1388 nat64State->set_prefix_manager_state(Nat64StateFromOtNat64State(otNat64GetPrefixManagerState(mInstance)));
1389 nat64State->set_translator_state(Nat64StateFromOtNat64State(otNat64GetTranslatorState(mInstance)));
1390 }
1391 // End of BorderRoutingNat64State section.
1392
1393 // Start of Nat64Mapping section.
1394 {
1395 otNat64AddressMappingIterator iterator;
1396 otNat64AddressMapping otMapping;
1397 Sha256::Hash hash;
1398 Sha256 sha256;
1399
1400 otNat64InitAddressMappingIterator(mInstance, &iterator);
1401 while (otNat64GetNextAddressMapping(mInstance, &iterator, &otMapping) == OT_ERROR_NONE)
1402 {
1403 auto nat64Mapping = wpanBorderRouter->add_nat64_mappings();
1404 auto nat64MappingCounters = nat64Mapping->mutable_counters();
1405
1406 nat64Mapping->set_mapping_id(otMapping.mId);
1407 CopyNat64TrafficCounters(otMapping.mCounters.mTcp, nat64MappingCounters->mutable_tcp());
1408 CopyNat64TrafficCounters(otMapping.mCounters.mUdp, nat64MappingCounters->mutable_udp());
1409 CopyNat64TrafficCounters(otMapping.mCounters.mIcmp, nat64MappingCounters->mutable_icmp());
1410
1411 sha256.Start();
1412 sha256.Update(otMapping.mIp6.mFields.m8, sizeof(otMapping.mIp6.mFields.m8));
1413 sha256.Update(mNat64PdCommonSalt, sizeof(mNat64PdCommonSalt));
1414 sha256.Finish(hash);
1415
1416 nat64Mapping->mutable_hashed_ipv6_address()->append(reinterpret_cast<const char *>(hash.GetBytes()),
1417 Sha256::Hash::kSize);
1418 // Remaining time is not included in the telemetry
1419 }
1420 }
1421 // End of Nat64Mapping section.
1422 #endif // OTBR_ENABLE_NAT64
1423 #if OTBR_ENABLE_DHCP6_PD
1424 // Start of Dhcp6PdState section.
1425 wpanBorderRouter->set_dhcp6_pd_state(Dhcp6PdStateFromOtDhcp6PdState(otBorderRoutingDhcp6PdGetState(mInstance)));
1426 // End of Dhcp6PdState section.
1427
1428 // Start of Hashed PD prefix
1429 {
1430 otBorderRoutingPrefixTableEntry aPrefixInfo;
1431 const uint8_t *prefixAddr = nullptr;
1432 const uint8_t *truncatedHash = nullptr;
1433 constexpr size_t kHashPrefixLength = 6;
1434 constexpr size_t kHashedPrefixLength = 2;
1435 std::vector<uint8_t> hashedPdHeader = {0x20, 0x01, 0x0d, 0xb8};
1436 std::vector<uint8_t> hashedPdTailer = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1437 std::vector<uint8_t> hashedPdPrefix;
1438 hashedPdPrefix.reserve(16);
1439 Sha256 sha256;
1440 Sha256::Hash hash;
1441
1442 otBorderRoutingGetPdOmrPrefix(mInstance, &aPrefixInfo);
1443 prefixAddr = aPrefixInfo.mPrefix.mPrefix.mFields.m8;
1444
1445 // TODO: Put below steps into a reusable function.
1446 sha256.Start();
1447 sha256.Update(prefixAddr, kHashPrefixLength);
1448 sha256.Update(mNat64PdCommonSalt, kNat64PdCommonHashSaltLength);
1449 sha256.Finish(hash);
1450
1451 // Append hashedPdHeader
1452 hashedPdPrefix.insert(hashedPdPrefix.end(), hashedPdHeader.begin(), hashedPdHeader.end());
1453
1454 // Append the first 2 bytes of the hashed prefix
1455 truncatedHash = hash.GetBytes();
1456 hashedPdPrefix.insert(hashedPdPrefix.end(), truncatedHash, truncatedHash + kHashedPrefixLength);
1457
1458 // Append ip[6] and ip[7]
1459 hashedPdPrefix.push_back(prefixAddr[6]);
1460 hashedPdPrefix.push_back(prefixAddr[7]);
1461
1462 // Append hashedPdTailer
1463 hashedPdPrefix.insert(hashedPdPrefix.end(), hashedPdTailer.begin(), hashedPdTailer.end());
1464
1465 wpanBorderRouter->mutable_hashed_pd_prefix()->append(reinterpret_cast<const char *>(hashedPdPrefix.data()),
1466 hashedPdPrefix.size());
1467 }
1468 // End of Hashed PD prefix
1469 // Start of DHCPv6 PD processed RA Info
1470 {
1471 auto pdProcessedRaInfo = wpanBorderRouter->mutable_pd_processed_ra_info();
1472 otPdProcessedRaInfo raInfo;
1473
1474 otBorderRoutingGetPdProcessedRaInfo(mInstance, &raInfo);
1475 pdProcessedRaInfo->set_num_platform_ra_received(raInfo.mNumPlatformRaReceived);
1476 pdProcessedRaInfo->set_num_platform_pio_processed(raInfo.mNumPlatformPioProcessed);
1477 pdProcessedRaInfo->set_last_platform_ra_msec(raInfo.mLastPlatformRaMsec);
1478 }
1479 // End of DHCPv6 PD processed RA Info
1480 #endif // OTBR_ENABLE_DHCP6_PD
1481 // End of WpanBorderRouter section.
1482
1483 // Start of WpanRcp section.
1484 {
1485 auto wpanRcp = telemetryData.mutable_wpan_rcp();
1486 const otRadioSpinelMetrics *otRadioSpinelMetrics = otSysGetRadioSpinelMetrics();
1487 auto rcpStabilityStatistics = wpanRcp->mutable_rcp_stability_statistics();
1488
1489 if (otRadioSpinelMetrics != nullptr)
1490 {
1491 rcpStabilityStatistics->set_rcp_timeout_count(otRadioSpinelMetrics->mRcpTimeoutCount);
1492 rcpStabilityStatistics->set_rcp_reset_count(otRadioSpinelMetrics->mRcpUnexpectedResetCount);
1493 rcpStabilityStatistics->set_rcp_restoration_count(otRadioSpinelMetrics->mRcpRestorationCount);
1494 rcpStabilityStatistics->set_spinel_parse_error_count(otRadioSpinelMetrics->mSpinelParseErrorCount);
1495 }
1496
1497 // TODO: provide rcp_firmware_update_count info.
1498 rcpStabilityStatistics->set_thread_stack_uptime(otInstanceGetUptime(mInstance));
1499
1500 const otRcpInterfaceMetrics *otRcpInterfaceMetrics = otSysGetRcpInterfaceMetrics();
1501
1502 if (otRcpInterfaceMetrics != nullptr)
1503 {
1504 auto rcpInterfaceStatistics = wpanRcp->mutable_rcp_interface_statistics();
1505
1506 rcpInterfaceStatistics->set_rcp_interface_type(otRcpInterfaceMetrics->mRcpInterfaceType);
1507 rcpInterfaceStatistics->set_transferred_frames_count(otRcpInterfaceMetrics->mTransferredFrameCount);
1508 rcpInterfaceStatistics->set_transferred_valid_frames_count(
1509 otRcpInterfaceMetrics->mTransferredValidFrameCount);
1510 rcpInterfaceStatistics->set_transferred_garbage_frames_count(
1511 otRcpInterfaceMetrics->mTransferredGarbageFrameCount);
1512 rcpInterfaceStatistics->set_rx_frames_count(otRcpInterfaceMetrics->mRxFrameCount);
1513 rcpInterfaceStatistics->set_rx_bytes_count(otRcpInterfaceMetrics->mRxFrameByteCount);
1514 rcpInterfaceStatistics->set_tx_frames_count(otRcpInterfaceMetrics->mTxFrameCount);
1515 rcpInterfaceStatistics->set_tx_bytes_count(otRcpInterfaceMetrics->mTxFrameByteCount);
1516 }
1517 }
1518 // End of WpanRcp section.
1519
1520 // Start of CoexMetrics section.
1521 {
1522 auto coexMetrics = telemetryData.mutable_coex_metrics();
1523 otRadioCoexMetrics otRadioCoexMetrics;
1524
1525 if (otPlatRadioGetCoexMetrics(mInstance, &otRadioCoexMetrics) == OT_ERROR_NONE)
1526 {
1527 coexMetrics->set_count_tx_request(otRadioCoexMetrics.mNumTxRequest);
1528 coexMetrics->set_count_tx_grant_immediate(otRadioCoexMetrics.mNumTxGrantImmediate);
1529 coexMetrics->set_count_tx_grant_wait(otRadioCoexMetrics.mNumTxGrantWait);
1530 coexMetrics->set_count_tx_grant_wait_activated(otRadioCoexMetrics.mNumTxGrantWaitActivated);
1531 coexMetrics->set_count_tx_grant_wait_timeout(otRadioCoexMetrics.mNumTxGrantWaitTimeout);
1532 coexMetrics->set_count_tx_grant_deactivated_during_request(
1533 otRadioCoexMetrics.mNumTxGrantDeactivatedDuringRequest);
1534 coexMetrics->set_tx_average_request_to_grant_time_us(otRadioCoexMetrics.mAvgTxRequestToGrantTime);
1535 coexMetrics->set_count_rx_request(otRadioCoexMetrics.mNumRxRequest);
1536 coexMetrics->set_count_rx_grant_immediate(otRadioCoexMetrics.mNumRxGrantImmediate);
1537 coexMetrics->set_count_rx_grant_wait(otRadioCoexMetrics.mNumRxGrantWait);
1538 coexMetrics->set_count_rx_grant_wait_activated(otRadioCoexMetrics.mNumRxGrantWaitActivated);
1539 coexMetrics->set_count_rx_grant_wait_timeout(otRadioCoexMetrics.mNumRxGrantWaitTimeout);
1540 coexMetrics->set_count_rx_grant_deactivated_during_request(
1541 otRadioCoexMetrics.mNumRxGrantDeactivatedDuringRequest);
1542 coexMetrics->set_count_rx_grant_none(otRadioCoexMetrics.mNumRxGrantNone);
1543 coexMetrics->set_rx_average_request_to_grant_time_us(otRadioCoexMetrics.mAvgRxRequestToGrantTime);
1544 }
1545 else
1546 {
1547 error = OT_ERROR_FAILED;
1548 }
1549 }
1550 // End of CoexMetrics section.
1551 }
1552
1553 #if OTBR_ENABLE_LINK_METRICS_TELEMETRY
1554 {
1555 auto lowPowerMetrics = telemetryData.mutable_low_power_metrics();
1556 // Begin of Link Metrics section.
1557 for (const otNeighborInfo &neighborInfo : neighborTable)
1558 {
1559 otError query_error;
1560 otLinkMetricsValues values;
1561
1562 query_error = otLinkMetricsManagerGetMetricsValueByExtAddr(mInstance, &neighborInfo.mExtAddress, &values);
1563 // Some neighbors don't support Link Metrics Subject feature. So it's expected that some other errors
1564 // are returned.
1565 if (query_error == OT_ERROR_NONE)
1566 {
1567 auto linkMetricsStats = lowPowerMetrics->add_link_metrics_entries();
1568 linkMetricsStats->set_link_margin(values.mLinkMarginValue);
1569 linkMetricsStats->set_rssi(values.mRssiValue);
1570 }
1571 }
1572 }
1573 #endif // OTBR_ENABLE_LINK_METRICS_TELEMETRY
1574
1575 return error;
1576 }
1577 #endif // OTBR_ENABLE_TELEMETRY_DATA_API
1578 } // namespace agent
1579 } // namespace otbr
1580