net: tcp: Add TCP statistics support
We did not collect any TCP statistics before but this commit changes that. Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
7a1a9a7946
commit
e253dcbd3b
9 changed files with 221 additions and 23 deletions
|
@ -22,6 +22,11 @@ extern "C" {
|
|||
|
||||
typedef u32_t net_stats_t;
|
||||
|
||||
struct net_stats_bytes {
|
||||
u32_t sent;
|
||||
u32_t received;
|
||||
};
|
||||
|
||||
struct net_stats_ip {
|
||||
/** Number of received packets at the IP layer. */
|
||||
net_stats_t recv;
|
||||
|
@ -78,6 +83,12 @@ struct net_stats_icmp {
|
|||
};
|
||||
|
||||
struct net_stats_tcp {
|
||||
/** Amount of received and sent TCP application data. */
|
||||
struct net_stats_bytes bytes;
|
||||
|
||||
/** Amount of retransmitted data. */
|
||||
net_stats_t resent;
|
||||
|
||||
/** Number of recived TCP segments. */
|
||||
net_stats_t recv;
|
||||
|
||||
|
@ -90,22 +101,25 @@ struct net_stats_tcp {
|
|||
/** Number of TCP segments with a bad checksum. */
|
||||
net_stats_t chkerr;
|
||||
|
||||
/** Number of TCP segments with a bad ACK number. */
|
||||
/** Number of received TCP segments with a bad ACK number. */
|
||||
net_stats_t ackerr;
|
||||
|
||||
/** Number of received bad TCP RST (reset) segments. */
|
||||
net_stats_t rsterr;
|
||||
|
||||
/** Number of received TCP RST (reset) segments. */
|
||||
net_stats_t rst;
|
||||
|
||||
/** Number of retransmitted TCP segments. */
|
||||
net_stats_t rexmit;
|
||||
|
||||
/** Number of dropped SYNs because too few connections were
|
||||
* available.
|
||||
/** Number of dropped connection attempts because too few connections
|
||||
* were available.
|
||||
*/
|
||||
net_stats_t syndrop;
|
||||
net_stats_t conndrop;
|
||||
|
||||
/** Number of SYNs for closed ports, triggering a RST. */
|
||||
net_stats_t synrst;
|
||||
/** Number of connection attempts for closed ports, triggering a RST. */
|
||||
net_stats_t connrst;
|
||||
};
|
||||
|
||||
struct net_stats_udp {
|
||||
|
@ -207,11 +221,6 @@ struct net_stats_ipv6_mld {
|
|||
net_stats_t drop;
|
||||
};
|
||||
|
||||
struct net_stats_bytes {
|
||||
u32_t sent;
|
||||
u32_t received;
|
||||
};
|
||||
|
||||
struct net_stats {
|
||||
net_stats_t processing_error;
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ config NET_STATISTICS_UDP
|
|||
config NET_STATISTICS_TCP
|
||||
bool "TCP statistics"
|
||||
depends on NET_TCP
|
||||
default n
|
||||
default y
|
||||
help
|
||||
Keep track of TCP related statistics
|
||||
|
||||
|
|
|
@ -843,9 +843,7 @@ enum net_verdict net_conn_input(enum net_ip_protocol proto, struct net_pkt *pkt)
|
|||
goto drop;
|
||||
}
|
||||
|
||||
if (proto == IPPROTO_UDP) {
|
||||
net_stats_update_udp_recv();
|
||||
}
|
||||
net_stats_update_per_proto_recv(proto);
|
||||
|
||||
return NET_OK;
|
||||
}
|
||||
|
@ -871,12 +869,14 @@ enum net_verdict net_conn_input(enum net_ip_protocol proto, struct net_pkt *pkt)
|
|||
#endif
|
||||
{
|
||||
send_icmp_error(pkt);
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_TCP) && proto == IPPROTO_TCP) {
|
||||
net_stats_update_tcp_seg_connrst();
|
||||
}
|
||||
}
|
||||
|
||||
drop:
|
||||
if (proto == IPPROTO_UDP) {
|
||||
net_stats_update_udp_drop();
|
||||
}
|
||||
net_stats_update_per_proto_drop(proto);
|
||||
|
||||
return NET_DROP;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "ipv4.h"
|
||||
#include "udp.h"
|
||||
#include "tcp.h"
|
||||
#include "net_stats.h"
|
||||
|
||||
#define NET_MAX_CONTEXT CONFIG_NET_MAX_CONTEXTS
|
||||
|
||||
|
@ -823,9 +824,12 @@ NET_CONN_CB(tcp_established)
|
|||
if (tcp_flags & NET_TCP_RST) {
|
||||
/* We only accept RST packet that has valid seq field. */
|
||||
if (!net_tcp_validate_seq(context->tcp, pkt)) {
|
||||
net_stats_update_tcp_seg_rsterr();
|
||||
return NET_DROP;
|
||||
}
|
||||
|
||||
net_stats_update_tcp_seg_rst();
|
||||
|
||||
net_tcp_print_recv_info("RST", pkt, NET_TCP_HDR(pkt)->src_port);
|
||||
|
||||
if (context->recv_cb) {
|
||||
|
@ -917,9 +921,12 @@ NET_CONN_CB(tcp_synack_received)
|
|||
if (NET_TCP_FLAGS(pkt) & NET_TCP_RST) {
|
||||
/* We only accept RST packet that has valid seq field. */
|
||||
if (!net_tcp_validate_seq(context->tcp, pkt)) {
|
||||
net_stats_update_tcp_seg_rsterr();
|
||||
return NET_DROP;
|
||||
}
|
||||
|
||||
net_stats_update_tcp_seg_rst();
|
||||
|
||||
if (context->connect_cb) {
|
||||
context->connect_cb(context, -ECONNREFUSED,
|
||||
context->user_data);
|
||||
|
@ -1350,9 +1357,12 @@ NET_CONN_CB(tcp_syn_rcvd)
|
|||
|
||||
/* We only accept RST packet that has valid seq field. */
|
||||
if (!net_tcp_validate_seq(tcp, pkt)) {
|
||||
net_stats_update_tcp_seg_rsterr();
|
||||
return NET_DROP;
|
||||
}
|
||||
|
||||
net_stats_update_tcp_seg_rst();
|
||||
|
||||
ack_timer_cancel(tcp);
|
||||
|
||||
net_tcp_print_recv_info("RST", pkt, NET_TCP_HDR(pkt)->src_port);
|
||||
|
@ -1399,7 +1409,7 @@ NET_CONN_CB(tcp_syn_rcvd)
|
|||
if (ret < 0) {
|
||||
NET_DBG("Cannot get accepted context, "
|
||||
"connection reset");
|
||||
goto reset;
|
||||
goto conndrop;
|
||||
}
|
||||
|
||||
new_context->tcp->recv_max_ack = context->tcp->recv_max_ack;
|
||||
|
@ -1460,7 +1470,7 @@ NET_CONN_CB(tcp_syn_rcvd)
|
|||
NET_DBG("Cannot bind accepted context, "
|
||||
"connection reset");
|
||||
net_context_unref(new_context);
|
||||
goto reset;
|
||||
goto conndrop;
|
||||
}
|
||||
|
||||
new_context->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
|
||||
|
@ -1479,7 +1489,7 @@ NET_CONN_CB(tcp_syn_rcvd)
|
|||
NET_DBG("Cannot register accepted TCP handler (%d)",
|
||||
ret);
|
||||
net_context_unref(new_context);
|
||||
goto reset;
|
||||
goto conndrop;
|
||||
}
|
||||
|
||||
/* Swap the newly-created TCP states with the one that
|
||||
|
@ -1512,6 +1522,9 @@ NET_CONN_CB(tcp_syn_rcvd)
|
|||
|
||||
return NET_DROP;
|
||||
|
||||
conndrop:
|
||||
net_stats_update_tcp_seg_conndrop();
|
||||
|
||||
reset:
|
||||
{
|
||||
struct sockaddr peer;
|
||||
|
@ -1930,6 +1943,8 @@ static enum net_verdict packet_received(struct net_conn *conn,
|
|||
net_pkt_appdata(pkt), net_pkt_appdatalen(pkt),
|
||||
net_pkt_get_len(pkt));
|
||||
|
||||
net_stats_update_tcp_recv(net_pkt_appdatalen(pkt));
|
||||
|
||||
context->recv_cb(context, pkt, 0, user_data);
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
|
||||
|
|
|
@ -70,8 +70,15 @@ static inline void net_context_send_cb(struct net_context *context,
|
|||
#if defined(CONFIG_NET_UDP)
|
||||
if (net_context_get_ip_proto(context) == IPPROTO_UDP) {
|
||||
net_stats_update_udp_sent();
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
#if defined(CONFIG_NET_TCP)
|
||||
if (net_context_get_ip_proto(context) == IPPROTO_TCP) {
|
||||
net_stats_update_tcp_seg_sent();
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
static bool net_if_tx(struct net_if *iface)
|
||||
|
|
|
@ -373,6 +373,27 @@ static inline void net_shell_print_statistics(void)
|
|||
GET_STAT(udp.chkerr));
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_STATISTICS_TCP)
|
||||
printk("TCP bytes recv %u\tsent\t%d\n",
|
||||
GET_STAT(tcp.bytes.received),
|
||||
GET_STAT(tcp.bytes.sent));
|
||||
printk("TCP seg recv %d\tsent\t%d\tdrop\t%d\n",
|
||||
GET_STAT(tcp.recv),
|
||||
GET_STAT(tcp.sent),
|
||||
GET_STAT(tcp.drop));
|
||||
printk("TCP seg resent %d\tchkerr\t%d\tackerr\t%d\n",
|
||||
GET_STAT(tcp.resent),
|
||||
GET_STAT(tcp.chkerr),
|
||||
GET_STAT(tcp.ackerr));
|
||||
printk("TCP seg rsterr %d\trst\t%d\tre-xmit\t%d\n",
|
||||
GET_STAT(tcp.rsterr),
|
||||
GET_STAT(tcp.rst),
|
||||
GET_STAT(tcp.rexmit));
|
||||
printk("TCP conn drop %d\tconnrst\t%d\n",
|
||||
GET_STAT(tcp.conndrop),
|
||||
GET_STAT(tcp.connrst));
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_STATISTICS_RPL)
|
||||
printk("RPL DIS recv %d\tsent\t%d\tdrop\t%d\n",
|
||||
GET_STAT(rpl.dis.recv),
|
||||
|
|
|
@ -23,7 +23,7 @@ struct net_stats net_stats;
|
|||
|
||||
#define PRINT_STATISTICS_INTERVAL (30 * MSEC_PER_SEC)
|
||||
|
||||
void net_print_statistics(void)
|
||||
static inline void stats(void)
|
||||
{
|
||||
static s64_t next_print;
|
||||
s64_t curr = k_uptime_get();
|
||||
|
@ -80,6 +80,27 @@ void net_print_statistics(void)
|
|||
GET_STAT(udp.chkerr));
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_STATISTICS_TCP)
|
||||
NET_INFO("TCP bytes recv %u\tsent\t%d",
|
||||
GET_STAT(tcp.bytes.received),
|
||||
GET_STAT(tcp.bytes.sent));
|
||||
NET_INFO("TCP seg recv %d\tsent\t%d\tdrop\t%d",
|
||||
GET_STAT(tcp.recv),
|
||||
GET_STAT(tcp.sent),
|
||||
GET_STAT(tcp.drop));
|
||||
NET_INFO("TCP seg resent %d\tchkerr\t%d\tackerr\t%d",
|
||||
GET_STAT(tcp.resent),
|
||||
GET_STAT(tcp.chkerr),
|
||||
GET_STAT(tcp.ackerr));
|
||||
NET_INFO("TCP seg rsterr %d\trst\t%d\tre-xmit\t%d",
|
||||
GET_STAT(tcp.rsterr),
|
||||
GET_STAT(tcp.rst),
|
||||
GET_STAT(tcp.rexmit));
|
||||
NET_INFO("TCP conn drop %d\tconnrst\t%d",
|
||||
GET_STAT(tcp.conndrop),
|
||||
GET_STAT(tcp.connrst));
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_STATISTICS_RPL)
|
||||
NET_INFO("RPL DIS recv %d\tsent\t%d\tdrop\t%d",
|
||||
GET_STAT(rpl.dis.recv),
|
||||
|
@ -129,6 +150,14 @@ void net_print_statistics(void)
|
|||
}
|
||||
}
|
||||
|
||||
void net_print_statistics(void)
|
||||
{
|
||||
/* In order to make the info print lines shorter, use shorter
|
||||
* function name.
|
||||
*/
|
||||
stats();
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_STATISTICS_PERIODIC_OUTPUT */
|
||||
|
||||
#if defined(CONFIG_NET_STATISTICS_USER_API)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#if defined(CONFIG_NET_STATISTICS)
|
||||
|
||||
#include <net/net_ip.h>
|
||||
#include <net/net_stats.h>
|
||||
|
||||
extern struct net_stats net_stats;
|
||||
|
@ -162,6 +163,106 @@ static inline void net_stats_update_udp_drop(void)
|
|||
#define net_stats_update_udp_drop()
|
||||
#endif /* CONFIG_NET_STATISTICS_UDP */
|
||||
|
||||
#if defined(CONFIG_NET_STATISTICS_TCP)
|
||||
/* TCP stats */
|
||||
static inline void net_stats_update_tcp_sent(u32_t bytes)
|
||||
{
|
||||
net_stats.tcp.bytes.sent += bytes;
|
||||
}
|
||||
|
||||
static inline void net_stats_update_tcp_recv(u32_t bytes)
|
||||
{
|
||||
net_stats.tcp.bytes.received += bytes;
|
||||
}
|
||||
|
||||
static inline void net_stats_update_tcp_resent(u32_t bytes)
|
||||
{
|
||||
net_stats.tcp.resent += bytes;
|
||||
}
|
||||
|
||||
static inline void net_stats_update_tcp_seg_sent(void)
|
||||
{
|
||||
net_stats.tcp.sent++;
|
||||
}
|
||||
|
||||
static inline void net_stats_update_tcp_seg_recv(void)
|
||||
{
|
||||
net_stats.tcp.recv++;
|
||||
}
|
||||
|
||||
static inline void net_stats_update_tcp_seg_drop(void)
|
||||
{
|
||||
net_stats.tcp.drop++;
|
||||
}
|
||||
|
||||
static inline void net_stats_update_tcp_seg_rst(void)
|
||||
{
|
||||
net_stats.tcp.rst++;
|
||||
}
|
||||
|
||||
static inline void net_stats_update_tcp_seg_conndrop(void)
|
||||
{
|
||||
net_stats.tcp.conndrop++;
|
||||
}
|
||||
|
||||
static inline void net_stats_update_tcp_seg_connrst(void)
|
||||
{
|
||||
net_stats.tcp.connrst++;
|
||||
}
|
||||
|
||||
static inline void net_stats_update_tcp_seg_chkerr(void)
|
||||
{
|
||||
net_stats.tcp.chkerr++;
|
||||
}
|
||||
|
||||
static inline void net_stats_update_tcp_seg_ackerr(void)
|
||||
{
|
||||
net_stats.tcp.ackerr++;
|
||||
}
|
||||
|
||||
static inline void net_stats_update_tcp_seg_rsterr(void)
|
||||
{
|
||||
net_stats.tcp.rsterr++;
|
||||
}
|
||||
|
||||
static inline void net_stats_update_tcp_seg_rexmit(void)
|
||||
{
|
||||
net_stats.tcp.rexmit++;
|
||||
}
|
||||
#else
|
||||
#define net_stats_update_tcp_sent(...)
|
||||
#define net_stats_update_tcp_resent(...)
|
||||
#define net_stats_update_tcp_recv(...)
|
||||
#define net_stats_update_tcp_seg_sent()
|
||||
#define net_stats_update_tcp_seg_recv()
|
||||
#define net_stats_update_tcp_seg_drop()
|
||||
#define net_stats_update_tcp_seg_rst()
|
||||
#define net_stats_update_tcp_seg_conndrop()
|
||||
#define net_stats_update_tcp_seg_connrst()
|
||||
#define net_stats_update_tcp_seg_chkerr()
|
||||
#define net_stats_update_tcp_seg_ackerr()
|
||||
#define net_stats_update_tcp_seg_rsterr()
|
||||
#define net_stats_update_tcp_seg_rexmit()
|
||||
#endif /* CONFIG_NET_STATISTICS_TCP */
|
||||
|
||||
static inline void net_stats_update_per_proto_recv(enum net_ip_protocol proto)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_NET_UDP) && proto == IPPROTO_UDP) {
|
||||
net_stats_update_udp_recv();
|
||||
} else if (IS_ENABLED(CONFIG_NET_TCP) && proto == IPPROTO_TCP) {
|
||||
net_stats_update_tcp_seg_recv();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void net_stats_update_per_proto_drop(enum net_ip_protocol proto)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_NET_UDP) && proto == IPPROTO_UDP) {
|
||||
net_stats_update_udp_drop();
|
||||
} else if (IS_ENABLED(CONFIG_NET_TCP) && proto == IPPROTO_TCP) {
|
||||
net_stats_update_tcp_seg_drop();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_STATISTICS_RPL)
|
||||
/* RPL stats */
|
||||
static inline void net_stats_update_rpl_resets(void)
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "ipv6.h"
|
||||
#include "ipv4.h"
|
||||
#include "tcp.h"
|
||||
#include "net_stats.h"
|
||||
|
||||
/*
|
||||
* Each TCP connection needs to be tracked by net_context, so
|
||||
|
@ -158,6 +159,11 @@ static void tcp_retry_expired(struct k_timer *timer)
|
|||
do_ref_if_needed(pkt);
|
||||
if (net_tcp_send_pkt(pkt) < 0 && !is_6lo_technology(pkt)) {
|
||||
net_pkt_unref(pkt);
|
||||
} else {
|
||||
if (IS_ENABLED(CONFIG_NET_STATISTICS_TCP) &&
|
||||
!is_6lo_technology(pkt)) {
|
||||
net_stats_update_tcp_seg_rexmit();
|
||||
}
|
||||
}
|
||||
} else if (IS_ENABLED(CONFIG_NET_TCP_TIME_WAIT)) {
|
||||
if (tcp->fin_sent && tcp->fin_rcvd) {
|
||||
|
@ -635,6 +641,8 @@ int net_tcp_queue_data(struct net_context *context, struct net_pkt *pkt)
|
|||
|
||||
context->tcp->send_seq += data_len;
|
||||
|
||||
net_stats_update_tcp_sent(data_len);
|
||||
|
||||
sys_slist_append(&context->tcp->sent_list, &pkt->sent_list);
|
||||
|
||||
/* We need to restart retry_timer if it is stopped. */
|
||||
|
@ -715,6 +723,8 @@ int net_tcp_send_pkt(struct net_pkt *pkt)
|
|||
ret = net_send_data(new_pkt);
|
||||
if (ret < 0) {
|
||||
net_pkt_unref(new_pkt);
|
||||
} else {
|
||||
net_stats_update_tcp_seg_rexmit();
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -773,6 +783,11 @@ void net_tcp_ack_received(struct net_context *ctx, u32_t ack)
|
|||
u32_t seq;
|
||||
bool valid_ack = false;
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_STATISTICS_TCP) &&
|
||||
sys_slist_is_empty(list)) {
|
||||
net_stats_update_tcp_seg_ackerr();
|
||||
}
|
||||
|
||||
while (!sys_slist_is_empty(list)) {
|
||||
head = sys_slist_peek_head(list);
|
||||
pkt = CONTAINER_OF(head, struct net_pkt, sent_list);
|
||||
|
@ -781,6 +796,7 @@ void net_tcp_ack_received(struct net_context *ctx, u32_t ack)
|
|||
seq = sys_get_be32(tcphdr->seq) + net_pkt_appdatalen(pkt) - 1;
|
||||
|
||||
if (!net_tcp_seq_greater(ack, seq)) {
|
||||
net_stats_update_tcp_seg_ackerr();
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue