diff --git a/include/net/net_stats.h b/include/net/net_stats.h index 5ab60c03a55..0d0318e2b56 100644 --- a/include/net/net_stats.h +++ b/include/net/net_stats.h @@ -237,6 +237,18 @@ struct net_stats_tc { } recv[NET_TC_RX_COUNT]; }; + +/** + * @brief Power management statistics + */ +struct net_stats_pm { + u64_t overall_suspend_time; + net_stats_t suspend_count; + u32_t last_suspend_time; + u32_t start_time; +}; + + /** * @brief All network statistics in one struct. */ @@ -308,6 +320,10 @@ struct net_stats { /** Network packet RX time statistics */ struct net_stats_rx_time rx_time; #endif + +#if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT) + struct net_stats_pm pm; +#endif }; /** @@ -432,6 +448,7 @@ enum net_request_stats_cmd { NET_REQUEST_STATS_CMD_GET_TCP, NET_REQUEST_STATS_CMD_GET_ETHERNET, NET_REQUEST_STATS_CMD_GET_PPP, + NET_REQUEST_STATS_CMD_GET_PM }; #define NET_REQUEST_STATS_GET_ALL \ @@ -512,6 +529,13 @@ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PPP); #endif /* CONFIG_NET_STATISTICS_USER_API */ +#if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT) +#define NET_REQUEST_STATS_GET_PM \ + (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_PM) + +NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PM); +#endif /* CONFIG_NET_STATISTICS_POWER_MANAGEMENT */ + /** * @} */ diff --git a/subsys/net/ip/Kconfig.stats b/subsys/net/ip/Kconfig.stats index 1764d9a91a1..ff62a7f5f4b 100644 --- a/subsys/net/ip/Kconfig.stats +++ b/subsys/net/ip/Kconfig.stats @@ -111,4 +111,11 @@ config NET_STATISTICS_ETHERNET_VENDOR key-value pairs. Deciphering the information may require vendor documentation. +config NET_STATISTICS_POWER_MANAGEMENT + bool "Power management statistics" + depends on NET_POWER_MANAGEMENT + help + This will provide how many time a network interface went + suspended, for how long the last time and on average. + endif # NET_STATISTICS diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index 0ec705c6cbc..db96baf7b23 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -3636,6 +3636,8 @@ int net_if_suspend(struct net_if *iface) return -EALREADY; } + net_stats_add_suspend_start_time(iface, k_cycle_get_32()); + return 0; } @@ -3647,6 +3649,8 @@ int net_if_resume(struct net_if *iface) net_if_flag_clear(iface, NET_IF_SUSPENDED); + net_stats_add_suspend_end_time(iface, k_cycle_get_32()); + return 0; } diff --git a/subsys/net/ip/net_stats.c b/subsys/net/ip/net_stats.c index c47ac58c0df..8061ef0a5dd 100644 --- a/subsys/net/ip/net_stats.c +++ b/subsys/net/ip/net_stats.c @@ -191,6 +191,18 @@ static inline void stats(struct net_if *iface) ARG_UNUSED(i); #endif /* NET_TC_COUNT > 1 */ +#if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT) + NET_INFO("Power management statistics:"); + NET_INFO("Last suspend time: %u ms", + GET_STAT(iface, pm.last_suspend_time)); + NET_INFO("Got suspended %d times", + GET_STAT(iface, pm.suspend_count)); + NET_INFO("Average suspend time: %u ms", + (u32_t)(GET_STAT(iface, pm.overall_suspend_time) / + GET_STAT(iface, pm.suspend_count))); + NET_INFO("Total suspended time: %llu ms", + GET_STAT(iface, pm.overall_suspend_time)); +#endif next_print = curr + PRINT_STATISTICS_INTERVAL; } } @@ -284,6 +296,12 @@ static int net_stats_get(u32_t mgmt_request, struct net_if *iface, len_chk = sizeof(struct net_stats_tcp); src = GET_STAT_ADDR(iface, tcp); break; +#endif +#if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT) + case NET_REQUEST_STATS_GET_PM: + len_chk = sizeof(struct net_stats_pm); + src = GET_STAT_ADDR(iface, pm); + break; #endif } @@ -338,6 +356,11 @@ NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_TCP, net_stats_get); #endif +#if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT) +NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PM, + net_stats_get); +#endif + #endif /* CONFIG_NET_STATISTICS_USER_API */ void net_stats_reset(struct net_if *iface) diff --git a/subsys/net/ip/net_stats.h b/subsys/net/ip/net_stats.h index 2bd9aea94bd..5e5da39fa18 100644 --- a/subsys/net/ip/net_stats.h +++ b/subsys/net/ip/net_stats.h @@ -463,6 +463,30 @@ static inline void net_stats_update_tc_rx_time(struct net_if *iface, #endif /* NET_PKT_RXTIME_STATS && NET_STATISTICS */ #endif /* NET_TC_COUNT > 1 */ +#if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT) \ + && defined(CONFIG_NET_STATISTICS) && defined(CONFIG_NET_NATIVE) +static inline void net_stats_add_suspend_start_time(struct net_if *iface, + u32_t time) +{ + UPDATE_STAT(iface, stats.pm.start_time = time); +} + +static inline void net_stats_add_suspend_end_time(struct net_if *iface, + u32_t time) +{ + u32_t diff_time = + k_cyc_to_ms_floor32(time - GET_STAT(iface, pm.start_time)); + + UPDATE_STAT(iface, stats.pm.start_time = 0); + UPDATE_STAT(iface, stats.pm.last_suspend_time = diff_time); + UPDATE_STAT(iface, stats.pm.suspend_count++); + UPDATE_STAT(iface, stats.pm.overall_suspend_time += diff_time); +} +#else +#define net_stats_add_suspend_start_time(iface, time) +#define net_stats_add_suspend_end_time(iface, time) +#endif + #if defined(CONFIG_NET_STATISTICS_PERIODIC_OUTPUT) \ && defined(CONFIG_NET_NATIVE) /* A simple periodic statistic printer, used only in net core */