Support packets in flight
[samplevnf.git] / VNFs / DPPD-PROX / stats_parser.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 <string.h>
18 #include <stddef.h>
19
20 #include "stats_parser.h"
21 #include "log.h"
22 #include "stats.h"
23 #include "parse_utils.h"
24 #include "handle_lat.h"
25 #include "prox_port_cfg.h"
26 #include "stats_port.h"
27 #include "stats_mempool.h"
28 #include "stats_ring.h"
29 #include "stats_l4gen.h"
30 #include "stats_latency.h"
31 #include "stats_global.h"
32 #include "stats_prio_task.h"
33 #include "stats_irq.h"
34 #include "prox_compat.h"
35
36 struct stats_path_str {
37         const char *str;
38         uint64_t (*func)(int argc, const char *argv[]);
39 };
40
41 static int args_to_core_task(const char *core_str, const char *task_str, uint32_t *lcore_id, uint32_t *task_id)
42 {
43         if (parse_list_set(lcore_id, core_str, 1) != 1)
44                 return -1;
45         *task_id = atoi(task_str);
46
47         return 0;
48 }
49
50 static uint64_t sp_task_idle_cycles(int argc, const char *argv[])
51 {
52         struct task_stats_sample *last;
53         uint32_t c, t;
54
55         if (args_to_core_task(argv[0], argv[1], &c, &t))
56                 return -1;
57         return stats_get_task_stats_sample(c, t, 1)->tsc;
58 }
59
60 static uint64_t sp_task_rx_packets(int argc, const char *argv[])
61 {
62         struct task_stats_sample *last;
63         uint32_t c, t;
64
65         if (args_to_core_task(argv[0], argv[1], &c, &t))
66                 return -1;
67         return stats_get_task_stats_sample(c, t, 1)->rx_pkt_count;
68 }
69
70 static uint64_t sp_task_tx_packets(int argc, const char *argv[])
71 {
72         struct task_stats_sample *last;
73         uint32_t c, t;
74
75         if (args_to_core_task(argv[0], argv[1], &c, &t))
76                 return -1;
77         return stats_get_task_stats_sample(c, t, 1)->tx_pkt_count;
78 }
79
80 static uint64_t sp_task_drop_tx_fail(int argc, const char *argv[])
81 {
82         struct task_stats_sample *last;
83         uint32_t c, t;
84
85         if (args_to_core_task(argv[0], argv[1], &c, &t))
86                 return -1;
87         return stats_get_task_stats_sample(c, t, 1)->drop_tx_fail;
88 }
89
90 static uint64_t sp_task_drop_tx_fail_prio(int argc, const char *argv[])
91 {
92         struct task_stats_sample *last;
93         uint32_t c, t;
94
95         if (args_to_core_task(argv[0], argv[1], &c, &t))
96                 return -1;
97         if (stats_get_prio_task_stats_sample_by_core_task(c, t, 1))
98                 return stats_get_prio_task_stats_sample_by_core_task(c, t, 1)->drop_tx_fail_prio[atoi(argv[2])];
99         else
100                 return -1;
101 }
102
103 static uint64_t sp_task_rx_prio(int argc, const char *argv[])
104 {
105         struct task_stats_sample *last;
106         uint32_t c, t;
107
108         if (args_to_core_task(argv[0], argv[1], &c, &t))
109                 return -1;
110         return stats_get_prio_task_stats_sample_by_core_task(c, t, 1)->rx_prio[atoi(argv[2])];
111 }
112
113 static uint64_t sp_task_max_irq(int argc, const char *argv[])
114 {
115         struct task_stats_sample *last;
116         uint32_t c, t;
117
118         if (args_to_core_task(argv[0], argv[1], &c, &t))
119                 return -1;
120         return get_max_irq_stats_by_core_task(c, t);
121 }
122
123 static uint64_t sp_task_irq(int argc, const char *argv[])
124 {
125         struct task_stats_sample *last;
126         uint32_t c, t;
127
128         if (args_to_core_task(argv[0], argv[1], &c, &t))
129                 return -1;
130         return get_irq_stats_by_core_task(c, t, atoi(argv[2]));
131 }
132
133 static uint64_t sp_task_drop_discard(int argc, const char *argv[])
134 {
135         struct task_stats_sample *last;
136         uint32_t c, t;
137
138         if (args_to_core_task(argv[0], argv[1], &c, &t))
139                 return -1;
140         return stats_get_task_stats_sample(c, t, 1)->drop_discard;
141 }
142
143 static uint64_t sp_task_drop_handled(int argc, const char *argv[])
144 {
145         struct task_stats_sample *last;
146         uint32_t c, t;
147
148         if (args_to_core_task(argv[0], argv[1], &c, &t))
149                 return -1;
150         return stats_get_task_stats_sample(c, t, 1)->drop_handled;
151 }
152
153 static uint64_t sp_task_rx_non_dp(int argc, const char *argv[])
154 {
155         struct task_stats_sample *last;
156         uint32_t c, t;
157         if (args_to_core_task(argv[0], argv[1], &c, &t))
158                 return -1;
159         return stats_get_task_stats_sample(c, t, 1)->rx_non_dp;
160 }
161
162 static uint64_t sp_task_tx_non_dp(int argc, const char *argv[])
163 {
164         struct task_stats_sample *last;
165         uint32_t c, t;
166         if (args_to_core_task(argv[0], argv[1], &c, &t))
167                 return -1;
168         return stats_get_task_stats_sample(c, t, 1)->tx_non_dp;
169 }
170 static uint64_t sp_task_rx_bytes(int argc, const char *argv[])
171 {
172         return -1;
173 }
174
175 static uint64_t sp_task_tx_bytes(int argc, const char *argv[])
176 {
177         return -1;
178 }
179
180 static uint64_t sp_task_tsc(int argc, const char *argv[])
181 {
182         struct task_stats_sample *last;
183         uint32_t c, t;
184
185         if (args_to_core_task(argv[0], argv[1], &c, &t))
186                 return -1;
187         return stats_get_task_stats_sample(c, t, 1)->tsc;
188 }
189
190 static uint64_t sp_l4gen_created(int argc, const char *argv[])
191 {
192         struct l4_stats_sample *clast = NULL;
193
194         if (atoi(argv[0]) >= stats_get_n_l4gen())
195                 return -1;
196         clast = stats_get_l4_stats_sample(atoi(argv[0]), 1);
197         return clast->stats.tcp_created + clast->stats.udp_created;
198 }
199
200 static uint64_t sp_l4gen_finished(int argc, const char *argv[])
201 {
202         struct l4_stats_sample *clast = NULL;
203
204         if (atoi(argv[0]) >= stats_get_n_l4gen())
205                 return -1;
206         clast = stats_get_l4_stats_sample(atoi(argv[0]), 1);
207         return clast->stats.tcp_finished_retransmit + clast->stats.tcp_finished_no_retransmit +
208                 clast->stats.udp_finished + clast->stats.udp_expired + clast->stats.tcp_expired;
209 }
210
211 static uint64_t sp_l4gen_expire_tcp(int argc, const char *argv[])
212 {
213         struct l4_stats_sample *clast = NULL;
214
215         if (atoi(argv[0]) >= stats_get_n_l4gen())
216                 return -1;
217         clast = stats_get_l4_stats_sample(atoi(argv[0]), 1);
218         return  clast->stats.tcp_expired;
219 }
220
221 static uint64_t sp_l4gen_expire_udp(int argc, const char *argv[])
222 {
223         struct l4_stats_sample *clast = NULL;
224
225         if (atoi(argv[0]) >= stats_get_n_l4gen())
226                 return -1;
227         clast = stats_get_l4_stats_sample(atoi(argv[0]), 1);
228         return clast->stats.udp_expired;
229 }
230
231 static uint64_t sp_l4gen_retx(int argc, const char *argv[])
232 {
233         struct l4_stats_sample *clast = NULL;
234
235         if (atoi(argv[0]) >= stats_get_n_l4gen())
236                 return -1;
237         clast = stats_get_l4_stats_sample(atoi(argv[0]), 1);
238         return clast->stats.tcp_retransmits;
239 }
240
241 static uint64_t sp_l4gen_tsc(int argc, const char *argv[])
242 {
243         struct l4_stats_sample *clast = NULL;
244
245         if (atoi(argv[0]) >= stats_get_n_l4gen())
246                 return -1;
247         clast = stats_get_l4_stats_sample(atoi(argv[0]), 1);
248         return clast->tsc;
249 }
250
251 static uint64_t sp_l4gen_torndown_no_retx(int argc, const char *argv[])
252 {
253         struct l4_stats_sample *clast = NULL;
254
255         if (atoi(argv[0]) >= stats_get_n_l4gen())
256                 return -1;
257         clast = stats_get_l4_stats_sample(atoi(argv[0]), 1);
258         return clast->stats.tcp_finished_no_retransmit;
259 }
260
261 static uint64_t sp_l4gen_torndown_retx(int argc, const char *argv[])
262 {
263         struct l4_stats_sample *clast = NULL;
264
265         if (atoi(argv[0]) >= stats_get_n_l4gen())
266                 return -1;
267         clast = stats_get_l4_stats_sample(atoi(argv[0]), 1);
268         return clast->stats.tcp_finished_retransmit;
269 }
270
271 static uint64_t sp_l4gen_torndown_udp(int argc, const char *argv[])
272 {
273         struct l4_stats_sample *clast = NULL;
274
275         if (atoi(argv[0]) >= stats_get_n_l4gen())
276                 return -1;
277         clast = stats_get_l4_stats_sample(atoi(argv[0]), 1);
278         return clast->stats.udp_finished;
279 }
280
281 static uint64_t sp_l4gen_created_tcp(int argc, const char *argv[])
282 {
283         struct l4_stats_sample *clast = NULL;
284
285         if (atoi(argv[0]) >= stats_get_n_l4gen())
286                 return -1;
287         clast = stats_get_l4_stats_sample(atoi(argv[0]), 1);
288         return clast->stats.tcp_created;
289
290 }
291
292 static uint64_t sp_l4gen_created_udp(int argc, const char *argv[])
293 {
294         struct l4_stats_sample *clast = NULL;
295
296         if (atoi(argv[0]) >= stats_get_n_l4gen())
297                 return -1;
298         clast = stats_get_l4_stats_sample(atoi(argv[0]), 1);
299         return clast->stats.udp_created;
300 }
301
302 static uint64_t sp_l4gen_created_all(int argc, const char *argv[])
303 {
304         struct l4_stats_sample *clast = NULL;
305
306         if (atoi(argv[0]) >= stats_get_n_l4gen())
307                 return -1;
308         clast = stats_get_l4_stats_sample(atoi(argv[0]), 1);
309         return clast->stats.tcp_created + clast->stats.udp_created;
310 }
311
312 static uint64_t sp_l4gen_created_bundles(int argc, const char *argv[])
313 {
314         struct l4_stats_sample *clast = NULL;
315
316         if (atoi(argv[0]) >= stats_get_n_l4gen())
317                 return -1;
318         clast = stats_get_l4_stats_sample(atoi(argv[0]), 1);
319         return clast->stats.bundles_created;
320 }
321
322 static uint64_t sp_latency_min(int argc, const char *argv[])
323 {
324         struct stats_latency *lat_test = NULL;
325
326         if (atoi(argv[0]) >= stats_get_n_latency())
327                 return -1;
328         lat_test = stats_latency_get(atoi(argv[0]));
329
330         if (!lat_test->tot_packets)
331                 return -1;
332
333         struct time_unit tu = lat_test->min.time;
334         return time_unit_to_usec(&tu);
335 }
336
337 static uint64_t sp_mem_used(int argc, const char *argv[])
338 {
339         struct mempool_stats *ms;
340
341         if (atoi(argv[0]) > stats_get_n_mempools())
342                 return -1;
343         ms = stats_get_mempool_stats(atoi(argv[0]));
344         return ms->size - ms->free;
345 }
346
347 static uint64_t sp_mem_free(int argc, const char *argv[])
348 {
349         struct mempool_stats *ms;
350
351         if (atoi(argv[0]) > stats_get_n_mempools())
352                 return -1;
353         ms = stats_get_mempool_stats(atoi(argv[0]));
354         return ms->free;
355 }
356
357 static uint64_t sp_mem_size(int argc, const char *argv[])
358 {
359         struct mempool_stats *ms;
360
361         if (atoi(argv[0]) > stats_get_n_mempools())
362                 return -1;
363         ms = stats_get_mempool_stats(atoi(argv[0]));
364         return ms->size;
365 }
366
367 static uint64_t sp_port_no_mbufs(int argc, const char *argv[])
368 {
369         uint32_t port_id = atoi(argv[0]);
370         struct port_stats_sample *ps;
371
372         if (port_id > PROX_MAX_PORTS || !prox_port_cfg[port_id].active)
373                 return -1;
374         ps = stats_get_port_stats_sample(port_id, 1);
375         return ps->no_mbufs;
376 }
377
378 static uint64_t sp_port_ierrors(int argc, const char *argv[])
379 {
380         uint32_t port_id = atoi(argv[0]);
381         struct port_stats_sample *ps;
382
383         if (port_id > PROX_MAX_PORTS || !prox_port_cfg[port_id].active)
384                 return -1;
385         ps = stats_get_port_stats_sample(port_id, 1);
386         return ps->ierrors;
387 }
388
389 static uint64_t sp_port_imissed(int argc, const char *argv[])
390 {
391         uint32_t port_id = atoi(argv[0]);
392         struct port_stats_sample *ps;
393
394         if (port_id > PROX_MAX_PORTS || !prox_port_cfg[port_id].active)
395                 return -1;
396         ps = stats_get_port_stats_sample(port_id, 1);
397         return ps->imissed;
398 }
399
400 static uint64_t sp_port_oerrors(int argc, const char *argv[])
401 {
402         uint32_t port_id = atoi(argv[0]);
403         struct port_stats_sample *ps;
404
405         if (port_id > PROX_MAX_PORTS || !prox_port_cfg[port_id].active)
406                 return -1;
407         ps = stats_get_port_stats_sample(port_id, 1);
408         return ps->oerrors;
409 }
410
411 static uint64_t sp_port_rx_packets(int argc, const char *argv[])
412 {
413         uint32_t port_id = atoi(argv[0]);
414         struct port_stats_sample *ps;
415
416         if (port_id > PROX_MAX_PORTS || !prox_port_cfg[port_id].active)
417                 return -1;
418         ps = stats_get_port_stats_sample(port_id, 1);
419         return ps->rx_tot;
420 }
421
422 static uint64_t sp_port_tx_packets(int argc, const char *argv[])
423 {
424         uint32_t port_id = atoi(argv[0]);
425         struct port_stats_sample *ps;
426
427         if (port_id > PROX_MAX_PORTS || !prox_port_cfg[port_id].active)
428                 return -1;
429         ps = stats_get_port_stats_sample(port_id, 1);
430         return ps->tx_tot;
431 }
432
433 static uint64_t sp_port_rx_bytes(int argc, const char *argv[])
434 {
435         uint32_t port_id = atoi(argv[0]);
436         struct port_stats_sample *ps;
437
438         if (port_id > PROX_MAX_PORTS || !prox_port_cfg[port_id].active)
439                 return -1;
440         ps = stats_get_port_stats_sample(port_id, 1);
441         return ps->rx_bytes;
442 }
443
444 static uint64_t sp_port_tx_bytes(int argc, const char *argv[])
445 {
446         uint32_t port_id = atoi(argv[0]);
447         struct port_stats_sample *ps;
448
449         if (port_id > PROX_MAX_PORTS || !prox_port_cfg[port_id].active)
450                 return -1;
451         ps = stats_get_port_stats_sample(port_id, 1);
452         return ps->tx_bytes;
453 }
454
455 static uint64_t sp_port_tx_packets_64(int argc, const char *argv[])
456 {
457         uint32_t port_id = atoi(argv[0]);
458         struct port_stats_sample *ps;
459
460         if (port_id > PROX_MAX_PORTS || !prox_port_cfg[port_id].active)
461                 return -1;
462         ps = stats_get_port_stats_sample(port_id, 1);
463         return ps->tx_pkt_size[PKT_SIZE_64];
464 }
465
466 static uint64_t sp_port_tx_packets_65_127(int argc, const char *argv[])
467 {
468         uint32_t port_id = atoi(argv[0]);
469         struct port_stats_sample *ps;
470
471         if (port_id > PROX_MAX_PORTS || !prox_port_cfg[port_id].active)
472                 return -1;
473         ps = stats_get_port_stats_sample(port_id, 1);
474         return ps->tx_pkt_size[PKT_SIZE_65];
475 }
476
477 static uint64_t sp_port_tx_packets_128_255(int argc, const char *argv[])
478 {
479         uint32_t port_id = atoi(argv[0]);
480         struct port_stats_sample *ps;
481
482         if (port_id > PROX_MAX_PORTS || !prox_port_cfg[port_id].active)
483                 return -1;
484         ps = stats_get_port_stats_sample(port_id, 1);
485         return ps->tx_pkt_size[PKT_SIZE_128];
486 }
487
488 static uint64_t sp_port_tx_packets_256_511(int argc, const char *argv[])
489 {
490         uint32_t port_id = atoi(argv[0]);
491         struct port_stats_sample *ps;
492
493         if (port_id > PROX_MAX_PORTS || !prox_port_cfg[port_id].active)
494                 return -1;
495         ps = stats_get_port_stats_sample(port_id, 1);
496         return ps->tx_pkt_size[PKT_SIZE_256];
497 }
498
499 static uint64_t sp_port_tx_packets_512_1023(int argc, const char *argv[])
500 {
501         uint32_t port_id = atoi(argv[0]);
502         struct port_stats_sample *ps;
503
504         if (port_id > PROX_MAX_PORTS || !prox_port_cfg[port_id].active)
505                 return -1;
506         ps = stats_get_port_stats_sample(port_id, 1);
507         return ps->tx_pkt_size[PKT_SIZE_512];
508 }
509
510 static uint64_t sp_port_tx_packets_1024_1522(int argc, const char *argv[])
511 {
512         uint32_t port_id = atoi(argv[0]);
513         struct port_stats_sample *ps;
514
515         if (port_id > PROX_MAX_PORTS || !prox_port_cfg[port_id].active)
516                 return -1;
517         ps = stats_get_port_stats_sample(port_id, 1);
518         return ps->tx_pkt_size[PKT_SIZE_1024];
519 }
520
521 static uint64_t sp_port_tx_packets_1523_max(int argc, const char *argv[])
522 {
523         uint32_t port_id = atoi(argv[0]);
524         struct port_stats_sample *ps;
525
526         if (port_id > PROX_MAX_PORTS || !prox_port_cfg[port_id].active)
527                 return -1;
528         ps = stats_get_port_stats_sample(port_id, 1);
529         return ps->tx_pkt_size[PKT_SIZE_1522];
530 }
531
532 static uint64_t sp_port_tsc(int argc, const char *argv[])
533 {
534         uint32_t port_id = atoi(argv[0]);
535         struct port_stats_sample *ps;
536
537         if (port_id > PROX_MAX_PORTS || !prox_port_cfg[port_id].active)
538                 return -1;
539         ps = stats_get_port_stats_sample(port_id, 1);
540         return ps->tsc;
541 }
542
543 static uint64_t sp_latency_max(int argc, const char *argv[])
544 {
545         struct stats_latency *lat_test = NULL;
546
547         if (atoi(argv[0]) >= stats_get_n_latency())
548                 return -1;
549         lat_test = stats_latency_get(atoi(argv[0]));
550
551         if (!lat_test->tot_packets)
552                 return -1;
553
554         struct time_unit tu = lat_test->max.time;
555         return time_unit_to_usec(&tu);
556 }
557
558 static uint64_t sp_latency_avg(int argc, const char *argv[])
559 {
560         struct stats_latency *lat_test = NULL;
561
562         if (atoi(argv[0]) >= stats_get_n_latency())
563                 return -1;
564         lat_test = stats_latency_get(atoi(argv[0]));
565
566         if (!lat_test->tot_packets)
567                 return -1;
568
569         struct time_unit tu = lat_test->avg.time;
570         return time_unit_to_usec(&tu);
571 }
572
573 static uint64_t sp_latency_lost(int argc, const char *argv[])
574 {
575         struct stats_latency *lat_test = NULL;
576
577         if (atoi(argv[0]) >= stats_get_n_latency())
578                 return -1;
579         lat_test = stats_latency_get(atoi(argv[0]));
580
581         if (!lat_test->tot_packets)
582                 return -1;
583
584         return lat_test->lost_packets;
585 }
586
587 static uint64_t sp_latency_tot_lost(int argc, const char *argv[])
588 {
589         struct stats_latency *lat_test = NULL;
590
591         if (atoi(argv[0]) >= stats_get_n_latency())
592                 return -1;
593         lat_test = stats_latency_tot_get(atoi(argv[0]));
594
595         if (!lat_test->tot_packets)
596                 return -1;
597
598         return lat_test->lost_packets;
599 }
600
601 static uint64_t sp_latency_total(int argc, const char *argv[])
602 {
603         struct stats_latency *lat_test = NULL;
604
605         if (atoi(argv[0]) >= stats_get_n_latency())
606                 return -1;
607         lat_test = stats_latency_get(atoi(argv[0]));
608
609         if (!lat_test->tot_all_packets)
610                 return -1;
611
612         return lat_test->tot_all_packets;
613 }
614
615 static uint64_t sp_latency_used(int argc, const char *argv[])
616 {
617         struct stats_latency *lat_test = NULL;
618
619         if (atoi(argv[0]) >= stats_get_n_latency())
620                 return -1;
621         lat_test = stats_latency_get(atoi(argv[0]));
622
623         if (!lat_test->tot_all_packets)
624                 return -1;
625
626         return lat_test->tot_packets;
627 }
628
629 static uint64_t sp_latency_tot_total(int argc, const char *argv[])
630 {
631         struct stats_latency *lat_test = NULL;
632
633         if (atoi(argv[0]) >= stats_get_n_latency())
634                 return -1;
635         lat_test = stats_latency_tot_get(atoi(argv[0]));
636
637         if (!lat_test->tot_all_packets)
638                 return -1;
639
640         return lat_test->tot_all_packets;
641 }
642
643 static uint64_t sp_latency_tot_used(int argc, const char *argv[])
644 {
645         struct stats_latency *lat_test = NULL;
646
647         if (atoi(argv[0]) >= stats_get_n_latency())
648                 return -1;
649         lat_test = stats_latency_tot_get(atoi(argv[0]));
650
651         if (!lat_test->tot_all_packets)
652                 return -1;
653
654         return lat_test->tot_packets;
655 }
656
657 static uint64_t sp_latency_tot_min(int argc, const char *argv[])
658 {
659         struct stats_latency *lat_test = NULL;
660
661         if (atoi(argv[0]) >= stats_get_n_latency())
662                 return -1;
663         lat_test = stats_latency_tot_get(atoi(argv[0]));
664
665         if (!lat_test->tot_packets)
666                 return -1;
667
668         struct time_unit tu = lat_test->min.time;
669         return time_unit_to_usec(&tu);
670 }
671
672 static uint64_t sp_latency_tot_max(int argc, const char *argv[])
673 {
674         struct stats_latency *lat_test = NULL;
675
676         if (atoi(argv[0]) >= stats_get_n_latency())
677                 return -1;
678         lat_test = stats_latency_tot_get(atoi(argv[0]));
679
680         if (!lat_test->tot_packets)
681                 return -1;
682
683         struct time_unit tu = lat_test->max.time;
684         return time_unit_to_usec(&tu);
685 }
686
687 static uint64_t sp_latency_tot_avg(int argc, const char *argv[])
688 {
689         struct stats_latency *lat_test = NULL;
690
691         if (atoi(argv[0]) >= stats_get_n_latency())
692                 return -1;
693         lat_test = stats_latency_tot_get(atoi(argv[0]));
694
695         if (!lat_test->tot_packets)
696                 return -1;
697
698         struct time_unit tu = lat_test->avg.time;
699         return time_unit_to_usec(&tu);
700 }
701
702 static uint64_t sp_latency_stddev(int argc, const char *argv[])
703 {
704         struct stats_latency *lat_test = NULL;
705
706         if (atoi(argv[0]) >= stats_get_n_latency())
707                 return -1;
708         lat_test = stats_latency_get(atoi(argv[0]));
709
710         if (!lat_test->tot_packets)
711                 return -1;
712
713         struct time_unit tu = lat_test->stddev.time;
714         return time_unit_to_usec(&tu);
715 }
716
717 static uint64_t sp_ring_used(int argc, const char *argv[])
718 {
719         struct ring_stats *rs = NULL;
720
721         if (atoi(argv[0]) >= stats_get_n_rings())
722                 return -1;
723         rs = stats_get_ring_stats(atoi(argv[0]));
724         return rs->size - rs->free;
725 }
726
727 static uint64_t sp_ring_free(int argc, const char *argv[])
728 {
729         struct ring_stats *rs = NULL;
730
731         if (atoi(argv[0]) >= stats_get_n_rings())
732                 return -1;
733         rs = stats_get_ring_stats(atoi(argv[0]));
734         return rs->free;
735 }
736
737 static uint64_t sp_ring_size(int argc, const char *argv[])
738 {
739         struct ring_stats *rs = NULL;
740
741         if (atoi(argv[0]) >= stats_get_n_rings())
742                 return -1;
743         rs = stats_get_ring_stats(atoi(argv[0]));
744         return rs->size;
745 }
746
747 static uint64_t sp_global_host_rx_packets(int argc, const char *argv[])
748 {
749         return stats_get_global_stats(1)->host_rx_packets;
750 }
751
752 static uint64_t sp_global_host_tx_packets(int argc, const char *argv[])
753 {
754         return stats_get_global_stats(1)->host_tx_packets;
755 }
756
757 static uint64_t sp_global_nics_rx_packets(int argc, const char *argv[])
758 {
759         return stats_get_global_stats(1)->nics_rx_packets;
760 }
761
762 static uint64_t sp_global_nics_tx_packets(int argc, const char *argv[])
763 {
764         return stats_get_global_stats(1)->nics_tx_packets;
765 }
766
767 static uint64_t sp_global_nics_ierrors(int argc, const char *argv[])
768 {
769         return stats_get_global_stats(1)->nics_ierrors;
770 }
771
772 static uint64_t sp_global_nics_imissed(int argc, const char *argv[])
773 {
774         return stats_get_global_stats(1)->nics_imissed;
775 }
776
777 static uint64_t sp_global_tsc(int argc, const char *argv[])
778 {
779         return stats_get_global_stats(1)->tsc;
780 }
781
782 static uint64_t sp_hz(int argc, const char *argv[])
783 {
784         return rte_get_tsc_hz();
785 }
786
787 struct stats_path_str stats_paths[] = {
788         {"hz", sp_hz},
789
790         {"global.host.rx.packets", sp_global_host_rx_packets},
791         {"global.host.tx.packets", sp_global_host_tx_packets},
792         {"global.nics.rx.packets", sp_global_nics_rx_packets},
793         {"global.nics.tx.packets", sp_global_nics_tx_packets},
794         {"global.nics.ierrrors", sp_global_nics_ierrors},
795         {"global.nics.imissed", sp_global_nics_imissed},
796         {"global.tsc", sp_global_tsc},
797
798         {"task.core(#).task(#).idle_cycles", sp_task_idle_cycles},
799         {"task.core(#).task(#).rx.packets", sp_task_rx_packets},
800         {"task.core(#).task(#).tx.packets", sp_task_tx_packets},
801         {"task.core(#).task(#).drop.tx_fail", sp_task_drop_tx_fail},
802         {"task.core(#).task(#).drop.discard", sp_task_drop_discard},
803         {"task.core(#).task(#).drop.handled", sp_task_drop_handled},
804         {"task.core(#).task(#).rx.bytes", sp_task_rx_bytes},
805         {"task.core(#).task(#).tx.bytes", sp_task_tx_bytes},
806         {"task.core(#).task(#).tsc", sp_task_tsc},
807         {"task.core(#).task(#).drop.tx_fail_prio(#)", sp_task_drop_tx_fail_prio},
808         {"task.core(#).task(#).rx_prio(#)", sp_task_rx_prio},
809         {"task.core(#).task(#).max_irq", sp_task_max_irq},
810         {"task.core(#).task(#).irq(#)", sp_task_irq},
811         {"task.core(#).task(#).rx_non_dp", sp_task_rx_non_dp},
812         {"task.core(#).task(#).tx_non_dp", sp_task_tx_non_dp},
813
814         {"port(#).no_mbufs", sp_port_no_mbufs},
815         {"port(#).ierrors", sp_port_ierrors},
816         {"port(#).imissed", sp_port_imissed},
817         {"port(#).oerrors", sp_port_oerrors},
818         {"port(#).rx.packets", sp_port_rx_packets},
819         {"port(#).tx.packets", sp_port_tx_packets},
820         {"port(#).rx.bytes", sp_port_rx_bytes},
821         {"port(#).tx.bytes", sp_port_tx_bytes},
822         {"port(#).tx.packets_64", sp_port_tx_packets_64},
823         {"port(#).tx.packets_65_127", sp_port_tx_packets_65_127},
824         {"port(#).tx.packets_128_255", sp_port_tx_packets_128_255},
825         {"port(#).tx.packets_256_511", sp_port_tx_packets_256_511},
826         {"port(#).tx.packets_512_1023", sp_port_tx_packets_512_1023},
827         {"port(#).tx.packets_1024_1522", sp_port_tx_packets_1024_1522},
828         {"port(#).tx.packets_1523_max", sp_port_tx_packets_1523_max},
829         {"port(#).tsc", sp_port_tsc},
830
831         {"mem(#).used", sp_mem_used},
832         {"mem(#).free", sp_mem_free},
833         {"mem(#).size", sp_mem_size},
834
835         {"latency(#).min", sp_latency_min},
836         {"latency(#).max", sp_latency_max},
837         {"latency(#).avg", sp_latency_avg},
838         {"latency(#).lost", sp_latency_lost},
839         {"latency(#).used", sp_latency_used},
840         {"latency(#).total", sp_latency_total},
841         {"latency(#).tot.min", sp_latency_tot_min},
842         {"latency(#).tot.max", sp_latency_tot_max},
843         {"latency(#).tot.avg", sp_latency_tot_avg},
844         {"latency(#).tot.lost", sp_latency_tot_lost},
845         {"latency(#).tot.used", sp_latency_tot_used},
846         {"latency(#).tot.total", sp_latency_tot_total},
847         {"latency(#).stddev", sp_latency_stddev},
848
849         {"ring(#).used", sp_ring_used},
850         {"ring(#).free", sp_ring_free},
851         {"ring(#).size", sp_ring_size},
852
853         {"l4gen(#).created.tcp", sp_l4gen_created_tcp},
854         {"l4gen(#).created.udp", sp_l4gen_created_udp},
855         {"l4gen(#).created.all", sp_l4gen_created_all},
856         {"l4gen(#).created.bundles", sp_l4gen_created_bundles},
857         {"l4gen(#).torndown.no_retx", sp_l4gen_torndown_no_retx},
858         {"l4gen(#).torndown.retx", sp_l4gen_torndown_retx},
859         {"l4gen(#).torndown.udp", sp_l4gen_torndown_udp},
860         {"l4gen(#).expired.tcp", sp_l4gen_expire_tcp},
861         {"l4gen(#).expired.udp", sp_l4gen_expire_udp},
862         {"l4gen(#).created", sp_l4gen_created},
863         {"l4gen(#).finished", sp_l4gen_finished},
864         {"l4gen(#).retx", sp_l4gen_retx},
865         {"l4gen(#).tsc", sp_l4gen_tsc},
866 };
867
868 static int stats_parser_extract_args(char *stats_path, size_t *argc, char **argv)
869 {
870         size_t len = strlen(stats_path);
871         size_t j = 0;
872         size_t k = 0;
873         int state = 0;
874
875         for (size_t i = 0; i < len; ++i) {
876                 switch (state) {
877                 case 0:
878                         if (stats_path[i] == '(') {
879                                 state = 1;
880                                 k = 0;
881                         }
882                         else if (stats_path[i] == ')')
883                                 return -1;
884                         stats_path[j] = stats_path[i];
885                         j++;
886                         break;
887                 case 1:
888                         if (stats_path[i] == ')') {
889                                 state = 0;
890                                 stats_path[j] = '#';
891                                 j++;
892                                 stats_path[j] = ')';
893                                 j++;
894                                 (*argc)++;
895                         }
896                         else {
897                                 argv[*argc][k++] = stats_path[i];
898                         }
899                         break;
900                 }
901         }
902         if (state == 1)
903                 return -1;
904         stats_path[j] = 0;
905         return 0;
906 }
907
908 uint64_t stats_parser_get(const char *stats_path)
909 {
910         size_t stats_path_len;
911
912         char stats_path_cpy[128];
913
914         prox_strncpy(stats_path_cpy, stats_path, sizeof(stats_path_cpy));
915         stats_path_len = strlen(stats_path);
916
917         size_t max_argc = 16;
918         size_t argc = 0;
919         char argv_data[16][16] = {{0}};
920         char *argv[16];
921         const char *argv_c[16];
922
923         for (size_t i = 0; i < 16; ++i) {
924                 argv[i] = argv_data[i];
925                 argv_c[i] = argv_data[i];
926         }
927
928         if (stats_parser_extract_args(stats_path_cpy, &argc, argv))
929                 return -1;
930
931         for (size_t i = 0; i < sizeof(stats_paths)/sizeof(stats_paths[0]); ++i) {
932                 if (strcmp(stats_paths[i].str, stats_path_cpy) == 0) {
933                         if (stats_paths[i].func == NULL)
934                                 return -1;
935                         return stats_paths[i].func(argc, argv_c);
936                 }
937         }
938
939         return -1;
940 }