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_IPV6_PMTU)
47 printk("IPv6 PMTU recv %d\tsent\t%d\tdrop\t%d\n",
48 GET_STAT(iface, ipv6_pmtu.recv),
49 GET_STAT(iface, ipv6_pmtu.sent),
50 GET_STAT(iface, ipv6_pmtu.drop));
51 #endif /* CONFIG_NET_IPV6_PMTU */
52 #if defined(CONFIG_NET_STATISTICS_MLD)
53 printk("IPv6 MLD recv %d\tsent\t%d\tdrop\t%d\n",
54 GET_STAT(iface, ipv6_mld.recv),
55 GET_STAT(iface, ipv6_mld.sent),
56 GET_STAT(iface, ipv6_mld.drop));
57 #endif /* CONFIG_NET_STATISTICS_MLD */
58 #endif /* CONFIG_NET_IPV6 */
59
60 #if defined(CONFIG_NET_IPV4)
61 printk("IPv4 recv %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n",
62 GET_STAT(iface, ipv4.recv),
63 GET_STAT(iface, ipv4.sent),
64 GET_STAT(iface, ipv4.drop),
65 GET_STAT(iface, ipv4.forwarded));
66 #endif /* CONFIG_NET_IPV4 */
67
68 printk("IP vhlerr %d\thblener\t%d\tlblener\t%d\n",
69 GET_STAT(iface, ip_errors.vhlerr),
70 GET_STAT(iface, ip_errors.hblenerr),
71 GET_STAT(iface, ip_errors.lblenerr));
72 printk("IP fragerr %d\tchkerr\t%d\tprotoer\t%d\n",
73 GET_STAT(iface, ip_errors.fragerr),
74 GET_STAT(iface, ip_errors.chkerr),
75 GET_STAT(iface, ip_errors.protoerr));
76
77 #if defined(CONFIG_NET_IPV4_PMTU)
78 printk("IPv4 PMTU recv %d\tsent\t%d\tdrop\t%d\n",
79 GET_STAT(iface, ipv4_pmtu.recv),
80 GET_STAT(iface, ipv4_pmtu.sent),
81 GET_STAT(iface, ipv4_pmtu.drop));
82 #endif /* CONFIG_NET_IPV4_PMTU */
83
84 printk("ICMP recv %d\tsent\t%d\tdrop\t%d\n",
85 GET_STAT(iface, icmp.recv),
86 GET_STAT(iface, icmp.sent),
87 GET_STAT(iface, icmp.drop));
88 printk("ICMP typeer %d\tchkerr\t%d\n",
89 GET_STAT(iface, icmp.typeerr),
90 GET_STAT(iface, icmp.chkerr));
91
92 #if defined(CONFIG_NET_UDP)
93 printk("UDP recv %d\tsent\t%d\tdrop\t%d\n",
94 GET_STAT(iface, udp.recv),
95 GET_STAT(iface, udp.sent),
96 GET_STAT(iface, udp.drop));
97 printk("UDP chkerr %d\n",
98 GET_STAT(iface, udp.chkerr));
99 #endif
100
101 #if defined(CONFIG_NET_STATISTICS_TCP)
102 printk("TCP bytes recv %u\tsent\t%d\n",
103 GET_STAT(iface, tcp.bytes.received),
104 GET_STAT(iface, tcp.bytes.sent));
105 printk("TCP seg recv %d\tsent\t%d\tdrop\t%d\n",
106 GET_STAT(iface, tcp.recv),
107 GET_STAT(iface, tcp.sent),
108 GET_STAT(iface, tcp.drop));
109 printk("TCP seg resent %d\tchkerr\t%d\tackerr\t%d\n",
110 GET_STAT(iface, tcp.resent),
111 GET_STAT(iface, tcp.chkerr),
112 GET_STAT(iface, tcp.ackerr));
113 printk("TCP seg rsterr %d\trst\t%d\tre-xmit\t%d\n",
114 GET_STAT(iface, tcp.rsterr),
115 GET_STAT(iface, tcp.rst),
116 GET_STAT(iface, tcp.rexmit));
117 printk("TCP conn drop %d\tconnrst\t%d\n",
118 GET_STAT(iface, tcp.conndrop),
119 GET_STAT(iface, tcp.connrst));
120 #endif
121
122 printk("Bytes received %u\n", GET_STAT(iface, bytes.received));
123 printk("Bytes sent %u\n", GET_STAT(iface, bytes.sent));
124 printk("Processing err %d\n", GET_STAT(iface, processing_error));
125 }
126
127 #if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
iface_cb(struct net_if * iface,void * user_data)128 static void iface_cb(struct net_if *iface, void *user_data)
129 {
130 struct net_stats *data = user_data;
131
132 net_mgmt(NET_REQUEST_STATS_GET_ALL, iface, data, sizeof(*data));
133
134 print_stats(iface, data);
135 }
136 #endif
137
138 #if defined(CONFIG_NET_STATISTICS_ETHERNET)
print_eth_stats(struct net_if * iface,struct net_stats_eth * data)139 static void print_eth_stats(struct net_if *iface, struct net_stats_eth *data)
140 {
141 printk("Statistics for Ethernet interface %p [%d]\n", iface,
142 net_if_get_by_iface(iface));
143
144 printk("Bytes received : %u\n", data->bytes.received);
145 printk("Bytes sent : %u\n", data->bytes.sent);
146 printk("Packets received : %u\n", data->pkts.rx);
147 printk("Packets sent : %u\n", data->pkts.tx);
148 printk("Bcast received : %u\n", data->broadcast.rx);
149 printk("Bcast sent : %u\n", data->broadcast.tx);
150 printk("Mcast received : %u\n", data->multicast.rx);
151 printk("Mcast sent : %u\n", data->multicast.tx);
152 }
153
eth_iface_cb(struct net_if * iface,void * user_data)154 static void eth_iface_cb(struct net_if *iface, void *user_data)
155 {
156 struct net_stats_eth eth_data;
157 int ret;
158
159 if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) {
160 return;
161 }
162
163 ret = net_mgmt(NET_REQUEST_STATS_GET_ETHERNET, iface, ð_data,
164 sizeof(eth_data));
165 if (ret < 0) {
166 return;
167 }
168
169 print_eth_stats(iface, ð_data);
170 }
171 #endif
172
stats(struct k_work * work)173 static void stats(struct k_work *work)
174 {
175 struct net_stats data;
176
177 /* It is also possible to query some specific statistics by setting
178 * the first request parameter properly. See include/net/net_stats.h
179 * what requests are available.
180 */
181 net_mgmt(NET_REQUEST_STATS_GET_ALL, NULL, &data, sizeof(data));
182
183 print_stats(NULL, &data);
184
185 #if defined(CONFIG_NET_STATISTICS_PER_INTERFACE)
186 net_if_foreach(iface_cb, &data);
187 #endif
188
189 #if defined(CONFIG_NET_STATISTICS_ETHERNET)
190 net_if_foreach(eth_iface_cb, &data);
191 #endif
192
193 k_work_reschedule(&stats_timer, K_SECONDS(CONFIG_SAMPLE_PERIOD));
194 }
195
init_app(void)196 static void init_app(void)
197 {
198 k_work_init_delayable(&stats_timer, stats);
199 k_work_reschedule(&stats_timer, K_SECONDS(CONFIG_SAMPLE_PERIOD));
200 }
201
main(void)202 int main(void)
203 {
204 /* Register a timer that will collect statistics after every n seconds.
205 */
206 init_app();
207 return 0;
208 }
209