1 /*
2  * Copyright (c) 2018 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(net_stats_sample, LOG_LEVEL_DBG);
9 
10 #include <zephyr/kernel.h>
11 #include <errno.h>
12 
13 #include <zephyr/net/net_core.h>
14 #include <zephyr/net/net_if.h>
15 #include <zephyr/net/net_stats.h>
16 
17 static struct k_work_delayable stats_timer;
18 
19 #if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
20 #define GET_STAT(iface, s) (iface ? iface->stats.s : data->s)
21 #else
22 #define GET_STAT(iface, s) data->s
23 #endif
24 
print_stats(struct net_if * iface,struct net_stats * data)25 static void print_stats(struct net_if *iface, struct net_stats *data)
26 {
27 	if (iface) {
28 		printk("Statistics for interface %p [%d]\n", iface,
29 		       net_if_get_by_iface(iface));
30 	} else {
31 		printk("Global network statistics\n");
32 	}
33 
34 #if defined(CONFIG_NET_IPV6)
35 	printk("IPv6 recv      %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n",
36 	       GET_STAT(iface, ipv6.recv),
37 	       GET_STAT(iface, ipv6.sent),
38 	       GET_STAT(iface, ipv6.drop),
39 	       GET_STAT(iface, ipv6.forwarded));
40 #if defined(CONFIG_NET_IPV6_ND)
41 	printk("IPv6 ND recv   %d\tsent\t%d\tdrop\t%d\n",
42 	       GET_STAT(iface, ipv6_nd.recv),
43 	       GET_STAT(iface, ipv6_nd.sent),
44 	       GET_STAT(iface, ipv6_nd.drop));
45 #endif /* CONFIG_NET_IPV6_ND */
46 #if defined(CONFIG_NET_STATISTICS_MLD)
47 	printk("IPv6 MLD recv  %d\tsent\t%d\tdrop\t%d\n",
48 	       GET_STAT(iface, ipv6_mld.recv),
49 	       GET_STAT(iface, ipv6_mld.sent),
50 	       GET_STAT(iface, ipv6_mld.drop));
51 #endif /* CONFIG_NET_STATISTICS_MLD */
52 #endif /* CONFIG_NET_IPV6 */
53 
54 #if defined(CONFIG_NET_IPV4)
55 	printk("IPv4 recv      %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n",
56 	       GET_STAT(iface, ipv4.recv),
57 	       GET_STAT(iface, ipv4.sent),
58 	       GET_STAT(iface, ipv4.drop),
59 	       GET_STAT(iface, ipv4.forwarded));
60 #endif /* CONFIG_NET_IPV4 */
61 
62 	printk("IP vhlerr      %d\thblener\t%d\tlblener\t%d\n",
63 	       GET_STAT(iface, ip_errors.vhlerr),
64 	       GET_STAT(iface, ip_errors.hblenerr),
65 	       GET_STAT(iface, ip_errors.lblenerr));
66 	printk("IP fragerr     %d\tchkerr\t%d\tprotoer\t%d\n",
67 	       GET_STAT(iface, ip_errors.fragerr),
68 	       GET_STAT(iface, ip_errors.chkerr),
69 	       GET_STAT(iface, ip_errors.protoerr));
70 
71 	printk("ICMP recv      %d\tsent\t%d\tdrop\t%d\n",
72 	       GET_STAT(iface, icmp.recv),
73 	       GET_STAT(iface, icmp.sent),
74 	       GET_STAT(iface, icmp.drop));
75 	printk("ICMP typeer    %d\tchkerr\t%d\n",
76 	       GET_STAT(iface, icmp.typeerr),
77 	       GET_STAT(iface, icmp.chkerr));
78 
79 #if defined(CONFIG_NET_UDP)
80 	printk("UDP recv       %d\tsent\t%d\tdrop\t%d\n",
81 	       GET_STAT(iface, udp.recv),
82 	       GET_STAT(iface, udp.sent),
83 	       GET_STAT(iface, udp.drop));
84 	printk("UDP chkerr     %d\n",
85 	       GET_STAT(iface, udp.chkerr));
86 #endif
87 
88 #if defined(CONFIG_NET_STATISTICS_TCP)
89 	printk("TCP bytes recv %u\tsent\t%d\n",
90 	       GET_STAT(iface, tcp.bytes.received),
91 	       GET_STAT(iface, tcp.bytes.sent));
92 	printk("TCP seg recv   %d\tsent\t%d\tdrop\t%d\n",
93 	       GET_STAT(iface, tcp.recv),
94 	       GET_STAT(iface, tcp.sent),
95 	       GET_STAT(iface, tcp.drop));
96 	printk("TCP seg resent %d\tchkerr\t%d\tackerr\t%d\n",
97 	       GET_STAT(iface, tcp.resent),
98 	       GET_STAT(iface, tcp.chkerr),
99 	       GET_STAT(iface, tcp.ackerr));
100 	printk("TCP seg rsterr %d\trst\t%d\tre-xmit\t%d\n",
101 	       GET_STAT(iface, tcp.rsterr),
102 	       GET_STAT(iface, tcp.rst),
103 	       GET_STAT(iface, tcp.rexmit));
104 	printk("TCP conn drop  %d\tconnrst\t%d\n",
105 	       GET_STAT(iface, tcp.conndrop),
106 	       GET_STAT(iface, tcp.connrst));
107 #endif
108 
109 	printk("Bytes received %u\n", GET_STAT(iface, bytes.received));
110 	printk("Bytes sent     %u\n", GET_STAT(iface, bytes.sent));
111 	printk("Processing err %d\n", GET_STAT(iface, processing_error));
112 }
113 
114 #if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
iface_cb(struct net_if * iface,void * user_data)115 static void iface_cb(struct net_if *iface, void *user_data)
116 {
117 	struct net_stats *data = user_data;
118 
119 	net_mgmt(NET_REQUEST_STATS_GET_ALL, iface, data, sizeof(*data));
120 
121 	print_stats(iface, data);
122 }
123 #endif
124 
125 #if defined(CONFIG_NET_STATISTICS_ETHERNET)
print_eth_stats(struct net_if * iface,struct net_stats_eth * data)126 static void print_eth_stats(struct net_if *iface, struct net_stats_eth *data)
127 {
128 	printk("Statistics for Ethernet interface %p [%d]\n", iface,
129 	       net_if_get_by_iface(iface));
130 
131 	printk("Bytes received   : %u\n", data->bytes.received);
132 	printk("Bytes sent       : %u\n", data->bytes.sent);
133 	printk("Packets received : %u\n", data->pkts.rx);
134 	printk("Packets sent     : %u\n", data->pkts.tx);
135 	printk("Bcast received   : %u\n", data->broadcast.rx);
136 	printk("Bcast sent       : %u\n", data->broadcast.tx);
137 	printk("Mcast received   : %u\n", data->multicast.rx);
138 	printk("Mcast sent       : %u\n", data->multicast.tx);
139 }
140 
eth_iface_cb(struct net_if * iface,void * user_data)141 static void eth_iface_cb(struct net_if *iface, void *user_data)
142 {
143 	struct net_stats_eth eth_data;
144 	int ret;
145 
146 	if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
147 		return;
148 	}
149 
150 	ret = net_mgmt(NET_REQUEST_STATS_GET_ETHERNET, iface, &eth_data,
151 		       sizeof(eth_data));
152 	if (ret < 0) {
153 		return;
154 	}
155 
156 	print_eth_stats(iface, &eth_data);
157 }
158 #endif
159 
stats(struct k_work * work)160 static void stats(struct k_work *work)
161 {
162 	struct net_stats data;
163 
164 	/* It is also possible to query some specific statistics by setting
165 	 * the first request parameter properly. See include/net/net_stats.h
166 	 * what requests are available.
167 	 */
168 	net_mgmt(NET_REQUEST_STATS_GET_ALL, NULL, &data, sizeof(data));
169 
170 	print_stats(NULL, &data);
171 
172 #if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
173 	net_if_foreach(iface_cb, &data);
174 #endif
175 
176 #if defined(CONFIG_NET_STATISTICS_ETHERNET)
177 	net_if_foreach(eth_iface_cb, &data);
178 #endif
179 
180 	k_work_reschedule(&stats_timer, K_SECONDS(CONFIG_SAMPLE_PERIOD));
181 }
182 
init_app(void)183 static void init_app(void)
184 {
185 	k_work_init_delayable(&stats_timer, stats);
186 	k_work_reschedule(&stats_timer, K_SECONDS(CONFIG_SAMPLE_PERIOD));
187 }
188 
main(void)189 int main(void)
190 {
191 	/* Register a timer that will collect statistics after every n seconds.
192 	 */
193 	init_app();
194 	return 0;
195 }
196