net: Add statistics how long packets have spent in TX path
Calculate how long on average net_pkt has spent on its way from application to the network device driver. The data is calculated for all network packets and not just for UDP or TCP ones like in RX statistics. Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
4f92b7b648
commit
d03cb7367c
|
@ -97,10 +97,21 @@ struct net_pkt {
|
|||
struct net_if *orig_iface; /* Original network interface */
|
||||
#endif
|
||||
|
||||
/* We do not support combination of TXTIME and TXTIME_STATS as the
|
||||
* same variable is shared in net_pkt.h
|
||||
*/
|
||||
#if defined(CONFIG_NET_PKT_TXTIME) && defined(CONFIG_NET_PKT_TXTIME_STATS)
|
||||
#error \
|
||||
"Cannot define both CONFIG_NET_PKT_TXTIME and CONFIG_NET_PKT_TXTIME_STATS"
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_PKT_TIMESTAMP) || defined(CONFIG_NET_PKT_TXTIME) || \
|
||||
defined(CONFIG_NET_PKT_RXTIME_STATS)
|
||||
defined(CONFIG_NET_PKT_RXTIME_STATS) || \
|
||||
defined(CONFIG_NET_PKT_TXTIME_STATS)
|
||||
union {
|
||||
#if defined(CONFIG_NET_PKT_TIMESTAMP) || defined(CONFIG_NET_PKT_RXTIME_STATS)
|
||||
#if defined(CONFIG_NET_PKT_TIMESTAMP) || \
|
||||
defined(CONFIG_NET_PKT_RXTIME_STATS) || \
|
||||
defined(CONFIG_NET_PKT_TXTIME_STATS)
|
||||
/** Timestamp if available. */
|
||||
struct net_ptp_time timestamp;
|
||||
#endif /* CONFIG_NET_PKT_TIMESTAMP */
|
||||
|
|
|
@ -203,11 +203,11 @@ struct net_stats_ipv6_mld {
|
|||
};
|
||||
|
||||
/**
|
||||
* @brief Network packet transfer times
|
||||
* @brief Network packet transfer times for calculating average TX time
|
||||
*/
|
||||
struct net_stats_tx_time {
|
||||
u64_t time_sum;
|
||||
net_stats_t time_count;
|
||||
u64_t sum;
|
||||
net_stats_t count;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -223,10 +223,10 @@ struct net_stats_rx_time {
|
|||
*/
|
||||
struct net_stats_tc {
|
||||
struct {
|
||||
struct net_stats_tx_time tx_time;
|
||||
net_stats_t pkts;
|
||||
net_stats_t bytes;
|
||||
u8_t priority;
|
||||
struct net_stats_tx_time tx_time;
|
||||
} sent[NET_TC_TX_COUNT];
|
||||
|
||||
struct {
|
||||
|
@ -293,7 +293,13 @@ struct net_stats {
|
|||
struct net_stats_tc tc;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_TIMESTAMP)
|
||||
#if defined(CONFIG_NET_CONTEXT_TIMESTAMP) && \
|
||||
defined(CONFIG_NET_PKT_TXTIME_STATS)
|
||||
#error \
|
||||
"Cannot define both CONFIG_NET_CONTEXT_TIMESTAMP and CONFIG_NET_PKT_TXTIME_STATS"
|
||||
#endif
|
||||
#if defined(CONFIG_NET_CONTEXT_TIMESTAMP) || \
|
||||
defined(CONFIG_NET_PKT_TXTIME_STATS)
|
||||
/** Network packet TX time statistics */
|
||||
struct net_stats_tx_time tx_time;
|
||||
#endif
|
||||
|
|
|
@ -661,6 +661,23 @@ config NET_PKT_RXTIME_STATS
|
|||
in net-shell.
|
||||
The RX statistics are only calculated for UDP and TCP packets.
|
||||
|
||||
config NET_PKT_TXTIME_STATS
|
||||
bool "Enable network packet TX time statistics"
|
||||
select NET_PKT_TIMESTAMP
|
||||
select NET_STATISTICS
|
||||
depends on (NET_UDP || NET_TCP) && !NET_PKT_TXTIME
|
||||
help
|
||||
Enable network packet TX time statistics support. This is used to
|
||||
calculate how long on average it takes for a packet to travel from
|
||||
application to just before it is sent to network. The TX timing
|
||||
information can then be seen in network interface statistics in
|
||||
net-shell.
|
||||
The RX calculation is done only for UDP or TCP packets, but for TX
|
||||
we do not know the protocol so the TX packet timing is done for all
|
||||
network protocol packets.
|
||||
Note that CONFIG_NET_PKT_TXTIME cannot be set at the same time
|
||||
because net_pkt shares the time variable for statistics and TX time.
|
||||
|
||||
config NET_PROMISCUOUS_MODE
|
||||
bool "Enable promiscuous mode support [EXPERIMENTAL]"
|
||||
select NET_MGMT
|
||||
|
|
|
@ -150,14 +150,12 @@ static bool net_if_tx(struct net_if *iface, struct net_pkt *pkt)
|
|||
struct net_context *context;
|
||||
int status;
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_TIMESTAMP)
|
||||
/* Timestamp of the current network packet sent */
|
||||
/* Timestamp of the current network packet sent if enabled */
|
||||
struct net_ptp_time start_timestamp;
|
||||
u32_t curr_time = 0;
|
||||
|
||||
/* We collect send statistics for each socket priority */
|
||||
/* We collect send statistics for each socket priority if enabled */
|
||||
u8_t pkt_priority;
|
||||
#endif
|
||||
|
||||
if (!pkt) {
|
||||
return false;
|
||||
|
@ -175,8 +173,7 @@ static bool net_if_tx(struct net_if *iface, struct net_pkt *pkt)
|
|||
net_pkt_set_queued(pkt, false);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_TIMESTAMP)
|
||||
if (context) {
|
||||
if (IS_ENABLED(CONFIG_NET_CONTEXT_TIMESTAMP) && context) {
|
||||
if (net_context_get_timestamp(context, pkt,
|
||||
&start_timestamp) < 0) {
|
||||
start_timestamp.nanosecond = 0;
|
||||
|
@ -184,17 +181,28 @@ static bool net_if_tx(struct net_if *iface, struct net_pkt *pkt)
|
|||
pkt_priority = net_pkt_priority(pkt);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_PKT_TXTIME_STATS)) {
|
||||
memcpy(&start_timestamp, net_pkt_timestamp(pkt),
|
||||
sizeof(start_timestamp));
|
||||
pkt_priority = net_pkt_priority(pkt);
|
||||
}
|
||||
|
||||
status = net_if_l2(iface)->send(iface, pkt);
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_TIMESTAMP)
|
||||
if (status >= 0 && context) {
|
||||
if (IS_ENABLED(CONFIG_NET_CONTEXT_TIMESTAMP) && status >= 0 &&
|
||||
context) {
|
||||
if (start_timestamp.nanosecond > 0) {
|
||||
curr_time = k_cycle_get_32();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_PKT_TXTIME_STATS) && status >= 0) {
|
||||
net_stats_update_tc_tx_time(iface,
|
||||
pkt_priority,
|
||||
start_timestamp.nanosecond,
|
||||
k_cycle_get_32());
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Drop packet if interface is not up */
|
||||
|
@ -214,9 +222,8 @@ static bool net_if_tx(struct net_if *iface, struct net_pkt *pkt)
|
|||
|
||||
net_context_send_cb(context, status);
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_TIMESTAMP)
|
||||
if (status >= 0 && start_timestamp.nanosecond &&
|
||||
curr_time > 0) {
|
||||
if (IS_ENABLED(CONFIG_NET_CONTEXT_TIMESTAMP) && status >= 0 &&
|
||||
start_timestamp.nanosecond && curr_time > 0) {
|
||||
/* So we know now how long the network packet was in
|
||||
* transit from when it was allocated to when we
|
||||
* got information that it was sent successfully.
|
||||
|
@ -226,7 +233,6 @@ static bool net_if_tx(struct net_if *iface, struct net_pkt *pkt)
|
|||
start_timestamp.nanosecond,
|
||||
curr_time);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (dst->addr) {
|
||||
|
|
|
@ -1193,13 +1193,14 @@ static struct net_pkt *pkt_alloc(struct k_mem_slab *slab, s32_t timeout)
|
|||
net_pkt_set_priority(pkt, CONFIG_NET_RX_DEFAULT_PRIORITY);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_PKT_RXTIME_STATS)) {
|
||||
if (IS_ENABLED(CONFIG_NET_PKT_RXTIME_STATS) ||
|
||||
IS_ENABLED(CONFIG_NET_PKT_TXTIME_STATS)) {
|
||||
struct net_ptp_time tp = {
|
||||
/* Use the nanosecond field to temporarily
|
||||
* store the cycle count as it is a 32-bit
|
||||
* variable. The net_pkt timestamp field is used
|
||||
* to calculate how long it takes the packet to travel
|
||||
* from network device driver to the application.
|
||||
* between network device driver and application.
|
||||
*/
|
||||
.nanosecond = k_cycle_get_32(),
|
||||
};
|
||||
|
|
|
@ -88,6 +88,17 @@ char *net_sprint_addr(sa_family_t af, const void *addr);
|
|||
int net_context_get_timestamp(struct net_context *context,
|
||||
struct net_pkt *pkt,
|
||||
struct net_ptp_time *timestamp);
|
||||
#else
|
||||
static inline int net_context_get_timestamp(struct net_context *context,
|
||||
struct net_pkt *pkt,
|
||||
struct net_ptp_time *timestamp)
|
||||
{
|
||||
ARG_UNUSED(context);
|
||||
ARG_UNUSED(pkt);
|
||||
ARG_UNUSED(timestamp);
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_COAP)
|
||||
|
|
|
@ -318,27 +318,21 @@ static inline void net_stats_update_ipv6_mld_drop(struct net_if *iface)
|
|||
#define net_stats_update_ipv6_mld_drop(iface)
|
||||
#endif /* CONFIG_NET_STATISTICS_MLD */
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_TIMESTAMP) && defined(CONFIG_NET_STATISTICS)
|
||||
#if (defined(CONFIG_NET_CONTEXT_TIMESTAMP) || \
|
||||
defined(CONFIG_NET_PKT_TXTIME_STATS)) && defined(CONFIG_NET_STATISTICS)
|
||||
static inline void net_stats_update_tx_time(struct net_if *iface,
|
||||
u32_t start_time,
|
||||
u32_t end_time)
|
||||
{
|
||||
u32_t diff = abs(end_time - start_time);
|
||||
u32_t diff = end_time - start_time;
|
||||
|
||||
UPDATE_STAT(iface, stats.tx_time.time_sum +=
|
||||
SYS_CLOCK_HW_CYCLES_TO_NS64(diff) / 1000);
|
||||
UPDATE_STAT(iface, stats.tx_time.time_count += 1);
|
||||
UPDATE_STAT(iface, stats.tx_time.sum +=
|
||||
SYS_CLOCK_HW_CYCLES_TO_NS64(diff) / NSEC_PER_USEC);
|
||||
UPDATE_STAT(iface, stats.tx_time.count += 1);
|
||||
}
|
||||
#else
|
||||
static inline void net_stats_update_tx_time(struct net_if *iface,
|
||||
u32_t start_time,
|
||||
u32_t end_time)
|
||||
{
|
||||
ARG_UNUSED(iface);
|
||||
ARG_UNUSED(start_time);
|
||||
ARG_UNUSED(end_time);
|
||||
}
|
||||
#endif /* CONFIG_NET_CONTEXT_TIMESTAMP && STATISTICS */
|
||||
#define net_stats_update_tx_time(iface, start_time, end_time)
|
||||
#endif /* (TIMESTAMP || NET_PKT_TXTIME_STATS) && NET_STATISTICS */
|
||||
|
||||
#if defined(CONFIG_NET_PKT_RXTIME_STATS) && defined(CONFIG_NET_STATISTICS)
|
||||
static inline void net_stats_update_rx_time(struct net_if *iface,
|
||||
|
@ -353,7 +347,7 @@ static inline void net_stats_update_rx_time(struct net_if *iface,
|
|||
}
|
||||
#else
|
||||
#define net_stats_update_rx_time(iface, start_time, end_time)
|
||||
#endif /* CONFIG_NET_CONTEXT_TIMESTAMP && STATISTICS */
|
||||
#endif /* NET_CONTEXT_TIMESTAMP && STATISTICS */
|
||||
|
||||
#if (NET_TC_COUNT > 1) && defined(CONFIG_NET_STATISTICS) \
|
||||
&& defined(CONFIG_NET_NATIVE)
|
||||
|
@ -374,33 +368,25 @@ static inline void net_stats_update_tc_sent_priority(struct net_if *iface,
|
|||
UPDATE_STAT(iface, stats.tc.sent[tc].priority = priority);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_TIMESTAMP) && defined(CONFIG_NET_STATISTICS) \
|
||||
&& defined(CONFIG_NET_NATIVE)
|
||||
#if (defined(CONFIG_NET_CONTEXT_TIMESTAMP) || \
|
||||
defined(CONFIG_NET_PKT_TXTIME_STATS)) && \
|
||||
defined(CONFIG_NET_STATISTICS) && defined(CONFIG_NET_NATIVE)
|
||||
static inline void net_stats_update_tc_tx_time(struct net_if *iface,
|
||||
u8_t tc,
|
||||
u32_t start_time,
|
||||
u32_t end_time)
|
||||
{
|
||||
u32_t diff = abs(end_time - start_time);
|
||||
u32_t diff = end_time - start_time;
|
||||
|
||||
UPDATE_STAT(iface, stats.tc.sent[tc].tx_time.time_sum +=
|
||||
SYS_CLOCK_HW_CYCLES_TO_NS64(diff) / 1000);
|
||||
UPDATE_STAT(iface, stats.tc.sent[tc].tx_time.time_count += 1);
|
||||
UPDATE_STAT(iface, stats.tc.sent[tc].tx_time.sum +=
|
||||
SYS_CLOCK_HW_CYCLES_TO_NS64(diff) / NSEC_PER_USEC);
|
||||
UPDATE_STAT(iface, stats.tc.sent[tc].tx_time.count += 1);
|
||||
|
||||
net_stats_update_tx_time(iface, start_time, end_time);
|
||||
}
|
||||
#else
|
||||
static inline void net_stats_update_tc_tx_time(struct net_if *iface,
|
||||
u8_t tc,
|
||||
u32_t start_time,
|
||||
u32_t end_time)
|
||||
{
|
||||
ARG_UNUSED(iface);
|
||||
ARG_UNUSED(tc);
|
||||
ARG_UNUSED(start_time);
|
||||
ARG_UNUSED(end_time);
|
||||
}
|
||||
#endif /* CONFIG_NET_CONTEXT_TIMESTAMP && CONFIG_NET_STATISTICS */
|
||||
#define net_stats_update_tc_tx_time(iface, tc, start_time, end_time)
|
||||
#endif /* (NET_CONTEXT_TIMESTAMP || NET_PKT_TXTIME_STATS) && NET_STATISTICS */
|
||||
|
||||
#if defined(CONFIG_NET_PKT_RXTIME_STATS) && defined(CONFIG_NET_STATISTICS) \
|
||||
&& defined(CONFIG_NET_NATIVE)
|
||||
|
@ -445,8 +431,9 @@ static inline void net_stats_update_tc_recv_priority(struct net_if *iface,
|
|||
#define net_stats_update_tc_recv_bytes(iface, tc, bytes)
|
||||
#define net_stats_update_tc_recv_priority(iface, tc, priority)
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_TIMESTAMP) && defined(CONFIG_NET_STATISTICS) \
|
||||
&& defined(CONFIG_NET_NATIVE)
|
||||
#if (defined(CONFIG_NET_CONTEXT_TIMESTAMP) || \
|
||||
defined(CONFIG_NET_PKT_TXTIME_STATS)) && \
|
||||
defined(CONFIG_NET_STATISTICS) && defined(CONFIG_NET_NATIVE)
|
||||
static inline void net_stats_update_tc_tx_time(struct net_if *iface,
|
||||
u8_t pkt_priority,
|
||||
u32_t start_time,
|
||||
|
@ -457,17 +444,8 @@ static inline void net_stats_update_tc_tx_time(struct net_if *iface,
|
|||
net_stats_update_tx_time(iface, start_time, end_time);
|
||||
}
|
||||
#else
|
||||
static inline void net_stats_update_tc_tx_time(struct net_if *iface,
|
||||
u8_t pkt_priority,
|
||||
u32_t start_time,
|
||||
u32_t end_time)
|
||||
{
|
||||
ARG_UNUSED(iface);
|
||||
ARG_UNUSED(pkt_priority);
|
||||
ARG_UNUSED(start_time);
|
||||
ARG_UNUSED(end_time);
|
||||
}
|
||||
#endif /* CONFIG_NET_CONTEXT_TIMESTAMP && CONFIG_NET_STATISTICS */
|
||||
#define net_stats_update_tc_tx_time(iface, priority, start_time, end_time)
|
||||
#endif /* (NET_CONTEXT_TIMESTAMP || NET_PKT_TXTIME_STATS) && NET_STATISTICS */
|
||||
|
||||
#if defined(CONFIG_NET_PKT_RXTIME_STATS) && defined(CONFIG_NET_STATISTICS) \
|
||||
&& defined(CONFIG_NET_NATIVE)
|
||||
|
|
Loading…
Reference in a new issue