From df20f3d91a12c1101331c29c42f2732a4dd06a56 Mon Sep 17 00:00:00 2001 From: whd <7058128+superwhd@users.noreply.github.com> Date: Fri, 4 Nov 2022 15:13:10 +0800 Subject: [PATCH] [telemetry] border routing packet counters (#8280) This commit introduces `otBorderRoutingCounters` which contains the number of packets and bytes forwarded via border routing. The counters have 4 categories: inbound unicast, inbound multicast, outbound unicast, outbound multicast. I've verified this feature locally on a BR device by ping command in following scenarios: - A host pings an ED's OMR. - An ED pings a host's onlink address. - A host pings a multicast address which an ED subscribes to. - An ED pings a multicast address which a host subscribes to. --- include/openthread/instance.h | 2 +- include/openthread/ip6.h | 34 +++++++++++++++++++ src/core/api/ip6_api.cpp | 7 ++++ src/core/config/ip6.h | 12 +++++++ src/core/net/ip6.cpp | 62 +++++++++++++++++++++++++++++++++++ src/core/net/ip6.hpp | 17 ++++++++++ 6 files changed, 133 insertions(+), 1 deletion(-) diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 8d403ff4d..1ea231f48 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (259) +#define OPENTHREAD_API_VERSION (260) /** * @addtogroup api-instance diff --git a/include/openthread/ip6.h b/include/openthread/ip6.h index 73bd59744..39534d880 100644 --- a/include/openthread/ip6.h +++ b/include/openthread/ip6.h @@ -851,6 +851,40 @@ otError otIp6SetMeshLocalIid(otInstance *aInstance, const otIp6InterfaceIdentifi */ const char *otIp6ProtoToString(uint8_t aIpProto); +/** + * This structure represents the counters for packets and bytes. + * + */ +typedef struct otPacketsAndBytes +{ + uint64_t mPackets; ///< The number of packets. + uint64_t mBytes; ///< The number of bytes. +} otPacketsAndBytes; + +/** + * This structure represents the counters of packets forwarded via Border Routing. + * + */ +typedef struct otBorderRoutingCounters +{ + otPacketsAndBytes mInboundUnicast; ///< The counters for inbound unicast. + otPacketsAndBytes mInboundMulticast; ///< The counters for inbound multicast. + otPacketsAndBytes mOutboundUnicast; ///< The counters for outbound unicast. + otPacketsAndBytes mOutboundMulticast; ///< The counters for outbound multicast. +} otBorderRoutingCounters; + +/** + * Gets the Border Routing counters. + * + * This function requires the build-time feature `OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE` to be enabled. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * + * @returns A pointer to the Border Routing counters. + * + */ +const otBorderRoutingCounters *otIp6GetBorderRoutingCounters(otInstance *aInstance); + /** * @} * diff --git a/src/core/api/ip6_api.cpp b/src/core/api/ip6_api.cpp index 454132b4d..78fb477eb 100644 --- a/src/core/api/ip6_api.cpp +++ b/src/core/api/ip6_api.cpp @@ -294,3 +294,10 @@ const char *otIp6ProtoToString(uint8_t aIpProto) { return Ip6::Ip6::IpProtoToString(aIpProto); } + +#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE +const otBorderRoutingCounters *otIp6GetBorderRoutingCounters(otInstance *aInstance) +{ + return &AsCoreType(aInstance).Get().GetBorderRoutingCounters(); +} +#endif diff --git a/src/core/config/ip6.h b/src/core/config/ip6.h index b84918fec..268a2cd47 100644 --- a/src/core/config/ip6.h +++ b/src/core/config/ip6.h @@ -35,6 +35,8 @@ #ifndef CONFIG_IP6_H_ #define CONFIG_IP6_H_ +#include "config/border_routing.h" + /** * @def OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS * @@ -180,4 +182,14 @@ #define OPENTHREAD_CONFIG_IP6_ALLOW_LOOP_BACK_HOST_DATAGRAMS 1 #endif +/** + * @def OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE + * + * Define as 1 to enable IPv6 Border Routing counters. + * + */ +#ifndef OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE +#define OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE +#endif + #endif // CONFIG_IP6_H_ diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index 752d98d84..74da1e8d6 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -1019,6 +1019,11 @@ Error Ip6::ProcessReceiveCallback(Message & aMessage, { Error error = kErrorNone; Message *message = &aMessage; +#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE + Header header; + + IgnoreError(header.ParseFrom(aMessage)); +#endif VerifyOrExit(aOrigin != kFromHostDisallowLoopBack, error = kErrorNoRoute); @@ -1103,6 +1108,10 @@ Error Ip6::ProcessReceiveCallback(Message & aMessage, mReceiveIp6DatagramCallback(message, mReceiveIp6DatagramCallbackContext); +#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE + UpdateBorderRoutingCounters(header, aMessage.GetLength(), /* aIsInbound */ false); +#endif + exit: if ((error != kErrorNone) && (aMessageOwnership == Message::kTakeCustody)) @@ -1135,6 +1144,10 @@ Error Ip6::SendRaw(Message &aMessage, bool aAllowLoopBackToHost) error = HandleDatagram(aMessage, aAllowLoopBackToHost ? kFromHostAllowLoopBack : kFromHostDisallowLoopBack); freed = true; +#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE + UpdateBorderRoutingCounters(header, aMessage.GetLength(), /* aIsInbound */ true); +#endif + exit: if (!freed) @@ -1492,6 +1505,55 @@ exit: return rval; } +#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE +void Ip6::UpdateBorderRoutingCounters(const Header &aHeader, uint16_t aMessageLength, bool aIsInbound) +{ + otPacketsAndBytes *counter = nullptr; + + VerifyOrExit(!aHeader.GetSource().IsLinkLocal()); + VerifyOrExit(!aHeader.GetDestination().IsLinkLocal()); + VerifyOrExit(aHeader.GetSource().GetPrefix() != Get().GetMeshLocalPrefix()); + VerifyOrExit(aHeader.GetDestination().GetPrefix() != Get().GetMeshLocalPrefix()); + + if (aIsInbound) + { + VerifyOrExit(!Get().HasUnicastAddress(aHeader.GetSource())); + + if (aHeader.GetDestination().IsMulticast()) + { + VerifyOrExit(aHeader.GetDestination().IsMulticastLargerThanRealmLocal()); + counter = &mBorderRoutingCounters.mInboundMulticast; + } + else + { + counter = &mBorderRoutingCounters.mInboundUnicast; + } + } + else + { + VerifyOrExit(!Get().HasUnicastAddress(aHeader.GetDestination())); + + if (aHeader.GetDestination().IsMulticast()) + { + VerifyOrExit(aHeader.GetDestination().IsMulticastLargerThanRealmLocal()); + counter = &mBorderRoutingCounters.mOutboundMulticast; + } + else + { + counter = &mBorderRoutingCounters.mOutboundUnicast; + } + } + +exit: + + if (counter) + { + counter->mPackets += 1; + counter->mBytes += aMessageLength; + } +} +#endif + // LCOV_EXCL_START const char *Ip6::IpProtoToString(uint8_t aIpProto) diff --git a/src/core/net/ip6.hpp b/src/core/net/ip6.hpp index 037f02f47..1b97dccdc 100644 --- a/src/core/net/ip6.hpp +++ b/src/core/net/ip6.hpp @@ -340,6 +340,16 @@ public: */ static const char *EcnToString(Ecn aEcn); +#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE + /** + * This method returns a reference to the Border Routing counters. + * + * @returns A reference to the Border Routing counters. + * + */ + const otBorderRoutingCounters &GetBorderRoutingCounters(void) const { return mBorderRoutingCounters; } +#endif + private: static constexpr uint8_t kDefaultHopLimit = OPENTHREAD_CONFIG_IP6_HOP_LIMIT_DEFAULT; static constexpr uint8_t kIp6ReassemblyTimeout = OPENTHREAD_CONFIG_IP6_REASSEMBLY_TIMEOUT; @@ -384,6 +394,9 @@ private: Message::Ownership aMessageOwnership); bool ShouldForwardToThread(const MessageInfo &aMessageInfo, MessageOrigin aOrigin) const; bool IsOnLink(const Address &aAddress) const; +#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE + void UpdateBorderRoutingCounters(const Header &aHeader, uint16_t aMessageLength, bool aIsInbound); +#endif using SendQueueTask = TaskletIn; @@ -411,6 +424,10 @@ private: #if OPENTHREAD_CONFIG_IP6_FRAGMENTATION_ENABLE MessageQueue mReassemblyList; #endif + +#if OPENTHREAD_CONFIG_IP6_BR_COUNTERS_ENABLE + otBorderRoutingCounters mBorderRoutingCounters; +#endif }; /**