[telemetry] add API for TREL telemetry (#9710)

Create OT API to support trel telemetry which is supported through
platform API and also add cli support to get/reset trel counters.

Metrics we are adding are:
- trel_frames_tx
- trel_bytes_tx
- trel_frames_rx
- trel_bytes_rx
- trel_frames_tx_failed
- num_trel_peers

Metrics already supported through API:
- trel_enabled
This commit is contained in:
Yang Liu
2024-01-05 22:10:27 -08:00
committed by GitHub
parent 09d07a7c6a
commit d81c6fab98
14 changed files with 261 additions and 11 deletions
+19 -4
View File
@@ -73,10 +73,11 @@ static uint16_t sPortOffset = 0;
static bool sEnabled = false;
static uint16_t sUdpPort;
static bool sServiceRegistered = false;
static uint16_t sServicePort;
static uint8_t sServiceTxtLength;
static char sServiceTxtData[TREL_MAX_SERVICE_TXT_DATA_LEN];
static bool sServiceRegistered = false;
static uint16_t sServicePort;
static uint8_t sServiceTxtLength;
static char sServiceTxtData[TREL_MAX_SERVICE_TXT_DATA_LEN];
static otPlatTrelCounters sCounters;
#if DEBUG_LOG
static void dumpBuffer(const void *aBuffer, uint16_t aLength)
@@ -388,6 +389,8 @@ void otPlatTrelSend(otInstance *aInstance,
#if DEBUG_LOG
fprintf(stderr, "\r\n[trel-sim] otPlatTrelSend(len:%u, port:%u)\r\n", aUdpPayloadLen, aDestSockAddr->mPort);
#endif
++sCounters.mTxPackets;
sCounters.mTxBytes += aUdpPayloadLen;
}
//---------------------------------------------------------------------------------------------------------------------
@@ -473,6 +476,18 @@ void platformTrelProcess(otInstance *aInstance, const fd_set *aReadFdSet, const
}
}
const otPlatTrelCounters *otPlatTrelGetCounters(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
return &sCounters;
}
void otPlatTrelResetCounters(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
memset(&sCounters, 0, sizeof(sCounters));
}
//---------------------------------------------------------------------------------------------------------------------
// This is added for RCP build to be built ok
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (387)
#define OPENTHREAD_API_VERSION (388)
/**
* @addtogroup api-instance
+29
View File
@@ -197,6 +197,35 @@ void otPlatTrelSend(otInstance *aInstance,
*/
extern void otPlatTrelHandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength);
/**
* Represents a group of TREL related counters in the platform layer.
*
*/
typedef struct otPlatTrelCounters
{
uint64_t mTxPackets; ///< Number of packets successfully transmitted through TREL.
uint64_t mTxBytes; ///< Sum of size of packets successfully transmitted through TREL.
uint64_t mTxFailure; ///< Number of packet transmission failures through TREL.
uint64_t mRxPackets; ///< Number of packets received through TREL.
uint64_t mRxBytes; ///< Sum of size of packets received through TREL.
} otPlatTrelCounters;
/**
* Gets the pointer to the TREL counters in the platform layer.
*
* @param[in] aInstance The OpenThread instance structure.
*
*/
const otPlatTrelCounters *otPlatTrelGetCounters(otInstance *aInstance);
/**
* Resets the TREL counters in the platform layer.
*
* @param[in] aInstance The OpenThread instance structure.
*
*/
void otPlatTrelResetCounters(otInstance *aInstance);
/**
* @}
*
+35
View File
@@ -39,6 +39,7 @@
#include <openthread/dataset.h>
#include <openthread/ip6.h>
#include <openthread/platform/radio.h>
#include "openthread/platform/trel.h"
#ifdef __cplusplus
extern "C" {
@@ -123,6 +124,16 @@ void otTrelInitPeerIterator(otInstance *aInstance, otTrelPeerIterator *aIterator
*/
const otTrelPeer *otTrelGetNextPeer(otInstance *aInstance, otTrelPeerIterator *aIterator);
/**
* Returns the number of TREL peers.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @returns The number of TREL peers.
*
*/
uint16_t otTrelGetNumberOfPeers(otInstance *aInstance);
/**
* Sets the filter mode (enables/disables filtering).
*
@@ -149,6 +160,30 @@ void otTrelSetFilterEnabled(otInstance *aInstance, bool aEnable);
*/
bool otTrelIsFilterEnabled(otInstance *aInstance);
/**
* Represents a group of TREL related counters.
*
*/
typedef otPlatTrelCounters otTrelCounters;
/**
* Gets the TREL counters.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @returns A pointer to the TREL counters.
*
*/
const otTrelCounters *otTrelGetCounters(otInstance *aInstance);
/**
* Resets the TREL counters.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
*/
void otTrelResetCounters(otInstance *aInstance);
/**
* @}
*
+48
View File
@@ -7800,6 +7800,41 @@ template <> otError Interpreter::Process<Cmd("trel")>(Arg aArgs[])
}
}
}
/**
* @cli trel counters
* @code
* trel counters
* Inbound: Packets 32 Bytes 4000
* Outbound: Packets 4 Bytes 320 Failures 1
* Done
* @endcode
* @par api_copy
* #otTrelGetCounters
*/
else if (aArgs[0] == "counters")
{
if (aArgs[1].IsEmpty())
{
OutputTrelCounters(*otTrelGetCounters(GetInstancePtr()));
}
/**
* @cli trel counters reset
* @code
* trel counters reset
* Done
* @endcode
* @par api_copy
* #otTrelResetCounters
*/
else if ((aArgs[1] == "reset") && aArgs[2].IsEmpty())
{
otTrelResetCounters(GetInstancePtr());
}
else
{
error = OT_ERROR_INVALID_ARGS;
}
}
else
{
error = OT_ERROR_INVALID_ARGS;
@@ -7808,6 +7843,19 @@ template <> otError Interpreter::Process<Cmd("trel")>(Arg aArgs[])
exit:
return error;
}
void Interpreter::OutputTrelCounters(const otTrelCounters &aCounters)
{
Uint64StringBuffer u64StringBuffer;
OutputFormat("Inbound: Packets %s ", Uint64ToString(aCounters.mRxPackets, u64StringBuffer));
OutputLine("Bytes %s", Uint64ToString(aCounters.mRxBytes, u64StringBuffer));
OutputFormat("Outbound: Packets %s ", Uint64ToString(aCounters.mTxPackets, u64StringBuffer));
OutputFormat("Bytes %s ", Uint64ToString(aCounters.mTxBytes, u64StringBuffer));
OutputLine("Failures %s", Uint64ToString(aCounters.mTxFailure, u64StringBuffer));
}
#endif
template <> otError Interpreter::Process<Cmd("vendor")>(Arg aArgs[])
+3
View File
@@ -483,6 +483,9 @@ private:
void OutputChildTableEntry(uint8_t aIndentSize, const otNetworkDiagChildEntry &aChildEntry);
#endif
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
void OutputTrelCounters(const otTrelCounters &aCounters);
#endif
#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
void OutputNat64Counters(const otNat64Counters &aCounters);
#endif
+12
View File
@@ -60,6 +60,11 @@ const otTrelPeer *otTrelGetNextPeer(otInstance *aInstance, otTrelPeerIterator *a
return AsCoreType(aInstance).Get<Trel::Interface>().GetNextPeer(*aIterator);
}
uint16_t otTrelGetNumberOfPeers(otInstance *aInstance)
{
return AsCoreType(aInstance).Get<Trel::Interface>().GetNumberOfPeers();
}
void otTrelSetFilterEnabled(otInstance *aInstance, bool aEnable)
{
AsCoreType(aInstance).Get<Trel::Interface>().SetFilterEnabled(aEnable);
@@ -70,4 +75,11 @@ bool otTrelIsFilterEnabled(otInstance *aInstance)
return AsCoreType(aInstance).Get<Trel::Interface>().IsFilterEnabled();
}
const otTrelCounters *otTrelGetCounters(otInstance *aInstance)
{
return AsCoreType(aInstance).Get<Trel::Interface>().GetCounters();
}
void otTrelResetCounters(otInstance *aInstance) { AsCoreType(aInstance).Get<Trel::Interface>().ResetCounters(); }
#endif // OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
+4
View File
@@ -352,6 +352,10 @@ void Interface::RemovePeerEntry(Peer &aEntry)
mPeerTable.PopBack();
}
const Counters *Interface::GetCounters(void) const { return otPlatTrelGetCounters(&GetInstance()); }
void Interface::ResetCounters(void) { otPlatTrelResetCounters(&GetInstance()); }
Error Interface::Send(const Packet &aPacket, bool aIsDiscovery)
{
Error error = kErrorNone;
+28
View File
@@ -59,6 +59,12 @@ class Link;
extern "C" void otPlatTrelHandleReceived(otInstance *aInstance, uint8_t *aBuffer, uint16_t aLength);
extern "C" void otPlatTrelHandleDiscoveredPeerInfo(otInstance *aInstance, const otPlatTrelPeerInfo *aInfo);
/**
* Represents a group of TREL counters.
*
*/
typedef otTrelCounters Counters;
/**
* Represents a TREL link interface.
*
@@ -205,6 +211,14 @@ public:
*/
const Peer *GetNextPeer(PeerIterator &aIterator) const;
/**
* Returns the number of TREL peers.
*
* @returns The number of TREL peers.
*
*/
uint16_t GetNumberOfPeers(void) const { return mPeerTable.GetLength(); }
/**
* Sets the filter mode (enables/disables filtering).
*
@@ -228,6 +242,20 @@ public:
*/
bool IsFilterEnabled(void) const { return mFiltered; }
/**
* Gets the TREL counters.
*
* The counters are initialized to zero when the TREL platform is initialized.
*
*/
const Counters *GetCounters(void) const;
/**
* Resets the TREL counters.
*
*/
void ResetCounters(void);
private:
#if OPENTHREAD_COFNIG_TREL_PEER_TABLE_SIZE != 0
static constexpr uint16_t kPeerTableSize = OPENTHREAD_COFNIG_TREL_PEER_TABLE_SIZE;
+36 -6
View File
@@ -61,11 +61,12 @@ typedef struct TxPacket
otSockAddr mDestSockAddr;
} TxPacket;
static uint8_t sRxPacketBuffer[kMaxPacketSize];
static uint16_t sRxPacketLength;
static TxPacket sTxPacketPool[OPENTHREAD_POSIX_CONFIG_TREL_TX_PACKET_POOL_SIZE];
static TxPacket *sFreeTxPacketHead; // A singly linked list of free/available `TxPacket` from pool.
static TxPacket *sTxPacketQueueTail; // A circular linked list for queued tx packets.
static uint8_t sRxPacketBuffer[kMaxPacketSize];
static uint16_t sRxPacketLength;
static TxPacket sTxPacketPool[OPENTHREAD_POSIX_CONFIG_TREL_TX_PACKET_POOL_SIZE];
static TxPacket *sFreeTxPacketHead; // A singly linked list of free/available `TxPacket` from pool.
static TxPacket *sTxPacketQueueTail; // A circular linked list for queued tx packets.
static otPlatTrelCounters sCounters;
static char sInterfaceName[IFNAMSIZ + 1];
static bool sInitialized = false;
@@ -186,11 +187,19 @@ static otError SendPacket(const uint8_t *aBuffer, uint16_t aLength, const otSock
error = OT_ERROR_INVALID_STATE;
}
}
else
{
++sCounters.mTxPackets;
sCounters.mTxBytes += aLength;
}
exit:
otLogDebgPlat("[trel] SendPacket([%s]:%u) err:%s pkt:%s", Ip6AddrToString(&aDestSockAddr->mAddress),
aDestSockAddr->mPort, otThreadErrorToString(error), BufferToString(aBuffer, aLength));
if (error != OT_ERROR_NONE)
{
++sCounters.mTxFailure;
}
return error;
}
@@ -218,6 +227,8 @@ static void ReceivePacket(int aSocket, otInstance *aInstance)
if (sEnabled)
{
++sCounters.mRxPackets;
sCounters.mRxBytes += sRxPacketLength;
otPlatTrelHandleReceived(aInstance, sRxPacketBuffer, sRxPacketLength);
}
}
@@ -305,6 +316,8 @@ exit:
return;
}
static void ResetCounters() { memset(&sCounters, 0, sizeof(sCounters)); }
//---------------------------------------------------------------------------------------------------------------------
// trelDnssd
//
@@ -485,6 +498,21 @@ exit:
return;
}
// We keep counters at the platform layer because TREL failures can only be captured accurately within
// the platform layer as the platform sometimes only queues the packet and the packet will be sent later
// and the error is only known after sent.
const otPlatTrelCounters *otPlatTrelGetCounters(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
return &sCounters;
}
void otPlatTrelResetCounters(otInstance *aInstance)
{
OT_UNUSED_VARIABLE(aInstance);
ResetCounters();
}
//---------------------------------------------------------------------------------------------------------------------
// platformTrel system
@@ -506,6 +534,8 @@ void platformTrelInit(const char *aTrelUrl)
InitPacketQueue();
sInitialized = true;
ResetCounters();
}
void platformTrelDeinit(void)
@@ -143,6 +143,23 @@ class TestTrelConnectivity(thread_cert.TestCase):
self.assertTrue(med1.ping(router2_mleid))
self.assertTrue(sed1.ping(router2_mleid))
counters = br1.get_trel_counters()
print('br1 trel counters', counters)
self.assertTrue(counters['Inbound']['packets'] > 0)
self.assertTrue(counters['Inbound']['bytes'] > 0)
self.assertTrue(counters['Outbound']['packets'] > 0)
self.assertTrue(counters['Outbound']['bytes'] > 0)
self.assertTrue(counters['Outbound']['failures'] >= 0)
br1.reset_trel_counters()
counters = br1.get_trel_counters()
print('br1 trel counters after reset', counters)
self.assertTrue(counters['Inbound']['packets'] == 0)
self.assertTrue(counters['Inbound']['bytes'] == 0)
self.assertTrue(counters['Outbound']['packets'] == 0)
self.assertTrue(counters['Outbound']['bytes'] == 0)
self.assertTrue(counters['Outbound']['failures'] == 0)
def verify(self, pv: PacketVerifier):
pkts: PacketFilter = pv.pkts
BR1_RLOC16 = pv.vars['BR1_RLOC16']
+24
View File
@@ -1390,6 +1390,30 @@ class NodeImpl:
raise
def get_trel_counters(self):
cmd = 'trel counters'
self.send_command(cmd)
result = self._expect_command_output()
counters = {}
for line in result:
m = re.match(r'(\w+)\:[^\d]+(\d+)[^\d]+(\d+)(?:[^\d]+(\d+))?', line)
if m:
groups = m.groups()
sub_counters = {
'packets': int(groups[1]),
'bytes': int(groups[2]),
}
if groups[3]:
sub_counters['failures'] = int(groups[3])
counters[groups[0]] = sub_counters
return counters
def reset_trel_counters(self):
cmd = 'trel counters reset'
self.send_command(cmd)
self._expect_done()
def _encode_txt_entry(self, entry):
"""Encodes the TXT entry to the DNS-SD TXT record format as a HEX string.
+4
View File
@@ -424,6 +424,10 @@ OT_TOOL_WEAK void otPlatTrelDisable(otInstance *) {}
OT_TOOL_WEAK void otPlatTrelSend(otInstance *, const uint8_t *, uint16_t, const otSockAddr *) {}
OT_TOOL_WEAK void otPlatTrelRegisterService(otInstance *, uint16_t, const uint8_t *, uint8_t) {}
OT_TOOL_WEAK const otPlatTrelCounters *otPlatTrelGetCounters(otInstance *) { return nullptr; }
OT_TOOL_WEAK void otPlatTrelResetCounters(otInstance *) {}
#endif
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
+1
View File
@@ -40,6 +40,7 @@
#include <openthread/platform/misc.h>
#include <openthread/platform/multipan.h>
#include <openthread/platform/radio.h>
#include <openthread/platform/trel.h>
#include "common/code_utils.hpp"
#include "instance/instance.hpp"