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, ð_data,
151 sizeof(eth_data));
152 if (ret < 0) {
153 return;
154 }
155
156 print_eth_stats(iface, ð_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