Imported Upstream version 16.07-rc1
[deb_dpdk.git] / app / proc_info / main.c
1 /*
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdint.h>
37 #include <errno.h>
38 #include <stdarg.h>
39 #include <inttypes.h>
40 #include <sys/queue.h>
41 #include <stdlib.h>
42 #include <getopt.h>
43
44 #include <rte_eal.h>
45 #include <rte_common.h>
46 #include <rte_debug.h>
47 #include <rte_ethdev.h>
48 #include <rte_malloc.h>
49 #include <rte_memory.h>
50 #include <rte_memzone.h>
51 #include <rte_launch.h>
52 #include <rte_tailq.h>
53 #include <rte_per_lcore.h>
54 #include <rte_lcore.h>
55 #include <rte_debug.h>
56 #include <rte_log.h>
57 #include <rte_atomic.h>
58 #include <rte_branch_prediction.h>
59 #include <rte_string_fns.h>
60
61 /* Maximum long option length for option parsing. */
62 #define MAX_LONG_OPT_SZ 64
63 #define RTE_LOGTYPE_APP RTE_LOGTYPE_USER1
64
65 /**< mask of enabled ports */
66 static uint32_t enabled_port_mask;
67 /**< Enable stats. */
68 static uint32_t enable_stats;
69 /**< Enable xstats. */
70 static uint32_t enable_xstats;
71 /**< Enable stats reset. */
72 static uint32_t reset_stats;
73 /**< Enable xstats reset. */
74 static uint32_t reset_xstats;
75 /**< Enable memory info. */
76 static uint32_t mem_info;
77
78 /**< display usage */
79 static void
80 proc_info_usage(const char *prgname)
81 {
82         printf("%s [EAL options] -- -p PORTMASK\n"
83                 "  -m to display DPDK memory zones, segments and TAILQ information\n"
84                 "  -p PORTMASK: hexadecimal bitmask of ports to retrieve stats for\n"
85                 "  --stats: to display port statistics, enabled by default\n"
86                 "  --xstats: to display extended port statistics, disabled by "
87                         "default\n"
88                 "  --stats-reset: to reset port statistics\n"
89                 "  --xstats-reset: to reset port extended statistics\n",
90                 prgname);
91 }
92
93 /*
94  * Parse the portmask provided at run time.
95  */
96 static int
97 parse_portmask(const char *portmask)
98 {
99         char *end = NULL;
100         unsigned long pm;
101
102         errno = 0;
103
104         /* parse hexadecimal string */
105         pm = strtoul(portmask, &end, 16);
106         if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0') ||
107                 (errno != 0)) {
108                 printf("%s ERROR parsing the port mask\n", __func__);
109                 return -1;
110         }
111
112         if (pm == 0)
113                 return -1;
114
115         return pm;
116
117 }
118
119 /* Parse the argument given in the command line of the application */
120 static int
121 proc_info_parse_args(int argc, char **argv)
122 {
123         int opt;
124         int option_index;
125         char *prgname = argv[0];
126         static struct option long_option[] = {
127                 {"stats", 0, NULL, 0},
128                 {"stats-reset", 0, NULL, 0},
129                 {"xstats", 0, NULL, 0},
130                 {"xstats-reset", 0, NULL, 0},
131                 {NULL, 0, 0, 0}
132         };
133
134         if (argc == 1)
135                 proc_info_usage(prgname);
136
137         /* Parse command line */
138         while ((opt = getopt_long(argc, argv, "p:m",
139                         long_option, &option_index)) != EOF) {
140                 switch (opt) {
141                 /* portmask */
142                 case 'p':
143                         enabled_port_mask = parse_portmask(optarg);
144                         if (enabled_port_mask == 0) {
145                                 printf("invalid portmask\n");
146                                 proc_info_usage(prgname);
147                                 return -1;
148                         }
149                         break;
150                 case 'm':
151                         mem_info = 1;
152                         break;
153                 case 0:
154                         /* Print stats */
155                         if (!strncmp(long_option[option_index].name, "stats",
156                                         MAX_LONG_OPT_SZ))
157                                 enable_stats = 1;
158                         /* Print xstats */
159                         else if (!strncmp(long_option[option_index].name, "xstats",
160                                         MAX_LONG_OPT_SZ))
161                                 enable_xstats = 1;
162                         /* Reset stats */
163                         if (!strncmp(long_option[option_index].name, "stats-reset",
164                                         MAX_LONG_OPT_SZ))
165                                 reset_stats = 1;
166                         /* Reset xstats */
167                         else if (!strncmp(long_option[option_index].name, "xstats-reset",
168                                         MAX_LONG_OPT_SZ))
169                                 reset_xstats = 1;
170                         break;
171
172                 default:
173                         proc_info_usage(prgname);
174                         return -1;
175                 }
176         }
177         return 0;
178 }
179
180 static void
181 meminfo_display(void)
182 {
183         printf("----------- MEMORY_SEGMENTS -----------\n");
184         rte_dump_physmem_layout(stdout);
185         printf("--------- END_MEMORY_SEGMENTS ---------\n");
186
187         printf("------------ MEMORY_ZONES -------------\n");
188         rte_memzone_dump(stdout);
189         printf("---------- END_MEMORY_ZONES -----------\n");
190
191         printf("------------- TAIL_QUEUES -------------\n");
192         rte_dump_tailq(stdout);
193         printf("---------- END_TAIL_QUEUES ------------\n");
194 }
195
196 static void
197 nic_stats_display(uint8_t port_id)
198 {
199         struct rte_eth_stats stats;
200         uint8_t i;
201
202         static const char *nic_stats_border = "########################";
203
204         rte_eth_stats_get(port_id, &stats);
205         printf("\n  %s NIC statistics for port %-2d %s\n",
206                    nic_stats_border, port_id, nic_stats_border);
207
208         printf("  RX-packets: %-10"PRIu64"  RX-errors:  %-10"PRIu64
209                "  RX-bytes:  %-10"PRIu64"\n", stats.ipackets, stats.ierrors,
210                stats.ibytes);
211         printf("  RX-nombuf:  %-10"PRIu64"\n", stats.rx_nombuf);
212         printf("  TX-packets: %-10"PRIu64"  TX-errors:  %-10"PRIu64
213                "  TX-bytes:  %-10"PRIu64"\n", stats.opackets, stats.oerrors,
214                stats.obytes);
215
216         printf("\n");
217         for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
218                 printf("  Stats reg %2d RX-packets: %-10"PRIu64
219                        "  RX-errors: %-10"PRIu64
220                        "  RX-bytes: %-10"PRIu64"\n",
221                        i, stats.q_ipackets[i], stats.q_errors[i], stats.q_ibytes[i]);
222         }
223
224         printf("\n");
225         for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
226                 printf("  Stats reg %2d TX-packets: %-10"PRIu64
227                        "  TX-bytes: %-10"PRIu64"\n",
228                        i, stats.q_opackets[i], stats.q_obytes[i]);
229         }
230
231         printf("  %s############################%s\n",
232                    nic_stats_border, nic_stats_border);
233 }
234
235 static void
236 nic_stats_clear(uint8_t port_id)
237 {
238         printf("\n Clearing NIC stats for port %d\n", port_id);
239         rte_eth_stats_reset(port_id);
240         printf("\n  NIC statistics for port %d cleared\n", port_id);
241 }
242
243 static void
244 nic_xstats_display(uint8_t port_id)
245 {
246         struct rte_eth_xstat_name *xstats_names;
247         struct rte_eth_xstat *xstats;
248         int len, ret, i;
249         static const char *nic_stats_border = "########################";
250
251         len = rte_eth_xstats_get_names(port_id, NULL, 0);
252         if (len < 0) {
253                 printf("Cannot get xstats count\n");
254                 return;
255         }
256         xstats = malloc(sizeof(xstats[0]) * len);
257         if (xstats == NULL) {
258                 printf("Cannot allocate memory for xstats\n");
259                 return;
260         }
261
262         xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * len);
263         if (xstats_names == NULL) {
264                 printf("Cannot allocate memory for xstat names\n");
265                 free(xstats);
266                 return;
267         }
268         if (len != rte_eth_xstats_get_names(
269                         port_id, xstats_names, len)) {
270                 printf("Cannot get xstat names\n");
271                 return;
272         }
273
274         printf("###### NIC extended statistics for port %-2d #########\n",
275                            port_id);
276         printf("%s############################\n",
277                            nic_stats_border);
278         ret = rte_eth_xstats_get(port_id, xstats, len);
279         if (ret < 0 || ret > len) {
280                 printf("Cannot get xstats\n");
281                 free(xstats);
282                 return;
283         }
284
285         for (i = 0; i < len; i++)
286                 printf("%s: %"PRIu64"\n",
287                         xstats_names[i].name,
288                         xstats[i].value);
289
290         printf("%s############################\n",
291                            nic_stats_border);
292         free(xstats);
293         free(xstats_names);
294 }
295
296 static void
297 nic_xstats_clear(uint8_t port_id)
298 {
299         printf("\n Clearing NIC xstats for port %d\n", port_id);
300         rte_eth_xstats_reset(port_id);
301         printf("\n  NIC extended statistics for port %d cleared\n", port_id);
302 }
303
304 int
305 main(int argc, char **argv)
306 {
307         int ret;
308         int i;
309         char c_flag[] = "-c1";
310         char n_flag[] = "-n4";
311         char mp_flag[] = "--proc-type=secondary";
312         char *argp[argc + 3];
313         uint8_t nb_ports;
314
315         argp[0] = argv[0];
316         argp[1] = c_flag;
317         argp[2] = n_flag;
318         argp[3] = mp_flag;
319
320         for (i = 1; i < argc; i++)
321                 argp[i + 3] = argv[i];
322
323         argc += 3;
324
325         ret = rte_eal_init(argc, argp);
326         if (ret < 0)
327                 rte_panic("Cannot init EAL\n");
328
329         argc -= ret;
330         argv += (ret - 3);
331
332         /* parse app arguments */
333         ret = proc_info_parse_args(argc, argv);
334         if (ret < 0)
335                 rte_exit(EXIT_FAILURE, "Invalid argument\n");
336
337         if (mem_info) {
338                 meminfo_display();
339                 return 0;
340         }
341
342         nb_ports = rte_eth_dev_count();
343         if (nb_ports == 0)
344                 rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
345
346         /* If no port mask was specified*/
347         if (enabled_port_mask == 0)
348                 enabled_port_mask = 0xffff;
349
350         for (i = 0; i < nb_ports; i++) {
351                 if (enabled_port_mask & (1 << i)) {
352                         if (enable_stats)
353                                 nic_stats_display(i);
354                         else if (enable_xstats)
355                                 nic_xstats_display(i);
356                         else if (reset_stats)
357                                 nic_stats_clear(i);
358                         else if (reset_xstats)
359                                 nic_xstats_clear(i);
360                 }
361         }
362
363         return 0;
364 }