net: stats: Collect bytes sent and received

Keep track of amount of bytes that are sent or received from
all network interfaces.

Change-Id: I706481aab1a7e0cf2bc78d032f2ef4ebbabe3184
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
diff --git a/include/net/net_stats.h b/include/net/net_stats.h
index 1277a18..b87254a 100644
--- a/include/net/net_stats.h
+++ b/include/net/net_stats.h
@@ -196,9 +196,20 @@
 	struct net_stats_rpl_dao_ack dao_ack;
 };
 
+struct net_stats_bytes {
+	uint32_t sent;
+	uint32_t received;
+};
+
 struct net_stats {
 	net_stats_t processing_error;
 
+	/*
+	 * This calculates amount of data transferred through all the
+	 * network interfaces.
+	 */
+	struct net_stats_bytes bytes;
+
 	struct net_stats_ip_errors ip_errors;
 
 #if defined(CONFIG_NET_STATISTICS_IPV6)
@@ -243,6 +254,7 @@
 enum net_request_stats_cmd {
 	NET_REQUEST_STATS_CMD_GET_ALL = 1,
 	NET_REQUEST_STATS_CMD_GET_PROCESSING_ERROR,
+	NET_REQUEST_STATS_CMD_GET_BYTES,
 	NET_REQUEST_STATS_CMD_GET_IP_ERRORS,
 	NET_REQUEST_STATS_CMD_GET_IPV4,
 	NET_REQUEST_STATS_CMD_GET_IPV6,
@@ -263,6 +275,11 @@
 
 //NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PROCESSING_ERROR);
 
+#define NET_REQUEST_STATS_GET_BYTES				\
+	(_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_BYTES)
+
+//NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_BYTES);
+
 #define NET_REQUEST_STATS_GET_IP_ERRORS				\
 	(_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_IP_ERRORS)
 
diff --git a/subsys/net/ip/net_core.c b/subsys/net/ip/net_core.c
index de34f72..76c5eec 100644
--- a/subsys/net/ip/net_core.c
+++ b/subsys/net/ip/net_core.c
@@ -535,12 +535,20 @@
 	net_if_init();
 
 	while (1) {
+#if defined(CONFIG_NET_STATISTICS) || defined(CONFIG_NET_DEBUG_CORE)
+		size_t pkt_len;
+#endif
+
 		buf = net_buf_get(&rx_queue, K_FOREVER);
 
 		net_analyze_stack("RX thread", rx_stack, sizeof(rx_stack));
 
-		NET_DBG("Received buf %p len %zu", buf,
-			net_buf_frags_len(buf));
+#if defined(CONFIG_NET_STATISTICS) || defined(CONFIG_NET_DEBUG_CORE)
+		pkt_len = net_buf_frags_len(buf);
+#endif
+		NET_DBG("Received buf %p len %zu", buf, pkt_len);
+
+		net_stats_update_bytes_recv(pkt_len);
 
 		processing_data(buf, false);
 
diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c
index cb47253..25f29d8 100644
--- a/subsys/net/ip/net_if.c
+++ b/subsys/net/ip/net_if.c
@@ -86,7 +86,9 @@
 		void *context_token;
 		struct net_buf *buf;
 		int status;
-
+#if defined(CONFIG_NET_STATISTICS)
+		size_t pkt_len;
+#endif
 		/* Get next packet from application - wait if necessary */
 		buf = net_buf_get(&iface->tx_queue, K_FOREVER);
 
@@ -97,6 +99,9 @@
 		context_token = net_nbuf_token(buf);
 
 		if (atomic_test_bit(iface->flags, NET_IF_UP)) {
+#if defined(CONFIG_NET_STATISTICS)
+			pkt_len = net_buf_frags_len(buf);
+#endif
 			status = api->send(iface, buf);
 		} else {
 			/* Drop packet if interface is not up */
@@ -106,6 +111,8 @@
 
 		if (status < 0) {
 			net_nbuf_unref(buf);
+		} else {
+			net_stats_update_bytes_sent(pkt_len);
 		}
 
 		if (context) {
diff --git a/subsys/net/ip/net_shell.c b/subsys/net/ip/net_shell.c
index 0388579..4d4cffe 100644
--- a/subsys/net/ip/net_shell.c
+++ b/subsys/net/ip/net_shell.c
@@ -451,6 +451,8 @@
 	       GET_STAT(rpl.root_repairs));
 #endif
 
+	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));
 }
 #endif /* CONFIG_NET_STATISTICS */
diff --git a/subsys/net/ip/net_stats.c b/subsys/net/ip/net_stats.c
index a58c9e9..d230560 100644
--- a/subsys/net/ip/net_stats.c
+++ b/subsys/net/ip/net_stats.c
@@ -114,6 +114,8 @@
 			 GET_STAT(rpl.root_repairs));
 #endif
 
+		NET_INFO("Bytes received %u", GET_STAT(bytes.received));
+		NET_INFO("Bytes sent     %u", GET_STAT(bytes.sent));
 		NET_INFO("Processing err %d", GET_STAT(processing_error));
 
 		new_print = curr + PRINT_STATISTICS_INTERVAL;
@@ -148,6 +150,10 @@
 		len_chk = sizeof(net_stats_t);
 		src = &net_stats.processing_error;
 		break;
+	case NET_REQUEST_STATS_CMD_GET_BYTES:
+		len_chk = sizeof(struct net_stats_bytes);
+		src = &net_stats.bytes;
+		break;
 	case NET_REQUEST_STATS_CMD_GET_IP_ERRORS:
 		len_chk = sizeof(struct net_stats_ip_errors);
 		src = &net_stats.ip_errors;
@@ -211,6 +217,9 @@
 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PROCESSING_ERROR,
 				  net_stats_get);
 
+NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_BYTES,
+				  net_stats_get);
+
 NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_STATS_GET_IP_ERRORS,
 				  net_stats_get);
 
diff --git a/subsys/net/ip/net_stats.h b/subsys/net/ip/net_stats.h
index 8d474fd..6176f27 100644
--- a/subsys/net/ip/net_stats.h
+++ b/subsys/net/ip/net_stats.h
@@ -31,10 +31,22 @@
 {
 	net_stats.ip_errors.vhlerr++;
 }
+
+static inline void net_stats_update_bytes_recv(uint32_t bytes)
+{
+	net_stats.bytes.received += bytes;
+}
+
+static inline void net_stats_update_bytes_sent(uint32_t bytes)
+{
+	net_stats.bytes.sent += bytes;
+}
 #else
 #define net_stats_update_processing_error()
 #define net_stats_update_ip_errors_protoerr()
 #define net_stats_update_ip_errors_vhlerr()
+#define net_stats_update_bytes_recv(...)
+#define net_stats_update_bytes_sent(...)
 #endif /* CONFIG_NET_STATISTICS */
 
 #if defined(CONFIG_NET_STATISTICS_IPV6)