mirror of
https://github.com/espressif/openthread.git
synced 2026-08-12 13:47:47 +00:00
[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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
|
||||
@@ -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[])
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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']
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user