• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &currentTime);
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