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