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