• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *    Copyright (c) 2023, The OpenThread Authors.
3  *    All rights reserved.
4  *
5  *    Redistribution and use in source and binary forms, with or without
6  *    modification, are permitted provided that the following conditions are met:
7  *    1. Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *    2. Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *    3. Neither the name of the copyright holder nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *    POSSIBILITY OF SUCH DAMAGE.
27  */
28 #include "android/otdaemon_telemetry.hpp"
29 
30 #include <openthread/openthread-system.h>
31 #include <openthread/thread.h>
32 #include <openthread/thread_ftd.h>
33 #include <openthread/platform/radio.h>
34 
35 #if OTBR_ENABLE_DNSSD_DISCOVERY_PROXY
36 #include <openthread/dnssd_server.h>
37 #endif
38 #if OTBR_ENABLE_SRP_ADVERTISING_PROXY
39 #include <openthread/srp_server.h>
40 #endif
41 
42 #include "statslog_threadnetwork.h"
43 #include "common/code_utils.hpp"
44 #include "mdns/mdns.hpp"
45 #include "proto/threadnetwork_atoms.pb.h"
46 
47 namespace otbr {
48 namespace Android {
49 using android::os::statsd::threadnetwork::ThreadnetworkDeviceInfoReported;
50 using android::os::statsd::threadnetwork::ThreadnetworkTelemetryDataReported;
51 using android::os::statsd::threadnetwork::ThreadnetworkTopoEntryRepeated;
52 
TelemetryNodeTypeFromRoleAndLinkMode(const otDeviceRole & aRole,const otLinkModeConfig & aLinkModeCfg)53 static uint32_t TelemetryNodeTypeFromRoleAndLinkMode(const otDeviceRole &aRole, const otLinkModeConfig &aLinkModeCfg)
54 {
55     uint32_t nodeType;
56 
57     switch (aRole)
58     {
59     case OT_DEVICE_ROLE_DISABLED:
60         nodeType = ThreadnetworkTelemetryDataReported::NODE_TYPE_DISABLED;
61         break;
62     case OT_DEVICE_ROLE_DETACHED:
63         nodeType = ThreadnetworkTelemetryDataReported::NODE_TYPE_DETACHED;
64         break;
65     case OT_DEVICE_ROLE_ROUTER:
66         nodeType = ThreadnetworkTelemetryDataReported::NODE_TYPE_ROUTER;
67         break;
68     case OT_DEVICE_ROLE_LEADER:
69         nodeType = ThreadnetworkTelemetryDataReported::NODE_TYPE_LEADER;
70         break;
71     case OT_DEVICE_ROLE_CHILD:
72         if (!aLinkModeCfg.mRxOnWhenIdle)
73         {
74             nodeType = ThreadnetworkTelemetryDataReported::NODE_TYPE_SLEEPY_END;
75         }
76         else if (!aLinkModeCfg.mDeviceType)
77         {
78             // If it's not an FTD, return as minimal end device.
79             nodeType = ThreadnetworkTelemetryDataReported::NODE_TYPE_MINIMAL_END;
80         }
81         else
82         {
83             nodeType = ThreadnetworkTelemetryDataReported::NODE_TYPE_END;
84         }
85         break;
86     default:
87         nodeType = ThreadnetworkTelemetryDataReported::NODE_TYPE_UNSPECIFIED;
88     }
89 
90     return nodeType;
91 }
92 
93 #if OTBR_ENABLE_SRP_ADVERTISING_PROXY
SrpServerStateFromOtSrpServerState(otSrpServerState aSrpServerState)94 ThreadnetworkTelemetryDataReported::SrpServerState SrpServerStateFromOtSrpServerState(otSrpServerState aSrpServerState)
95 {
96     ThreadnetworkTelemetryDataReported::SrpServerState srpServerState;
97 
98     switch (aSrpServerState)
99     {
100     case OT_SRP_SERVER_STATE_DISABLED:
101         srpServerState = ThreadnetworkTelemetryDataReported::SRP_SERVER_STATE_DISABLED;
102         break;
103     case OT_SRP_SERVER_STATE_RUNNING:
104         srpServerState = ThreadnetworkTelemetryDataReported::SRP_SERVER_STATE_RUNNING;
105         break;
106     case OT_SRP_SERVER_STATE_STOPPED:
107         srpServerState = ThreadnetworkTelemetryDataReported::SRP_SERVER_STATE_STOPPED;
108         break;
109     default:
110         srpServerState = ThreadnetworkTelemetryDataReported::SRP_SERVER_STATE_UNSPECIFIED;
111     }
112     return srpServerState;
113 }
114 
SrpServerAddressModeFromOtSrpServerAddressMode(otSrpServerAddressMode aSrpServerAddressMode)115 ThreadnetworkTelemetryDataReported::SrpServerAddressMode SrpServerAddressModeFromOtSrpServerAddressMode(
116     otSrpServerAddressMode aSrpServerAddressMode)
117 {
118     ThreadnetworkTelemetryDataReported::SrpServerAddressMode srpServerAddressMode;
119 
120     switch (aSrpServerAddressMode)
121     {
122     case OT_SRP_SERVER_ADDRESS_MODE_ANYCAST:
123         srpServerAddressMode = ThreadnetworkTelemetryDataReported::SRP_SERVER_ADDRESS_MODE_STATE_ANYCAST;
124         break;
125     case OT_SRP_SERVER_ADDRESS_MODE_UNICAST:
126         srpServerAddressMode = ThreadnetworkTelemetryDataReported::SRP_SERVER_ADDRESS_MODE_UNICAST;
127         break;
128     default:
129         srpServerAddressMode = ThreadnetworkTelemetryDataReported::SRP_SERVER_ADDRESS_MODE_UNSPECIFIED;
130     }
131     return srpServerAddressMode;
132 }
133 #endif // OTBR_ENABLE_SRP_ADVERTISING_PROXY
134 
CopyMdnsResponseCounters(const MdnsResponseCounters & from,ThreadnetworkTelemetryDataReported::MdnsResponseCounters * to)135 void CopyMdnsResponseCounters(const MdnsResponseCounters                               &from,
136                               ThreadnetworkTelemetryDataReported::MdnsResponseCounters *to)
137 {
138     to->set_success_count(from.mSuccess);
139     to->set_not_found_count(from.mNotFound);
140     to->set_invalid_args_count(from.mInvalidArgs);
141     to->set_duplicated_count(from.mDuplicated);
142     to->set_not_implemented_count(from.mNotImplemented);
143     to->set_unknown_error_count(from.mUnknownError);
144     to->set_aborted_count(from.mAborted);
145     to->set_invalid_state_count(from.mInvalidState);
146 }
147 
RetrieveTelemetryAtom(otInstance * otInstance,Mdns::Publisher * aPublisher,ThreadnetworkTelemetryDataReported & telemetryDataReported,ThreadnetworkTopoEntryRepeated & topoEntryRepeated,ThreadnetworkDeviceInfoReported & deviceInfoReported)148 otError RetrieveTelemetryAtom(otInstance                         *otInstance,
149                               Mdns::Publisher                    *aPublisher,
150                               ThreadnetworkTelemetryDataReported &telemetryDataReported,
151                               ThreadnetworkTopoEntryRepeated     &topoEntryRepeated,
152                               ThreadnetworkDeviceInfoReported    &deviceInfoReported)
153 {
154     otError                     error = OT_ERROR_NONE;
155     std::vector<otNeighborInfo> neighborTable;
156 
157     // Begin of WpanStats section.
158     auto wpanStats = telemetryDataReported.mutable_wpan_stats();
159 
160     {
161         otDeviceRole     role  = otThreadGetDeviceRole(otInstance);
162         otLinkModeConfig otCfg = otThreadGetLinkMode(otInstance);
163 
164         wpanStats->set_node_type(TelemetryNodeTypeFromRoleAndLinkMode(role, otCfg));
165     }
166 
167     wpanStats->set_channel(otLinkGetChannel(otInstance));
168 
169     {
170         uint16_t ccaFailureRate = otLinkGetCcaFailureRate(otInstance);
171 
172         wpanStats->set_mac_cca_fail_rate(static_cast<float>(ccaFailureRate) / 0xffff);
173     }
174 
175     {
176         int8_t radioTxPower;
177 
178         if (otPlatRadioGetTransmitPower(otInstance, &radioTxPower) == OT_ERROR_NONE)
179         {
180             wpanStats->set_radio_tx_power(radioTxPower);
181         }
182         else
183         {
184             error = OT_ERROR_FAILED;
185         }
186     }
187 
188     {
189         const otMacCounters *linkCounters = otLinkGetCounters(otInstance);
190 
191         wpanStats->set_phy_rx(linkCounters->mRxTotal);
192         wpanStats->set_phy_tx(linkCounters->mTxTotal);
193         wpanStats->set_mac_unicast_rx(linkCounters->mRxUnicast);
194         wpanStats->set_mac_unicast_tx(linkCounters->mTxUnicast);
195         wpanStats->set_mac_broadcast_rx(linkCounters->mRxBroadcast);
196         wpanStats->set_mac_broadcast_tx(linkCounters->mTxBroadcast);
197         wpanStats->set_mac_tx_ack_req(linkCounters->mTxAckRequested);
198         wpanStats->set_mac_tx_no_ack_req(linkCounters->mTxNoAckRequested);
199         wpanStats->set_mac_tx_acked(linkCounters->mTxAcked);
200         wpanStats->set_mac_tx_data(linkCounters->mTxData);
201         wpanStats->set_mac_tx_data_poll(linkCounters->mTxDataPoll);
202         wpanStats->set_mac_tx_beacon(linkCounters->mTxBeacon);
203         wpanStats->set_mac_tx_beacon_req(linkCounters->mTxBeaconRequest);
204         wpanStats->set_mac_tx_other_pkt(linkCounters->mTxOther);
205         wpanStats->set_mac_tx_retry(linkCounters->mTxRetry);
206         wpanStats->set_mac_rx_data(linkCounters->mRxData);
207         wpanStats->set_mac_rx_data_poll(linkCounters->mRxDataPoll);
208         wpanStats->set_mac_rx_beacon(linkCounters->mRxBeacon);
209         wpanStats->set_mac_rx_beacon_req(linkCounters->mRxBeaconRequest);
210         wpanStats->set_mac_rx_other_pkt(linkCounters->mRxOther);
211         wpanStats->set_mac_rx_filter_whitelist(linkCounters->mRxAddressFiltered);
212         wpanStats->set_mac_rx_filter_dest_addr(linkCounters->mRxDestAddrFiltered);
213         wpanStats->set_mac_tx_fail_cca(linkCounters->mTxErrCca);
214         wpanStats->set_mac_rx_fail_decrypt(linkCounters->mRxErrSec);
215         wpanStats->set_mac_rx_fail_no_frame(linkCounters->mRxErrNoFrame);
216         wpanStats->set_mac_rx_fail_unknown_neighbor(linkCounters->mRxErrUnknownNeighbor);
217         wpanStats->set_mac_rx_fail_invalid_src_addr(linkCounters->mRxErrInvalidSrcAddr);
218         wpanStats->set_mac_rx_fail_fcs(linkCounters->mRxErrFcs);
219         wpanStats->set_mac_rx_fail_other(linkCounters->mRxErrOther);
220     }
221 
222     {
223         const otIpCounters *ipCounters = otThreadGetIp6Counters(otInstance);
224 
225         wpanStats->set_ip_tx_success(ipCounters->mTxSuccess);
226         wpanStats->set_ip_rx_success(ipCounters->mRxSuccess);
227         wpanStats->set_ip_tx_failure(ipCounters->mTxFailure);
228         wpanStats->set_ip_rx_failure(ipCounters->mRxFailure);
229     }
230     // End of WpanStats section.
231 
232     {
233         // Begin of WpanTopoFull section.
234         auto     wpanTopoFull = telemetryDataReported.mutable_wpan_topo_full();
235         uint16_t rloc16       = otThreadGetRloc16(otInstance);
236 
237         wpanTopoFull->set_rloc16(rloc16);
238 
239         {
240             otRouterInfo info;
241 
242             if (otThreadGetRouterInfo(otInstance, rloc16, &info) == OT_ERROR_NONE)
243             {
244                 wpanTopoFull->set_router_id(info.mRouterId);
245             }
246             else
247             {
248                 error = OT_ERROR_FAILED;
249             }
250         }
251 
252         {
253             otNeighborInfoIterator iter = OT_NEIGHBOR_INFO_ITERATOR_INIT;
254             otNeighborInfo         neighborInfo;
255 
256             while (otThreadGetNextNeighborInfo(otInstance, &iter, &neighborInfo) == OT_ERROR_NONE)
257             {
258                 neighborTable.push_back(neighborInfo);
259             }
260         }
261         wpanTopoFull->set_neighbor_table_size(neighborTable.size());
262 
263         uint16_t                 childIndex = 0;
264         otChildInfo              childInfo;
265         std::vector<otChildInfo> childTable;
266 
267         while (otThreadGetChildInfoByIndex(otInstance, childIndex, &childInfo) == OT_ERROR_NONE)
268         {
269             childTable.push_back(childInfo);
270             childIndex++;
271         }
272         wpanTopoFull->set_child_table_size(childTable.size());
273 
274         {
275             struct otLeaderData leaderData;
276 
277             if (otThreadGetLeaderData(otInstance, &leaderData) == OT_ERROR_NONE)
278             {
279                 wpanTopoFull->set_leader_router_id(leaderData.mLeaderRouterId);
280                 wpanTopoFull->set_leader_weight(leaderData.mWeighting);
281                 // Do not log network_data_version.
282             }
283             else
284             {
285                 error = OT_ERROR_FAILED;
286             }
287         }
288 
289         uint8_t weight = otThreadGetLocalLeaderWeight(otInstance);
290 
291         wpanTopoFull->set_leader_local_weight(weight);
292 
293         int8_t rssi = otPlatRadioGetRssi(otInstance);
294 
295         wpanTopoFull->set_instant_rssi(rssi);
296 
297         const otExtendedPanId *extPanId = otThreadGetExtendedPanId(otInstance);
298         uint64_t               extPanIdVal;
299 
300         extPanIdVal = ConvertOpenThreadUint64(extPanId->m8);
301         wpanTopoFull->set_has_extended_pan_id(extPanIdVal != 0);
302         // Note: Used leader_router_id instead of leader_rloc16.
303         // Note: Network level info (e.g., extended_pan_id, partition_id, is_active_br) is not logged.
304         // TODO: populate is_active_srp_server, sum_on_link_prefix_changes, preferred_router_id
305         // if needed.
306         // End of WpanTopoFull section.
307 
308         // Begin of TopoEntry section.
309         std::map<uint16_t, const otChildInfo *> childMap;
310 
311         for (const otChildInfo &childInfo : childTable)
312         {
313             auto pair = childMap.insert({childInfo.mRloc16, &childInfo});
314             if (!pair.second)
315             {
316                 // This shouldn't happen, so log an error. It doesn't matter which
317                 // duplicate is kept.
318                 otbrLogErr("Children with duplicate RLOC16 found: 0x%04x", static_cast<int>(childInfo.mRloc16));
319             }
320         }
321 
322         for (const otNeighborInfo &neighborInfo : neighborTable)
323         {
324             auto topoEntry = topoEntryRepeated.mutable_topo_entry_repeated()->add_topo_entries();
325 
326             // 0~15: uint16_t rloc_16
327             // 16~31: uint16_t version Thread version of the neighbor
328             uint32_t comboTelemetry1 = 0;
329             comboTelemetry1 |= (((uint32_t)neighborInfo.mRloc16) & 0x0000FFFF);
330             comboTelemetry1 |= ((((uint32_t)neighborInfo.mVersion) & 0x0000FFFF) << 16);
331             topoEntry->set_combo_telemetry1(comboTelemetry1);
332 
333             topoEntry->set_age_sec(neighborInfo.mAge);
334 
335             // 0~7: uint8_t link_quality_in
336             // 8~15: int8_t average_rssi
337             // 16~23: int8_t last_rssi
338             // 24~31: uint8_t network_data_version
339             uint32_t comboTelemetry2 = 0;
340             comboTelemetry2 |= (((uint32_t)neighborInfo.mLinkQualityIn) & 0x000000FF);
341             comboTelemetry2 |= ((((uint32_t)neighborInfo.mAverageRssi) & 0x000000FF) << 8);
342             comboTelemetry2 |= ((((uint32_t)neighborInfo.mLastRssi) & 0x000000FF) << 16);
343             // network_data_version is populated in the next section.
344             topoEntry->set_combo_telemetry2(comboTelemetry2);
345 
346             // Each bit on the flag represents a bool flag
347             // 0: rx_on_when_idle
348             // 1: full_function
349             // 2: secure_data_request
350             // 3: full_network_data
351             // 4: is_child
352             uint32_t topoEntryFlags = 0;
353             topoEntryFlags |= (neighborInfo.mRxOnWhenIdle ? 1 : 0);
354             topoEntryFlags |= ((neighborInfo.mFullThreadDevice ? 1 : 0) << 1);
355             topoEntryFlags |= ((/* secure_data_request */ true ? 1 : 0) << 2);
356             topoEntryFlags |= ((neighborInfo.mFullNetworkData ? 1 : 0) << 3);
357             topoEntry->set_topo_entry_flags(topoEntryFlags);
358 
359             topoEntry->set_link_frame_counter(neighborInfo.mLinkFrameCounter);
360             topoEntry->set_mle_frame_counter(neighborInfo.mMleFrameCounter);
361 
362             // 0~15: uint16_t mac_frame_error_rate. Frame error rate (0xffff->100%). Requires error tracking feature.
363             // 16~31: uint16_t ip_message_error_rate. (IPv6) msg error rate (0xffff->100%). Requires error tracking
364             // feature.
365             uint32_t comboTelemetry3 = 0;
366             comboTelemetry3 |= ((uint32_t)(neighborInfo.mFrameErrorRate) & 0x0000FFFF);
367             comboTelemetry3 |= ((((uint32_t)neighborInfo.mMessageErrorRate) & 0x0000FFFF) << 16);
368             topoEntry->set_combo_telemetry3(comboTelemetry3);
369 
370             if (!neighborInfo.mIsChild)
371             {
372                 continue;
373             }
374 
375             auto it = childMap.find(neighborInfo.mRloc16);
376             if (it == childMap.end())
377             {
378                 otbrLogErr("Neighbor 0x%04x not found in child table", static_cast<int>(neighborInfo.mRloc16));
379                 continue;
380             }
381             const otChildInfo *childInfo = it->second;
382 
383             comboTelemetry2 |= ((((uint32_t)childInfo->mNetworkDataVersion) & 0x000000FF) << 24);
384             topoEntry->set_combo_telemetry2(comboTelemetry2);
385 
386             topoEntryFlags |= ((/* is_child */ true ? 1 : 0) << 4);
387             topoEntry->set_topo_entry_flags(topoEntryFlags);
388 
389             topoEntry->set_timeout_sec(childInfo->mTimeout);
390         }
391         // End of TopoEntry section.
392     }
393 
394     {
395         // Begin of WpanBorderRouter section.
396         auto wpanBorderRouter = telemetryDataReported.mutable_wpan_border_router();
397         // Begin of BorderRoutingCounters section.
398         auto                           borderRoutingCouters    = wpanBorderRouter->mutable_border_routing_counters();
399         const otBorderRoutingCounters *otBorderRoutingCounters = otIp6GetBorderRoutingCounters(otInstance);
400 
401         borderRoutingCouters->mutable_inbound_unicast()->set_packet_count(
402             otBorderRoutingCounters->mInboundUnicast.mPackets);
403         borderRoutingCouters->mutable_inbound_unicast()->set_byte_count(
404             otBorderRoutingCounters->mInboundUnicast.mBytes);
405         borderRoutingCouters->mutable_inbound_multicast()->set_packet_count(
406             otBorderRoutingCounters->mInboundMulticast.mPackets);
407         borderRoutingCouters->mutable_inbound_multicast()->set_byte_count(
408             otBorderRoutingCounters->mInboundMulticast.mBytes);
409         borderRoutingCouters->mutable_outbound_unicast()->set_packet_count(
410             otBorderRoutingCounters->mOutboundUnicast.mPackets);
411         borderRoutingCouters->mutable_outbound_unicast()->set_byte_count(
412             otBorderRoutingCounters->mOutboundUnicast.mBytes);
413         borderRoutingCouters->mutable_outbound_multicast()->set_packet_count(
414             otBorderRoutingCounters->mOutboundMulticast.mPackets);
415         borderRoutingCouters->mutable_outbound_multicast()->set_byte_count(
416             otBorderRoutingCounters->mOutboundMulticast.mBytes);
417         borderRoutingCouters->set_ra_rx(otBorderRoutingCounters->mRaRx);
418         borderRoutingCouters->set_ra_tx_success(otBorderRoutingCounters->mRaTxSuccess);
419         borderRoutingCouters->set_ra_tx_failure(otBorderRoutingCounters->mRaTxFailure);
420         borderRoutingCouters->set_rs_rx(otBorderRoutingCounters->mRsRx);
421         borderRoutingCouters->set_rs_tx_success(otBorderRoutingCounters->mRsTxSuccess);
422         borderRoutingCouters->set_rs_tx_failure(otBorderRoutingCounters->mRsTxFailure);
423 
424         // End of BorderRoutingCounters section.
425 
426 #if OTBR_ENABLE_SRP_ADVERTISING_PROXY
427         // Begin of SrpServerInfo section.
428         {
429             auto                               srpServer = wpanBorderRouter->mutable_srp_server();
430             otSrpServerLeaseInfo               leaseInfo;
431             const otSrpServerHost             *host             = nullptr;
432             const otSrpServerResponseCounters *responseCounters = otSrpServerGetResponseCounters(otInstance);
433 
434             srpServer->set_state(SrpServerStateFromOtSrpServerState(otSrpServerGetState(otInstance)));
435             srpServer->set_port(otSrpServerGetPort(otInstance));
436             srpServer->set_address_mode(
437                 SrpServerAddressModeFromOtSrpServerAddressMode(otSrpServerGetAddressMode(otInstance)));
438 
439             auto srpServerHosts            = srpServer->mutable_hosts();
440             auto srpServerServices         = srpServer->mutable_services();
441             auto srpServerResponseCounters = srpServer->mutable_response_counters();
442 
443             while ((host = otSrpServerGetNextHost(otInstance, host)))
444             {
445                 const otSrpServerService *service = nullptr;
446 
447                 if (otSrpServerHostIsDeleted(host))
448                 {
449                     srpServerHosts->set_deleted_count(srpServerHosts->deleted_count() + 1);
450                 }
451                 else
452                 {
453                     srpServerHosts->set_fresh_count(srpServerHosts->fresh_count() + 1);
454                     otSrpServerHostGetLeaseInfo(host, &leaseInfo);
455                     srpServerHosts->set_lease_time_total_ms(srpServerHosts->lease_time_total_ms() + leaseInfo.mLease);
456                     srpServerHosts->set_key_lease_time_total_ms(srpServerHosts->key_lease_time_total_ms() +
457                                                                 leaseInfo.mKeyLease);
458                     srpServerHosts->set_remaining_lease_time_total_ms(srpServerHosts->remaining_lease_time_total_ms() +
459                                                                       leaseInfo.mRemainingLease);
460                     srpServerHosts->set_remaining_key_lease_time_total_ms(
461                         srpServerHosts->remaining_key_lease_time_total_ms() + leaseInfo.mRemainingKeyLease);
462                 }
463 
464                 while ((service = otSrpServerHostGetNextService(host, service)))
465                 {
466                     if (otSrpServerServiceIsDeleted(service))
467                     {
468                         srpServerServices->set_deleted_count(srpServerServices->deleted_count() + 1);
469                     }
470                     else
471                     {
472                         srpServerServices->set_fresh_count(srpServerServices->fresh_count() + 1);
473                         otSrpServerServiceGetLeaseInfo(service, &leaseInfo);
474                         srpServerServices->set_lease_time_total_ms(srpServerServices->lease_time_total_ms() +
475                                                                    leaseInfo.mLease);
476                         srpServerServices->set_key_lease_time_total_ms(srpServerServices->key_lease_time_total_ms() +
477                                                                        leaseInfo.mKeyLease);
478                         srpServerServices->set_remaining_lease_time_total_ms(
479                             srpServerServices->remaining_lease_time_total_ms() + leaseInfo.mRemainingLease);
480                         srpServerServices->set_remaining_key_lease_time_total_ms(
481                             srpServerServices->remaining_key_lease_time_total_ms() + leaseInfo.mRemainingKeyLease);
482                     }
483                 }
484             }
485 
486             srpServerResponseCounters->set_success_count(responseCounters->mSuccess);
487             srpServerResponseCounters->set_server_failure_count(responseCounters->mServerFailure);
488             srpServerResponseCounters->set_format_error_count(responseCounters->mFormatError);
489             srpServerResponseCounters->set_name_exists_count(responseCounters->mNameExists);
490             srpServerResponseCounters->set_refused_count(responseCounters->mRefused);
491             srpServerResponseCounters->set_other_count(responseCounters->mOther);
492         }
493         // End of SrpServerInfo section.
494 #endif // OTBR_ENABLE_SRP_ADVERTISING_PROXY
495 
496 #if OTBR_ENABLE_DNSSD_DISCOVERY_PROXY
497         // Begin of DnsServerInfo section.
498         {
499             auto            dnsServer                 = wpanBorderRouter->mutable_dns_server();
500             auto            dnsServerResponseCounters = dnsServer->mutable_response_counters();
501             otDnssdCounters otDnssdCounters           = *otDnssdGetCounters(otInstance);
502 
503             dnsServerResponseCounters->set_success_count(otDnssdCounters.mSuccessResponse);
504             dnsServerResponseCounters->set_server_failure_count(otDnssdCounters.mServerFailureResponse);
505             dnsServerResponseCounters->set_format_error_count(otDnssdCounters.mFormatErrorResponse);
506             dnsServerResponseCounters->set_name_error_count(otDnssdCounters.mNameErrorResponse);
507             dnsServerResponseCounters->set_not_implemented_count(otDnssdCounters.mNotImplementedResponse);
508             dnsServerResponseCounters->set_other_count(otDnssdCounters.mOtherResponse);
509 
510             dnsServer->set_resolved_by_local_srp_count(otDnssdCounters.mResolvedBySrp);
511         }
512         // End of DnsServerInfo section.
513 #endif // OTBR_ENABLE_DNSSD_DISCOVERY_PROXY
514 
515         // Start of MdnsInfo section.
516         if (aPublisher != nullptr)
517         {
518             auto                     mdns     = wpanBorderRouter->mutable_mdns();
519             const MdnsTelemetryInfo &mdnsInfo = aPublisher->GetMdnsTelemetryInfo();
520 
521             CopyMdnsResponseCounters(mdnsInfo.mHostRegistrations, mdns->mutable_host_registration_responses());
522             CopyMdnsResponseCounters(mdnsInfo.mServiceRegistrations, mdns->mutable_service_registration_responses());
523             CopyMdnsResponseCounters(mdnsInfo.mHostResolutions, mdns->mutable_host_resolution_responses());
524             CopyMdnsResponseCounters(mdnsInfo.mServiceResolutions, mdns->mutable_service_resolution_responses());
525 
526             mdns->set_host_registration_ema_latency_ms(mdnsInfo.mHostRegistrationEmaLatency);
527             mdns->set_service_registration_ema_latency_ms(mdnsInfo.mServiceRegistrationEmaLatency);
528             mdns->set_host_resolution_ema_latency_ms(mdnsInfo.mHostResolutionEmaLatency);
529             mdns->set_service_resolution_ema_latency_ms(mdnsInfo.mServiceResolutionEmaLatency);
530         }
531         // End of MdnsInfo section.
532 
533         // End of WpanBorderRouter section.
534 
535         // Start of WpanRcp section.
536         {
537             auto                        wpanRcp                = telemetryDataReported.mutable_wpan_rcp();
538             const otRadioSpinelMetrics *otRadioSpinelMetrics   = otSysGetRadioSpinelMetrics();
539             auto                        rcpStabilityStatistics = wpanRcp->mutable_rcp_stability_statistics();
540 
541             if (otRadioSpinelMetrics != nullptr)
542             {
543                 rcpStabilityStatistics->set_rcp_timeout_count(otRadioSpinelMetrics->mRcpTimeoutCount);
544                 rcpStabilityStatistics->set_rcp_reset_count(otRadioSpinelMetrics->mRcpUnexpectedResetCount);
545                 rcpStabilityStatistics->set_rcp_restoration_count(otRadioSpinelMetrics->mRcpRestorationCount);
546                 rcpStabilityStatistics->set_spinel_parse_error_count(otRadioSpinelMetrics->mSpinelParseErrorCount);
547             }
548 
549             // TODO: provide rcp_firmware_update_count info.
550             rcpStabilityStatistics->set_thread_stack_uptime(otInstanceGetUptime(otInstance));
551 
552             const otRcpInterfaceMetrics *otRcpInterfaceMetrics = otSysGetRcpInterfaceMetrics();
553 
554             if (otRcpInterfaceMetrics != nullptr)
555             {
556                 auto rcpInterfaceStatistics = wpanRcp->mutable_rcp_interface_statistics();
557 
558                 rcpInterfaceStatistics->set_rcp_interface_type(otRcpInterfaceMetrics->mRcpInterfaceType);
559                 rcpInterfaceStatistics->set_transferred_frames_count(otRcpInterfaceMetrics->mTransferredFrameCount);
560                 rcpInterfaceStatistics->set_transferred_valid_frames_count(
561                     otRcpInterfaceMetrics->mTransferredValidFrameCount);
562                 rcpInterfaceStatistics->set_transferred_garbage_frames_count(
563                     otRcpInterfaceMetrics->mTransferredGarbageFrameCount);
564                 rcpInterfaceStatistics->set_rx_frames_count(otRcpInterfaceMetrics->mRxFrameCount);
565                 rcpInterfaceStatistics->set_rx_bytes_count(otRcpInterfaceMetrics->mRxFrameByteCount);
566                 rcpInterfaceStatistics->set_tx_frames_count(otRcpInterfaceMetrics->mTxFrameCount);
567                 rcpInterfaceStatistics->set_tx_bytes_count(otRcpInterfaceMetrics->mTxFrameByteCount);
568             }
569         }
570         // End of WpanRcp section.
571 
572         // Start of CoexMetrics section.
573         {
574             auto               coexMetrics = telemetryDataReported.mutable_coex_metrics();
575             otRadioCoexMetrics otRadioCoexMetrics;
576 
577             if (otPlatRadioGetCoexMetrics(otInstance, &otRadioCoexMetrics) == OT_ERROR_NONE)
578             {
579                 coexMetrics->set_count_tx_request(otRadioCoexMetrics.mNumTxRequest);
580                 coexMetrics->set_count_tx_grant_immediate(otRadioCoexMetrics.mNumTxGrantImmediate);
581                 coexMetrics->set_count_tx_grant_wait(otRadioCoexMetrics.mNumTxGrantWait);
582                 coexMetrics->set_count_tx_grant_wait_activated(otRadioCoexMetrics.mNumTxGrantWaitActivated);
583                 coexMetrics->set_count_tx_grant_wait_timeout(otRadioCoexMetrics.mNumTxGrantWaitTimeout);
584                 coexMetrics->set_count_tx_grant_deactivated_during_request(
585                     otRadioCoexMetrics.mNumTxGrantDeactivatedDuringRequest);
586                 coexMetrics->set_tx_average_request_to_grant_time_us(otRadioCoexMetrics.mAvgTxRequestToGrantTime);
587                 coexMetrics->set_count_rx_request(otRadioCoexMetrics.mNumRxRequest);
588                 coexMetrics->set_count_rx_grant_immediate(otRadioCoexMetrics.mNumRxGrantImmediate);
589                 coexMetrics->set_count_rx_grant_wait(otRadioCoexMetrics.mNumRxGrantWait);
590                 coexMetrics->set_count_rx_grant_wait_activated(otRadioCoexMetrics.mNumRxGrantWaitActivated);
591                 coexMetrics->set_count_rx_grant_wait_timeout(otRadioCoexMetrics.mNumRxGrantWaitTimeout);
592                 coexMetrics->set_count_rx_grant_deactivated_during_request(
593                     otRadioCoexMetrics.mNumRxGrantDeactivatedDuringRequest);
594                 coexMetrics->set_count_rx_grant_none(otRadioCoexMetrics.mNumRxGrantNone);
595                 coexMetrics->set_rx_average_request_to_grant_time_us(otRadioCoexMetrics.mAvgRxRequestToGrantTime);
596             }
597             else
598             {
599                 error = OT_ERROR_FAILED;
600             }
601         }
602         // End of CoexMetrics section.
603     }
604 
605     deviceInfoReported.set_thread_version(otThreadGetVersion());
606     deviceInfoReported.set_ot_rcp_version(otGetRadioVersionString(otInstance));
607     // TODO: populate ot_host_version, thread_daemon_version.
608 
609     return error;
610 }
611 
PushAtom(const ThreadnetworkTelemetryDataReported & telemetryDataReported)612 int PushAtom(const ThreadnetworkTelemetryDataReported &telemetryDataReported)
613 {
614     const std::string        &wpanStats        = telemetryDataReported.wpan_stats().SerializeAsString();
615     const std::string        &wpanTopoFull     = telemetryDataReported.wpan_topo_full().SerializeAsString();
616     const std::string        &wpanBorderRouter = telemetryDataReported.wpan_border_router().SerializeAsString();
617     const std::string        &wpanRcp          = telemetryDataReported.wpan_rcp().SerializeAsString();
618     const std::string        &coexMetrics      = telemetryDataReported.coex_metrics().SerializeAsString();
619     threadnetwork::BytesField wpanStatsBytesField{wpanStats.c_str(), wpanStats.size()};
620     threadnetwork::BytesField wpanTopoFullBytesField{wpanTopoFull.c_str(), wpanTopoFull.size()};
621     threadnetwork::BytesField wpanBorderRouterBytesField{wpanBorderRouter.c_str(), wpanBorderRouter.size()};
622     threadnetwork::BytesField wpanRcpBytesField{wpanRcp.c_str(), wpanRcp.size()};
623     threadnetwork::BytesField coexMetricsBytesField{coexMetrics.c_str(), coexMetrics.size()};
624     return threadnetwork::stats_write(threadnetwork::THREADNETWORK_TELEMETRY_DATA_REPORTED, wpanStatsBytesField,
625                                       wpanTopoFullBytesField, wpanBorderRouterBytesField, wpanRcpBytesField,
626                                       coexMetricsBytesField);
627 }
628 
PushAtom(const ThreadnetworkTopoEntryRepeated & topoEntryRepeated)629 int PushAtom(const ThreadnetworkTopoEntryRepeated &topoEntryRepeated)
630 {
631     const std::string        &topoEntryField = topoEntryRepeated.topo_entry_repeated().SerializeAsString();
632     threadnetwork::BytesField topoEntryFieldBytesField{topoEntryField.c_str(), topoEntryField.size()};
633     return threadnetwork::stats_write(threadnetwork::THREADNETWORK_TOPO_ENTRY_REPEATED, topoEntryFieldBytesField);
634 }
635 
PushAtom(const ThreadnetworkDeviceInfoReported & deviceInfoReported)636 int PushAtom(const ThreadnetworkDeviceInfoReported &deviceInfoReported)
637 {
638     const std::string &otHostVersion       = deviceInfoReported.ot_host_version();
639     const std::string &otRcpVersion        = deviceInfoReported.ot_rcp_version();
640     const int32_t     &threadVersion       = deviceInfoReported.thread_version();
641     const std::string &threadDaemonVersion = deviceInfoReported.thread_daemon_version();
642     return threadnetwork::stats_write(threadnetwork::THREADNETWORK_DEVICE_INFO_REPORTED, otHostVersion.c_str(),
643                                       otRcpVersion.c_str(), threadVersion, threadDaemonVersion.c_str());
644 }
645 
RetrieveAndPushAtoms(otInstance * otInstance)646 void RetrieveAndPushAtoms(otInstance *otInstance)
647 {
648     ThreadnetworkTelemetryDataReported telemetryDataReported;
649     ThreadnetworkTopoEntryRepeated     topoEntryRepeated;
650     ThreadnetworkDeviceInfoReported    deviceInfoReported;
651 
652     otbrLogInfo("Try to push threadnetwork ATOMs.");
653     if (RetrieveTelemetryAtom(otInstance, nullptr, telemetryDataReported, topoEntryRepeated, deviceInfoReported) !=
654         OTBR_ERROR_NONE)
655     {
656         otbrLogWarning("Some telemetries are not populated");
657     }
658     if (PushAtom(telemetryDataReported) <= 0)
659     {
660         otbrLogWarning("Failed to push ThreadnetworkTelemetryDataReported");
661     }
662     if (PushAtom(topoEntryRepeated) <= 0)
663     {
664         otbrLogWarning("Failed to push ThreadnetworkTopoEntryRepeated");
665     }
666     if (PushAtom(deviceInfoReported) <= 0)
667     {
668         otbrLogWarning("Failed to push ThreadnetworkDeviceInfoReported");
669     }
670     otbrLogInfo("Pushed threadnetwork ATOMs.");
671 }
672 } // namespace Android
673 } // namespace otbr
674