net/netdev: Add periodic log for netdev statistics

Work for every network device using `CONFIG_NETDEV_STATISTICS`.

Log style:
<interface>: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 <wengzhe@xiaomi.com>
This commit is contained in:
Zhe Weng 2024-08-14 18:22:12 +08:00 committed by Xiang Xiao
parent f5fe7646ed
commit acbddd11d5
6 changed files with 168 additions and 2 deletions

View File

@ -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

View File

@ -73,6 +73,14 @@
# include <nuttx/net/mld.h>
#endif
#ifndef CONFIG_NETDEV_STATISTICS_LOG_PERIOD
# define CONFIG_NETDEV_STATISTICS_LOG_PERIOD 0
#endif
#if CONFIG_NETDEV_STATISTICS_LOG_PERIOD > 0
# include <nuttx/wqueue.h>
#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 */

View File

@ -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})

View File

@ -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

99
net/netdev/netdev_stats.c Normal file
View File

@ -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 <nuttx/config.h>
#include <syslog.h>
#include <nuttx/net/netdev.h>
#include <nuttx/net/netstats.h>
/****************************************************************************
* 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

View File

@ -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],