From 22fa54dfa2ad42a7de6a0e02d08a242db8fb8a5d Mon Sep 17 00:00:00 2001 From: whd <7058128+superwhd@users.noreply.github.com> Date: Wed, 11 Jan 2023 23:58:38 +0800 Subject: [PATCH] [infra-if] add API for querying infra link status (#8619) This commit introduces 2 APIs to query infra link status: - `otSysGetInfraNetifFlags` returns the `ifr_flags` of the infra network interface. - `otSysCountInfraNetifAddresses` counts the numbers of LLA, ULA and GUA on the infra network interface. --- .../include/openthread/openthread-system.h | 23 ++++++++ src/posix/platform/infra_if.cpp | 57 ++++++++++++++++++- src/posix/platform/infra_if.hpp | 17 ++++++ 3 files changed, 95 insertions(+), 2 deletions(-) diff --git a/src/posix/platform/include/openthread/openthread-system.h b/src/posix/platform/include/openthread/openthread-system.h index e8a09dcb8..35ae71501 100644 --- a/src/posix/platform/include/openthread/openthread-system.h +++ b/src/posix/platform/include/openthread/openthread-system.h @@ -219,6 +219,29 @@ const otRadioSpinelMetrics *otSysGetRadioSpinelMetrics(void); */ const otRcpInterfaceMetrics *otSysGetRcpInterfaceMetrics(void); +/** + * This function returns the ifr_flags of the infrastructure network interface. + * + * @returns The ifr_flags of infrastructure network interface. + * + */ +uint32_t otSysGetInfraNetifFlags(void); + +typedef struct otSysInfraNetIfAddressCounters +{ + uint32_t mLinkLocalAddresses; + uint32_t mUniqueLocalAddresses; + uint32_t mGlobalUnicastAddresses; +} otSysInfraNetIfAddressCounters; + +/** + * This functions counts the number of addresses on the infrastructure network interface. + * + * @param[out] aAddressCounters The counters of addresses on infrastructure network interface. + * + */ +void otSysCountInfraNetifAddresses(otSysInfraNetIfAddressCounters *aAddressCounters); + #ifdef __cplusplus } // end of extern "C" #endif diff --git a/src/posix/platform/infra_if.cpp b/src/posix/platform/infra_if.cpp index adbbf7e33..4becc3261 100644 --- a/src/posix/platform/infra_if.cpp +++ b/src/posix/platform/infra_if.cpp @@ -113,6 +113,13 @@ bool platformInfraIfIsRunning(void) { return ot::Posix::InfraNetif::Get().IsRunn const char *otSysGetInfraNetifName(void) { return ot::Posix::InfraNetif::Get().GetNetifName(); } +uint32_t otSysGetInfraNetifFlags(void) { return ot::Posix::InfraNetif::Get().GetFlags(); } + +void otSysCountInfraNetifAddresses(otSysInfraNetIfAddressCounters *aAddressCounters) +{ + ot::Posix::InfraNetif::Get().CountAddresses(*aAddressCounters); +} + namespace ot { namespace Posix { namespace { @@ -163,6 +170,15 @@ int CreateIcmp6Socket(void) return sock; } +bool IsAddressLinkLocal(const in6_addr &aAddress) +{ + return ((aAddress.s6_addr[0] & 0xff) == 0xfe) && ((aAddress.s6_addr[1] & 0xc0) == 0x80); +} + +bool IsAddressUniqueLocal(const in6_addr &aAddress) { return (aAddress.s6_addr[0] & 0xfe) == 0xfc; } + +bool IsAddressGlobalUnicast(const in6_addr &aAddress) { return (aAddress.s6_addr[0] & 0xe0) == 0x20; } + // Create a net-link socket that subscribes to link & addresses events. int CreateNetLinkSocket(void) { @@ -259,7 +275,9 @@ exit: return error; } -bool InfraNetif::IsRunning(void) const +bool InfraNetif::IsRunning(void) const { return (GetFlags() & IFF_RUNNING) && HasLinkLocalAddress(); } + +uint32_t InfraNetif::GetFlags(void) const { int sock; struct ifreq ifReq; @@ -277,7 +295,42 @@ bool InfraNetif::IsRunning(void) const close(sock); - return (ifReq.ifr_flags & IFF_RUNNING) && HasLinkLocalAddress(); + return ifReq.ifr_flags; +} + +void InfraNetif::CountAddresses(otSysInfraNetIfAddressCounters &aAddressCounters) const +{ + struct ifaddrs *ifAddrs = nullptr; + + aAddressCounters.mLinkLocalAddresses = 0; + aAddressCounters.mUniqueLocalAddresses = 0; + aAddressCounters.mGlobalUnicastAddresses = 0; + + if (getifaddrs(&ifAddrs) < 0) + { + otLogWarnPlat("failed to get netif addresses: %s", strerror(errno)); + ExitNow(); + } + + for (struct ifaddrs *addr = ifAddrs; addr != nullptr; addr = addr->ifa_next) + { + in6_addr *in6Addr; + + if (strncmp(addr->ifa_name, mInfraIfName, sizeof(mInfraIfName)) != 0 || addr->ifa_addr->sa_family != AF_INET6) + { + continue; + } + + in6Addr = &(reinterpret_cast(addr->ifa_addr)->sin6_addr); + aAddressCounters.mLinkLocalAddresses += IsAddressLinkLocal(*in6Addr); + aAddressCounters.mUniqueLocalAddresses += IsAddressUniqueLocal(*in6Addr); + aAddressCounters.mGlobalUnicastAddresses += IsAddressGlobalUnicast(*in6Addr); + } + + freeifaddrs(ifAddrs); + +exit: + return; } bool InfraNetif::HasLinkLocalAddress(void) const diff --git a/src/posix/platform/infra_if.hpp b/src/posix/platform/infra_if.hpp index a46e9b782..03146fa27 100644 --- a/src/posix/platform/infra_if.hpp +++ b/src/posix/platform/infra_if.hpp @@ -35,6 +35,7 @@ #include #include +#include #include "core/common/non_copyable.hpp" #include "posix/platform/mainloop.hpp" @@ -107,6 +108,22 @@ public: */ bool IsRunning(void) const; + /** + * This method returns the ifr_flags of the infrastructure network interface. + * + * @returns The ifr_flags of the infrastructure network interface. + * + */ + uint32_t GetFlags(void) const; + + /** + * This functions counts the number of addresses on the infrastructure network interface. + * + * @param[out] aAddressCounters The counters of addresses on infrastructure network interface. + * + */ + void CountAddresses(otSysInfraNetIfAddressCounters &aAddressCounters) const; + /** * This method sends an ICMPv6 Neighbor Discovery message on given infrastructure interface. *