diff --git a/include/net/net_pkt.h b/include/net/net_pkt.h index 209beb7402d..237a3e062b8 100644 --- a/include/net/net_pkt.h +++ b/include/net/net_pkt.h @@ -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 */ diff --git a/include/net/net_stats.h b/include/net/net_stats.h index 97c23264302..5ab60c03a55 100644 --- a/include/net/net_stats.h +++ b/include/net/net_stats.h @@ -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 diff --git a/subsys/net/ip/Kconfig b/subsys/net/ip/Kconfig index 30891d9e5ac..7ebc95ecebf 100644 --- a/subsys/net/ip/Kconfig +++ b/subsys/net/ip/Kconfig @@ -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 diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index fbea02e0e95..abbf3b886d1 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -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) { diff --git a/subsys/net/ip/net_pkt.c b/subsys/net/ip/net_pkt.c index e3e24278eb1..32f752dd6c3 100644 --- a/subsys/net/ip/net_pkt.c +++ b/subsys/net/ip/net_pkt.c @@ -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(), }; diff --git a/subsys/net/ip/net_private.h b/subsys/net/ip/net_private.h index 8d7909905f3..a3a73753743 100644 --- a/subsys/net/ip/net_private.h +++ b/subsys/net/ip/net_private.h @@ -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) diff --git a/subsys/net/ip/net_stats.h b/subsys/net/ip/net_stats.h index 35a74a9f958..1f6b0173d5a 100644 --- a/subsys/net/ip/net_stats.h +++ b/subsys/net/ip/net_stats.h @@ -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)