Skip to content

Commit

Permalink
[zephyr] Added support for getting GeneralDiagnostics attributes (#12552
Browse files Browse the repository at this point in the history
)

nrfconnect/Zephyr platform doesn't support get methods for
GeneralDiagnostics attributes

* Added methods for getting RebootCount, NetworkInterfaces
and BootReasons
* Added to the InetIterator methods allowing to get interface
type and hardware address using Zephyr API
* Added BootReasonType to the DiagnosticDataProvider to remove
dependency between platform and auto-generated code
  • Loading branch information
kkasperczyk-no authored and pull[bot] committed Feb 21, 2024
1 parent 92f3a2b commit 4346680
Show file tree
Hide file tree
Showing 18 changed files with 345 additions and 30 deletions.
3 changes: 3 additions & 0 deletions config/nrfconnect/app/sample-defaults.conf
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ CONFIG_ASSERT=y
CONFIG_HW_STACK_PROTECTION=y
CONFIG_SHELL=y

# Enable getting reboot reasons information
CONFIG_HWINFO=y

# Generic networking options
CONFIG_NETWORKING=y
CONFIG_NET_SOCKETS=y
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ using chip::DeviceLayer::ConnectivityMgr;
using chip::DeviceLayer::DiagnosticDataProvider;
using chip::DeviceLayer::GetDiagnosticDataProvider;

static_assert(sizeof(DiagnosticDataProvider::BootReasonType) == sizeof(EmberAfBootReasonType),
"BootReasonType size doesn't match EmberAfBootReasonType size");
static_assert(static_cast<uint8_t>(DiagnosticDataProvider::BootReasonType::Unspecified) == EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED &&
static_cast<uint8_t>(DiagnosticDataProvider::BootReasonType::SoftwareReset) ==
EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_RESET,
"BootReasonType and EmberAfBootReasonType values does not match.");

namespace {

class GeneralDiagosticsAttrAccess : public AttributeAccessInterface
Expand Down
11 changes: 11 additions & 0 deletions src/include/platform/DiagnosticDataProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,17 @@ class WiFiDiagnosticsDelegate
class DiagnosticDataProvider
{
public:
enum BootReasonType : uint8_t
{
Unspecified = 0,
PowerOnReboot = 1,
BrownOutReset = 2,
SoftwareWatchdogReset = 3,
HardwareWatchdogReset = 4,
SoftwareUpdateCompleted = 5,
SoftwareReset = 6,
};

void SetGeneralDiagnosticsDelegate(GeneralDiagnosticsDelegate * delegate) { mGeneralDiagnosticsDelegate = delegate; }
GeneralDiagnosticsDelegate * GetGeneralDiagnosticsDelegate() const { return mGeneralDiagnosticsDelegate; }

Expand Down
66 changes: 66 additions & 0 deletions src/inet/InetInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,16 @@ bool InterfaceIterator::HasBroadcastAddress()
return HasCurrent() && (mCurNetif->flags & NETIF_FLAG_BROADCAST) != 0;
}

CHIP_ERROR InterfaceIterator::GetInterfaceType(InterfaceType & type)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}

CHIP_ERROR InterfaceIterator::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}

bool InterfaceAddressIterator::HasCurrent()
{
return mIntfIter.HasCurrent() && ((mCurAddrIndex != kBeforeStartIndex) || Next());
Expand Down Expand Up @@ -619,6 +629,16 @@ short InterfaceIterator::GetFlags()
return mIntfFlags;
}

CHIP_ERROR InterfaceIterator::GetInterfaceType(InterfaceType & type)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}

CHIP_ERROR InterfaceIterator::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}

InterfaceAddressIterator::InterfaceAddressIterator()
{
mAddrsList = nullptr;
Expand Down Expand Up @@ -850,6 +870,52 @@ bool InterfaceIterator::HasBroadcastAddress()
return HasCurrent() && INET_CONFIG_ENABLE_IPV4;
}

CHIP_ERROR InterfaceIterator::GetInterfaceType(InterfaceType & type)
{
VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);

const net_linkaddr * linkAddr = net_if_get_link_addr(mCurrentInterface);
if (!linkAddr)
return CHIP_ERROR_INCORRECT_STATE;

// Do not consider other than WiFi and Thread for now.
if (linkAddr->type == NET_LINK_IEEE802154)
{
type = InterfaceType::Thread;
}
// Zephyr doesn't define WiFi address type, so it shares the same type as Ethernet.
else if (linkAddr->type == NET_LINK_ETHERNET)
{
type = InterfaceType::WiFi;
}
else
{
type = InterfaceType::Unknown;
}

return CHIP_NO_ERROR;
}

CHIP_ERROR InterfaceIterator::GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize)
{
VerifyOrReturnError(HasCurrent(), CHIP_ERROR_INCORRECT_STATE);

if (!addressBuffer)
return CHIP_ERROR_INVALID_ARGUMENT;

const net_linkaddr * linkAddr = net_if_get_link_addr(mCurrentInterface);
if (!linkAddr)
return CHIP_ERROR_INCORRECT_STATE;

if (linkAddr->len > addressBufferSize)
return CHIP_ERROR_BUFFER_TOO_SMALL;

addressSize = linkAddr->len;
memcpy(addressBuffer, linkAddr->addr, linkAddr->len);

return CHIP_NO_ERROR;
}

InterfaceAddressIterator::InterfaceAddressIterator() = default;

bool InterfaceAddressIterator::HasCurrent()
Expand Down
28 changes: 28 additions & 0 deletions src/inet/InetInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ namespace Inet {
class IPAddress;
class IPPrefix;

/**
* Data type describing interface type.
*/
enum class InterfaceType
{
Unknown = 0,
WiFi = 1,
Ethernet = 2,
Cellular = 3,
Thread = 4,
};

/**
* Indicator for system network interfaces.
*/
Expand Down Expand Up @@ -299,6 +311,22 @@ class InterfaceIterator
*/
bool HasBroadcastAddress();

/**
* Get the interface type of the current network interface.
*
* @param[out] type Object to save the interface type.
*/
CHIP_ERROR GetInterfaceType(InterfaceType & type);

/**
* Get the hardware address of the current network interface
*
* @param[out] addressBuffer Region of memory to write the hardware address.
* @param[out] addressSize Size of the address saved to a buffer.
* @param[in] addressBufferSize Maximum size of a buffer to save data.
*/
CHIP_ERROR GetHardwareAddress(uint8_t * addressBuffer, uint8_t & addressSize, uint8_t addressBufferSize);

protected:
#if CHIP_SYSTEM_CONFIG_USE_LWIP
struct netif * mCurNetif;
Expand Down
29 changes: 29 additions & 0 deletions src/inet/tests/TestInetEndPoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ static void TestInetInterface(nlTestSuite * inSuite, void * inContext)
InterfaceId intId;
IPAddress addr;
IPPrefix addrWithPrefix;
InterfaceType intType;
// 64 bit IEEE MAC address
const uint8_t kMaxHardwareAddressSize = 8;
uint8_t intHwAddress[kMaxHardwareAddressSize];
uint8_t intHwAddressSize;

CHIP_ERROR err;

#ifndef __MBED__
Expand Down Expand Up @@ -165,13 +171,36 @@ static void TestInetInterface(nlTestSuite * inSuite, void * inContext)

intId.GetLinkLocalAddr(&addr);
InterfaceId::MatchLocalIPv6Subnet(addr);

// Not all platforms support getting interface type and hardware address
err = intIterator.GetInterfaceType(intType);
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR || err == CHIP_ERROR_NOT_IMPLEMENTED);

err = intIterator.GetHardwareAddress(intHwAddress, intHwAddressSize, sizeof(intHwAddress));
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR || err == CHIP_ERROR_NOT_IMPLEMENTED);
if (err == CHIP_NO_ERROR)
{
NL_TEST_ASSERT(inSuite, intHwAddressSize == 6 || intHwAddressSize == 8);
NL_TEST_ASSERT(inSuite,
intIterator.GetHardwareAddress(nullptr, intHwAddressSize, sizeof(intHwAddress)) ==
CHIP_ERROR_INVALID_ARGUMENT);
NL_TEST_ASSERT(inSuite,
intIterator.GetHardwareAddress(intHwAddress, intHwAddressSize, 4) == CHIP_ERROR_BUFFER_TOO_SMALL);
}
}

NL_TEST_ASSERT(inSuite, !intIterator.Next());
NL_TEST_ASSERT(inSuite, intIterator.GetInterfaceId() == InterfaceId::Null());
NL_TEST_ASSERT(inSuite, intIterator.GetInterfaceName(intName, sizeof(intName)) == CHIP_ERROR_INCORRECT_STATE);
NL_TEST_ASSERT(inSuite, !intIterator.SupportsMulticast());
NL_TEST_ASSERT(inSuite, !intIterator.HasBroadcastAddress());

// Not all platforms support getting interface type and hardware address
err = intIterator.GetInterfaceType(intType);
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE || err == CHIP_ERROR_NOT_IMPLEMENTED);
err = intIterator.GetHardwareAddress(intHwAddress, intHwAddressSize, sizeof(intHwAddress));
NL_TEST_ASSERT(inSuite, err == CHIP_ERROR_INCORRECT_STATE || err == CHIP_ERROR_NOT_IMPLEMENTED);

printf(" Addresses:\n");
for (; addrIterator.HasCurrent(); addrIterator.Next())
{
Expand Down
3 changes: 2 additions & 1 deletion src/platform/Ameba/ConfigurationManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include <platform/Ameba/AmebaConfig.h>
#include <platform/ConfigurationManager.h>
#include <platform/DiagnosticDataProvider.h>
#include <platform/internal/GenericConfigurationManagerImpl.cpp>
#include <support/CodeUtils.h>
#include <support/logging/CHIPLogging.h>
Expand Down Expand Up @@ -79,7 +80,7 @@ CHIP_ERROR ConfigurationManagerImpl::Init()

if (!AmebaConfig::ConfigValueExists(AmebaConfig::kCounterKey_BootReason))
{
err = StoreBootReason(EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED);
err = StoreBootReason(DiagnosticDataProvider::BootReasonType::Unspecified);
SuccessOrExit(err);
}

Expand Down
23 changes: 12 additions & 11 deletions src/platform/EFR32/ConfigurationManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <platform/internal/GenericConfigurationManagerImpl.cpp>

#include <platform/ConfigurationManager.h>
#include <platform/DiagnosticDataProvider.h>
#include <platform/EFR32/EFR32Config.h>

#include "em_rmu.h"
Expand Down Expand Up @@ -106,50 +107,50 @@ uint32_t ConfigurationManagerImpl::GetBootReason(void)
#if defined(_SILICON_LABS_32B_SERIES_1)
if (rebootCause & RMU_RSTCAUSE_PORST || rebootCause & RMU_RSTCAUSE_EXTRST) // PowerOn or External pin reset
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_POWER_ON_REBOOT;
matterBootCause = DiagnosticDataProvider::BootReasonType::PowerOnReboot;
}
else if (rebootCause & RMU_RSTCAUSE_AVDDBOD || rebootCause & RMU_RSTCAUSE_DVDDBOD || rebootCause & RMU_RSTCAUSE_DECBOD)
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_BROWN_OUT_RESET;
matterBootCause = DiagnosticDataProvider::BootReasonType::BrownOutReset;
}
else if (rebootCause & RMU_RSTCAUSE_SYSREQRST)
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_RESET;
matterBootCause = DiagnosticDataProvider::BootReasonType::SoftwareReset;
}
else if (rebootCause & RMU_RSTCAUSE_WDOGRST)
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_WATCHDOG_RESET;
matterBootCause = DiagnosticDataProvider::BootReasonType::SoftwareWatchdogReset;
}
else
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED;
matterBootCause = DiagnosticDataProvider::BootReasonType::Unspecified;
}
// Not tracked HARDWARE_WATCHDOG_RESET && SOFTWARE_UPDATE_COMPLETED
#elif defined(_SILICON_LABS_32B_SERIES_2)
if (rebootCause & EMU_RSTCAUSE_POR || rebootCause & EMU_RSTCAUSE_PIN) // PowerOn or External pin reset
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_POWER_ON_REBOOT;
matterBootCause = DiagnosticDataProvider::BootReasonType::PowerOnReboot;
}
else if (rebootCause & EMU_RSTCAUSE_AVDDBOD || rebootCause & EMU_RSTCAUSE_DVDDBOD || rebootCause & EMU_RSTCAUSE_DECBOD ||
rebootCause & EMU_RSTCAUSE_VREGIN || rebootCause & EMU_RSTCAUSE_IOVDD0BOD || rebootCause & EMU_RSTCAUSE_DVDDLEBOD)
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_BROWN_OUT_RESET;
matterBootCause = DiagnosticDataProvider::BootReasonType::BrownOutReset;
}
else if (rebootCause & EMU_RSTCAUSE_SYSREQ)
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_RESET;
matterBootCause = DiagnosticDataProvider::BootReasonType::SoftwareReset;
}
else if (rebootCause & EMU_RSTCAUSE_WDOG0 || rebootCause & EMU_RSTCAUSE_WDOG1)
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_WATCHDOG_RESET;
matterBootCause = DiagnosticDataProvider::BootReasonType::SoftwareWatchdogReset;
}
else
{
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED;
matterBootCause = DiagnosticDataProvider::BootReasonType::Unspecified;
}
// Not tracked HARDWARE_WATCHDOG_RESET && SOFTWARE_UPDATE_COMPLETED
#else
matterBootCause = EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED;
matterBootCause = DiagnosticDataProvider::BootReasonType::Unspecified;
#endif

return matterBootCause;
Expand Down
12 changes: 6 additions & 6 deletions src/platform/ESP32/DiagnosticDataProviderImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,28 +167,28 @@ CHIP_ERROR DiagnosticDataProviderImpl::GetTotalOperationalHours(uint32_t & total

CHIP_ERROR DiagnosticDataProviderImpl::GetBootReason(uint8_t & bootReason)
{
bootReason = EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED;
bootReason = BootReasonType::Unspecified;
uint8_t reason;
reason = static_cast<uint8_t>(esp_reset_reason());
if (reason == ESP_RST_UNKNOWN)
{
bootReason = EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED;
bootReason = BootReasonType::Unspecified;
}
else if (reason == ESP_RST_POWERON)
{
bootReason = EMBER_ZCL_BOOT_REASON_TYPE_POWER_ON_REBOOT;
bootReason = BootReasonType::PowerOnReboot;
}
else if (reason == ESP_RST_BROWNOUT)
{
bootReason = EMBER_ZCL_BOOT_REASON_TYPE_BROWN_OUT_RESET;
bootReason = BootReasonType::BrownOutReset;
}
else if (reason == ESP_RST_SW)
{
bootReason = EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_RESET;
bootReason = BootReasonType::SoftwareReset;
}
else if (reason == ESP_RST_INT_WDT)
{
bootReason = EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_WATCHDOG_RESET;
bootReason = BootReasonType::SoftwareWatchdogReset;
/* Reboot can be due to hardware or software watchdog*/
}
return CHIP_NO_ERROR;
Expand Down
3 changes: 2 additions & 1 deletion src/platform/Linux/ConfigurationManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <lib/support/logging/CHIPLogging.h>
#include <netpacket/packet.h>
#include <platform/ConfigurationManager.h>
#include <platform/DiagnosticDataProvider.h>
#include <platform/Linux/PosixConfig.h>
#include <platform/internal/GenericConfigurationManagerImpl.cpp>

Expand Down Expand Up @@ -87,7 +88,7 @@ CHIP_ERROR ConfigurationManagerImpl::Init()

if (!PosixConfig::ConfigValueExists(PosixConfig::kCounterKey_BootReason))
{
err = StoreBootReason(EMBER_ZCL_BOOT_REASON_TYPE_UNSPECIFIED);
err = StoreBootReason(DiagnosticDataProvider::BootReasonType::Unspecified);
SuccessOrExit(err);
}

Expand Down
12 changes: 6 additions & 6 deletions src/platform/Linux/PlatformManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,27 +63,27 @@ void SignalHandler(int signum)
switch (signum)
{
case SIGINT:
ConfigurationMgr().StoreBootReason(EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_RESET);
ConfigurationMgr().StoreBootReason(DiagnosticDataProvider::BootReasonType::SoftwareReset);
err = CHIP_ERROR_REBOOT_SIGNAL_RECEIVED;
break;
case SIGHUP:
ConfigurationMgr().StoreBootReason(EMBER_ZCL_BOOT_REASON_TYPE_BROWN_OUT_RESET);
ConfigurationMgr().StoreBootReason(DiagnosticDataProvider::BootReasonType::BrownOutReset);
err = CHIP_ERROR_REBOOT_SIGNAL_RECEIVED;
break;
case SIGTERM:
ConfigurationMgr().StoreBootReason(EMBER_ZCL_BOOT_REASON_TYPE_POWER_ON_REBOOT);
ConfigurationMgr().StoreBootReason(DiagnosticDataProvider::BootReasonType::PowerOnReboot);
err = CHIP_ERROR_REBOOT_SIGNAL_RECEIVED;
break;
case SIGUSR1:
ConfigurationMgr().StoreBootReason(EMBER_ZCL_BOOT_REASON_TYPE_HARDWARE_WATCHDOG_RESET);
ConfigurationMgr().StoreBootReason(DiagnosticDataProvider::BootReasonType::HardwareWatchdogReset);
err = CHIP_ERROR_REBOOT_SIGNAL_RECEIVED;
break;
case SIGUSR2:
ConfigurationMgr().StoreBootReason(EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_WATCHDOG_RESET);
ConfigurationMgr().StoreBootReason(DiagnosticDataProvider::BootReasonType::SoftwareWatchdogReset);
err = CHIP_ERROR_REBOOT_SIGNAL_RECEIVED;
break;
case SIGTSTP:
ConfigurationMgr().StoreBootReason(EMBER_ZCL_BOOT_REASON_TYPE_SOFTWARE_UPDATE_COMPLETED);
ConfigurationMgr().StoreBootReason(DiagnosticDataProvider::BootReasonType::SoftwareUpdateCompleted);
err = CHIP_ERROR_REBOOT_SIGNAL_RECEIVED;
break;
case SIGTRAP:
Expand Down
Loading

0 comments on commit 4346680

Please sign in to comment.