From acbddd11d53c22e7fc7f24ffbb8f62322f590742 Mon Sep 17 00:00:00 2001 From: Zhe Weng Date: Wed, 14 Aug 2024 18:22:12 +0800 Subject: [PATCH] net/netdev: Add periodic log for netdev statistics Work for every network device using `CONFIG_NETDEV_STATISTICS`. Log style: :T{done}/{total},R({v4}+{v6})/{total} {Protocol}:T{tx},R{rx},D{drop} Example: wlan0:T10/10,R(10+20)/31 TCP:T0,R0,D0 UDP:T0,R10,D0 ICMP:T0,R0,D0 ICMP6:T0,R0,D0 Signed-off-by: Zhe Weng --- drivers/net/Kconfig | 8 +++ include/nuttx/net/netdev.h | 51 +++++++++++++++++- net/netdev/CMakeLists.txt | 4 ++ net/netdev/Make.defs | 4 ++ net/netdev/netdev_stats.c | 99 ++++++++++++++++++++++++++++++++++ net/netdev/netdev_unregister.c | 4 ++ 6 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 net/netdev/netdev_stats.c diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index f304f829b0..78bb450e3b 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -131,6 +131,14 @@ config NETDEV_STATISTICS Enable to collect statistics from the network drivers (if supported by the network driver). +config NETDEV_STATISTICS_LOG_PERIOD + int "Network device statistics log period" + default 0 + depends on NETDEV_STATISTICS && DEBUG_FEATURES + ---help--- + Period in seconds to log network device statistics. Zero means + disable logging. + config NET_DUMPPACKET bool "Enable packet dumping" depends on DEBUG_FEATURES diff --git a/include/nuttx/net/netdev.h b/include/nuttx/net/netdev.h index 2bd529cd1e..78210d4cc7 100644 --- a/include/nuttx/net/netdev.h +++ b/include/nuttx/net/netdev.h @@ -73,6 +73,14 @@ # include #endif +#ifndef CONFIG_NETDEV_STATISTICS_LOG_PERIOD +# define CONFIG_NETDEV_STATISTICS_LOG_PERIOD 0 +#endif + +#if CONFIG_NETDEV_STATISTICS_LOG_PERIOD > 0 +# include +#endif + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -112,7 +120,26 @@ } \ while (0) -# define NETDEV_RXPACKETS(dev) _NETDEV_STATISTIC(dev,rx_packets) +# if CONFIG_NETDEV_STATISTICS_LOG_PERIOD > 0 +# define NETDEV_STATISTICS_WORK LPWORK +# define _NETDEV_STATISTIC_LOG(dev,name) \ + do \ + { \ + _NETDEV_STATISTIC(dev,name); \ + if (work_available(&(dev)->d_statistics.logwork)) \ + { \ + work_queue(NETDEV_STATISTICS_WORK, \ + &(dev)->d_statistics.logwork, \ + netdev_statistics_log, (dev), \ + SEC2TICK(CONFIG_NETDEV_STATISTICS_LOG_PERIOD)); \ + } \ + } \ + while (0) +# else +# define _NETDEV_STATISTIC_LOG(dev,name) _NETDEV_STATISTIC(dev,name) +# endif + +# define NETDEV_RXPACKETS(dev) _NETDEV_STATISTIC_LOG(dev,rx_packets) # define NETDEV_RXFRAGMENTS(dev) _NETDEV_STATISTIC(dev,rx_fragments) # define NETDEV_RXERRORS(dev) _NETDEV_ERROR(dev,rx_errors) # ifdef CONFIG_NET_IPv4 @@ -132,7 +159,7 @@ # endif # define NETDEV_RXDROPPED(dev) _NETDEV_STATISTIC(dev,rx_dropped) -# define NETDEV_TXPACKETS(dev) _NETDEV_STATISTIC(dev,tx_packets) +# define NETDEV_TXPACKETS(dev) _NETDEV_STATISTIC_LOG(dev,tx_packets) # define NETDEV_TXDONE(dev) _NETDEV_STATISTIC(dev,tx_done) # define NETDEV_TXERRORS(dev) _NETDEV_ERROR(dev,tx_errors) # define NETDEV_TXTIMEOUTS(dev) _NETDEV_ERROR(dev,tx_timeouts) @@ -219,6 +246,10 @@ struct netdev_statistics_s /* Other status */ uint32_t errors; /* Total number of errors */ + +#if CONFIG_NETDEV_STATISTICS_LOG_PERIOD > 0 + struct work_s logwork; /* For periodic log work */ +#endif }; #endif @@ -1196,4 +1227,20 @@ int netdev_ipv6_foreach(FAR struct net_driver_s *dev, devif_ipv6_callback_t callback, FAR void *arg); #endif +/**************************************************************************** + * Name: netdev_statistics_log + * + * Description: + * The actual implementation of the network statistics logging. Log + * network statistics at regular intervals. + * + * Input Parameters: + * arg - The pointer to the network device + * + ****************************************************************************/ + +#if CONFIG_NETDEV_STATISTICS_LOG_PERIOD > 0 +void netdev_statistics_log(FAR void *arg); +#endif + #endif /* __INCLUDE_NUTTX_NET_NETDEV_H */ diff --git a/net/netdev/CMakeLists.txt b/net/netdev/CMakeLists.txt index 53c9254bac..d2b8cf8ccc 100644 --- a/net/netdev/CMakeLists.txt +++ b/net/netdev/CMakeLists.txt @@ -46,4 +46,8 @@ if(CONFIG_NET_IPv6) list(APPEND SRCS netdev_ipv6.c) endif() +if(CONFIG_NETDEV_STATISTICS) + list(APPEND SRCS netdev_stats.c) +endif() + target_sources(net PRIVATE ${SRCS}) diff --git a/net/netdev/Make.defs b/net/netdev/Make.defs index a273c5d6a9..4df0e4a335 100644 --- a/net/netdev/Make.defs +++ b/net/netdev/Make.defs @@ -38,6 +38,10 @@ ifeq ($(CONFIG_NET_IPv6),y) NETDEV_CSRCS += netdev_ipv6.c endif +ifeq ($(CONFIG_NETDEV_STATISTICS),y) +NETDEV_CSRCS += netdev_stats.c +endif + # Include netdev build support DEPPATH += --dep-path netdev diff --git a/net/netdev/netdev_stats.c b/net/netdev/netdev_stats.c new file mode 100644 index 0000000000..2db04d9c8f --- /dev/null +++ b/net/netdev/netdev_stats.c @@ -0,0 +1,99 @@ +/**************************************************************************** + * net/netdev/netdev_stats.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define stats_log(format, ...) syslog(LOG_NOTICE, format, ##__VA_ARGS__) + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: netdev_statistics_log + * + * Description: + * The actual implementation of the network statistics logging. Log + * network statistics at regular intervals. + * + * Input Parameters: + * arg - The pointer to the network device + * + ****************************************************************************/ + +#if CONFIG_NETDEV_STATISTICS_LOG_PERIOD > 0 +void netdev_statistics_log(FAR void *arg) +{ + FAR struct net_driver_s *dev = arg; + FAR struct netdev_statistics_s *stats = &dev->d_statistics; + + stats_log("%s:T%" PRIu32 "/%" PRIu32 ",R" +#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6) + "(%" PRIu32 "+%" PRIu32 ")/" +#endif + "%" PRIu32 +#ifdef CONFIG_NET_TCP + " TCP:T%" PRIu16 ",R%" PRIu16 ",D%" PRIu16 +#endif +#ifdef CONFIG_NET_UDP + " UDP:T%" PRIu16 ",R%" PRIu16 ",D%" PRIu16 +#endif +#ifdef CONFIG_NET_ICMP + " ICMP:T%" PRIu16 ",R%" PRIu16 ",D%" PRIu16 +#endif +#ifdef CONFIG_NET_ICMPv6 + " ICMP6:T%" PRIu16 ",R%" PRIu16 ",D%" PRIu16 +#endif + "\n", + dev->d_ifname, stats->tx_done, stats->tx_packets +#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6) + , stats->rx_ipv4, stats->rx_ipv6 +#endif + , stats->rx_packets +#ifdef CONFIG_NET_TCP + , g_netstats.tcp.sent, g_netstats.tcp.recv, g_netstats.tcp.drop +#endif +#ifdef CONFIG_NET_UDP + , g_netstats.udp.sent, g_netstats.udp.recv, g_netstats.udp.drop +#endif +#ifdef CONFIG_NET_ICMP + , g_netstats.icmp.sent, g_netstats.icmp.recv, + g_netstats.icmp.drop +#endif +#ifdef CONFIG_NET_ICMPv6 + , g_netstats.icmpv6.sent, g_netstats.icmpv6.recv, + g_netstats.icmpv6.drop +#endif + ); +} +#endif diff --git a/net/netdev/netdev_unregister.c b/net/netdev/netdev_unregister.c index dd5d2df768..c0f9b219b6 100644 --- a/net/netdev/netdev_unregister.c +++ b/net/netdev/netdev_unregister.c @@ -150,6 +150,10 @@ int netdev_unregister(FAR struct net_driver_s *dev) #endif net_unlock(); +#if CONFIG_NETDEV_STATISTICS_LOG_PERIOD > 0 + work_cancel_sync(NETDEV_STATISTICS_WORK, &dev->d_statistics.logwork); +#endif + #ifdef CONFIG_NET_ETHERNET ninfo("Unregistered MAC: %02x:%02x:%02x:%02x:%02x:%02x as dev: %s\n", dev->d_mac.ether.ether_addr_octet[0],