From 6707c20b7d34a7e488826056615111e969a6dad2 Mon Sep 17 00:00:00 2001 From: Oleg Hahm <oleg@hobbykeller.org> Date: Sun, 14 Feb 2016 14:49:03 +0100 Subject: [PATCH] netstats: initial import of IPv6 netstats --- Makefile.dep | 4 + Makefile.pseudomodules | 2 + examples/gnrc_networking/Makefile | 2 + sys/include/net/gnrc/ipv6/netif.h | 16 ++++ sys/include/net/netstats.h | 11 +++ sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c | 18 ++++ .../ipv6/netif/gnrc_ipv6_netif.c | 8 ++ sys/shell/commands/sc_netif.c | 83 ++++++++++++++++--- 8 files changed, 132 insertions(+), 12 deletions(-) diff --git a/Makefile.dep b/Makefile.dep index aeeeeba1e0..1eb0b3870a 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -507,6 +507,10 @@ ifneq (,$(filter gnrc_netdev2,$(USEMODULE))) USEMODULE += netopt endif +ifneq (,$(filter netstats_%, $(USEMODULE))) + USEMODULE += netstats +endif + ifneq (,$(filter pthread,$(USEMODULE))) USEMODULE += xtimer USEMODULE += timex diff --git a/Makefile.pseudomodules b/Makefile.pseudomodules index 2bc202a645..ddb8d76fcd 100644 --- a/Makefile.pseudomodules +++ b/Makefile.pseudomodules @@ -33,7 +33,9 @@ PSEUDOMODULES += lwip_udp PSEUDOMODULES += lwip_udplite PSEUDOMODULES += netdev_default PSEUDOMODULES += netif +PSEUDOMODULES += netstats PSEUDOMODULES += netstats_l2 +PSEUDOMODULES += netstats_ipv6 PSEUDOMODULES += newlib PSEUDOMODULES += newlib_nano PSEUDOMODULES += pktqueue diff --git a/examples/gnrc_networking/Makefile b/examples/gnrc_networking/Makefile index ce2441c12b..a40d111056 100644 --- a/examples/gnrc_networking/Makefile +++ b/examples/gnrc_networking/Makefile @@ -29,6 +29,8 @@ USEMODULE += gnrc_icmpv6_echo USEMODULE += shell USEMODULE += shell_commands USEMODULE += ps +USEMODULE += netstats_l2 +USEMODULE += netstats_ipv6 # Comment this out to disable code in RIOT that does safety checking # which is not needed in a production environment but helps in the diff --git a/sys/include/net/gnrc/ipv6/netif.h b/sys/include/net/gnrc/ipv6/netif.h index a1bcfa571b..4de109421e 100644 --- a/sys/include/net/gnrc/ipv6/netif.h +++ b/sys/include/net/gnrc/ipv6/netif.h @@ -30,6 +30,7 @@ #include "mutex.h" #include "net/ipv6.h" #include "net/ipv6/addr.h" +#include "net/netstats.h" #include "xtimer.h" #ifdef __cplusplus @@ -344,6 +345,9 @@ typedef struct { xtimer_t rtr_adv_timer; /**< Timer for periodic router advertisements */ msg_t rtr_adv_msg; /**< msg_t for gnrc_ipv6_netif_t::rtr_adv_timer */ #endif +#ifdef MODULE_NETSTATS_IPV6 + netstats_t stats; /**< transceiver's statistics */ +#endif } gnrc_ipv6_netif_t; /** @@ -587,6 +591,18 @@ static inline bool gnrc_ipv6_netif_addr_is_non_unicast(const ipv6_addr_t *addr) */ void gnrc_ipv6_netif_init_by_dev(void); +/** + * @brief Get sent and received statistics about IPv6 traffic on this interface. + * + * @note This function is only available if compiled with module `netstats_ipv6`. + * + * @param[in] pid The PID to the interface. + * + * @return A @ref netstats_t pointer to the statistics. + * @return NULL if no statistics are available. + */ +netstats_t *gnrc_ipv6_netif_get_stats(kernel_pid_t pid); + #ifdef __cplusplus } #endif diff --git a/sys/include/net/netstats.h b/sys/include/net/netstats.h index 152bbc6e30..1bbb4ee32b 100644 --- a/sys/include/net/netstats.h +++ b/sys/include/net/netstats.h @@ -18,6 +18,8 @@ * @author Oliver Hahm <oliver.hahm@inria.fr> */ +#include <stdint.h> + #ifndef NETSTATS_H #define NETSTATS_H @@ -25,6 +27,15 @@ extern "C" { #endif +/** + * @name @ref net_netstats module names + * @{ + */ +#define NETSTATS_LAYER2 (0x01) +#define NETSTATS_IPV6 (0x02) +#define NETSTATS_ALL (0xFF) +/** @} */ + /** * @brief Global statistics struct */ diff --git a/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c b/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c index 27cdd52569..397429c0dd 100644 --- a/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c +++ b/sys/net/gnrc/network_layer/ipv6/gnrc_ipv6.c @@ -373,6 +373,11 @@ static void _send_to_iface(kernel_pid_t iface, gnrc_pktsnip_t *pkt) gnrc_pktbuf_release(pkt); return; } +#ifdef MODULE_NETSTATS_IPV6 + if_entry->stats.tx_success++; + if_entry->stats.tx_bytes += gnrc_pkt_len(pkt->next); +#endif + #ifdef MODULE_GNRC_SIXLOWPAN if (if_entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) { DEBUG("ipv6: send to 6LoWPAN instead\n"); @@ -419,6 +424,9 @@ static void _send_unicast(kernel_pid_t iface, uint8_t *dst_l2addr, DEBUG("ipv6: send unicast over interface %" PRIkernel_pid "\n", iface); /* and send to interface */ +#ifdef MODULE_NETSTATS_IPV6 + gnrc_ipv6_netif_get_stats(iface)->tx_unicast_count++; +#endif _send_to_iface(iface, pkt); } @@ -486,6 +494,9 @@ static inline void _send_multicast_over_iface(kernel_pid_t iface, gnrc_pktsnip_t DEBUG("ipv6: send multicast over interface %" PRIkernel_pid "\n", iface); /* mark as multicast */ ((gnrc_netif_hdr_t *)pkt->data)->flags |= GNRC_NETIF_HDR_FLAGS_MULTICAST; +#ifdef MODULE_NETSTATS_IPV6 + gnrc_ipv6_netif_get_stats(iface)->tx_mcast_count++; +#endif /* and send to interface */ _send_to_iface(iface, pkt); } @@ -788,6 +799,13 @@ static void _receive(gnrc_pktsnip_t *pkt) if (netif != NULL) { iface = ((gnrc_netif_hdr_t *)netif->data)->if_pid; + +#ifdef MODULE_NETSTATS_IPV6 + assert(iface); + netstats_t *stats = gnrc_ipv6_netif_get_stats(iface); + stats->rx_count++; + stats->rx_bytes += (gnrc_pkt_len(pkt) - netif->size); +#endif } first_ext = pkt; diff --git a/sys/net/gnrc/network_layer/ipv6/netif/gnrc_ipv6_netif.c b/sys/net/gnrc/network_layer/ipv6/netif/gnrc_ipv6_netif.c index 553423a7e4..c083b2946e 100644 --- a/sys/net/gnrc/network_layer/ipv6/netif/gnrc_ipv6_netif.c +++ b/sys/net/gnrc/network_layer/ipv6/netif/gnrc_ipv6_netif.c @@ -897,6 +897,14 @@ void gnrc_ipv6_netif_init_by_dev(void) } } +#ifdef MODULE_NETSTATS_IPV6 +netstats_t *gnrc_ipv6_netif_get_stats(kernel_pid_t pid) +{ + gnrc_ipv6_netif_t *iface = gnrc_ipv6_netif_get(pid); + return &(iface->stats); +} +#endif + /** * @} */ diff --git a/sys/shell/commands/sc_netif.c b/sys/shell/commands/sc_netif.c index f6d760e49e..343ed0f4c0 100644 --- a/sys/shell/commands/sc_netif.c +++ b/sys/shell/commands/sc_netif.c @@ -73,23 +73,51 @@ static bool _is_iface(kernel_pid_t dev) return false; } -#ifdef MODULE_NETSTATS_L2 -static int _netif_stats(kernel_pid_t dev, bool reset) +#if defined(MODULE_NETSTATS) +const char *_netstats_module_to_str(uint8_t module) +{ + switch (module) { + case NETSTATS_LAYER2: + return "Layer 2"; + case NETSTATS_IPV6: + return "IPv6"; + case NETSTATS_ALL: + return "all"; + default: + return "Unknown"; + } +} + +static int _netif_stats(kernel_pid_t dev, unsigned module, bool reset) { netstats_t *stats; int res = -ENOTSUP; - res = gnrc_netapi_get(dev, NETOPT_STATS, 0, &stats, sizeof(&stats)); + + if (module == NETSTATS_LAYER2) { + res = gnrc_netapi_get(dev, NETOPT_STATS, 0, &stats, sizeof(&stats)); + } +#ifdef MODULE_NETSTATS_IPV6 + else if (module == NETSTATS_IPV6) { + stats = gnrc_ipv6_netif_get_stats(dev); + if (stats != NULL) { + res = 1; + } + } +#endif + if (res < 0) { puts(" Protocol or device doesn't provide statistics."); } else if (reset) { memset(stats, 0, sizeof(netstats_t)); - puts("Reset statistics!"); + printf("Reset statistics for module %s!\n", _netstats_module_to_str(module)); } else { - printf(" RX packets %u bytes %u\n" - " TX packets %u (Multicast: %u) bytes %u\n" - " TX succeeded %u errors %u\n", + printf(" Statistics for %s\n" + " RX packets %u bytes %u\n" + " TX packets %u (Multicast: %u) bytes %u\n" + " TX succeeded %u errors %u\n", + _netstats_module_to_str(module), (unsigned) stats->rx_count, (unsigned) stats->rx_bytes, (unsigned) (stats->tx_unicast_count + stats->tx_mcast_count), @@ -97,6 +125,7 @@ static int _netif_stats(kernel_pid_t dev, bool reset) (unsigned) stats->tx_bytes, (unsigned) stats->tx_success, (unsigned) stats->tx_failed); + res = 0; } return res; } @@ -155,7 +184,8 @@ static void _del_usage(char *cmd_name) static void _stats_usage(char *cmd_name) { - printf("usage: %s <if_id> stats [reset]\n", cmd_name); + printf("usage: %s <if_id> stats [l2|ipv6] [reset]\n", cmd_name); + puts(" reset can be only used if the module is specified."); } static void _print_netopt(netopt_t opt) @@ -460,7 +490,10 @@ static void _netif_list(kernel_pid_t dev) #ifdef MODULE_NETSTATS_L2 puts(""); - _netif_stats(dev, false); + _netif_stats(dev, NETSTATS_LAYER2, false); +#endif +#ifdef MODULE_NETSTATS_IPV6 + _netif_stats(dev, NETSTATS_IPV6, false); #endif puts(""); } @@ -1106,13 +1139,39 @@ int _netif_config(int argc, char **argv) return _netif_mtu((kernel_pid_t)dev, argv[3]); } -#ifdef MODULE_NETSTATS_L2 +#ifdef MODULE_NETSTATS else if (strcmp(argv[2], "stats") == 0) { + uint8_t module; bool reset = false; - if ((argc > 3) && (strncmp(argv[3], "reset", 5) == 0)) { + + /* check for requested module */ + if ((argc == 3) || (strcmp(argv[3], "all") == 0)) { + module = NETSTATS_ALL; + } + else if (strcmp(argv[3], "l2") == 0) { + module = NETSTATS_LAYER2; + } + else if (strcmp(argv[3], "ipv6") == 0) { + module = NETSTATS_IPV6; + } + else { + printf("Module %s doesn't exist or does not provide statistics.\n", argv[3]); + + return 0; + } + + /* check if reset flag was given */ + if ((argc > 4) && (strncmp(argv[4], "reset", 5) == 0)) { reset = true; } - return _netif_stats((kernel_pid_t)dev, reset); + if (module & NETSTATS_LAYER2) { + _netif_stats((kernel_pid_t) dev, NETSTATS_LAYER2, reset); + } + if (module & NETSTATS_IPV6) { + _netif_stats((kernel_pid_t) dev, NETSTATS_IPV6, reset); + } + + return 1; } #endif #ifdef MODULE_GNRC_IPV6_NETIF -- GitLab