Preparation for packet mis-ordering stats
[samplevnf.git] / VNFs / DPPD-PROX / display_tasks.c
1 /*
2 // Copyright (c) 2010-2017 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 #include "display_tasks.h"
18 #include "display.h"
19 #include "prox_globals.h"
20 #include "stats_task.h"
21 #include "stats_core.h"
22 #include "lconf.h"
23
24 struct task_stats_disp {
25         uint32_t lcore_id;
26         uint32_t task_id;
27         uint32_t lcore_stat_id;
28 };
29
30 static int col_offset;
31 static struct task_stats_disp task_stats_disp[RTE_MAX_LCORE * MAX_TASKS_PER_CORE];
32
33 static struct display_page display_page_tasks;
34
35 static struct display_column *nb_col;
36 static struct display_column *name_col;
37 static struct display_column *mode_col;
38 static struct display_column *rx_name_col;
39 static struct display_column *tx_name_col;
40 static struct display_column *idle_col;
41 static struct display_column *rx_col;
42 static struct display_column *tx_col;
43 static struct display_column *tx_fail_col;
44 static struct display_column *discard_col;
45 static struct display_column *handled_col;
46 static struct display_column *cpp_col;
47 static struct display_column *ghz_col;
48 static struct display_column *rx_col;
49 static struct display_column *tx_col;
50 static struct display_column *tx_fail_col;
51 static struct display_column *discard_col;
52 static struct display_column *handled_col;
53 static struct display_column *occup_col;
54 static struct display_column *mask_col;
55 static struct display_column *class_col;
56 static struct display_column *mbm_tot_col;
57 static struct display_column *mbm_loc_col;
58 static struct display_column *frac_col;
59 static struct display_column *rx_non_dp_col;
60 static struct display_column *tx_non_dp_col;
61
62 static void stats_display_core_task_entry(struct lcore_cfg *lconf, struct task_args *targ, unsigned row)
63 {
64         display_column_print_core_task(nb_col, row, lconf, targ);
65
66         display_column_print(name_col, row, "%s", targ->id == 0 ? lconf->name : "");
67         display_column_print(mode_col, row, "%s", targ->task_init->mode_str);
68
69         display_column_port_ring(rx_name_col, row, targ->rx_port_queue, targ->nb_rxports, targ->rx_rings, targ->nb_rxrings);
70         display_column_port_ring(tx_name_col, row, targ->tx_port_queue, targ->nb_txports, targ->tx_rings, targ->nb_txrings);
71 }
72
73 static void display_tasks_draw_frame(struct screen_state *state)
74 {
75         const uint32_t n_tasks_tot = stats_get_n_tasks_tot();
76
77         display_page_init(&display_page_tasks);
78
79         struct display_table *core_task = display_page_add_table(&display_page_tasks);
80         struct display_table *rx_tx = display_page_add_table(&display_page_tasks);
81
82         display_table_init(core_task, "Core/Task");
83
84         nb_col = display_table_add_col(core_task);
85         display_column_init(nb_col, "Nb", 4);
86         name_col = display_table_add_col(core_task);
87         display_column_init(name_col, "Name", 7);
88         mode_col = display_table_add_col(core_task);
89         display_column_init(mode_col, "Mode", 9);
90
91         display_table_init(rx_tx, "Port ID/Ring Name");
92         rx_name_col = display_table_add_col(rx_tx);
93         display_column_init(rx_name_col, "RX", 9);
94         tx_name_col = display_table_add_col(rx_tx);
95         display_column_init(tx_name_col, "TX", 9);
96
97         struct display_table *stats = display_page_add_table(&display_page_tasks);
98
99         if (state->toggle == 0) {
100                 display_table_init(stats, "Statistics per second");
101
102                 idle_col = display_table_add_col(stats);
103                 display_column_init(idle_col, "Idle (%)", 5);
104
105                 rx_col = display_table_add_col(stats);
106                 display_column_init(rx_col, "RX (K)", 9);
107
108                 tx_col = display_table_add_col(stats);
109                 display_column_init(tx_col, "TX (K)", 9);
110
111                 tx_fail_col = display_table_add_col(stats);
112                 display_column_init(tx_fail_col, "TX Fail (K)", 9);
113
114                 discard_col = display_table_add_col(stats);
115                 display_column_init(discard_col, "Discard (K)", 9);
116
117                 handled_col = display_table_add_col(stats);
118                 display_column_init(handled_col, "Handled (K)", 9);
119
120                 rx_non_dp_col = display_table_add_col(stats);
121                 display_column_init(rx_non_dp_col, "Rx non DP (K)", 9);
122
123                 tx_non_dp_col = display_table_add_col(stats);
124                 display_column_init(tx_non_dp_col, "Tx non DP (K)", 9);
125
126                 if (stats_cpu_freq_enabled()) {
127                         struct display_table *other = display_page_add_table(&display_page_tasks);
128
129                         display_table_init(other, "Other");
130
131                         cpp_col = display_table_add_col(other);
132                         display_column_init(cpp_col, "CPP", 9);
133
134                         ghz_col = display_table_add_col(other);
135                         display_column_init(ghz_col, "Clk (GHz)", 9);
136                 }
137                 if (stats_mbm_enabled()) {
138                         struct display_table *other = display_page_add_table(&display_page_tasks);
139                         mbm_tot_col = display_table_add_col(other);
140                         display_column_init(mbm_tot_col, "Tot Bdw(M)", 10);
141                         mbm_loc_col = display_table_add_col(other);
142                         display_column_init(mbm_loc_col, "Loc Bdw(M)", 10);
143                 }
144         } else {
145                 display_table_init(stats, "Total Statistics");
146
147                 rx_col = display_table_add_col(stats);
148                 display_column_init(rx_col, "RX (K)", 14);
149
150                 tx_col = display_table_add_col(stats);
151                 display_column_init(tx_col, "TX (K)", 14);
152
153                 tx_fail_col = display_table_add_col(stats);
154                 display_column_init(tx_fail_col, "TX Fail (K)", 14);
155
156                 discard_col = display_table_add_col(stats);
157                 display_column_init(discard_col, "Discard (K)", 14);
158
159                 handled_col = display_table_add_col(stats);
160                 display_column_init(handled_col, "Handled (K)", 14);
161
162                 rx_non_dp_col = display_table_add_col(stats);
163                 display_column_init(rx_non_dp_col, "RX non DP (K)", 14);
164
165                 tx_non_dp_col = display_table_add_col(stats);
166                 display_column_init(tx_non_dp_col, "TX non DP (K)", 14);
167
168                 if (stats_cmt_enabled()) {
169                         struct display_table *other = display_page_add_table(&display_page_tasks);
170
171                         display_table_init(other, "Cache QoS Monitoring");
172
173                         occup_col = display_table_add_col(other);
174                         display_column_init(occup_col, "Occupancy (KB)", 15);
175
176                         frac_col = display_table_add_col(other);
177                         display_column_init(frac_col, "Fraction", 9);
178                 }
179                 if (stats_cat_enabled()) {
180                         struct display_table *other = display_page_add_table(&display_page_tasks);
181                         mask_col = display_table_add_col(other);
182                         display_column_init(mask_col, "Cache mask", 10);
183                         class_col = display_table_add_col(other);
184                         display_column_init(class_col, "Class", 5);
185                 }
186         }
187         display_page_draw_frame(&display_page_tasks, n_tasks_tot);
188
189         uint16_t element_count = 0;
190
191         struct lcore_cfg *lconf = NULL;
192         struct task_args *targ;
193
194         while (core_targ_next(&lconf, &targ, 0) == 0) {
195                 PROX_ASSERT(element_count < RTE_MAX_LCORE * MAX_TASKS_PER_CORE);
196
197                 stats_display_core_task_entry(lconf, targ, element_count);
198
199                 task_stats_disp[element_count].lcore_id = lconf->id;
200                 task_stats_disp[element_count].task_id = targ->id;
201                 task_stats_disp[element_count].lcore_stat_id = stats_lcore_find_stat_id(lconf->id);
202                 element_count++;
203         }
204 }
205
206 static void print_kpps(struct display_column *col, int row, uint64_t nb_pkts, uint64_t delta_t)
207 {
208         nb_pkts *= tsc_hz;
209         if (nb_pkts && nb_pkts /100 < delta_t) {
210                 uint64_t int_part = nb_pkts/delta_t;
211                 uint64_t frac_part = (nb_pkts - int_part * delta_t) * 1000 /delta_t;
212                 display_column_print(col, row, "%2lu.%03lu", int_part, frac_part);
213         }
214         else {
215                 display_column_print(col, row, "%9lu", nb_pkts / delta_t);
216         }
217 }
218
219 static void display_core_task_stats_per_sec(const struct task_stats_disp *t, struct screen_state *state, int row)
220 {
221         struct task_stats_sample *last = stats_get_task_stats_sample(t->lcore_id, t->task_id, 1);
222         struct task_stats_sample *prev = stats_get_task_stats_sample(t->lcore_id, t->task_id, 0);
223
224         /* delta_t in units of clock ticks */
225         uint64_t delta_t = last->tsc - prev->tsc;
226
227         uint64_t empty_cycles = last->empty_cycles - prev->empty_cycles;
228
229         if (empty_cycles > delta_t) {
230                 empty_cycles = 10000;
231         }
232         else {
233                 empty_cycles = empty_cycles * 10000 / delta_t;
234         }
235
236         /* empty_cycles has 2 digits after point, (usefull when only a very small idle time) */
237
238         display_column_print(idle_col, row, "%3lu.%02lu", empty_cycles / 100, empty_cycles % 100);
239
240         // Display per second statistics in Kpps unit
241         delta_t *= state->pps_unit;
242
243         print_kpps(rx_col, row, last->rx_pkt_count - prev->rx_pkt_count, delta_t);
244         print_kpps(tx_col, row, last->tx_pkt_count - prev->tx_pkt_count, delta_t);
245         print_kpps(tx_fail_col, row, last->drop_tx_fail - prev->drop_tx_fail, delta_t);
246         print_kpps(discard_col, row, last->drop_discard - prev->drop_discard, delta_t);
247         print_kpps(handled_col, row, last->drop_handled - prev->drop_handled, delta_t);
248         print_kpps(rx_non_dp_col, row, last->rx_non_dp - prev->rx_non_dp, delta_t);
249         print_kpps(tx_non_dp_col, row, last->tx_non_dp - prev->tx_non_dp, delta_t);
250
251         if (stats_cpu_freq_enabled()) {
252                 uint8_t lcore_stat_id = t->lcore_stat_id;
253                 struct lcore_stats_sample *clast = stats_get_lcore_stats_sample(lcore_stat_id, 1);
254                 struct lcore_stats_sample *cprev = stats_get_lcore_stats_sample(lcore_stat_id, 0);
255
256                 uint64_t adiff = clast->afreq - cprev->afreq;
257                 uint64_t mdiff = clast->mfreq - cprev->mfreq;
258
259                 uint64_t cpp = 0;
260
261                 uint64_t pkt_diff_rx = last->rx_pkt_count - prev->rx_pkt_count;
262                 uint64_t pkt_diff_tx = last->tx_pkt_count - prev->tx_pkt_count;
263
264                 uint64_t pkt_diff = pkt_diff_tx > pkt_diff_rx? pkt_diff_tx : pkt_diff_rx;
265
266                 if (pkt_diff && mdiff) {
267                         cpp = delta_t/pkt_diff*adiff/mdiff/1000;
268                 }
269
270                 uint64_t mhz;
271                 if (mdiff)
272                         mhz = tsc_hz*adiff/mdiff/1000000;
273                 else
274                         mhz = 0;
275
276                 display_column_print(cpp_col, row, "%lu", cpp);
277                 display_column_print(ghz_col, row, "%lu.%03lu", mhz/1000, mhz%1000);
278         }
279         if (stats_mbm_enabled()) {
280                 struct lcore_stats *c = stats_get_lcore_stats(t->lcore_stat_id);
281                 uint8_t lcore_stat_id = t->lcore_stat_id;
282                 struct lcore_stats_sample *clast = stats_get_lcore_stats_sample(lcore_stat_id, 1);
283                 struct lcore_stats_sample *cprev = stats_get_lcore_stats_sample(lcore_stat_id, 0);
284                 if ((clast->mbm_tot_bytes - cprev->mbm_tot_bytes) >> 20)
285                         display_column_print(mbm_tot_col, row, "%lu", (clast->mbm_tot_bytes - cprev->mbm_tot_bytes) >> 20);
286                 else
287                         display_column_print(mbm_tot_col, row, "0.%03lu", (clast->mbm_tot_bytes - cprev->mbm_tot_bytes) >> 10);
288                 if( (clast->mbm_loc_bytes - cprev->mbm_loc_bytes) >> 20)
289                         display_column_print(mbm_loc_col, row, "%lu", (clast->mbm_loc_bytes - cprev->mbm_loc_bytes) >> 20);
290                 else
291                         display_column_print(mbm_loc_col, row, "0.%03lu", (clast->mbm_loc_bytes - cprev->mbm_loc_bytes) >> 10);
292         }
293 }
294
295 static void display_core_task_stats_tot(const struct task_stats_disp *t, struct screen_state *state, int row)
296 {
297         struct task_stats *ts = stats_get_task_stats(t->lcore_id, t->task_id);
298
299         display_column_print(rx_col, row, "%lu", ts->tot_rx_pkt_count);
300         display_column_print(tx_col, row, "%lu", ts->tot_tx_pkt_count);
301         display_column_print(tx_fail_col, row, "%lu", ts->tot_drop_tx_fail);
302         display_column_print(discard_col, row, "%lu", ts->tot_drop_discard);
303         display_column_print(handled_col, row, "%lu", ts->tot_drop_handled);
304         display_column_print(rx_non_dp_col, row, "%lu", ts->tot_rx_non_dp);
305         display_column_print(tx_non_dp_col, row, "%lu", ts->tot_tx_non_dp);
306
307         if (stats_cmt_enabled()) {
308                 struct lcore_stats *c = stats_get_lcore_stats(t->lcore_stat_id);
309                 display_column_print(occup_col, row, "%lu", c->cmt_bytes >> 10);
310                 display_column_print(frac_col, row, "%3lu.%02lu", c->cmt_fraction/100, c->cmt_fraction%100);
311         }
312         if (stats_cat_enabled()) {
313                 struct lcore_stats *c = stats_get_lcore_stats(t->lcore_stat_id);
314                 display_column_print(mask_col, row, "%x", c->cat_mask);
315                 display_column_print(class_col, row, "%x", c->class);
316         }
317 }
318
319 static void display_tasks_draw_stats(struct screen_state *state)
320 {
321         const uint32_t n_tasks_tot = stats_get_n_tasks_tot();
322
323         for (uint8_t i = 0; i < n_tasks_tot; ++i) {
324                 const struct task_stats_disp *disp = &task_stats_disp[i];
325
326                 if (state->toggle == 0) {
327                         display_core_task_stats_per_sec(disp, state, i);
328                 } else {
329                         display_core_task_stats_tot(disp, state, i);
330                 }
331         }
332 }
333
334 static int display_tasks_get_height(void)
335 {
336         return stats_get_n_tasks_tot();
337 }
338
339 static struct display_screen display_screen_tasks = {
340         .draw_frame = display_tasks_draw_frame,
341         .draw_stats = display_tasks_draw_stats,
342         .get_height = display_tasks_get_height,
343         .title = "tasks",
344 };
345
346 struct display_screen *display_tasks(void)
347 {
348         return &display_screen_tasks;
349 }