mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-08-03 15:34:20 +00:00
net: stats: Add traffic class statistics
Add statistics for number of packets and bytes to each traffic class. Print this information in net-shell. Also make sure that we do not calculate total packet length many times. So calculate network packet total length once and then use that value instead of calculating it many times in a row. Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
2a3de97ce9
commit
99e93db6b2
|
@ -58,3 +58,9 @@
|
|||
^(?P<filename>[-._/\w]+/doc/api/networking.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*net_context.options
|
||||
^[- \t]*\^
|
||||
#
|
||||
# include/net/net_stats.h
|
||||
#
|
||||
^(?P<filename>[-._/\w]+/doc/api/networking.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
|
||||
^.*net_stats_tc.[a-z]+
|
||||
^[- \t]*\^
|
||||
|
|
|
@ -80,6 +80,13 @@ struct net_pkt {
|
|||
struct net_linkaddr lladdr_src;
|
||||
struct net_linkaddr lladdr_dst;
|
||||
|
||||
#if defined(CONFIG_NET_STATISTICS)
|
||||
/* If statistics is enabled, then speed up length calculation by
|
||||
* doing it only once. This value is updated in net_if_queue_tx()
|
||||
* when packet is about to be sent.
|
||||
*/
|
||||
u16_t total_pkt_len;
|
||||
#endif
|
||||
u16_t data_len; /* amount of payload data that can be added */
|
||||
|
||||
u16_t appdatalen;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#define __NET_STATS_H
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <net/net_core.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -228,6 +229,23 @@ struct net_stats_ipv6_mld {
|
|||
net_stats_t drop;
|
||||
};
|
||||
|
||||
struct net_stats_tc {
|
||||
/** Traffic class sent statistics */
|
||||
struct {
|
||||
net_stats_t pkts;
|
||||
net_stats_t bytes;
|
||||
u8_t priority;
|
||||
} sent[NET_TC_TX_COUNT];
|
||||
|
||||
/** Traffic class receive statistics */
|
||||
struct {
|
||||
net_stats_t pkts;
|
||||
net_stats_t bytes;
|
||||
u8_t priority;
|
||||
} recv[NET_TC_RX_COUNT];
|
||||
};
|
||||
|
||||
|
||||
struct net_stats {
|
||||
net_stats_t processing_error;
|
||||
|
||||
|
@ -270,6 +288,10 @@ struct net_stats {
|
|||
#if defined(CONFIG_NET_IPV6_MLD)
|
||||
struct net_stats_ipv6_mld ipv6_mld;
|
||||
#endif
|
||||
|
||||
#if NET_TC_COUNT > 1
|
||||
struct net_stats_tc tc;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(CONFIG_NET_STATISTICS_USER_API)
|
||||
|
|
|
@ -284,7 +284,12 @@ int net_send_data(struct net_pkt *pkt)
|
|||
static void net_rx(struct net_if *iface, struct net_pkt *pkt)
|
||||
{
|
||||
#if defined(CONFIG_NET_STATISTICS) || defined(CONFIG_NET_DEBUG_CORE)
|
||||
size_t pkt_len = net_pkt_get_len(pkt);
|
||||
size_t pkt_len;
|
||||
#if defined(CONFIG_NET_STATISTICS)
|
||||
pkt_len = pkt->total_pkt_len;
|
||||
#else
|
||||
pkt_len = net_pkt_get_len(pkt);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
NET_DBG("Received pkt %p len %zu", pkt, pkt_len);
|
||||
|
@ -313,6 +318,14 @@ static void net_queue_rx(struct net_if *iface, struct net_pkt *pkt)
|
|||
|
||||
k_work_init(net_pkt_work(pkt), process_rx_packet);
|
||||
|
||||
#if defined(CONFIG_NET_STATISTICS)
|
||||
pkt->total_pkt_len = net_pkt_get_len(pkt);
|
||||
|
||||
net_stats_update_tc_recv_pkt(tc);
|
||||
net_stats_update_tc_recv_bytes(tc, pkt->total_pkt_len);
|
||||
net_stats_update_tc_recv_priority(tc, prio);
|
||||
#endif
|
||||
|
||||
#if NET_TC_RX_COUNT > 1
|
||||
NET_DBG("TC %d with prio %d pkt %p", tc, prio, pkt);
|
||||
#endif
|
||||
|
|
|
@ -70,17 +70,25 @@ static sys_slist_t mcast_monitor_callbacks;
|
|||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_DEBUG_IF)
|
||||
#if defined(CONFIG_NET_STATISTICS)
|
||||
#define debug_check_packet(pkt) \
|
||||
{ \
|
||||
size_t len = net_pkt_get_len(pkt); \
|
||||
\
|
||||
NET_DBG("Processing (pkt %p, data len %zu, " \
|
||||
do { \
|
||||
NET_DBG("Processing (pkt %p, data len %d, " \
|
||||
"prio %d) network packet", \
|
||||
pkt, len, \
|
||||
pkt, pkt->total_pkt_len, \
|
||||
net_pkt_priority(pkt)); \
|
||||
\
|
||||
NET_ASSERT(pkt->frags && len); \
|
||||
NET_ASSERT(pkt->frags && pkt->total_pkt_len); \
|
||||
} while (0)
|
||||
#else /* CONFIG_NET_STATISTICS */
|
||||
#define debug_check_packet(pkt) \
|
||||
do { \
|
||||
NET_DBG("Processing (pkt %p, prio %d) network packet", \
|
||||
pkt, net_pkt_priority(pkt)); \
|
||||
\
|
||||
NET_ASSERT(pkt->frags); \
|
||||
} while (0)
|
||||
#endif /* CONFIG_NET_STATISTICS */
|
||||
#else
|
||||
#define debug_check_packet(...)
|
||||
#endif /* CONFIG_NET_DEBUG_IF */
|
||||
|
@ -117,9 +125,6 @@ static bool net_if_tx(struct net_if *iface, struct net_pkt *pkt)
|
|||
struct net_context *context;
|
||||
void *context_token;
|
||||
int status;
|
||||
#if defined(CONFIG_NET_STATISTICS)
|
||||
size_t pkt_len;
|
||||
#endif
|
||||
|
||||
if (!pkt) {
|
||||
return false;
|
||||
|
@ -132,10 +137,6 @@ static bool net_if_tx(struct net_if *iface, struct net_pkt *pkt)
|
|||
context_token = net_pkt_token(pkt);
|
||||
|
||||
if (atomic_test_bit(iface->if_dev->flags, NET_IF_UP)) {
|
||||
#if defined(CONFIG_NET_STATISTICS)
|
||||
pkt_len = net_pkt_get_len(pkt);
|
||||
#endif
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_TCP)) {
|
||||
net_pkt_set_sent(pkt, true);
|
||||
net_pkt_set_queued(pkt, false);
|
||||
|
@ -155,7 +156,7 @@ static bool net_if_tx(struct net_if *iface, struct net_pkt *pkt)
|
|||
|
||||
net_pkt_unref(pkt);
|
||||
} else {
|
||||
net_stats_update_bytes_sent(pkt_len);
|
||||
net_stats_update_bytes_sent(pkt->total_pkt_len);
|
||||
}
|
||||
|
||||
if (context) {
|
||||
|
@ -188,6 +189,14 @@ void net_if_queue_tx(struct net_if *iface, struct net_pkt *pkt)
|
|||
|
||||
k_work_init(net_pkt_work(pkt), process_tx_packet);
|
||||
|
||||
#if defined(CONFIG_NET_STATISTICS)
|
||||
pkt->total_pkt_len = net_pkt_get_len(pkt);
|
||||
|
||||
net_stats_update_tc_sent_pkt(tc);
|
||||
net_stats_update_tc_sent_bytes(tc, pkt->total_pkt_len);
|
||||
net_stats_update_tc_sent_priority(tc, prio);
|
||||
#endif
|
||||
|
||||
#if NET_TC_TX_COUNT > 1
|
||||
NET_DBG("TC %d with prio %d pkt %p", tc, prio, pkt);
|
||||
#endif
|
||||
|
|
|
@ -446,6 +446,32 @@ static void iface_per_mcast_route_cb(struct net_if *iface, void *user_data)
|
|||
|
||||
#if defined(CONFIG_NET_STATISTICS)
|
||||
|
||||
#if NET_TC_COUNT > 1
|
||||
static const char *priority2str(enum net_priority priority)
|
||||
{
|
||||
switch (priority) {
|
||||
case NET_PRIORITY_BK:
|
||||
return "BK"; /* Background */
|
||||
case NET_PRIORITY_BE:
|
||||
return "BE"; /* Best effort */
|
||||
case NET_PRIORITY_EE:
|
||||
return "EE"; /* Excellent effort */
|
||||
case NET_PRIORITY_CA:
|
||||
return "CA"; /* Critical applications */
|
||||
case NET_PRIORITY_VI:
|
||||
return "VI"; /* Video, < 100 ms latency and jitter */
|
||||
case NET_PRIORITY_VO:
|
||||
return "VO"; /* Voice, < 10 ms latency and jitter */
|
||||
case NET_PRIORITY_IC:
|
||||
return "IC"; /* Internetwork control */
|
||||
case NET_PRIORITY_NC:
|
||||
return "NC"; /* Network control */
|
||||
}
|
||||
|
||||
return "??";
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void net_shell_print_statistics(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
|
@ -560,6 +586,38 @@ static inline void net_shell_print_statistics(void)
|
|||
printk("Bytes received %u\n", GET_STAT(bytes.received));
|
||||
printk("Bytes sent %u\n", GET_STAT(bytes.sent));
|
||||
printk("Processing err %d\n", GET_STAT(processing_error));
|
||||
|
||||
#if NET_TC_COUNT > 1
|
||||
{
|
||||
int i;
|
||||
|
||||
#if NET_TC_TX_COUNT > 1
|
||||
printk("TX traffic class statistics:\n");
|
||||
printk("TC Priority\tSent pkts\tbytes\n");
|
||||
|
||||
for (i = 0; i < NET_TC_TX_COUNT; i++) {
|
||||
printk("[%d] %s (%d)\t%d\t\t%d\n", i,
|
||||
priority2str(GET_STAT(tc.sent[i].priority)),
|
||||
GET_STAT(tc.sent[i].priority),
|
||||
GET_STAT(tc.sent[i].pkts),
|
||||
GET_STAT(tc.sent[i].bytes));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NET_TC_RX_COUNT > 1
|
||||
printk("RX traffic class statistics:\n");
|
||||
printk("TC Priority\tRecv pkts\tbytes\n");
|
||||
|
||||
for (i = 0; i < NET_TC_RX_COUNT; i++) {
|
||||
printk("[%d] %s (%d)\t%d\t\t%d\n", i,
|
||||
priority2str(GET_STAT(tc.recv[i].priority)),
|
||||
GET_STAT(tc.recv[i].priority),
|
||||
GET_STAT(tc.recv[i].pkts),
|
||||
GET_STAT(tc.recv[i].bytes));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* NET_TC_COUNT > 1 */
|
||||
}
|
||||
#endif /* CONFIG_NET_STATISTICS */
|
||||
|
||||
|
|
|
@ -390,6 +390,45 @@ static inline void net_stats_update_ipv6_mld_drop(void)
|
|||
#define net_stats_update_ipv6_mld_drop()
|
||||
#endif /* CONFIG_NET_STATISTICS_MLD */
|
||||
|
||||
#if (NET_TC_COUNT > 1) && defined(CONFIG_NET_STATISTICS)
|
||||
static inline void net_stats_update_tc_sent_pkt(u8_t tc)
|
||||
{
|
||||
net_stats.tc.sent[tc].pkts++;
|
||||
}
|
||||
|
||||
static inline void net_stats_update_tc_sent_bytes(u8_t tc, size_t bytes)
|
||||
{
|
||||
net_stats.tc.sent[tc].bytes += bytes;
|
||||
}
|
||||
|
||||
static inline void net_stats_update_tc_sent_priority(u8_t tc, u8_t priority)
|
||||
{
|
||||
net_stats.tc.sent[tc].priority = priority;
|
||||
}
|
||||
|
||||
static inline void net_stats_update_tc_recv_pkt(u8_t tc)
|
||||
{
|
||||
net_stats.tc.recv[tc].pkts++;
|
||||
}
|
||||
|
||||
static inline void net_stats_update_tc_recv_bytes(u8_t tc, size_t bytes)
|
||||
{
|
||||
net_stats.tc.recv[tc].bytes += bytes;
|
||||
}
|
||||
|
||||
static inline void net_stats_update_tc_recv_priority(u8_t tc, u8_t priority)
|
||||
{
|
||||
net_stats.tc.recv[tc].priority = priority;
|
||||
}
|
||||
#else
|
||||
#define net_stats_update_tc_sent_pkt(tc)
|
||||
#define net_stats_update_tc_sent_bytes(tc, bytes)
|
||||
#define net_stats_update_tc_sent_priority(tc, priority)
|
||||
#define net_stats_update_tc_recv_pkt(tc)
|
||||
#define net_stats_update_tc_recv_bytes(tc, bytes)
|
||||
#define net_stats_update_tc_recv_priority(tc, priority)
|
||||
#endif /* NET_TC_COUNT > 1 */
|
||||
|
||||
#if defined(CONFIG_NET_STATISTICS_PERIODIC_OUTPUT)
|
||||
/* A simple periodic statistic printer, used only in net core */
|
||||
void net_print_statistics(void);
|
||||
|
|
|
@ -266,6 +266,29 @@ static int rx_tc2thread(int tc)
|
|||
#define RX_STACK(idx) NET_STACK_GET_NAME(RX, rx_stack, 0)[idx]
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_STATISTICS)
|
||||
/* Fixup the traffic class statistics so that "net stats" shell command will
|
||||
* print output correctly.
|
||||
*/
|
||||
static void tc_tx_stats_priority_setup(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
net_stats_update_tc_sent_priority(net_tx_priority2tc(i), i);
|
||||
}
|
||||
}
|
||||
|
||||
static void tc_rx_stats_priority_setup(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
net_stats_update_tc_recv_priority(net_rx_priority2tc(i), i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create workqueue for each traffic class we are using. All the network
|
||||
* traffic goes through these classes. There needs to be at least one traffic
|
||||
* class in the system.
|
||||
|
@ -276,6 +299,10 @@ void net_tc_tx_init(void)
|
|||
|
||||
BUILD_ASSERT(NET_TC_TX_COUNT > 0);
|
||||
|
||||
#if defined(CONFIG_NET_STATISTICS)
|
||||
tc_tx_stats_priority_setup();
|
||||
#endif
|
||||
|
||||
for (i = 0; i < NET_TC_TX_COUNT; i++) {
|
||||
u8_t thread_priority;
|
||||
|
||||
|
@ -312,6 +339,10 @@ void net_tc_rx_init(void)
|
|||
|
||||
BUILD_ASSERT(NET_TC_RX_COUNT > 0);
|
||||
|
||||
#if defined(CONFIG_NET_STATISTICS)
|
||||
tc_rx_stats_priority_setup();
|
||||
#endif
|
||||
|
||||
for (i = 0; i < NET_TC_RX_COUNT; i++) {
|
||||
u8_t thread_priority;
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user