1
+ #pragma once
2
+ /*
3
+ * This library aims to provide debug utilities for performances on Network interfaces
4
+ * that are being used in lwip wrapper
5
+ *
6
+ * USAGE:
7
+ *
8
+ * In the Net interface define the struct (it should be accessible from outside)
9
+ *
10
+ * #ifdef CNETIF_STATS_ENABLED
11
+ * struct netif_stats stats;
12
+ * #endif
13
+ *
14
+ * Initialize the struct:
15
+ *
16
+ * NETIF_STATS_INIT(stats);
17
+ *
18
+ * Then use the MACROS defined in this file. NOTE if CNETIF_STATS_ENABLED is not defined the macros will
19
+ * be solved as empty, thus no need to use #ifdef.
20
+ *
21
+ * In the sketch you need to import the symbol for the stats and define a buffer
22
+ * (in can be dinamically allocated, it should only require 300 chars).
23
+ *
24
+ * #include <CNetifStats.h>
25
+ * #ifdef CNETIF_STATS_ENABLED
26
+ * extern netif_stats stats;
27
+ * char cnetif_stats_buffer[300];
28
+ * #endif
29
+ *
30
+ * Then you can call the routine to print the stats:
31
+ *
32
+ * #ifdef CNETIF_STATS_ENABLED
33
+ * NETIF_STATS_SPRINT_DEBUG(cnetif_stats_buffer, stats);
34
+ * DEBUG_INFO(cnetif_stats_buffer);
35
+ * #endif
36
+ *
37
+ * You can optionally print the metrics yourself, for how to look at netif_stats_sprintf function
38
+ */
39
+
40
+ // #define CNETIF_STATS_ENABLED
41
+ #ifdef CNETIF_STATS_ENABLED
42
+
43
+ #include < stdio.h>
44
+
45
+ struct netif_stats {
46
+ // this metric cunts the number of times the rx interrupt routine is called by the driver
47
+ uint32_t rx_interrupt_calls;
48
+ // this metric count the number of time the transmit routine is invoked on the driver
49
+ uint32_t tx_transmit_calls;
50
+ // this metric counts the total number of failed rx calls, for whatever reason
51
+ uint32_t rx_interrupt_failed_calls;
52
+ // this metric count the number of times the rx routine failed allocating the buffer for the incoming packet
53
+ uint32_t rx_pbuf_alloc_failed_calls;
54
+ // this metric count the number of times the rx routing failed inserting the pbuf inside lwip
55
+ uint32_t rx_ni_input_failed_calls;
56
+ // this metric counts the number of times the tx routine failed
57
+ uint32_t tx_transmit_failed_calls;
58
+
59
+ // the following metrics count the size (bytes) of packets being handled in rx and tx
60
+ uint32_t rx_bytes;
61
+ uint32_t tx_bytes;
62
+
63
+ // the following measure contains the size (bytes) of packets being handled in rx and tx
64
+ // before the reset, used to calculate avg speed
65
+ uint32_t prev_rx_bytes;
66
+ uint32_t prev_tx_bytes;
67
+ time_t measure_start;
68
+
69
+ // the following metrics are used to calculate the average time spent in rx interrupt and tx routine, measured in us
70
+ float average_rx_time;
71
+ uint32_t average_rx_time_counter;
72
+ float average_tx_time;
73
+ uint32_t average_tx_time_counter;
74
+
75
+ // the following variables are used to hold the starting time for average a single time measurement
76
+ time_t rx_time_start;
77
+ time_t tx_time_start;
78
+ };
79
+
80
+ /*
81
+ * This function initializes the counters on the netif_struct_t
82
+ */
83
+ inline void netif_stats_init (struct netif_stats & stats, time_t time=micros()) {
84
+ stats.rx_interrupt_calls = 0 ;
85
+ stats.rx_interrupt_failed_calls = 0 ;
86
+ stats.rx_pbuf_alloc_failed_calls = 0 ;
87
+ stats.rx_ni_input_failed_calls = 0 ;
88
+ stats.tx_transmit_calls = 0 ;
89
+ stats.tx_transmit_failed_calls = 0 ;
90
+
91
+ stats.rx_bytes = 0 ;
92
+ stats.tx_bytes = 0 ;
93
+ stats.prev_rx_bytes = 0 ;
94
+ stats.prev_tx_bytes = 0 ;
95
+ stats.measure_start = time ;
96
+
97
+
98
+ stats.average_rx_time = 0 ;
99
+ stats.average_rx_time_counter = 0 ;
100
+ stats.average_tx_time = 0 ;
101
+ stats.average_tx_time_counter = 0 ;
102
+ }
103
+
104
+ /*
105
+ * This is an utility function used to calculate an average of a sequence of numbers without storing them,
106
+ * it can accept any tipes that support *, + and / operators.
107
+ * This function automatically increments the counter
108
+ * This function returns the next average
109
+ */
110
+ template <typename T, typename S>
111
+ inline T netif_stats_streaming_average (const T& metric, const T new_value, S& counter) {
112
+ return ((metric*counter) + (new_value)) / (++counter);
113
+ }
114
+
115
+ /*
116
+ * This function is used to reset the metrics that are used for averages.
117
+ * It is intended to be called after the prints
118
+ */
119
+ inline void netif_stats_reset_averages (struct netif_stats & stats, time_t time=micros()) {
120
+ stats.prev_rx_bytes = stats.rx_bytes ;
121
+ stats.prev_tx_bytes = stats.tx_bytes ;
122
+
123
+ stats.average_rx_time = 0 ;
124
+ stats.average_rx_time_counter = 0 ;
125
+
126
+ stats.average_tx_time = 0 ;
127
+ stats.average_tx_time_counter = 0 ;
128
+ stats.measure_start = time ;
129
+ }
130
+
131
+ /*
132
+ * This routine outputs a string containing a summary of the measured stats,
133
+ * the buffer passed should be 270 bytes
134
+ */
135
+ inline void netif_stats_sprintf (char * buffer, const struct netif_stats & stats, size_t size=500 , time_t time=micros()) {
136
+ snprintf (
137
+ buffer,
138
+ size,
139
+ " RX bytes: %10u, calls: %10u, failed: %10u, failed alloc: %10u, failed inputs: %10u\n "
140
+ " TX bytes: %10u, calls: %10u, failed: %10u\n "
141
+ " RX time: %10.2fus speed: %10.2fKB/s\n "
142
+ " TX time: %10.2fus speed: %10.2fKB/s\n " ,
143
+ stats.rx_bytes , stats.rx_interrupt_calls , stats.rx_interrupt_failed_calls , stats.rx_pbuf_alloc_failed_calls , stats.rx_ni_input_failed_calls ,
144
+ stats.tx_bytes , stats.tx_transmit_calls , stats.tx_transmit_failed_calls ,
145
+ stats.average_rx_time , float (stats.rx_bytes - stats.prev_rx_bytes ) / (time -stats.measure_start ) * 10e6 / 1024 , // Measured in KB/s
146
+ stats.average_tx_time , float (stats.tx_bytes - stats.prev_tx_bytes ) / (time -stats.measure_start ) * 10e6 / 1024
147
+ );
148
+ }
149
+
150
+ #define NETIF_STATS_INIT (stats ) netif_stats_init(stats)
151
+ #define NETIF_STATS_RESET_AVERAGES (stats ) netif_stats_reset_averages(stats)
152
+ #define NETIF_STATS_SPRINT_DEBUG (buffer, stats ) netif_stats_sprintf(buffer, stats)
153
+
154
+ #define NETIF_STATS_INCREMENT_RX_INTERRUPT_CALLS (stats ) stats.rx_interrupt_calls++
155
+ #define NETIF_STATS_INCREMENT_RX_INTERRUPT_FAILED_CALLS (stats ) stats.rx_interrupt_failed_calls++
156
+ #define NETIF_STATS_INCREMENT_RX_PBUF_ALLOC_FAILED_CALLS (stats ) stats.rx_pbuf_alloc_failed_calls++
157
+ #define NETIF_STATS_INCREMENT_RX_NI_INPUT_FAILED_CALLS (stats ) stats.rx_ni_input_failed_calls++
158
+ #define NETIF_STATS_INCREMENT_TX_TRANSMIT_CALLS (stats ) stats.tx_transmit_calls++
159
+ #define NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS (stats ) stats.tx_transmit_failed_calls++
160
+
161
+ #define NETIF_STATS_INCREMENT_RX_BYTES (stats, bytes ) stats.rx_bytes+=bytes
162
+ #define NETIF_STATS_INCREMENT_TX_BYTES (stats, bytes ) stats.tx_bytes+=bytes
163
+
164
+ #define NETIF_STATS_RX_TIME_START (stats ) stats.rx_time_start = micros()
165
+ #define NETIF_STATS_RX_TIME_AVERAGE (stats ) stats.average_rx_time = netif_stats_streaming_average(stats.average_rx_time, float (micros() - stats.rx_time_start), stats.average_rx_time_counter)
166
+
167
+ #define NETIF_STATS_TX_TIME_START (stats ) stats.tx_time_start = micros()
168
+ #define NETIF_STATS_TX_TIME_AVERAGE (stats ) stats.average_tx_time = netif_stats_streaming_average(stats.average_tx_time, float (micros() - stats.tx_time_start), stats.average_tx_time_counter)
169
+
170
+
171
+ #else // CNETIF_STATS_ENABLED
172
+
173
+ #define NETIF_STATS_INIT (stats ) (void )0
174
+ #define NETIF_STATS_RESET_AVERAGES (stats ) (void )0
175
+ #define NETIF_STATS_SPRINT_DEBUG (stats, buffer ) (void )0
176
+
177
+ #define NETIF_STATS_INCREMENT_RX_INTERRUPT_CALLS (stats ) (void )0
178
+ #define NETIF_STATS_INCREMENT_RX_INTERRUPT_FAILED_CALLS (stats ) (void )0
179
+ #define NETIF_STATS_INCREMENT_RX_PBUF_ALLOC_FAILED_CALLS (stats ) (void )0
180
+ #define NETIF_STATS_INCREMENT_RX_NI_INPUT_FAILED_CALLS (stats ) (void )0
181
+ #define NETIF_STATS_INCREMENT_TX_TRANSMIT_CALLS (stats ) (void )0
182
+ #define NETIF_STATS_INCREMENT_TX_TRANSMIT_FAILED_CALLS (stats ) (void )0
183
+
184
+ #define NETIF_STATS_INCREMENT_RX_BYTES (stats, bytes ) (void )0
185
+ #define NETIF_STATS_INCREMENT_TX_BYTES (stats, bytes ) (void )0
186
+
187
+ #define NETIF_STATS_RX_TIME_START (stats ) (void )0
188
+ #define NETIF_STATS_RX_TIME_AVERAGE (stats ) (void )0
189
+
190
+ #define NETIF_STATS_TX_TIME_START (stats ) (void )0
191
+ #define NETIF_STATS_TX_TIME_AVERAGE (stats ) (void )0
192
+
193
+
194
+ #endif // CNETIF_STATS_ENABLED
0 commit comments