doc: update bbdev guide
[dpdk.git] / app / test-pmd / config.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2016 Intel Corporation.
3  * Copyright 2013-2014 6WIND S.A.
4  */
5
6 #include <stdarg.h>
7 #include <errno.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdint.h>
11 #include <inttypes.h>
12
13 #include <sys/queue.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <fcntl.h>
17 #include <unistd.h>
18
19 #include <rte_common.h>
20 #include <rte_byteorder.h>
21 #include <rte_debug.h>
22 #include <rte_log.h>
23 #include <rte_memory.h>
24 #include <rte_memcpy.h>
25 #include <rte_memzone.h>
26 #include <rte_launch.h>
27 #include <rte_eal.h>
28 #include <rte_per_lcore.h>
29 #include <rte_lcore.h>
30 #include <rte_atomic.h>
31 #include <rte_branch_prediction.h>
32 #include <rte_mempool.h>
33 #include <rte_mbuf.h>
34 #include <rte_interrupts.h>
35 #include <rte_pci.h>
36 #include <rte_ether.h>
37 #include <rte_ethdev.h>
38 #include <rte_string_fns.h>
39 #include <rte_cycles.h>
40 #include <rte_flow.h>
41 #include <rte_errno.h>
42 #ifdef RTE_LIBRTE_IXGBE_PMD
43 #include <rte_pmd_ixgbe.h>
44 #endif
45 #ifdef RTE_LIBRTE_I40E_PMD
46 #include <rte_pmd_i40e.h>
47 #endif
48 #ifdef RTE_LIBRTE_BNXT_PMD
49 #include <rte_pmd_bnxt.h>
50 #endif
51 #include <rte_gro.h>
52 #include <rte_hexdump.h>
53
54 #include "testpmd.h"
55
56 #define ETHDEV_FWVERS_LEN 32
57
58 #ifdef CLOCK_MONOTONIC_RAW /* Defined in glibc bits/time.h */
59 #define CLOCK_TYPE_ID CLOCK_MONOTONIC_RAW
60 #else
61 #define CLOCK_TYPE_ID CLOCK_MONOTONIC
62 #endif
63
64 #define NS_PER_SEC 1E9
65
66 static char *flowtype_to_str(uint16_t flow_type);
67
68 static const struct {
69         enum tx_pkt_split split;
70         const char *name;
71 } tx_split_name[] = {
72         {
73                 .split = TX_PKT_SPLIT_OFF,
74                 .name = "off",
75         },
76         {
77                 .split = TX_PKT_SPLIT_ON,
78                 .name = "on",
79         },
80         {
81                 .split = TX_PKT_SPLIT_RND,
82                 .name = "rand",
83         },
84 };
85
86 const struct rss_type_info rss_type_table[] = {
87         { "all", ETH_RSS_ETH | ETH_RSS_VLAN | ETH_RSS_IP | ETH_RSS_TCP |
88                 ETH_RSS_UDP | ETH_RSS_SCTP | ETH_RSS_L2_PAYLOAD |
89                 ETH_RSS_L2TPV3 | ETH_RSS_ESP | ETH_RSS_AH | ETH_RSS_PFCP |
90                 ETH_RSS_GTPU},
91         { "none", 0 },
92         { "eth", ETH_RSS_ETH },
93         { "l2-src-only", ETH_RSS_L2_SRC_ONLY },
94         { "l2-dst-only", ETH_RSS_L2_DST_ONLY },
95         { "vlan", ETH_RSS_VLAN },
96         { "s-vlan", ETH_RSS_S_VLAN },
97         { "c-vlan", ETH_RSS_C_VLAN },
98         { "ipv4", ETH_RSS_IPV4 },
99         { "ipv4-frag", ETH_RSS_FRAG_IPV4 },
100         { "ipv4-tcp", ETH_RSS_NONFRAG_IPV4_TCP },
101         { "ipv4-udp", ETH_RSS_NONFRAG_IPV4_UDP },
102         { "ipv4-sctp", ETH_RSS_NONFRAG_IPV4_SCTP },
103         { "ipv4-other", ETH_RSS_NONFRAG_IPV4_OTHER },
104         { "ipv6", ETH_RSS_IPV6 },
105         { "ipv6-frag", ETH_RSS_FRAG_IPV6 },
106         { "ipv6-tcp", ETH_RSS_NONFRAG_IPV6_TCP },
107         { "ipv6-udp", ETH_RSS_NONFRAG_IPV6_UDP },
108         { "ipv6-sctp", ETH_RSS_NONFRAG_IPV6_SCTP },
109         { "ipv6-other", ETH_RSS_NONFRAG_IPV6_OTHER },
110         { "l2-payload", ETH_RSS_L2_PAYLOAD },
111         { "ipv6-ex", ETH_RSS_IPV6_EX },
112         { "ipv6-tcp-ex", ETH_RSS_IPV6_TCP_EX },
113         { "ipv6-udp-ex", ETH_RSS_IPV6_UDP_EX },
114         { "port", ETH_RSS_PORT },
115         { "vxlan", ETH_RSS_VXLAN },
116         { "geneve", ETH_RSS_GENEVE },
117         { "nvgre", ETH_RSS_NVGRE },
118         { "ip", ETH_RSS_IP },
119         { "udp", ETH_RSS_UDP },
120         { "tcp", ETH_RSS_TCP },
121         { "sctp", ETH_RSS_SCTP },
122         { "tunnel", ETH_RSS_TUNNEL },
123         { "l3-pre32", RTE_ETH_RSS_L3_PRE32 },
124         { "l3-pre40", RTE_ETH_RSS_L3_PRE40 },
125         { "l3-pre48", RTE_ETH_RSS_L3_PRE48 },
126         { "l3-pre56", RTE_ETH_RSS_L3_PRE56 },
127         { "l3-pre64", RTE_ETH_RSS_L3_PRE64 },
128         { "l3-pre96", RTE_ETH_RSS_L3_PRE96 },
129         { "l3-src-only", ETH_RSS_L3_SRC_ONLY },
130         { "l3-dst-only", ETH_RSS_L3_DST_ONLY },
131         { "l4-src-only", ETH_RSS_L4_SRC_ONLY },
132         { "l4-dst-only", ETH_RSS_L4_DST_ONLY },
133         { "esp", ETH_RSS_ESP },
134         { "ah", ETH_RSS_AH },
135         { "l2tpv3", ETH_RSS_L2TPV3 },
136         { "pfcp", ETH_RSS_PFCP },
137         { "pppoe", ETH_RSS_PPPOE },
138         { "gtpu", ETH_RSS_GTPU },
139         { NULL, 0 },
140 };
141
142 static const struct {
143         enum rte_eth_fec_mode mode;
144         const char *name;
145 } fec_mode_name[] = {
146         {
147                 .mode = RTE_ETH_FEC_NOFEC,
148                 .name = "off",
149         },
150         {
151                 .mode = RTE_ETH_FEC_AUTO,
152                 .name = "auto",
153         },
154         {
155                 .mode = RTE_ETH_FEC_BASER,
156                 .name = "baser",
157         },
158         {
159                 .mode = RTE_ETH_FEC_RS,
160                 .name = "rs",
161         },
162 };
163
164 static void
165 print_ethaddr(const char *name, struct rte_ether_addr *eth_addr)
166 {
167         char buf[RTE_ETHER_ADDR_FMT_SIZE];
168         rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, eth_addr);
169         printf("%s%s", name, buf);
170 }
171
172 void
173 nic_stats_display(portid_t port_id)
174 {
175         static uint64_t prev_pkts_rx[RTE_MAX_ETHPORTS];
176         static uint64_t prev_pkts_tx[RTE_MAX_ETHPORTS];
177         static uint64_t prev_bytes_rx[RTE_MAX_ETHPORTS];
178         static uint64_t prev_bytes_tx[RTE_MAX_ETHPORTS];
179         static uint64_t prev_ns[RTE_MAX_ETHPORTS];
180         struct timespec cur_time;
181         uint64_t diff_pkts_rx, diff_pkts_tx, diff_bytes_rx, diff_bytes_tx,
182                                                                 diff_ns;
183         uint64_t mpps_rx, mpps_tx, mbps_rx, mbps_tx;
184         struct rte_eth_stats stats;
185         struct rte_port *port = &ports[port_id];
186         uint8_t i;
187
188         static const char *nic_stats_border = "########################";
189
190         if (port_id_is_invalid(port_id, ENABLED_WARN)) {
191                 print_valid_ports();
192                 return;
193         }
194         rte_eth_stats_get(port_id, &stats);
195         printf("\n  %s NIC statistics for port %-2d %s\n",
196                nic_stats_border, port_id, nic_stats_border);
197
198         if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) {
199                 printf("  RX-packets: %-10"PRIu64" RX-missed: %-10"PRIu64" RX-bytes:  "
200                        "%-"PRIu64"\n",
201                        stats.ipackets, stats.imissed, stats.ibytes);
202                 printf("  RX-errors: %-"PRIu64"\n", stats.ierrors);
203                 printf("  RX-nombuf:  %-10"PRIu64"\n",
204                        stats.rx_nombuf);
205                 printf("  TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64" TX-bytes:  "
206                        "%-"PRIu64"\n",
207                        stats.opackets, stats.oerrors, stats.obytes);
208         }
209         else {
210                 printf("  RX-packets:              %10"PRIu64"    RX-errors: %10"PRIu64
211                        "    RX-bytes: %10"PRIu64"\n",
212                        stats.ipackets, stats.ierrors, stats.ibytes);
213                 printf("  RX-errors:  %10"PRIu64"\n", stats.ierrors);
214                 printf("  RX-nombuf:               %10"PRIu64"\n",
215                        stats.rx_nombuf);
216                 printf("  TX-packets:              %10"PRIu64"    TX-errors: %10"PRIu64
217                        "    TX-bytes: %10"PRIu64"\n",
218                        stats.opackets, stats.oerrors, stats.obytes);
219         }
220
221         if (port->rx_queue_stats_mapping_enabled) {
222                 printf("\n");
223                 for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
224                         printf("  Stats reg %2d RX-packets: %10"PRIu64
225                                "    RX-errors: %10"PRIu64
226                                "    RX-bytes: %10"PRIu64"\n",
227                                i, stats.q_ipackets[i], stats.q_errors[i], stats.q_ibytes[i]);
228                 }
229         }
230         if (port->tx_queue_stats_mapping_enabled) {
231                 printf("\n");
232                 for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
233                         printf("  Stats reg %2d TX-packets: %10"PRIu64
234                                "                             TX-bytes: %10"PRIu64"\n",
235                                i, stats.q_opackets[i], stats.q_obytes[i]);
236                 }
237         }
238
239         diff_ns = 0;
240         if (clock_gettime(CLOCK_TYPE_ID, &cur_time) == 0) {
241                 uint64_t ns;
242
243                 ns = cur_time.tv_sec * NS_PER_SEC;
244                 ns += cur_time.tv_nsec;
245
246                 if (prev_ns[port_id] != 0)
247                         diff_ns = ns - prev_ns[port_id];
248                 prev_ns[port_id] = ns;
249         }
250
251         diff_pkts_rx = (stats.ipackets > prev_pkts_rx[port_id]) ?
252                 (stats.ipackets - prev_pkts_rx[port_id]) : 0;
253         diff_pkts_tx = (stats.opackets > prev_pkts_tx[port_id]) ?
254                 (stats.opackets - prev_pkts_tx[port_id]) : 0;
255         prev_pkts_rx[port_id] = stats.ipackets;
256         prev_pkts_tx[port_id] = stats.opackets;
257         mpps_rx = diff_ns > 0 ?
258                 (double)diff_pkts_rx / diff_ns * NS_PER_SEC : 0;
259         mpps_tx = diff_ns > 0 ?
260                 (double)diff_pkts_tx / diff_ns * NS_PER_SEC : 0;
261
262         diff_bytes_rx = (stats.ibytes > prev_bytes_rx[port_id]) ?
263                 (stats.ibytes - prev_bytes_rx[port_id]) : 0;
264         diff_bytes_tx = (stats.obytes > prev_bytes_tx[port_id]) ?
265                 (stats.obytes - prev_bytes_tx[port_id]) : 0;
266         prev_bytes_rx[port_id] = stats.ibytes;
267         prev_bytes_tx[port_id] = stats.obytes;
268         mbps_rx = diff_ns > 0 ?
269                 (double)diff_bytes_rx / diff_ns * NS_PER_SEC : 0;
270         mbps_tx = diff_ns > 0 ?
271                 (double)diff_bytes_tx / diff_ns * NS_PER_SEC : 0;
272
273         printf("\n  Throughput (since last show)\n");
274         printf("  Rx-pps: %12"PRIu64"          Rx-bps: %12"PRIu64"\n  Tx-pps: %12"
275                PRIu64"          Tx-bps: %12"PRIu64"\n", mpps_rx, mbps_rx * 8,
276                mpps_tx, mbps_tx * 8);
277
278         printf("  %s############################%s\n",
279                nic_stats_border, nic_stats_border);
280 }
281
282 void
283 nic_stats_clear(portid_t port_id)
284 {
285         int ret;
286
287         if (port_id_is_invalid(port_id, ENABLED_WARN)) {
288                 print_valid_ports();
289                 return;
290         }
291
292         ret = rte_eth_stats_reset(port_id);
293         if (ret != 0) {
294                 printf("%s: Error: failed to reset stats (port %u): %s",
295                        __func__, port_id, strerror(-ret));
296                 return;
297         }
298
299         ret = rte_eth_stats_get(port_id, &ports[port_id].stats);
300         if (ret != 0) {
301                 if (ret < 0)
302                         ret = -ret;
303                 printf("%s: Error: failed to get stats (port %u): %s",
304                        __func__, port_id, strerror(ret));
305                 return;
306         }
307         printf("\n  NIC statistics for port %d cleared\n", port_id);
308 }
309
310 void
311 nic_xstats_display(portid_t port_id)
312 {
313         struct rte_eth_xstat *xstats;
314         int cnt_xstats, idx_xstat;
315         struct rte_eth_xstat_name *xstats_names;
316
317         if (port_id_is_invalid(port_id, ENABLED_WARN)) {
318                 print_valid_ports();
319                 return;
320         }
321         printf("###### NIC extended statistics for port %-2d\n", port_id);
322         if (!rte_eth_dev_is_valid_port(port_id)) {
323                 printf("Error: Invalid port number %i\n", port_id);
324                 return;
325         }
326
327         /* Get count */
328         cnt_xstats = rte_eth_xstats_get_names(port_id, NULL, 0);
329         if (cnt_xstats  < 0) {
330                 printf("Error: Cannot get count of xstats\n");
331                 return;
332         }
333
334         /* Get id-name lookup table */
335         xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * cnt_xstats);
336         if (xstats_names == NULL) {
337                 printf("Cannot allocate memory for xstats lookup\n");
338                 return;
339         }
340         if (cnt_xstats != rte_eth_xstats_get_names(
341                         port_id, xstats_names, cnt_xstats)) {
342                 printf("Error: Cannot get xstats lookup\n");
343                 free(xstats_names);
344                 return;
345         }
346
347         /* Get stats themselves */
348         xstats = malloc(sizeof(struct rte_eth_xstat) * cnt_xstats);
349         if (xstats == NULL) {
350                 printf("Cannot allocate memory for xstats\n");
351                 free(xstats_names);
352                 return;
353         }
354         if (cnt_xstats != rte_eth_xstats_get(port_id, xstats, cnt_xstats)) {
355                 printf("Error: Unable to get xstats\n");
356                 free(xstats_names);
357                 free(xstats);
358                 return;
359         }
360
361         /* Display xstats */
362         for (idx_xstat = 0; idx_xstat < cnt_xstats; idx_xstat++) {
363                 if (xstats_hide_zero && !xstats[idx_xstat].value)
364                         continue;
365                 printf("%s: %"PRIu64"\n",
366                         xstats_names[idx_xstat].name,
367                         xstats[idx_xstat].value);
368         }
369         free(xstats_names);
370         free(xstats);
371 }
372
373 void
374 nic_xstats_clear(portid_t port_id)
375 {
376         int ret;
377
378         if (port_id_is_invalid(port_id, ENABLED_WARN)) {
379                 print_valid_ports();
380                 return;
381         }
382
383         ret = rte_eth_xstats_reset(port_id);
384         if (ret != 0) {
385                 printf("%s: Error: failed to reset xstats (port %u): %s",
386                        __func__, port_id, strerror(-ret));
387                 return;
388         }
389
390         ret = rte_eth_stats_get(port_id, &ports[port_id].stats);
391         if (ret != 0) {
392                 if (ret < 0)
393                         ret = -ret;
394                 printf("%s: Error: failed to get stats (port %u): %s",
395                        __func__, port_id, strerror(ret));
396                 return;
397         }
398 }
399
400 void
401 nic_stats_mapping_display(portid_t port_id)
402 {
403         struct rte_port *port = &ports[port_id];
404         uint16_t i;
405
406         static const char *nic_stats_mapping_border = "########################";
407
408         if (port_id_is_invalid(port_id, ENABLED_WARN)) {
409                 print_valid_ports();
410                 return;
411         }
412
413         if ((!port->rx_queue_stats_mapping_enabled) && (!port->tx_queue_stats_mapping_enabled)) {
414                 printf("Port id %d - either does not support queue statistic mapping or"
415                        " no queue statistic mapping set\n", port_id);
416                 return;
417         }
418
419         printf("\n  %s NIC statistics mapping for port %-2d %s\n",
420                nic_stats_mapping_border, port_id, nic_stats_mapping_border);
421
422         if (port->rx_queue_stats_mapping_enabled) {
423                 for (i = 0; i < nb_rx_queue_stats_mappings; i++) {
424                         if (rx_queue_stats_mappings[i].port_id == port_id) {
425                                 printf("  RX-queue %2d mapped to Stats Reg %2d\n",
426                                        rx_queue_stats_mappings[i].queue_id,
427                                        rx_queue_stats_mappings[i].stats_counter_id);
428                         }
429                 }
430                 printf("\n");
431         }
432
433
434         if (port->tx_queue_stats_mapping_enabled) {
435                 for (i = 0; i < nb_tx_queue_stats_mappings; i++) {
436                         if (tx_queue_stats_mappings[i].port_id == port_id) {
437                                 printf("  TX-queue %2d mapped to Stats Reg %2d\n",
438                                        tx_queue_stats_mappings[i].queue_id,
439                                        tx_queue_stats_mappings[i].stats_counter_id);
440                         }
441                 }
442         }
443
444         printf("  %s####################################%s\n",
445                nic_stats_mapping_border, nic_stats_mapping_border);
446 }
447
448 void
449 rx_queue_infos_display(portid_t port_id, uint16_t queue_id)
450 {
451         struct rte_eth_burst_mode mode;
452         struct rte_eth_rxq_info qinfo;
453         int32_t rc;
454         static const char *info_border = "*********************";
455
456         rc = rte_eth_rx_queue_info_get(port_id, queue_id, &qinfo);
457         if (rc != 0) {
458                 printf("Failed to retrieve information for port: %u, "
459                         "RX queue: %hu\nerror desc: %s(%d)\n",
460                         port_id, queue_id, strerror(-rc), rc);
461                 return;
462         }
463
464         printf("\n%s Infos for port %-2u, RX queue %-2u %s",
465                info_border, port_id, queue_id, info_border);
466
467         printf("\nMempool: %s", (qinfo.mp == NULL) ? "NULL" : qinfo.mp->name);
468         printf("\nRX prefetch threshold: %hhu", qinfo.conf.rx_thresh.pthresh);
469         printf("\nRX host threshold: %hhu", qinfo.conf.rx_thresh.hthresh);
470         printf("\nRX writeback threshold: %hhu", qinfo.conf.rx_thresh.wthresh);
471         printf("\nRX free threshold: %hu", qinfo.conf.rx_free_thresh);
472         printf("\nRX drop packets: %s",
473                 (qinfo.conf.rx_drop_en != 0) ? "on" : "off");
474         printf("\nRX deferred start: %s",
475                 (qinfo.conf.rx_deferred_start != 0) ? "on" : "off");
476         printf("\nRX scattered packets: %s",
477                 (qinfo.scattered_rx != 0) ? "on" : "off");
478         if (qinfo.rx_buf_size != 0)
479                 printf("\nRX buffer size: %hu", qinfo.rx_buf_size);
480         printf("\nNumber of RXDs: %hu", qinfo.nb_desc);
481
482         if (rte_eth_rx_burst_mode_get(port_id, queue_id, &mode) == 0)
483                 printf("\nBurst mode: %s%s",
484                        mode.info,
485                        mode.flags & RTE_ETH_BURST_FLAG_PER_QUEUE ?
486                                 " (per queue)" : "");
487
488         printf("\n");
489 }
490
491 void
492 tx_queue_infos_display(portid_t port_id, uint16_t queue_id)
493 {
494         struct rte_eth_burst_mode mode;
495         struct rte_eth_txq_info qinfo;
496         int32_t rc;
497         static const char *info_border = "*********************";
498
499         rc = rte_eth_tx_queue_info_get(port_id, queue_id, &qinfo);
500         if (rc != 0) {
501                 printf("Failed to retrieve information for port: %u, "
502                         "TX queue: %hu\nerror desc: %s(%d)\n",
503                         port_id, queue_id, strerror(-rc), rc);
504                 return;
505         }
506
507         printf("\n%s Infos for port %-2u, TX queue %-2u %s",
508                info_border, port_id, queue_id, info_border);
509
510         printf("\nTX prefetch threshold: %hhu", qinfo.conf.tx_thresh.pthresh);
511         printf("\nTX host threshold: %hhu", qinfo.conf.tx_thresh.hthresh);
512         printf("\nTX writeback threshold: %hhu", qinfo.conf.tx_thresh.wthresh);
513         printf("\nTX RS threshold: %hu", qinfo.conf.tx_rs_thresh);
514         printf("\nTX free threshold: %hu", qinfo.conf.tx_free_thresh);
515         printf("\nTX deferred start: %s",
516                 (qinfo.conf.tx_deferred_start != 0) ? "on" : "off");
517         printf("\nNumber of TXDs: %hu", qinfo.nb_desc);
518
519         if (rte_eth_tx_burst_mode_get(port_id, queue_id, &mode) == 0)
520                 printf("\nBurst mode: %s%s",
521                        mode.info,
522                        mode.flags & RTE_ETH_BURST_FLAG_PER_QUEUE ?
523                                 " (per queue)" : "");
524
525         printf("\n");
526 }
527
528 static int bus_match_all(const struct rte_bus *bus, const void *data)
529 {
530         RTE_SET_USED(bus);
531         RTE_SET_USED(data);
532         return 0;
533 }
534
535 void
536 device_infos_display(const char *identifier)
537 {
538         static const char *info_border = "*********************";
539         struct rte_bus *start = NULL, *next;
540         struct rte_dev_iterator dev_iter;
541         char name[RTE_ETH_NAME_MAX_LEN];
542         struct rte_ether_addr mac_addr;
543         struct rte_device *dev;
544         struct rte_devargs da;
545         portid_t port_id;
546         char devstr[128];
547
548         memset(&da, 0, sizeof(da));
549         if (!identifier)
550                 goto skip_parse;
551
552         if (rte_devargs_parsef(&da, "%s", identifier)) {
553                 printf("cannot parse identifier\n");
554                 if (da.args)
555                         free(da.args);
556                 return;
557         }
558
559 skip_parse:
560         while ((next = rte_bus_find(start, bus_match_all, NULL)) != NULL) {
561
562                 start = next;
563                 if (identifier && da.bus != next)
564                         continue;
565
566                 /* Skip buses that don't have iterate method */
567                 if (!next->dev_iterate)
568                         continue;
569
570                 snprintf(devstr, sizeof(devstr), "bus=%s", next->name);
571                 RTE_DEV_FOREACH(dev, devstr, &dev_iter) {
572
573                         if (!dev->driver)
574                                 continue;
575                         /* Check for matching device if identifier is present */
576                         if (identifier &&
577                             strncmp(da.name, dev->name, strlen(dev->name)))
578                                 continue;
579                         printf("\n%s Infos for device %s %s\n",
580                                info_border, dev->name, info_border);
581                         printf("Bus name: %s", dev->bus->name);
582                         printf("\nDriver name: %s", dev->driver->name);
583                         printf("\nDevargs: %s",
584                                dev->devargs ? dev->devargs->args : "");
585                         printf("\nConnect to socket: %d", dev->numa_node);
586                         printf("\n");
587
588                         /* List ports with matching device name */
589                         RTE_ETH_FOREACH_DEV_OF(port_id, dev) {
590                                 printf("\n\tPort id: %-2d", port_id);
591                                 if (eth_macaddr_get_print_err(port_id,
592                                                               &mac_addr) == 0)
593                                         print_ethaddr("\n\tMAC address: ",
594                                                       &mac_addr);
595                                 rte_eth_dev_get_name_by_port(port_id, name);
596                                 printf("\n\tDevice name: %s", name);
597                                 printf("\n");
598                         }
599                 }
600         };
601 }
602
603 void
604 port_infos_display(portid_t port_id)
605 {
606         struct rte_port *port;
607         struct rte_ether_addr mac_addr;
608         struct rte_eth_link link;
609         struct rte_eth_dev_info dev_info;
610         int vlan_offload;
611         struct rte_mempool * mp;
612         static const char *info_border = "*********************";
613         uint16_t mtu;
614         char name[RTE_ETH_NAME_MAX_LEN];
615         int ret;
616         char fw_version[ETHDEV_FWVERS_LEN];
617
618         if (port_id_is_invalid(port_id, ENABLED_WARN)) {
619                 print_valid_ports();
620                 return;
621         }
622         port = &ports[port_id];
623         ret = eth_link_get_nowait_print_err(port_id, &link);
624         if (ret < 0)
625                 return;
626
627         ret = eth_dev_info_get_print_err(port_id, &dev_info);
628         if (ret != 0)
629                 return;
630
631         printf("\n%s Infos for port %-2d %s\n",
632                info_border, port_id, info_border);
633         if (eth_macaddr_get_print_err(port_id, &mac_addr) == 0)
634                 print_ethaddr("MAC address: ", &mac_addr);
635         rte_eth_dev_get_name_by_port(port_id, name);
636         printf("\nDevice name: %s", name);
637         printf("\nDriver name: %s", dev_info.driver_name);
638
639         if (rte_eth_dev_fw_version_get(port_id, fw_version,
640                                                 ETHDEV_FWVERS_LEN) == 0)
641                 printf("\nFirmware-version: %s", fw_version);
642         else
643                 printf("\nFirmware-version: %s", "not available");
644
645         if (dev_info.device->devargs && dev_info.device->devargs->args)
646                 printf("\nDevargs: %s", dev_info.device->devargs->args);
647         printf("\nConnect to socket: %u", port->socket_id);
648
649         if (port_numa[port_id] != NUMA_NO_CONFIG) {
650                 mp = mbuf_pool_find(port_numa[port_id]);
651                 if (mp)
652                         printf("\nmemory allocation on the socket: %d",
653                                                         port_numa[port_id]);
654         } else
655                 printf("\nmemory allocation on the socket: %u",port->socket_id);
656
657         printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down"));
658         printf("Link speed: %s\n", rte_eth_link_speed_to_str(link.link_speed));
659         printf("Link duplex: %s\n", (link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
660                ("full-duplex") : ("half-duplex"));
661
662         if (!rte_eth_dev_get_mtu(port_id, &mtu))
663                 printf("MTU: %u\n", mtu);
664
665         printf("Promiscuous mode: %s\n",
666                rte_eth_promiscuous_get(port_id) ? "enabled" : "disabled");
667         printf("Allmulticast mode: %s\n",
668                rte_eth_allmulticast_get(port_id) ? "enabled" : "disabled");
669         printf("Maximum number of MAC addresses: %u\n",
670                (unsigned int)(port->dev_info.max_mac_addrs));
671         printf("Maximum number of MAC addresses of hash filtering: %u\n",
672                (unsigned int)(port->dev_info.max_hash_mac_addrs));
673
674         vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
675         if (vlan_offload >= 0){
676                 printf("VLAN offload: \n");
677                 if (vlan_offload & ETH_VLAN_STRIP_OFFLOAD)
678                         printf("  strip on, ");
679                 else
680                         printf("  strip off, ");
681
682                 if (vlan_offload & ETH_VLAN_FILTER_OFFLOAD)
683                         printf("filter on, ");
684                 else
685                         printf("filter off, ");
686
687                 if (vlan_offload & ETH_VLAN_EXTEND_OFFLOAD)
688                         printf("extend on, ");
689                 else
690                         printf("extend off, ");
691
692                 if (vlan_offload & ETH_QINQ_STRIP_OFFLOAD)
693                         printf("qinq strip on\n");
694                 else
695                         printf("qinq strip off\n");
696         }
697
698         if (dev_info.hash_key_size > 0)
699                 printf("Hash key size in bytes: %u\n", dev_info.hash_key_size);
700         if (dev_info.reta_size > 0)
701                 printf("Redirection table size: %u\n", dev_info.reta_size);
702         if (!dev_info.flow_type_rss_offloads)
703                 printf("No RSS offload flow type is supported.\n");
704         else {
705                 uint16_t i;
706                 char *p;
707
708                 printf("Supported RSS offload flow types:\n");
709                 for (i = RTE_ETH_FLOW_UNKNOWN + 1;
710                      i < sizeof(dev_info.flow_type_rss_offloads) * CHAR_BIT; i++) {
711                         if (!(dev_info.flow_type_rss_offloads & (1ULL << i)))
712                                 continue;
713                         p = flowtype_to_str(i);
714                         if (p)
715                                 printf("  %s\n", p);
716                         else
717                                 printf("  user defined %d\n", i);
718                 }
719         }
720
721         printf("Minimum size of RX buffer: %u\n", dev_info.min_rx_bufsize);
722         printf("Maximum configurable length of RX packet: %u\n",
723                 dev_info.max_rx_pktlen);
724         printf("Maximum configurable size of LRO aggregated packet: %u\n",
725                 dev_info.max_lro_pkt_size);
726         if (dev_info.max_vfs)
727                 printf("Maximum number of VFs: %u\n", dev_info.max_vfs);
728         if (dev_info.max_vmdq_pools)
729                 printf("Maximum number of VMDq pools: %u\n",
730                         dev_info.max_vmdq_pools);
731
732         printf("Current number of RX queues: %u\n", dev_info.nb_rx_queues);
733         printf("Max possible RX queues: %u\n", dev_info.max_rx_queues);
734         printf("Max possible number of RXDs per queue: %hu\n",
735                 dev_info.rx_desc_lim.nb_max);
736         printf("Min possible number of RXDs per queue: %hu\n",
737                 dev_info.rx_desc_lim.nb_min);
738         printf("RXDs number alignment: %hu\n", dev_info.rx_desc_lim.nb_align);
739
740         printf("Current number of TX queues: %u\n", dev_info.nb_tx_queues);
741         printf("Max possible TX queues: %u\n", dev_info.max_tx_queues);
742         printf("Max possible number of TXDs per queue: %hu\n",
743                 dev_info.tx_desc_lim.nb_max);
744         printf("Min possible number of TXDs per queue: %hu\n",
745                 dev_info.tx_desc_lim.nb_min);
746         printf("TXDs number alignment: %hu\n", dev_info.tx_desc_lim.nb_align);
747         printf("Max segment number per packet: %hu\n",
748                 dev_info.tx_desc_lim.nb_seg_max);
749         printf("Max segment number per MTU/TSO: %hu\n",
750                 dev_info.tx_desc_lim.nb_mtu_seg_max);
751
752         /* Show switch info only if valid switch domain and port id is set */
753         if (dev_info.switch_info.domain_id !=
754                 RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) {
755                 if (dev_info.switch_info.name)
756                         printf("Switch name: %s\n", dev_info.switch_info.name);
757
758                 printf("Switch domain Id: %u\n",
759                         dev_info.switch_info.domain_id);
760                 printf("Switch Port Id: %u\n",
761                         dev_info.switch_info.port_id);
762         }
763 }
764
765 void
766 port_summary_header_display(void)
767 {
768         uint16_t port_number;
769
770         port_number = rte_eth_dev_count_avail();
771         printf("Number of available ports: %i\n", port_number);
772         printf("%-4s %-17s %-12s %-14s %-8s %s\n", "Port", "MAC Address", "Name",
773                         "Driver", "Status", "Link");
774 }
775
776 void
777 port_summary_display(portid_t port_id)
778 {
779         struct rte_ether_addr mac_addr;
780         struct rte_eth_link link;
781         struct rte_eth_dev_info dev_info;
782         char name[RTE_ETH_NAME_MAX_LEN];
783         int ret;
784
785         if (port_id_is_invalid(port_id, ENABLED_WARN)) {
786                 print_valid_ports();
787                 return;
788         }
789
790         ret = eth_link_get_nowait_print_err(port_id, &link);
791         if (ret < 0)
792                 return;
793
794         ret = eth_dev_info_get_print_err(port_id, &dev_info);
795         if (ret != 0)
796                 return;
797
798         rte_eth_dev_get_name_by_port(port_id, name);
799         ret = eth_macaddr_get_print_err(port_id, &mac_addr);
800         if (ret != 0)
801                 return;
802
803         printf("%-4d %02X:%02X:%02X:%02X:%02X:%02X %-12s %-14s %-8s %s\n",
804                 port_id, mac_addr.addr_bytes[0], mac_addr.addr_bytes[1],
805                 mac_addr.addr_bytes[2], mac_addr.addr_bytes[3],
806                 mac_addr.addr_bytes[4], mac_addr.addr_bytes[5], name,
807                 dev_info.driver_name, (link.link_status) ? ("up") : ("down"),
808                 rte_eth_link_speed_to_str(link.link_speed));
809 }
810
811 void
812 port_eeprom_display(portid_t port_id)
813 {
814         struct rte_dev_eeprom_info einfo;
815         int ret;
816         if (port_id_is_invalid(port_id, ENABLED_WARN)) {
817                 print_valid_ports();
818                 return;
819         }
820
821         int len_eeprom = rte_eth_dev_get_eeprom_length(port_id);
822         if (len_eeprom < 0) {
823                 switch (len_eeprom) {
824                 case -ENODEV:
825                         printf("port index %d invalid\n", port_id);
826                         break;
827                 case -ENOTSUP:
828                         printf("operation not supported by device\n");
829                         break;
830                 case -EIO:
831                         printf("device is removed\n");
832                         break;
833                 default:
834                         printf("Unable to get EEPROM: %d\n", len_eeprom);
835                         break;
836                 }
837                 return;
838         }
839
840         char buf[len_eeprom];
841         einfo.offset = 0;
842         einfo.length = len_eeprom;
843         einfo.data = buf;
844
845         ret = rte_eth_dev_get_eeprom(port_id, &einfo);
846         if (ret != 0) {
847                 switch (ret) {
848                 case -ENODEV:
849                         printf("port index %d invalid\n", port_id);
850                         break;
851                 case -ENOTSUP:
852                         printf("operation not supported by device\n");
853                         break;
854                 case -EIO:
855                         printf("device is removed\n");
856                         break;
857                 default:
858                         printf("Unable to get EEPROM: %d\n", ret);
859                         break;
860                 }
861                 return;
862         }
863         rte_hexdump(stdout, "hexdump", einfo.data, einfo.length);
864         printf("Finish -- Port: %d EEPROM length: %d bytes\n", port_id, len_eeprom);
865 }
866
867 void
868 port_module_eeprom_display(portid_t port_id)
869 {
870         struct rte_eth_dev_module_info minfo;
871         struct rte_dev_eeprom_info einfo;
872         int ret;
873
874         if (port_id_is_invalid(port_id, ENABLED_WARN)) {
875                 print_valid_ports();
876                 return;
877         }
878
879
880         ret = rte_eth_dev_get_module_info(port_id, &minfo);
881         if (ret != 0) {
882                 switch (ret) {
883                 case -ENODEV:
884                         printf("port index %d invalid\n", port_id);
885                         break;
886                 case -ENOTSUP:
887                         printf("operation not supported by device\n");
888                         break;
889                 case -EIO:
890                         printf("device is removed\n");
891                         break;
892                 default:
893                         printf("Unable to get module EEPROM: %d\n", ret);
894                         break;
895                 }
896                 return;
897         }
898
899         char buf[minfo.eeprom_len];
900         einfo.offset = 0;
901         einfo.length = minfo.eeprom_len;
902         einfo.data = buf;
903
904         ret = rte_eth_dev_get_module_eeprom(port_id, &einfo);
905         if (ret != 0) {
906                 switch (ret) {
907                 case -ENODEV:
908                         printf("port index %d invalid\n", port_id);
909                         break;
910                 case -ENOTSUP:
911                         printf("operation not supported by device\n");
912                         break;
913                 case -EIO:
914                         printf("device is removed\n");
915                         break;
916                 default:
917                         printf("Unable to get module EEPROM: %d\n", ret);
918                         break;
919                 }
920                 return;
921         }
922
923         rte_hexdump(stdout, "hexdump", einfo.data, einfo.length);
924         printf("Finish -- Port: %d MODULE EEPROM length: %d bytes\n", port_id, einfo.length);
925 }
926
927 void
928 port_offload_cap_display(portid_t port_id)
929 {
930         struct rte_eth_dev_info dev_info;
931         static const char *info_border = "************";
932         int ret;
933
934         if (port_id_is_invalid(port_id, ENABLED_WARN))
935                 return;
936
937         ret = eth_dev_info_get_print_err(port_id, &dev_info);
938         if (ret != 0)
939                 return;
940
941         printf("\n%s Port %d supported offload features: %s\n",
942                 info_border, port_id, info_border);
943
944         if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_VLAN_STRIP) {
945                 printf("VLAN stripped:                 ");
946                 if (ports[port_id].dev_conf.rxmode.offloads &
947                     DEV_RX_OFFLOAD_VLAN_STRIP)
948                         printf("on\n");
949                 else
950                         printf("off\n");
951         }
952
953         if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_QINQ_STRIP) {
954                 printf("Double VLANs stripped:         ");
955                 if (ports[port_id].dev_conf.rxmode.offloads &
956                     DEV_RX_OFFLOAD_QINQ_STRIP)
957                         printf("on\n");
958                 else
959                         printf("off\n");
960         }
961
962         if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_IPV4_CKSUM) {
963                 printf("RX IPv4 checksum:              ");
964                 if (ports[port_id].dev_conf.rxmode.offloads &
965                     DEV_RX_OFFLOAD_IPV4_CKSUM)
966                         printf("on\n");
967                 else
968                         printf("off\n");
969         }
970
971         if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_UDP_CKSUM) {
972                 printf("RX UDP checksum:               ");
973                 if (ports[port_id].dev_conf.rxmode.offloads &
974                     DEV_RX_OFFLOAD_UDP_CKSUM)
975                         printf("on\n");
976                 else
977                         printf("off\n");
978         }
979
980         if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_CKSUM) {
981                 printf("RX TCP checksum:               ");
982                 if (ports[port_id].dev_conf.rxmode.offloads &
983                     DEV_RX_OFFLOAD_TCP_CKSUM)
984                         printf("on\n");
985                 else
986                         printf("off\n");
987         }
988
989         if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_SCTP_CKSUM) {
990                 printf("RX SCTP checksum:              ");
991                 if (ports[port_id].dev_conf.rxmode.offloads &
992                     DEV_RX_OFFLOAD_SCTP_CKSUM)
993                         printf("on\n");
994                 else
995                         printf("off\n");
996         }
997
998         if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM) {
999                 printf("RX Outer IPv4 checksum:        ");
1000                 if (ports[port_id].dev_conf.rxmode.offloads &
1001                     DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM)
1002                         printf("on\n");
1003                 else
1004                         printf("off\n");
1005         }
1006
1007         if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_OUTER_UDP_CKSUM) {
1008                 printf("RX Outer UDP checksum:         ");
1009                 if (ports[port_id].dev_conf.rxmode.offloads &
1010                     DEV_RX_OFFLOAD_OUTER_UDP_CKSUM)
1011                         printf("on\n");
1012                 else
1013                         printf("off\n");
1014         }
1015
1016         if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TCP_LRO) {
1017                 printf("Large receive offload:         ");
1018                 if (ports[port_id].dev_conf.rxmode.offloads &
1019                     DEV_RX_OFFLOAD_TCP_LRO)
1020                         printf("on\n");
1021                 else
1022                         printf("off\n");
1023         }
1024
1025         if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_TIMESTAMP) {
1026                 printf("HW timestamp:                  ");
1027                 if (ports[port_id].dev_conf.rxmode.offloads &
1028                     DEV_RX_OFFLOAD_TIMESTAMP)
1029                         printf("on\n");
1030                 else
1031                         printf("off\n");
1032         }
1033
1034         if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_KEEP_CRC) {
1035                 printf("Rx Keep CRC:                   ");
1036                 if (ports[port_id].dev_conf.rxmode.offloads &
1037                     DEV_RX_OFFLOAD_KEEP_CRC)
1038                         printf("on\n");
1039                 else
1040                         printf("off\n");
1041         }
1042
1043         if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_SECURITY) {
1044                 printf("RX offload security:           ");
1045                 if (ports[port_id].dev_conf.rxmode.offloads &
1046                     DEV_RX_OFFLOAD_SECURITY)
1047                         printf("on\n");
1048                 else
1049                         printf("off\n");
1050         }
1051
1052         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VLAN_INSERT) {
1053                 printf("VLAN insert:                   ");
1054                 if (ports[port_id].dev_conf.txmode.offloads &
1055                     DEV_TX_OFFLOAD_VLAN_INSERT)
1056                         printf("on\n");
1057                 else
1058                         printf("off\n");
1059         }
1060
1061         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_QINQ_INSERT) {
1062                 printf("Double VLANs insert:           ");
1063                 if (ports[port_id].dev_conf.txmode.offloads &
1064                     DEV_TX_OFFLOAD_QINQ_INSERT)
1065                         printf("on\n");
1066                 else
1067                         printf("off\n");
1068         }
1069
1070         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM) {
1071                 printf("TX IPv4 checksum:              ");
1072                 if (ports[port_id].dev_conf.txmode.offloads &
1073                     DEV_TX_OFFLOAD_IPV4_CKSUM)
1074                         printf("on\n");
1075                 else
1076                         printf("off\n");
1077         }
1078
1079         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) {
1080                 printf("TX UDP checksum:               ");
1081                 if (ports[port_id].dev_conf.txmode.offloads &
1082                     DEV_TX_OFFLOAD_UDP_CKSUM)
1083                         printf("on\n");
1084                 else
1085                         printf("off\n");
1086         }
1087
1088         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) {
1089                 printf("TX TCP checksum:               ");
1090                 if (ports[port_id].dev_conf.txmode.offloads &
1091                     DEV_TX_OFFLOAD_TCP_CKSUM)
1092                         printf("on\n");
1093                 else
1094                         printf("off\n");
1095         }
1096
1097         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SCTP_CKSUM) {
1098                 printf("TX SCTP checksum:              ");
1099                 if (ports[port_id].dev_conf.txmode.offloads &
1100                     DEV_TX_OFFLOAD_SCTP_CKSUM)
1101                         printf("on\n");
1102                 else
1103                         printf("off\n");
1104         }
1105
1106         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM) {
1107                 printf("TX Outer IPv4 checksum:        ");
1108                 if (ports[port_id].dev_conf.txmode.offloads &
1109                     DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM)
1110                         printf("on\n");
1111                 else
1112                         printf("off\n");
1113         }
1114
1115         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) {
1116                 printf("TX TCP segmentation:           ");
1117                 if (ports[port_id].dev_conf.txmode.offloads &
1118                     DEV_TX_OFFLOAD_TCP_TSO)
1119                         printf("on\n");
1120                 else
1121                         printf("off\n");
1122         }
1123
1124         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_TSO) {
1125                 printf("TX UDP segmentation:           ");
1126                 if (ports[port_id].dev_conf.txmode.offloads &
1127                     DEV_TX_OFFLOAD_UDP_TSO)
1128                         printf("on\n");
1129                 else
1130                         printf("off\n");
1131         }
1132
1133         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VXLAN_TNL_TSO) {
1134                 printf("TSO for VXLAN tunnel packet:   ");
1135                 if (ports[port_id].dev_conf.txmode.offloads &
1136                     DEV_TX_OFFLOAD_VXLAN_TNL_TSO)
1137                         printf("on\n");
1138                 else
1139                         printf("off\n");
1140         }
1141
1142         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GRE_TNL_TSO) {
1143                 printf("TSO for GRE tunnel packet:     ");
1144                 if (ports[port_id].dev_conf.txmode.offloads &
1145                     DEV_TX_OFFLOAD_GRE_TNL_TSO)
1146                         printf("on\n");
1147                 else
1148                         printf("off\n");
1149         }
1150
1151         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IPIP_TNL_TSO) {
1152                 printf("TSO for IPIP tunnel packet:    ");
1153                 if (ports[port_id].dev_conf.txmode.offloads &
1154                     DEV_TX_OFFLOAD_IPIP_TNL_TSO)
1155                         printf("on\n");
1156                 else
1157                         printf("off\n");
1158         }
1159
1160         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_GENEVE_TNL_TSO) {
1161                 printf("TSO for GENEVE tunnel packet:  ");
1162                 if (ports[port_id].dev_conf.txmode.offloads &
1163                     DEV_TX_OFFLOAD_GENEVE_TNL_TSO)
1164                         printf("on\n");
1165                 else
1166                         printf("off\n");
1167         }
1168
1169         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_IP_TNL_TSO) {
1170                 printf("IP tunnel TSO:  ");
1171                 if (ports[port_id].dev_conf.txmode.offloads &
1172                     DEV_TX_OFFLOAD_IP_TNL_TSO)
1173                         printf("on\n");
1174                 else
1175                         printf("off\n");
1176         }
1177
1178         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_TNL_TSO) {
1179                 printf("UDP tunnel TSO:  ");
1180                 if (ports[port_id].dev_conf.txmode.offloads &
1181                     DEV_TX_OFFLOAD_UDP_TNL_TSO)
1182                         printf("on\n");
1183                 else
1184                         printf("off\n");
1185         }
1186
1187         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_OUTER_UDP_CKSUM) {
1188                 printf("TX Outer UDP checksum:         ");
1189                 if (ports[port_id].dev_conf.txmode.offloads &
1190                     DEV_TX_OFFLOAD_OUTER_UDP_CKSUM)
1191                         printf("on\n");
1192                 else
1193                         printf("off\n");
1194         }
1195
1196         if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_SEND_ON_TIMESTAMP) {
1197                 printf("Tx scheduling on timestamp:    ");
1198                 if (ports[port_id].dev_conf.txmode.offloads &
1199                     DEV_TX_OFFLOAD_SEND_ON_TIMESTAMP)
1200                         printf("on\n");
1201                 else
1202                         printf("off\n");
1203         }
1204
1205 }
1206
1207 int
1208 port_id_is_invalid(portid_t port_id, enum print_warning warning)
1209 {
1210         uint16_t pid;
1211
1212         if (port_id == (portid_t)RTE_PORT_ALL)
1213                 return 0;
1214
1215         RTE_ETH_FOREACH_DEV(pid)
1216                 if (port_id == pid)
1217                         return 0;
1218
1219         if (warning == ENABLED_WARN)
1220                 printf("Invalid port %d\n", port_id);
1221
1222         return 1;
1223 }
1224
1225 void print_valid_ports(void)
1226 {
1227         portid_t pid;
1228
1229         printf("The valid ports array is [");
1230         RTE_ETH_FOREACH_DEV(pid) {
1231                 printf(" %d", pid);
1232         }
1233         printf(" ]\n");
1234 }
1235
1236 static int
1237 vlan_id_is_invalid(uint16_t vlan_id)
1238 {
1239         if (vlan_id < 4096)
1240                 return 0;
1241         printf("Invalid vlan_id %d (must be < 4096)\n", vlan_id);
1242         return 1;
1243 }
1244
1245 static int
1246 port_reg_off_is_invalid(portid_t port_id, uint32_t reg_off)
1247 {
1248         const struct rte_pci_device *pci_dev;
1249         const struct rte_bus *bus;
1250         uint64_t pci_len;
1251
1252         if (reg_off & 0x3) {
1253                 printf("Port register offset 0x%X not aligned on a 4-byte "
1254                        "boundary\n",
1255                        (unsigned)reg_off);
1256                 return 1;
1257         }
1258
1259         if (!ports[port_id].dev_info.device) {
1260                 printf("Invalid device\n");
1261                 return 0;
1262         }
1263
1264         bus = rte_bus_find_by_device(ports[port_id].dev_info.device);
1265         if (bus && !strcmp(bus->name, "pci")) {
1266                 pci_dev = RTE_DEV_TO_PCI(ports[port_id].dev_info.device);
1267         } else {
1268                 printf("Not a PCI device\n");
1269                 return 1;
1270         }
1271
1272         pci_len = pci_dev->mem_resource[0].len;
1273         if (reg_off >= pci_len) {
1274                 printf("Port %d: register offset %u (0x%X) out of port PCI "
1275                        "resource (length=%"PRIu64")\n",
1276                        port_id, (unsigned)reg_off, (unsigned)reg_off,  pci_len);
1277                 return 1;
1278         }
1279         return 0;
1280 }
1281
1282 static int
1283 reg_bit_pos_is_invalid(uint8_t bit_pos)
1284 {
1285         if (bit_pos <= 31)
1286                 return 0;
1287         printf("Invalid bit position %d (must be <= 31)\n", bit_pos);
1288         return 1;
1289 }
1290
1291 #define display_port_and_reg_off(port_id, reg_off) \
1292         printf("port %d PCI register at offset 0x%X: ", (port_id), (reg_off))
1293
1294 static inline void
1295 display_port_reg_value(portid_t port_id, uint32_t reg_off, uint32_t reg_v)
1296 {
1297         display_port_and_reg_off(port_id, (unsigned)reg_off);
1298         printf("0x%08X (%u)\n", (unsigned)reg_v, (unsigned)reg_v);
1299 }
1300
1301 void
1302 port_reg_bit_display(portid_t port_id, uint32_t reg_off, uint8_t bit_x)
1303 {
1304         uint32_t reg_v;
1305
1306
1307         if (port_id_is_invalid(port_id, ENABLED_WARN))
1308                 return;
1309         if (port_reg_off_is_invalid(port_id, reg_off))
1310                 return;
1311         if (reg_bit_pos_is_invalid(bit_x))
1312                 return;
1313         reg_v = port_id_pci_reg_read(port_id, reg_off);
1314         display_port_and_reg_off(port_id, (unsigned)reg_off);
1315         printf("bit %d=%d\n", bit_x, (int) ((reg_v & (1 << bit_x)) >> bit_x));
1316 }
1317
1318 void
1319 port_reg_bit_field_display(portid_t port_id, uint32_t reg_off,
1320                            uint8_t bit1_pos, uint8_t bit2_pos)
1321 {
1322         uint32_t reg_v;
1323         uint8_t  l_bit;
1324         uint8_t  h_bit;
1325
1326         if (port_id_is_invalid(port_id, ENABLED_WARN))
1327                 return;
1328         if (port_reg_off_is_invalid(port_id, reg_off))
1329                 return;
1330         if (reg_bit_pos_is_invalid(bit1_pos))
1331                 return;
1332         if (reg_bit_pos_is_invalid(bit2_pos))
1333                 return;
1334         if (bit1_pos > bit2_pos)
1335                 l_bit = bit2_pos, h_bit = bit1_pos;
1336         else
1337                 l_bit = bit1_pos, h_bit = bit2_pos;
1338
1339         reg_v = port_id_pci_reg_read(port_id, reg_off);
1340         reg_v >>= l_bit;
1341         if (h_bit < 31)
1342                 reg_v &= ((1 << (h_bit - l_bit + 1)) - 1);
1343         display_port_and_reg_off(port_id, (unsigned)reg_off);
1344         printf("bits[%d, %d]=0x%0*X (%u)\n", l_bit, h_bit,
1345                ((h_bit - l_bit) / 4) + 1, (unsigned)reg_v, (unsigned)reg_v);
1346 }
1347
1348 void
1349 port_reg_display(portid_t port_id, uint32_t reg_off)
1350 {
1351         uint32_t reg_v;
1352
1353         if (port_id_is_invalid(port_id, ENABLED_WARN))
1354                 return;
1355         if (port_reg_off_is_invalid(port_id, reg_off))
1356                 return;
1357         reg_v = port_id_pci_reg_read(port_id, reg_off);
1358         display_port_reg_value(port_id, reg_off, reg_v);
1359 }
1360
1361 void
1362 port_reg_bit_set(portid_t port_id, uint32_t reg_off, uint8_t bit_pos,
1363                  uint8_t bit_v)
1364 {
1365         uint32_t reg_v;
1366
1367         if (port_id_is_invalid(port_id, ENABLED_WARN))
1368                 return;
1369         if (port_reg_off_is_invalid(port_id, reg_off))
1370                 return;
1371         if (reg_bit_pos_is_invalid(bit_pos))
1372                 return;
1373         if (bit_v > 1) {
1374                 printf("Invalid bit value %d (must be 0 or 1)\n", (int) bit_v);
1375                 return;
1376         }
1377         reg_v = port_id_pci_reg_read(port_id, reg_off);
1378         if (bit_v == 0)
1379                 reg_v &= ~(1 << bit_pos);
1380         else
1381                 reg_v |= (1 << bit_pos);
1382         port_id_pci_reg_write(port_id, reg_off, reg_v);
1383         display_port_reg_value(port_id, reg_off, reg_v);
1384 }
1385
1386 void
1387 port_reg_bit_field_set(portid_t port_id, uint32_t reg_off,
1388                        uint8_t bit1_pos, uint8_t bit2_pos, uint32_t value)
1389 {
1390         uint32_t max_v;
1391         uint32_t reg_v;
1392         uint8_t  l_bit;
1393         uint8_t  h_bit;
1394
1395         if (port_id_is_invalid(port_id, ENABLED_WARN))
1396                 return;
1397         if (port_reg_off_is_invalid(port_id, reg_off))
1398                 return;
1399         if (reg_bit_pos_is_invalid(bit1_pos))
1400                 return;
1401         if (reg_bit_pos_is_invalid(bit2_pos))
1402                 return;
1403         if (bit1_pos > bit2_pos)
1404                 l_bit = bit2_pos, h_bit = bit1_pos;
1405         else
1406                 l_bit = bit1_pos, h_bit = bit2_pos;
1407
1408         if ((h_bit - l_bit) < 31)
1409                 max_v = (1 << (h_bit - l_bit + 1)) - 1;
1410         else
1411                 max_v = 0xFFFFFFFF;
1412
1413         if (value > max_v) {
1414                 printf("Invalid value %u (0x%x) must be < %u (0x%x)\n",
1415                                 (unsigned)value, (unsigned)value,
1416                                 (unsigned)max_v, (unsigned)max_v);
1417                 return;
1418         }
1419         reg_v = port_id_pci_reg_read(port_id, reg_off);
1420         reg_v &= ~(max_v << l_bit); /* Keep unchanged bits */
1421         reg_v |= (value << l_bit); /* Set changed bits */
1422         port_id_pci_reg_write(port_id, reg_off, reg_v);
1423         display_port_reg_value(port_id, reg_off, reg_v);
1424 }
1425
1426 void
1427 port_reg_set(portid_t port_id, uint32_t reg_off, uint32_t reg_v)
1428 {
1429         if (port_id_is_invalid(port_id, ENABLED_WARN))
1430                 return;
1431         if (port_reg_off_is_invalid(port_id, reg_off))
1432                 return;
1433         port_id_pci_reg_write(port_id, reg_off, reg_v);
1434         display_port_reg_value(port_id, reg_off, reg_v);
1435 }
1436
1437 void
1438 port_mtu_set(portid_t port_id, uint16_t mtu)
1439 {
1440         int diag;
1441         struct rte_port *rte_port = &ports[port_id];
1442         struct rte_eth_dev_info dev_info;
1443         uint16_t eth_overhead;
1444         int ret;
1445
1446         if (port_id_is_invalid(port_id, ENABLED_WARN))
1447                 return;
1448
1449         ret = eth_dev_info_get_print_err(port_id, &dev_info);
1450         if (ret != 0)
1451                 return;
1452
1453         if (mtu > dev_info.max_mtu || mtu < dev_info.min_mtu) {
1454                 printf("Set MTU failed. MTU:%u is not in valid range, min:%u - max:%u\n",
1455                         mtu, dev_info.min_mtu, dev_info.max_mtu);
1456                 return;
1457         }
1458         diag = rte_eth_dev_set_mtu(port_id, mtu);
1459         if (diag)
1460                 printf("Set MTU failed. diag=%d\n", diag);
1461         else if (dev_info.rx_offload_capa & DEV_RX_OFFLOAD_JUMBO_FRAME) {
1462                 /*
1463                  * Ether overhead in driver is equal to the difference of
1464                  * max_rx_pktlen and max_mtu in rte_eth_dev_info when the
1465                  * device supports jumbo frame.
1466                  */
1467                 eth_overhead = dev_info.max_rx_pktlen - dev_info.max_mtu;
1468                 if (mtu > RTE_ETHER_MAX_LEN - eth_overhead) {
1469                         rte_port->dev_conf.rxmode.offloads |=
1470                                                 DEV_RX_OFFLOAD_JUMBO_FRAME;
1471                         rte_port->dev_conf.rxmode.max_rx_pkt_len =
1472                                                 mtu + eth_overhead;
1473                 } else
1474                         rte_port->dev_conf.rxmode.offloads &=
1475                                                 ~DEV_RX_OFFLOAD_JUMBO_FRAME;
1476         }
1477 }
1478
1479 /* Generic flow management functions. */
1480
1481 /** Generate a port_flow entry from attributes/pattern/actions. */
1482 static struct port_flow *
1483 port_flow_new(const struct rte_flow_attr *attr,
1484               const struct rte_flow_item *pattern,
1485               const struct rte_flow_action *actions,
1486               struct rte_flow_error *error)
1487 {
1488         const struct rte_flow_conv_rule rule = {
1489                 .attr_ro = attr,
1490                 .pattern_ro = pattern,
1491                 .actions_ro = actions,
1492         };
1493         struct port_flow *pf;
1494         int ret;
1495
1496         ret = rte_flow_conv(RTE_FLOW_CONV_OP_RULE, NULL, 0, &rule, error);
1497         if (ret < 0)
1498                 return NULL;
1499         pf = calloc(1, offsetof(struct port_flow, rule) + ret);
1500         if (!pf) {
1501                 rte_flow_error_set
1502                         (error, errno, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
1503                          "calloc() failed");
1504                 return NULL;
1505         }
1506         if (rte_flow_conv(RTE_FLOW_CONV_OP_RULE, &pf->rule, ret, &rule,
1507                           error) >= 0)
1508                 return pf;
1509         free(pf);
1510         return NULL;
1511 }
1512
1513 /** Print a message out of a flow error. */
1514 static int
1515 port_flow_complain(struct rte_flow_error *error)
1516 {
1517         static const char *const errstrlist[] = {
1518                 [RTE_FLOW_ERROR_TYPE_NONE] = "no error",
1519                 [RTE_FLOW_ERROR_TYPE_UNSPECIFIED] = "cause unspecified",
1520                 [RTE_FLOW_ERROR_TYPE_HANDLE] = "flow rule (handle)",
1521                 [RTE_FLOW_ERROR_TYPE_ATTR_GROUP] = "group field",
1522                 [RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY] = "priority field",
1523                 [RTE_FLOW_ERROR_TYPE_ATTR_INGRESS] = "ingress field",
1524                 [RTE_FLOW_ERROR_TYPE_ATTR_EGRESS] = "egress field",
1525                 [RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER] = "transfer field",
1526                 [RTE_FLOW_ERROR_TYPE_ATTR] = "attributes structure",
1527                 [RTE_FLOW_ERROR_TYPE_ITEM_NUM] = "pattern length",
1528                 [RTE_FLOW_ERROR_TYPE_ITEM_SPEC] = "item specification",
1529                 [RTE_FLOW_ERROR_TYPE_ITEM_LAST] = "item specification range",
1530                 [RTE_FLOW_ERROR_TYPE_ITEM_MASK] = "item specification mask",
1531                 [RTE_FLOW_ERROR_TYPE_ITEM] = "specific pattern item",
1532                 [RTE_FLOW_ERROR_TYPE_ACTION_NUM] = "number of actions",
1533                 [RTE_FLOW_ERROR_TYPE_ACTION_CONF] = "action configuration",
1534                 [RTE_FLOW_ERROR_TYPE_ACTION] = "specific action",
1535         };
1536         const char *errstr;
1537         char buf[32];
1538         int err = rte_errno;
1539
1540         if ((unsigned int)error->type >= RTE_DIM(errstrlist) ||
1541             !errstrlist[error->type])
1542                 errstr = "unknown type";
1543         else
1544                 errstr = errstrlist[error->type];
1545         printf("%s(): Caught PMD error type %d (%s): %s%s: %s\n", __func__,
1546                error->type, errstr,
1547                error->cause ? (snprintf(buf, sizeof(buf), "cause: %p, ",
1548                                         error->cause), buf) : "",
1549                error->message ? error->message : "(no stated reason)",
1550                rte_strerror(err));
1551         return -err;
1552 }
1553
1554 static void
1555 rss_config_display(struct rte_flow_action_rss *rss_conf)
1556 {
1557         uint8_t i;
1558
1559         if (rss_conf == NULL) {
1560                 printf("Invalid rule\n");
1561                 return;
1562         }
1563
1564         printf("RSS:\n"
1565                " queues:");
1566         if (rss_conf->queue_num == 0)
1567                 printf(" none");
1568         for (i = 0; i < rss_conf->queue_num; i++)
1569                 printf(" %d", rss_conf->queue[i]);
1570         printf("\n");
1571
1572         printf(" function: ");
1573         switch (rss_conf->func) {
1574         case RTE_ETH_HASH_FUNCTION_DEFAULT:
1575                 printf("default\n");
1576                 break;
1577         case RTE_ETH_HASH_FUNCTION_TOEPLITZ:
1578                 printf("toeplitz\n");
1579                 break;
1580         case RTE_ETH_HASH_FUNCTION_SIMPLE_XOR:
1581                 printf("simple_xor\n");
1582                 break;
1583         case RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ:
1584                 printf("symmetric_toeplitz\n");
1585                 break;
1586         default:
1587                 printf("Unknown function\n");
1588                 return;
1589         }
1590
1591         printf(" types:\n");
1592         if (rss_conf->types == 0) {
1593                 printf("  none\n");
1594                 return;
1595         }
1596         for (i = 0; rss_type_table[i].str; i++) {
1597                 if ((rss_conf->types &
1598                     rss_type_table[i].rss_type) ==
1599                     rss_type_table[i].rss_type &&
1600                     rss_type_table[i].rss_type != 0)
1601                         printf("  %s\n", rss_type_table[i].str);
1602         }
1603 }
1604
1605 /** Validate flow rule. */
1606 int
1607 port_flow_validate(portid_t port_id,
1608                    const struct rte_flow_attr *attr,
1609                    const struct rte_flow_item *pattern,
1610                    const struct rte_flow_action *actions)
1611 {
1612         struct rte_flow_error error;
1613
1614         /* Poisoning to make sure PMDs update it in case of error. */
1615         memset(&error, 0x11, sizeof(error));
1616         if (rte_flow_validate(port_id, attr, pattern, actions, &error))
1617                 return port_flow_complain(&error);
1618         printf("Flow rule validated\n");
1619         return 0;
1620 }
1621
1622 /** Update age action context by port_flow pointer. */
1623 void
1624 update_age_action_context(const struct rte_flow_action *actions,
1625                         struct port_flow *pf)
1626 {
1627         struct rte_flow_action_age *age = NULL;
1628
1629         for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
1630                 switch (actions->type) {
1631                 case RTE_FLOW_ACTION_TYPE_AGE:
1632                         age = (struct rte_flow_action_age *)
1633                                 (uintptr_t)actions->conf;
1634                         age->context = pf;
1635                         return;
1636                 default:
1637                         break;
1638                 }
1639         }
1640 }
1641
1642 /** Create flow rule. */
1643 int
1644 port_flow_create(portid_t port_id,
1645                  const struct rte_flow_attr *attr,
1646                  const struct rte_flow_item *pattern,
1647                  const struct rte_flow_action *actions)
1648 {
1649         struct rte_flow *flow;
1650         struct rte_port *port;
1651         struct port_flow *pf;
1652         uint32_t id = 0;
1653         struct rte_flow_error error;
1654
1655         port = &ports[port_id];
1656         if (port->flow_list) {
1657                 if (port->flow_list->id == UINT32_MAX) {
1658                         printf("Highest rule ID is already assigned, delete"
1659                                " it first");
1660                         return -ENOMEM;
1661                 }
1662                 id = port->flow_list->id + 1;
1663         }
1664         pf = port_flow_new(attr, pattern, actions, &error);
1665         if (!pf)
1666                 return port_flow_complain(&error);
1667         update_age_action_context(actions, pf);
1668         /* Poisoning to make sure PMDs update it in case of error. */
1669         memset(&error, 0x22, sizeof(error));
1670         flow = rte_flow_create(port_id, attr, pattern, actions, &error);
1671         if (!flow) {
1672                 free(pf);
1673                 return port_flow_complain(&error);
1674         }
1675         pf->next = port->flow_list;
1676         pf->id = id;
1677         pf->flow = flow;
1678         port->flow_list = pf;
1679         printf("Flow rule #%u created\n", pf->id);
1680         return 0;
1681 }
1682
1683 /** Destroy a number of flow rules. */
1684 int
1685 port_flow_destroy(portid_t port_id, uint32_t n, const uint32_t *rule)
1686 {
1687         struct rte_port *port;
1688         struct port_flow **tmp;
1689         uint32_t c = 0;
1690         int ret = 0;
1691
1692         if (port_id_is_invalid(port_id, ENABLED_WARN) ||
1693             port_id == (portid_t)RTE_PORT_ALL)
1694                 return -EINVAL;
1695         port = &ports[port_id];
1696         tmp = &port->flow_list;
1697         while (*tmp) {
1698                 uint32_t i;
1699
1700                 for (i = 0; i != n; ++i) {
1701                         struct rte_flow_error error;
1702                         struct port_flow *pf = *tmp;
1703
1704                         if (rule[i] != pf->id)
1705                                 continue;
1706                         /*
1707                          * Poisoning to make sure PMDs update it in case
1708                          * of error.
1709                          */
1710                         memset(&error, 0x33, sizeof(error));
1711                         if (rte_flow_destroy(port_id, pf->flow, &error)) {
1712                                 ret = port_flow_complain(&error);
1713                                 continue;
1714                         }
1715                         printf("Flow rule #%u destroyed\n", pf->id);
1716                         *tmp = pf->next;
1717                         free(pf);
1718                         break;
1719                 }
1720                 if (i == n)
1721                         tmp = &(*tmp)->next;
1722                 ++c;
1723         }
1724         return ret;
1725 }
1726
1727 /** Remove all flow rules. */
1728 int
1729 port_flow_flush(portid_t port_id)
1730 {
1731         struct rte_flow_error error;
1732         struct rte_port *port = &ports[port_id];
1733         int ret = 0;
1734
1735         if (port->flow_list == NULL)
1736                 return ret;
1737
1738         /* Poisoning to make sure PMDs update it in case of error. */
1739         memset(&error, 0x44, sizeof(error));
1740         if (rte_flow_flush(port_id, &error)) {
1741                 ret = port_flow_complain(&error);
1742                 if (port_id_is_invalid(port_id, DISABLED_WARN) ||
1743                     port_id == (portid_t)RTE_PORT_ALL)
1744                         return ret;
1745         }
1746
1747         while (port->flow_list) {
1748                 struct port_flow *pf = port->flow_list->next;
1749
1750                 free(port->flow_list);
1751                 port->flow_list = pf;
1752         }
1753         return ret;
1754 }
1755
1756 /** Dump all flow rules. */
1757 int
1758 port_flow_dump(portid_t port_id, const char *file_name)
1759 {
1760         int ret = 0;
1761         FILE *file = stdout;
1762         struct rte_flow_error error;
1763
1764         if (file_name && strlen(file_name)) {
1765                 file = fopen(file_name, "w");
1766                 if (!file) {
1767                         printf("Failed to create file %s: %s\n", file_name,
1768                                strerror(errno));
1769                         return -errno;
1770                 }
1771         }
1772         ret = rte_flow_dev_dump(port_id, file, &error);
1773         if (ret) {
1774                 port_flow_complain(&error);
1775                 printf("Failed to dump flow: %s\n", strerror(-ret));
1776         } else
1777                 printf("Flow dump finished\n");
1778         if (file_name && strlen(file_name))
1779                 fclose(file);
1780         return ret;
1781 }
1782
1783 /** Query a flow rule. */
1784 int
1785 port_flow_query(portid_t port_id, uint32_t rule,
1786                 const struct rte_flow_action *action)
1787 {
1788         struct rte_flow_error error;
1789         struct rte_port *port;
1790         struct port_flow *pf;
1791         const char *name;
1792         union {
1793                 struct rte_flow_query_count count;
1794                 struct rte_flow_action_rss rss_conf;
1795         } query;
1796         int ret;
1797
1798         if (port_id_is_invalid(port_id, ENABLED_WARN) ||
1799             port_id == (portid_t)RTE_PORT_ALL)
1800                 return -EINVAL;
1801         port = &ports[port_id];
1802         for (pf = port->flow_list; pf; pf = pf->next)
1803                 if (pf->id == rule)
1804                         break;
1805         if (!pf) {
1806                 printf("Flow rule #%u not found\n", rule);
1807                 return -ENOENT;
1808         }
1809         ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTION_NAME_PTR,
1810                             &name, sizeof(name),
1811                             (void *)(uintptr_t)action->type, &error);
1812         if (ret < 0)
1813                 return port_flow_complain(&error);
1814         switch (action->type) {
1815         case RTE_FLOW_ACTION_TYPE_COUNT:
1816         case RTE_FLOW_ACTION_TYPE_RSS:
1817                 break;
1818         default:
1819                 printf("Cannot query action type %d (%s)\n",
1820                         action->type, name);
1821                 return -ENOTSUP;
1822         }
1823         /* Poisoning to make sure PMDs update it in case of error. */
1824         memset(&error, 0x55, sizeof(error));
1825         memset(&query, 0, sizeof(query));
1826         if (rte_flow_query(port_id, pf->flow, action, &query, &error))
1827                 return port_flow_complain(&error);
1828         switch (action->type) {
1829         case RTE_FLOW_ACTION_TYPE_COUNT:
1830                 printf("%s:\n"
1831                        " hits_set: %u\n"
1832                        " bytes_set: %u\n"
1833                        " hits: %" PRIu64 "\n"
1834                        " bytes: %" PRIu64 "\n",
1835                        name,
1836                        query.count.hits_set,
1837                        query.count.bytes_set,
1838                        query.count.hits,
1839                        query.count.bytes);
1840                 break;
1841         case RTE_FLOW_ACTION_TYPE_RSS:
1842                 rss_config_display(&query.rss_conf);
1843                 break;
1844         default:
1845                 printf("Cannot display result for action type %d (%s)\n",
1846                        action->type, name);
1847                 break;
1848         }
1849         return 0;
1850 }
1851
1852 /** List simply and destroy all aged flows. */
1853 void
1854 port_flow_aged(portid_t port_id, uint8_t destroy)
1855 {
1856         void **contexts;
1857         int nb_context, total = 0, idx;
1858         struct rte_flow_error error;
1859         struct port_flow *pf;
1860
1861         if (port_id_is_invalid(port_id, ENABLED_WARN) ||
1862             port_id == (portid_t)RTE_PORT_ALL)
1863                 return;
1864         total = rte_flow_get_aged_flows(port_id, NULL, 0, &error);
1865         printf("Port %u total aged flows: %d\n", port_id, total);
1866         if (total < 0) {
1867                 port_flow_complain(&error);
1868                 return;
1869         }
1870         if (total == 0)
1871                 return;
1872         contexts = malloc(sizeof(void *) * total);
1873         if (contexts == NULL) {
1874                 printf("Cannot allocate contexts for aged flow\n");
1875                 return;
1876         }
1877         printf("ID\tGroup\tPrio\tAttr\n");
1878         nb_context = rte_flow_get_aged_flows(port_id, contexts, total, &error);
1879         if (nb_context != total) {
1880                 printf("Port:%d get aged flows count(%d) != total(%d)\n",
1881                         port_id, nb_context, total);
1882                 free(contexts);
1883                 return;
1884         }
1885         for (idx = 0; idx < nb_context; idx++) {
1886                 pf = (struct port_flow *)contexts[idx];
1887                 if (!pf) {
1888                         printf("Error: get Null context in port %u\n", port_id);
1889                         continue;
1890                 }
1891                 printf("%" PRIu32 "\t%" PRIu32 "\t%" PRIu32 "\t%c%c%c\t\n",
1892                        pf->id,
1893                        pf->rule.attr->group,
1894                        pf->rule.attr->priority,
1895                        pf->rule.attr->ingress ? 'i' : '-',
1896                        pf->rule.attr->egress ? 'e' : '-',
1897                        pf->rule.attr->transfer ? 't' : '-');
1898         }
1899         if (destroy) {
1900                 int ret;
1901                 uint32_t flow_id;
1902
1903                 total = 0;
1904                 printf("\n");
1905                 for (idx = 0; idx < nb_context; idx++) {
1906                         pf = (struct port_flow *)contexts[idx];
1907                         if (!pf)
1908                                 continue;
1909                         flow_id = pf->id;
1910                         ret = port_flow_destroy(port_id, 1, &flow_id);
1911                         if (!ret)
1912                                 total++;
1913                 }
1914                 printf("%d flows be destroyed\n", total);
1915         }
1916         free(contexts);
1917 }
1918
1919 /** List flow rules. */
1920 void
1921 port_flow_list(portid_t port_id, uint32_t n, const uint32_t *group)
1922 {
1923         struct rte_port *port;
1924         struct port_flow *pf;
1925         struct port_flow *list = NULL;
1926         uint32_t i;
1927
1928         if (port_id_is_invalid(port_id, ENABLED_WARN) ||
1929             port_id == (portid_t)RTE_PORT_ALL)
1930                 return;
1931         port = &ports[port_id];
1932         if (!port->flow_list)
1933                 return;
1934         /* Sort flows by group, priority and ID. */
1935         for (pf = port->flow_list; pf != NULL; pf = pf->next) {
1936                 struct port_flow **tmp;
1937                 const struct rte_flow_attr *curr = pf->rule.attr;
1938
1939                 if (n) {
1940                         /* Filter out unwanted groups. */
1941                         for (i = 0; i != n; ++i)
1942                                 if (curr->group == group[i])
1943                                         break;
1944                         if (i == n)
1945                                 continue;
1946                 }
1947                 for (tmp = &list; *tmp; tmp = &(*tmp)->tmp) {
1948                         const struct rte_flow_attr *comp = (*tmp)->rule.attr;
1949
1950                         if (curr->group > comp->group ||
1951                             (curr->group == comp->group &&
1952                              curr->priority > comp->priority) ||
1953                             (curr->group == comp->group &&
1954                              curr->priority == comp->priority &&
1955                              pf->id > (*tmp)->id))
1956                                 continue;
1957                         break;
1958                 }
1959                 pf->tmp = *tmp;
1960                 *tmp = pf;
1961         }
1962         printf("ID\tGroup\tPrio\tAttr\tRule\n");
1963         for (pf = list; pf != NULL; pf = pf->tmp) {
1964                 const struct rte_flow_item *item = pf->rule.pattern;
1965                 const struct rte_flow_action *action = pf->rule.actions;
1966                 const char *name;
1967
1968                 printf("%" PRIu32 "\t%" PRIu32 "\t%" PRIu32 "\t%c%c%c\t",
1969                        pf->id,
1970                        pf->rule.attr->group,
1971                        pf->rule.attr->priority,
1972                        pf->rule.attr->ingress ? 'i' : '-',
1973                        pf->rule.attr->egress ? 'e' : '-',
1974                        pf->rule.attr->transfer ? 't' : '-');
1975                 while (item->type != RTE_FLOW_ITEM_TYPE_END) {
1976                         if (rte_flow_conv(RTE_FLOW_CONV_OP_ITEM_NAME_PTR,
1977                                           &name, sizeof(name),
1978                                           (void *)(uintptr_t)item->type,
1979                                           NULL) <= 0)
1980                                 name = "[UNKNOWN]";
1981                         if (item->type != RTE_FLOW_ITEM_TYPE_VOID)
1982                                 printf("%s ", name);
1983                         ++item;
1984                 }
1985                 printf("=>");
1986                 while (action->type != RTE_FLOW_ACTION_TYPE_END) {
1987                         if (rte_flow_conv(RTE_FLOW_CONV_OP_ACTION_NAME_PTR,
1988                                           &name, sizeof(name),
1989                                           (void *)(uintptr_t)action->type,
1990                                           NULL) <= 0)
1991                                 name = "[UNKNOWN]";
1992                         if (action->type != RTE_FLOW_ACTION_TYPE_VOID)
1993                                 printf(" %s", name);
1994                         ++action;
1995                 }
1996                 printf("\n");
1997         }
1998 }
1999
2000 /** Restrict ingress traffic to the defined flow rules. */
2001 int
2002 port_flow_isolate(portid_t port_id, int set)
2003 {
2004         struct rte_flow_error error;
2005
2006         /* Poisoning to make sure PMDs update it in case of error. */
2007         memset(&error, 0x66, sizeof(error));
2008         if (rte_flow_isolate(port_id, set, &error))
2009                 return port_flow_complain(&error);
2010         printf("Ingress traffic on port %u is %s to the defined flow rules\n",
2011                port_id,
2012                set ? "now restricted" : "not restricted anymore");
2013         return 0;
2014 }
2015
2016 /*
2017  * RX/TX ring descriptors display functions.
2018  */
2019 int
2020 rx_queue_id_is_invalid(queueid_t rxq_id)
2021 {
2022         if (rxq_id < nb_rxq)
2023                 return 0;
2024         printf("Invalid RX queue %d (must be < nb_rxq=%d)\n", rxq_id, nb_rxq);
2025         return 1;
2026 }
2027
2028 int
2029 tx_queue_id_is_invalid(queueid_t txq_id)
2030 {
2031         if (txq_id < nb_txq)
2032                 return 0;
2033         printf("Invalid TX queue %d (must be < nb_rxq=%d)\n", txq_id, nb_txq);
2034         return 1;
2035 }
2036
2037 static int
2038 get_rx_ring_size(portid_t port_id, queueid_t rxq_id, uint16_t *ring_size)
2039 {
2040         struct rte_port *port = &ports[port_id];
2041         struct rte_eth_rxq_info rx_qinfo;
2042         int ret;
2043
2044         ret = rte_eth_rx_queue_info_get(port_id, rxq_id, &rx_qinfo);
2045         if (ret == 0) {
2046                 *ring_size = rx_qinfo.nb_desc;
2047                 return ret;
2048         }
2049
2050         if (ret != -ENOTSUP)
2051                 return ret;
2052         /*
2053          * If the rte_eth_rx_queue_info_get is not support for this PMD,
2054          * ring_size stored in testpmd will be used for validity verification.
2055          * When configure the rxq by rte_eth_rx_queue_setup with nb_rx_desc
2056          * being 0, it will use a default value provided by PMDs to setup this
2057          * rxq. If the default value is 0, it will use the
2058          * RTE_ETH_DEV_FALLBACK_RX_RINGSIZE to setup this rxq.
2059          */
2060         if (port->nb_rx_desc[rxq_id])
2061                 *ring_size = port->nb_rx_desc[rxq_id];
2062         else if (port->dev_info.default_rxportconf.ring_size)
2063                 *ring_size = port->dev_info.default_rxportconf.ring_size;
2064         else
2065                 *ring_size = RTE_ETH_DEV_FALLBACK_RX_RINGSIZE;
2066         return 0;
2067 }
2068
2069 static int
2070 get_tx_ring_size(portid_t port_id, queueid_t txq_id, uint16_t *ring_size)
2071 {
2072         struct rte_port *port = &ports[port_id];
2073         struct rte_eth_txq_info tx_qinfo;
2074         int ret;
2075
2076         ret = rte_eth_tx_queue_info_get(port_id, txq_id, &tx_qinfo);
2077         if (ret == 0) {
2078                 *ring_size = tx_qinfo.nb_desc;
2079                 return ret;
2080         }
2081
2082         if (ret != -ENOTSUP)
2083                 return ret;
2084         /*
2085          * If the rte_eth_tx_queue_info_get is not support for this PMD,
2086          * ring_size stored in testpmd will be used for validity verification.
2087          * When configure the txq by rte_eth_tx_queue_setup with nb_tx_desc
2088          * being 0, it will use a default value provided by PMDs to setup this
2089          * txq. If the default value is 0, it will use the
2090          * RTE_ETH_DEV_FALLBACK_TX_RINGSIZE to setup this txq.
2091          */
2092         if (port->nb_tx_desc[txq_id])
2093                 *ring_size = port->nb_tx_desc[txq_id];
2094         else if (port->dev_info.default_txportconf.ring_size)
2095                 *ring_size = port->dev_info.default_txportconf.ring_size;
2096         else
2097                 *ring_size = RTE_ETH_DEV_FALLBACK_TX_RINGSIZE;
2098         return 0;
2099 }
2100
2101 static int
2102 rx_desc_id_is_invalid(portid_t port_id, queueid_t rxq_id, uint16_t rxdesc_id)
2103 {
2104         uint16_t ring_size;
2105         int ret;
2106
2107         ret = get_rx_ring_size(port_id, rxq_id, &ring_size);
2108         if (ret)
2109                 return 1;
2110
2111         if (rxdesc_id < ring_size)
2112                 return 0;
2113
2114         printf("Invalid RX descriptor %u (must be < ring_size=%u)\n",
2115                rxdesc_id, ring_size);
2116         return 1;
2117 }
2118
2119 static int
2120 tx_desc_id_is_invalid(portid_t port_id, queueid_t txq_id, uint16_t txdesc_id)
2121 {
2122         uint16_t ring_size;
2123         int ret;
2124
2125         ret = get_tx_ring_size(port_id, txq_id, &ring_size);
2126         if (ret)
2127                 return 1;
2128
2129         if (txdesc_id < ring_size)
2130                 return 0;
2131
2132         printf("Invalid TX descriptor %u (must be < ring_size=%u)\n",
2133                txdesc_id, ring_size);
2134         return 1;
2135 }
2136
2137 static const struct rte_memzone *
2138 ring_dma_zone_lookup(const char *ring_name, portid_t port_id, uint16_t q_id)
2139 {
2140         char mz_name[RTE_MEMZONE_NAMESIZE];
2141         const struct rte_memzone *mz;
2142
2143         snprintf(mz_name, sizeof(mz_name), "eth_p%d_q%d_%s",
2144                         port_id, q_id, ring_name);
2145         mz = rte_memzone_lookup(mz_name);
2146         if (mz == NULL)
2147                 printf("%s ring memory zoneof (port %d, queue %d) not"
2148                        "found (zone name = %s\n",
2149                        ring_name, port_id, q_id, mz_name);
2150         return mz;
2151 }
2152
2153 union igb_ring_dword {
2154         uint64_t dword;
2155         struct {
2156 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
2157                 uint32_t lo;
2158                 uint32_t hi;
2159 #else
2160                 uint32_t hi;
2161                 uint32_t lo;
2162 #endif
2163         } words;
2164 };
2165
2166 struct igb_ring_desc_32_bytes {
2167         union igb_ring_dword lo_dword;
2168         union igb_ring_dword hi_dword;
2169         union igb_ring_dword resv1;
2170         union igb_ring_dword resv2;
2171 };
2172
2173 struct igb_ring_desc_16_bytes {
2174         union igb_ring_dword lo_dword;
2175         union igb_ring_dword hi_dword;
2176 };
2177
2178 static void
2179 ring_rxd_display_dword(union igb_ring_dword dword)
2180 {
2181         printf("    0x%08X - 0x%08X\n", (unsigned)dword.words.lo,
2182                                         (unsigned)dword.words.hi);
2183 }
2184
2185 static void
2186 ring_rx_descriptor_display(const struct rte_memzone *ring_mz,
2187 #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC
2188                            portid_t port_id,
2189 #else
2190                            __rte_unused portid_t port_id,
2191 #endif
2192                            uint16_t desc_id)
2193 {
2194         struct igb_ring_desc_16_bytes *ring =
2195                 (struct igb_ring_desc_16_bytes *)ring_mz->addr;
2196 #ifndef RTE_LIBRTE_I40E_16BYTE_RX_DESC
2197         int ret;
2198         struct rte_eth_dev_info dev_info;
2199
2200         ret = eth_dev_info_get_print_err(port_id, &dev_info);
2201         if (ret != 0)
2202                 return;
2203
2204         if (strstr(dev_info.driver_name, "i40e") != NULL) {
2205                 /* 32 bytes RX descriptor, i40e only */
2206                 struct igb_ring_desc_32_bytes *ring =
2207                         (struct igb_ring_desc_32_bytes *)ring_mz->addr;
2208                 ring[desc_id].lo_dword.dword =
2209                         rte_le_to_cpu_64(ring[desc_id].lo_dword.dword);
2210                 ring_rxd_display_dword(ring[desc_id].lo_dword);
2211                 ring[desc_id].hi_dword.dword =
2212                         rte_le_to_cpu_64(ring[desc_id].hi_dword.dword);
2213                 ring_rxd_display_dword(ring[desc_id].hi_dword);
2214                 ring[desc_id].resv1.dword =
2215                         rte_le_to_cpu_64(ring[desc_id].resv1.dword);
2216                 ring_rxd_display_dword(ring[desc_id].resv1);
2217                 ring[desc_id].resv2.dword =
2218                         rte_le_to_cpu_64(ring[desc_id].resv2.dword);
2219                 ring_rxd_display_dword(ring[desc_id].resv2);
2220
2221                 return;
2222         }
2223 #endif
2224         /* 16 bytes RX descriptor */
2225         ring[desc_id].lo_dword.dword =
2226                 rte_le_to_cpu_64(ring[desc_id].lo_dword.dword);
2227         ring_rxd_display_dword(ring[desc_id].lo_dword);
2228         ring[desc_id].hi_dword.dword =
2229                 rte_le_to_cpu_64(ring[desc_id].hi_dword.dword);
2230         ring_rxd_display_dword(ring[desc_id].hi_dword);
2231 }
2232
2233 static void
2234 ring_tx_descriptor_display(const struct rte_memzone *ring_mz, uint16_t desc_id)
2235 {
2236         struct igb_ring_desc_16_bytes *ring;
2237         struct igb_ring_desc_16_bytes txd;
2238
2239         ring = (struct igb_ring_desc_16_bytes *)ring_mz->addr;
2240         txd.lo_dword.dword = rte_le_to_cpu_64(ring[desc_id].lo_dword.dword);
2241         txd.hi_dword.dword = rte_le_to_cpu_64(ring[desc_id].hi_dword.dword);
2242         printf("    0x%08X - 0x%08X / 0x%08X - 0x%08X\n",
2243                         (unsigned)txd.lo_dword.words.lo,
2244                         (unsigned)txd.lo_dword.words.hi,
2245                         (unsigned)txd.hi_dword.words.lo,
2246                         (unsigned)txd.hi_dword.words.hi);
2247 }
2248
2249 void
2250 rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id)
2251 {
2252         const struct rte_memzone *rx_mz;
2253
2254         if (rx_desc_id_is_invalid(port_id, rxq_id, rxd_id))
2255                 return;
2256         rx_mz = ring_dma_zone_lookup("rx_ring", port_id, rxq_id);
2257         if (rx_mz == NULL)
2258                 return;
2259         ring_rx_descriptor_display(rx_mz, port_id, rxd_id);
2260 }
2261
2262 void
2263 tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id)
2264 {
2265         const struct rte_memzone *tx_mz;
2266
2267         if (tx_desc_id_is_invalid(port_id, txq_id, txd_id))
2268                 return;
2269         tx_mz = ring_dma_zone_lookup("tx_ring", port_id, txq_id);
2270         if (tx_mz == NULL)
2271                 return;
2272         ring_tx_descriptor_display(tx_mz, txd_id);
2273 }
2274
2275 void
2276 fwd_lcores_config_display(void)
2277 {
2278         lcoreid_t lc_id;
2279
2280         printf("List of forwarding lcores:");
2281         for (lc_id = 0; lc_id < nb_cfg_lcores; lc_id++)
2282                 printf(" %2u", fwd_lcores_cpuids[lc_id]);
2283         printf("\n");
2284 }
2285 void
2286 rxtx_config_display(void)
2287 {
2288         portid_t pid;
2289         queueid_t qid;
2290
2291         printf("  %s packet forwarding%s packets/burst=%d\n",
2292                cur_fwd_eng->fwd_mode_name,
2293                retry_enabled == 0 ? "" : " with retry",
2294                nb_pkt_per_burst);
2295
2296         if (cur_fwd_eng == &tx_only_engine || cur_fwd_eng == &flow_gen_engine)
2297                 printf("  packet len=%u - nb packet segments=%d\n",
2298                                 (unsigned)tx_pkt_length, (int) tx_pkt_nb_segs);
2299
2300         printf("  nb forwarding cores=%d - nb forwarding ports=%d\n",
2301                nb_fwd_lcores, nb_fwd_ports);
2302
2303         RTE_ETH_FOREACH_DEV(pid) {
2304                 struct rte_eth_rxconf *rx_conf = &ports[pid].rx_conf[0];
2305                 struct rte_eth_txconf *tx_conf = &ports[pid].tx_conf[0];
2306                 uint16_t *nb_rx_desc = &ports[pid].nb_rx_desc[0];
2307                 uint16_t *nb_tx_desc = &ports[pid].nb_tx_desc[0];
2308                 struct rte_eth_rxq_info rx_qinfo;
2309                 struct rte_eth_txq_info tx_qinfo;
2310                 uint16_t rx_free_thresh_tmp;
2311                 uint16_t tx_free_thresh_tmp;
2312                 uint16_t tx_rs_thresh_tmp;
2313                 uint16_t nb_rx_desc_tmp;
2314                 uint16_t nb_tx_desc_tmp;
2315                 uint64_t offloads_tmp;
2316                 uint8_t pthresh_tmp;
2317                 uint8_t hthresh_tmp;
2318                 uint8_t wthresh_tmp;
2319                 int32_t rc;
2320
2321                 /* per port config */
2322                 printf("  port %d: RX queue number: %d Tx queue number: %d\n",
2323                                 (unsigned int)pid, nb_rxq, nb_txq);
2324
2325                 printf("    Rx offloads=0x%"PRIx64" Tx offloads=0x%"PRIx64"\n",
2326                                 ports[pid].dev_conf.rxmode.offloads,
2327                                 ports[pid].dev_conf.txmode.offloads);
2328
2329                 /* per rx queue config only for first queue to be less verbose */
2330                 for (qid = 0; qid < 1; qid++) {
2331                         rc = rte_eth_rx_queue_info_get(pid, qid, &rx_qinfo);
2332                         if (rc) {
2333                                 nb_rx_desc_tmp = nb_rx_desc[qid];
2334                                 rx_free_thresh_tmp =
2335                                         rx_conf[qid].rx_free_thresh;
2336                                 pthresh_tmp = rx_conf[qid].rx_thresh.pthresh;
2337                                 hthresh_tmp = rx_conf[qid].rx_thresh.hthresh;
2338                                 wthresh_tmp = rx_conf[qid].rx_thresh.wthresh;
2339                                 offloads_tmp = rx_conf[qid].offloads;
2340                         } else {
2341                                 nb_rx_desc_tmp = rx_qinfo.nb_desc;
2342                                 rx_free_thresh_tmp =
2343                                                 rx_qinfo.conf.rx_free_thresh;
2344                                 pthresh_tmp = rx_qinfo.conf.rx_thresh.pthresh;
2345                                 hthresh_tmp = rx_qinfo.conf.rx_thresh.hthresh;
2346                                 wthresh_tmp = rx_qinfo.conf.rx_thresh.wthresh;
2347                                 offloads_tmp = rx_qinfo.conf.offloads;
2348                         }
2349
2350                         printf("    RX queue: %d\n", qid);
2351                         printf("      RX desc=%d - RX free threshold=%d\n",
2352                                 nb_rx_desc_tmp, rx_free_thresh_tmp);
2353                         printf("      RX threshold registers: pthresh=%d hthresh=%d "
2354                                 " wthresh=%d\n",
2355                                 pthresh_tmp, hthresh_tmp, wthresh_tmp);
2356                         printf("      RX Offloads=0x%"PRIx64"\n", offloads_tmp);
2357                 }
2358
2359                 /* per tx queue config only for first queue to be less verbose */
2360                 for (qid = 0; qid < 1; qid++) {
2361                         rc = rte_eth_tx_queue_info_get(pid, qid, &tx_qinfo);
2362                         if (rc) {
2363                                 nb_tx_desc_tmp = nb_tx_desc[qid];
2364                                 tx_free_thresh_tmp =
2365                                         tx_conf[qid].tx_free_thresh;
2366                                 pthresh_tmp = tx_conf[qid].tx_thresh.pthresh;
2367                                 hthresh_tmp = tx_conf[qid].tx_thresh.hthresh;
2368                                 wthresh_tmp = tx_conf[qid].tx_thresh.wthresh;
2369                                 offloads_tmp = tx_conf[qid].offloads;
2370                                 tx_rs_thresh_tmp = tx_conf[qid].tx_rs_thresh;
2371                         } else {
2372                                 nb_tx_desc_tmp = tx_qinfo.nb_desc;
2373                                 tx_free_thresh_tmp =
2374                                                 tx_qinfo.conf.tx_free_thresh;
2375                                 pthresh_tmp = tx_qinfo.conf.tx_thresh.pthresh;
2376                                 hthresh_tmp = tx_qinfo.conf.tx_thresh.hthresh;
2377                                 wthresh_tmp = tx_qinfo.conf.tx_thresh.wthresh;
2378                                 offloads_tmp = tx_qinfo.conf.offloads;
2379                                 tx_rs_thresh_tmp = tx_qinfo.conf.tx_rs_thresh;
2380                         }
2381
2382                         printf("    TX queue: %d\n", qid);
2383                         printf("      TX desc=%d - TX free threshold=%d\n",
2384                                 nb_tx_desc_tmp, tx_free_thresh_tmp);
2385                         printf("      TX threshold registers: pthresh=%d hthresh=%d "
2386                                 " wthresh=%d\n",
2387                                 pthresh_tmp, hthresh_tmp, wthresh_tmp);
2388                         printf("      TX offloads=0x%"PRIx64" - TX RS bit threshold=%d\n",
2389                                 offloads_tmp, tx_rs_thresh_tmp);
2390                 }
2391         }
2392 }
2393
2394 void
2395 port_rss_reta_info(portid_t port_id,
2396                    struct rte_eth_rss_reta_entry64 *reta_conf,
2397                    uint16_t nb_entries)
2398 {
2399         uint16_t i, idx, shift;
2400         int ret;
2401
2402         if (port_id_is_invalid(port_id, ENABLED_WARN))
2403                 return;
2404
2405         ret = rte_eth_dev_rss_reta_query(port_id, reta_conf, nb_entries);
2406         if (ret != 0) {
2407                 printf("Failed to get RSS RETA info, return code = %d\n", ret);
2408                 return;
2409         }
2410
2411         for (i = 0; i < nb_entries; i++) {
2412                 idx = i / RTE_RETA_GROUP_SIZE;
2413                 shift = i % RTE_RETA_GROUP_SIZE;
2414                 if (!(reta_conf[idx].mask & (1ULL << shift)))
2415                         continue;
2416                 printf("RSS RETA configuration: hash index=%u, queue=%u\n",
2417                                         i, reta_conf[idx].reta[shift]);
2418         }
2419 }
2420
2421 /*
2422  * Displays the RSS hash functions of a port, and, optionaly, the RSS hash
2423  * key of the port.
2424  */
2425 void
2426 port_rss_hash_conf_show(portid_t port_id, int show_rss_key)
2427 {
2428         struct rte_eth_rss_conf rss_conf = {0};
2429         uint8_t rss_key[RSS_HASH_KEY_LENGTH];
2430         uint64_t rss_hf;
2431         uint8_t i;
2432         int diag;
2433         struct rte_eth_dev_info dev_info;
2434         uint8_t hash_key_size;
2435         int ret;
2436
2437         if (port_id_is_invalid(port_id, ENABLED_WARN))
2438                 return;
2439
2440         ret = eth_dev_info_get_print_err(port_id, &dev_info);
2441         if (ret != 0)
2442                 return;
2443
2444         if (dev_info.hash_key_size > 0 &&
2445                         dev_info.hash_key_size <= sizeof(rss_key))
2446                 hash_key_size = dev_info.hash_key_size;
2447         else {
2448                 printf("dev_info did not provide a valid hash key size\n");
2449                 return;
2450         }
2451
2452         /* Get RSS hash key if asked to display it */
2453         rss_conf.rss_key = (show_rss_key) ? rss_key : NULL;
2454         rss_conf.rss_key_len = hash_key_size;
2455         diag = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf);
2456         if (diag != 0) {
2457                 switch (diag) {
2458                 case -ENODEV:
2459                         printf("port index %d invalid\n", port_id);
2460                         break;
2461                 case -ENOTSUP:
2462                         printf("operation not supported by device\n");
2463                         break;
2464                 default:
2465                         printf("operation failed - diag=%d\n", diag);
2466                         break;
2467                 }
2468                 return;
2469         }
2470         rss_hf = rss_conf.rss_hf;
2471         if (rss_hf == 0) {
2472                 printf("RSS disabled\n");
2473                 return;
2474         }
2475         printf("RSS functions:\n ");
2476         for (i = 0; rss_type_table[i].str; i++) {
2477                 if (rss_hf & rss_type_table[i].rss_type)
2478                         printf("%s ", rss_type_table[i].str);
2479         }
2480         printf("\n");
2481         if (!show_rss_key)
2482                 return;
2483         printf("RSS key:\n");
2484         for (i = 0; i < hash_key_size; i++)
2485                 printf("%02X", rss_key[i]);
2486         printf("\n");
2487 }
2488
2489 void
2490 port_rss_hash_key_update(portid_t port_id, char rss_type[], uint8_t *hash_key,
2491                          uint hash_key_len)
2492 {
2493         struct rte_eth_rss_conf rss_conf;
2494         int diag;
2495         unsigned int i;
2496
2497         rss_conf.rss_key = NULL;
2498         rss_conf.rss_key_len = hash_key_len;
2499         rss_conf.rss_hf = 0;
2500         for (i = 0; rss_type_table[i].str; i++) {
2501                 if (!strcmp(rss_type_table[i].str, rss_type))
2502                         rss_conf.rss_hf = rss_type_table[i].rss_type;
2503         }
2504         diag = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf);
2505         if (diag == 0) {
2506                 rss_conf.rss_key = hash_key;
2507                 diag = rte_eth_dev_rss_hash_update(port_id, &rss_conf);
2508         }
2509         if (diag == 0)
2510                 return;
2511
2512         switch (diag) {
2513         case -ENODEV:
2514                 printf("port index %d invalid\n", port_id);
2515                 break;
2516         case -ENOTSUP:
2517                 printf("operation not supported by device\n");
2518                 break;
2519         default:
2520                 printf("operation failed - diag=%d\n", diag);
2521                 break;
2522         }
2523 }
2524
2525 /*
2526  * Setup forwarding configuration for each logical core.
2527  */
2528 static void
2529 setup_fwd_config_of_each_lcore(struct fwd_config *cfg)
2530 {
2531         streamid_t nb_fs_per_lcore;
2532         streamid_t nb_fs;
2533         streamid_t sm_id;
2534         lcoreid_t  nb_extra;
2535         lcoreid_t  nb_fc;
2536         lcoreid_t  nb_lc;
2537         lcoreid_t  lc_id;
2538
2539         nb_fs = cfg->nb_fwd_streams;
2540         nb_fc = cfg->nb_fwd_lcores;
2541         if (nb_fs <= nb_fc) {
2542                 nb_fs_per_lcore = 1;
2543                 nb_extra = 0;
2544         } else {
2545                 nb_fs_per_lcore = (streamid_t) (nb_fs / nb_fc);
2546                 nb_extra = (lcoreid_t) (nb_fs % nb_fc);
2547         }
2548
2549         nb_lc = (lcoreid_t) (nb_fc - nb_extra);
2550         sm_id = 0;
2551         for (lc_id = 0; lc_id < nb_lc; lc_id++) {
2552                 fwd_lcores[lc_id]->stream_idx = sm_id;
2553                 fwd_lcores[lc_id]->stream_nb = nb_fs_per_lcore;
2554                 sm_id = (streamid_t) (sm_id + nb_fs_per_lcore);
2555         }
2556
2557         /*
2558          * Assign extra remaining streams, if any.
2559          */
2560         nb_fs_per_lcore = (streamid_t) (nb_fs_per_lcore + 1);
2561         for (lc_id = 0; lc_id < nb_extra; lc_id++) {
2562                 fwd_lcores[nb_lc + lc_id]->stream_idx = sm_id;
2563                 fwd_lcores[nb_lc + lc_id]->stream_nb = nb_fs_per_lcore;
2564                 sm_id = (streamid_t) (sm_id + nb_fs_per_lcore);
2565         }
2566 }
2567
2568 static portid_t
2569 fwd_topology_tx_port_get(portid_t rxp)
2570 {
2571         static int warning_once = 1;
2572
2573         RTE_ASSERT(rxp < cur_fwd_config.nb_fwd_ports);
2574
2575         switch (port_topology) {
2576         default:
2577         case PORT_TOPOLOGY_PAIRED:
2578                 if ((rxp & 0x1) == 0) {
2579                         if (rxp + 1 < cur_fwd_config.nb_fwd_ports)
2580                                 return rxp + 1;
2581                         if (warning_once) {
2582                                 printf("\nWarning! port-topology=paired"
2583                                        " and odd forward ports number,"
2584                                        " the last port will pair with"
2585                                        " itself.\n\n");
2586                                 warning_once = 0;
2587                         }
2588                         return rxp;
2589                 }
2590                 return rxp - 1;
2591         case PORT_TOPOLOGY_CHAINED:
2592                 return (rxp + 1) % cur_fwd_config.nb_fwd_ports;
2593         case PORT_TOPOLOGY_LOOP:
2594                 return rxp;
2595         }
2596 }
2597
2598 static void
2599 simple_fwd_config_setup(void)
2600 {
2601         portid_t i;
2602
2603         cur_fwd_config.nb_fwd_ports = (portid_t) nb_fwd_ports;
2604         cur_fwd_config.nb_fwd_streams =
2605                 (streamid_t) cur_fwd_config.nb_fwd_ports;
2606
2607         /* reinitialize forwarding streams */
2608         init_fwd_streams();
2609
2610         /*
2611          * In the simple forwarding test, the number of forwarding cores
2612          * must be lower or equal to the number of forwarding ports.
2613          */
2614         cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores;
2615         if (cur_fwd_config.nb_fwd_lcores > cur_fwd_config.nb_fwd_ports)
2616                 cur_fwd_config.nb_fwd_lcores =
2617                         (lcoreid_t) cur_fwd_config.nb_fwd_ports;
2618         setup_fwd_config_of_each_lcore(&cur_fwd_config);
2619
2620         for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++) {
2621                 fwd_streams[i]->rx_port   = fwd_ports_ids[i];
2622                 fwd_streams[i]->rx_queue  = 0;
2623                 fwd_streams[i]->tx_port   =
2624                                 fwd_ports_ids[fwd_topology_tx_port_get(i)];
2625                 fwd_streams[i]->tx_queue  = 0;
2626                 fwd_streams[i]->peer_addr = fwd_streams[i]->tx_port;
2627                 fwd_streams[i]->retry_enabled = retry_enabled;
2628         }
2629 }
2630
2631 /**
2632  * For the RSS forwarding test all streams distributed over lcores. Each stream
2633  * being composed of a RX queue to poll on a RX port for input messages,
2634  * associated with a TX queue of a TX port where to send forwarded packets.
2635  */
2636 static void
2637 rss_fwd_config_setup(void)
2638 {
2639         portid_t   rxp;
2640         portid_t   txp;
2641         queueid_t  rxq;
2642         queueid_t  nb_q;
2643         streamid_t  sm_id;
2644
2645         nb_q = nb_rxq;
2646         if (nb_q > nb_txq)
2647                 nb_q = nb_txq;
2648         cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores;
2649         cur_fwd_config.nb_fwd_ports = nb_fwd_ports;
2650         cur_fwd_config.nb_fwd_streams =
2651                 (streamid_t) (nb_q * cur_fwd_config.nb_fwd_ports);
2652
2653         if (cur_fwd_config.nb_fwd_streams < cur_fwd_config.nb_fwd_lcores)
2654                 cur_fwd_config.nb_fwd_lcores =
2655                         (lcoreid_t)cur_fwd_config.nb_fwd_streams;
2656
2657         /* reinitialize forwarding streams */
2658         init_fwd_streams();
2659
2660         setup_fwd_config_of_each_lcore(&cur_fwd_config);
2661         rxp = 0; rxq = 0;
2662         for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) {
2663                 struct fwd_stream *fs;
2664
2665                 fs = fwd_streams[sm_id];
2666                 txp = fwd_topology_tx_port_get(rxp);
2667                 fs->rx_port = fwd_ports_ids[rxp];
2668                 fs->rx_queue = rxq;
2669                 fs->tx_port = fwd_ports_ids[txp];
2670                 fs->tx_queue = rxq;
2671                 fs->peer_addr = fs->tx_port;
2672                 fs->retry_enabled = retry_enabled;
2673                 rxp++;
2674                 if (rxp < nb_fwd_ports)
2675                         continue;
2676                 rxp = 0;
2677                 rxq++;
2678         }
2679 }
2680
2681 /**
2682  * For the DCB forwarding test, each core is assigned on each traffic class.
2683  *
2684  * Each core is assigned a multi-stream, each stream being composed of
2685  * a RX queue to poll on a RX port for input messages, associated with
2686  * a TX queue of a TX port where to send forwarded packets. All RX and
2687  * TX queues are mapping to the same traffic class.
2688  * If VMDQ and DCB co-exist, each traffic class on different POOLs share
2689  * the same core
2690  */
2691 static void
2692 dcb_fwd_config_setup(void)
2693 {
2694         struct rte_eth_dcb_info rxp_dcb_info, txp_dcb_info;
2695         portid_t txp, rxp = 0;
2696         queueid_t txq, rxq = 0;
2697         lcoreid_t  lc_id;
2698         uint16_t nb_rx_queue, nb_tx_queue;
2699         uint16_t i, j, k, sm_id = 0;
2700         uint8_t tc = 0;
2701
2702         cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores;
2703         cur_fwd_config.nb_fwd_ports = nb_fwd_ports;
2704         cur_fwd_config.nb_fwd_streams =
2705                 (streamid_t) (nb_rxq * cur_fwd_config.nb_fwd_ports);
2706
2707         /* reinitialize forwarding streams */
2708         init_fwd_streams();
2709         sm_id = 0;
2710         txp = 1;
2711         /* get the dcb info on the first RX and TX ports */
2712         (void)rte_eth_dev_get_dcb_info(fwd_ports_ids[rxp], &rxp_dcb_info);
2713         (void)rte_eth_dev_get_dcb_info(fwd_ports_ids[txp], &txp_dcb_info);
2714
2715         for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) {
2716                 fwd_lcores[lc_id]->stream_nb = 0;
2717                 fwd_lcores[lc_id]->stream_idx = sm_id;
2718                 for (i = 0; i < ETH_MAX_VMDQ_POOL; i++) {
2719                         /* if the nb_queue is zero, means this tc is
2720                          * not enabled on the POOL
2721                          */
2722                         if (rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue == 0)
2723                                 break;
2724                         k = fwd_lcores[lc_id]->stream_nb +
2725                                 fwd_lcores[lc_id]->stream_idx;
2726                         rxq = rxp_dcb_info.tc_queue.tc_rxq[i][tc].base;
2727                         txq = txp_dcb_info.tc_queue.tc_txq[i][tc].base;
2728                         nb_rx_queue = txp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue;
2729                         nb_tx_queue = txp_dcb_info.tc_queue.tc_txq[i][tc].nb_queue;
2730                         for (j = 0; j < nb_rx_queue; j++) {
2731                                 struct fwd_stream *fs;
2732
2733                                 fs = fwd_streams[k + j];
2734                                 fs->rx_port = fwd_ports_ids[rxp];
2735                                 fs->rx_queue = rxq + j;
2736                                 fs->tx_port = fwd_ports_ids[txp];
2737                                 fs->tx_queue = txq + j % nb_tx_queue;
2738                                 fs->peer_addr = fs->tx_port;
2739                                 fs->retry_enabled = retry_enabled;
2740                         }
2741                         fwd_lcores[lc_id]->stream_nb +=
2742                                 rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue;
2743                 }
2744                 sm_id = (streamid_t) (sm_id + fwd_lcores[lc_id]->stream_nb);
2745
2746                 tc++;
2747                 if (tc < rxp_dcb_info.nb_tcs)
2748                         continue;
2749                 /* Restart from TC 0 on next RX port */
2750                 tc = 0;
2751                 if (numa_support && (nb_fwd_ports <= (nb_ports >> 1)))
2752                         rxp = (portid_t)
2753                                 (rxp + ((nb_ports >> 1) / nb_fwd_ports));
2754                 else
2755                         rxp++;
2756                 if (rxp >= nb_fwd_ports)
2757                         return;
2758                 /* get the dcb information on next RX and TX ports */
2759                 if ((rxp & 0x1) == 0)
2760                         txp = (portid_t) (rxp + 1);
2761                 else
2762                         txp = (portid_t) (rxp - 1);
2763                 rte_eth_dev_get_dcb_info(fwd_ports_ids[rxp], &rxp_dcb_info);
2764                 rte_eth_dev_get_dcb_info(fwd_ports_ids[txp], &txp_dcb_info);
2765         }
2766 }
2767
2768 static void
2769 icmp_echo_config_setup(void)
2770 {
2771         portid_t  rxp;
2772         queueid_t rxq;
2773         lcoreid_t lc_id;
2774         uint16_t  sm_id;
2775
2776         if ((nb_txq * nb_fwd_ports) < nb_fwd_lcores)
2777                 cur_fwd_config.nb_fwd_lcores = (lcoreid_t)
2778                         (nb_txq * nb_fwd_ports);
2779         else
2780                 cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores;
2781         cur_fwd_config.nb_fwd_ports = nb_fwd_ports;
2782         cur_fwd_config.nb_fwd_streams =
2783                 (streamid_t) (nb_rxq * cur_fwd_config.nb_fwd_ports);
2784         if (cur_fwd_config.nb_fwd_streams < cur_fwd_config.nb_fwd_lcores)
2785                 cur_fwd_config.nb_fwd_lcores =
2786                         (lcoreid_t)cur_fwd_config.nb_fwd_streams;
2787         if (verbose_level > 0) {
2788                 printf("%s fwd_cores=%d fwd_ports=%d fwd_streams=%d\n",
2789                        __FUNCTION__,
2790                        cur_fwd_config.nb_fwd_lcores,
2791                        cur_fwd_config.nb_fwd_ports,
2792                        cur_fwd_config.nb_fwd_streams);
2793         }
2794
2795         /* reinitialize forwarding streams */
2796         init_fwd_streams();
2797         setup_fwd_config_of_each_lcore(&cur_fwd_config);
2798         rxp = 0; rxq = 0;
2799         for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) {
2800                 if (verbose_level > 0)
2801                         printf("  core=%d: \n", lc_id);
2802                 for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) {
2803                         struct fwd_stream *fs;
2804                         fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id];
2805                         fs->rx_port = fwd_ports_ids[rxp];
2806                         fs->rx_queue = rxq;
2807                         fs->tx_port = fs->rx_port;
2808                         fs->tx_queue = rxq;
2809                         fs->peer_addr = fs->tx_port;
2810                         fs->retry_enabled = retry_enabled;
2811                         if (verbose_level > 0)
2812                                 printf("  stream=%d port=%d rxq=%d txq=%d\n",
2813                                        sm_id, fs->rx_port, fs->rx_queue,
2814                                        fs->tx_queue);
2815                         rxq = (queueid_t) (rxq + 1);
2816                         if (rxq == nb_rxq) {
2817                                 rxq = 0;
2818                                 rxp = (portid_t) (rxp + 1);
2819                         }
2820                 }
2821         }
2822 }
2823
2824 void
2825 fwd_config_setup(void)
2826 {
2827         cur_fwd_config.fwd_eng = cur_fwd_eng;
2828         if (strcmp(cur_fwd_eng->fwd_mode_name, "icmpecho") == 0) {
2829                 icmp_echo_config_setup();
2830                 return;
2831         }
2832
2833         if ((nb_rxq > 1) && (nb_txq > 1)){
2834                 if (dcb_config)
2835                         dcb_fwd_config_setup();
2836                 else
2837                         rss_fwd_config_setup();
2838         }
2839         else
2840                 simple_fwd_config_setup();
2841 }
2842
2843 static const char *
2844 mp_alloc_to_str(uint8_t mode)
2845 {
2846         switch (mode) {
2847         case MP_ALLOC_NATIVE:
2848                 return "native";
2849         case MP_ALLOC_ANON:
2850                 return "anon";
2851         case MP_ALLOC_XMEM:
2852                 return "xmem";
2853         case MP_ALLOC_XMEM_HUGE:
2854                 return "xmemhuge";
2855         case MP_ALLOC_XBUF:
2856                 return "xbuf";
2857         default:
2858                 return "invalid";
2859         }
2860 }
2861
2862 void
2863 pkt_fwd_config_display(struct fwd_config *cfg)
2864 {
2865         struct fwd_stream *fs;
2866         lcoreid_t  lc_id;
2867         streamid_t sm_id;
2868
2869         printf("%s packet forwarding%s - ports=%d - cores=%d - streams=%d - "
2870                 "NUMA support %s, MP allocation mode: %s\n",
2871                 cfg->fwd_eng->fwd_mode_name,
2872                 retry_enabled == 0 ? "" : " with retry",
2873                 cfg->nb_fwd_ports, cfg->nb_fwd_lcores, cfg->nb_fwd_streams,
2874                 numa_support == 1 ? "enabled" : "disabled",
2875                 mp_alloc_to_str(mp_alloc_type));
2876
2877         if (retry_enabled)
2878                 printf("TX retry num: %u, delay between TX retries: %uus\n",
2879                         burst_tx_retry_num, burst_tx_delay_time);
2880         for (lc_id = 0; lc_id < cfg->nb_fwd_lcores; lc_id++) {
2881                 printf("Logical Core %u (socket %u) forwards packets on "
2882                        "%d streams:",
2883                        fwd_lcores_cpuids[lc_id],
2884                        rte_lcore_to_socket_id(fwd_lcores_cpuids[lc_id]),
2885                        fwd_lcores[lc_id]->stream_nb);
2886                 for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++) {
2887                         fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id];
2888                         printf("\n  RX P=%d/Q=%d (socket %u) -> TX "
2889                                "P=%d/Q=%d (socket %u) ",
2890                                fs->rx_port, fs->rx_queue,
2891                                ports[fs->rx_port].socket_id,
2892                                fs->tx_port, fs->tx_queue,
2893                                ports[fs->tx_port].socket_id);
2894                         print_ethaddr("peer=",
2895                                       &peer_eth_addrs[fs->peer_addr]);
2896                 }
2897                 printf("\n");
2898         }
2899         printf("\n");
2900 }
2901
2902 void
2903 set_fwd_eth_peer(portid_t port_id, char *peer_addr)
2904 {
2905         struct rte_ether_addr new_peer_addr;
2906         if (!rte_eth_dev_is_valid_port(port_id)) {
2907                 printf("Error: Invalid port number %i\n", port_id);
2908                 return;
2909         }
2910         if (rte_ether_unformat_addr(peer_addr, &new_peer_addr) < 0) {
2911                 printf("Error: Invalid ethernet address: %s\n", peer_addr);
2912                 return;
2913         }
2914         peer_eth_addrs[port_id] = new_peer_addr;
2915 }
2916
2917 int
2918 set_fwd_lcores_list(unsigned int *lcorelist, unsigned int nb_lc)
2919 {
2920         unsigned int i;
2921         unsigned int lcore_cpuid;
2922         int record_now;
2923
2924         record_now = 0;
2925  again:
2926         for (i = 0; i < nb_lc; i++) {
2927                 lcore_cpuid = lcorelist[i];
2928                 if (! rte_lcore_is_enabled(lcore_cpuid)) {
2929                         printf("lcore %u not enabled\n", lcore_cpuid);
2930                         return -1;
2931                 }
2932                 if (lcore_cpuid == rte_get_master_lcore()) {
2933                         printf("lcore %u cannot be masked on for running "
2934                                "packet forwarding, which is the master lcore "
2935                                "and reserved for command line parsing only\n",
2936                                lcore_cpuid);
2937                         return -1;
2938                 }
2939                 if (record_now)
2940                         fwd_lcores_cpuids[i] = lcore_cpuid;
2941         }
2942         if (record_now == 0) {
2943                 record_now = 1;
2944                 goto again;
2945         }
2946         nb_cfg_lcores = (lcoreid_t) nb_lc;
2947         if (nb_fwd_lcores != (lcoreid_t) nb_lc) {
2948                 printf("previous number of forwarding cores %u - changed to "
2949                        "number of configured cores %u\n",
2950                        (unsigned int) nb_fwd_lcores, nb_lc);
2951                 nb_fwd_lcores = (lcoreid_t) nb_lc;
2952         }
2953
2954         return 0;
2955 }
2956
2957 int
2958 set_fwd_lcores_mask(uint64_t lcoremask)
2959 {
2960         unsigned int lcorelist[64];
2961         unsigned int nb_lc;
2962         unsigned int i;
2963
2964         if (lcoremask == 0) {
2965                 printf("Invalid NULL mask of cores\n");
2966                 return -1;
2967         }
2968         nb_lc = 0;
2969         for (i = 0; i < 64; i++) {
2970                 if (! ((uint64_t)(1ULL << i) & lcoremask))
2971                         continue;
2972                 lcorelist[nb_lc++] = i;
2973         }
2974         return set_fwd_lcores_list(lcorelist, nb_lc);
2975 }
2976
2977 void
2978 set_fwd_lcores_number(uint16_t nb_lc)
2979 {
2980         if (nb_lc > nb_cfg_lcores) {
2981                 printf("nb fwd cores %u > %u (max. number of configured "
2982                        "lcores) - ignored\n",
2983                        (unsigned int) nb_lc, (unsigned int) nb_cfg_lcores);
2984                 return;
2985         }
2986         nb_fwd_lcores = (lcoreid_t) nb_lc;
2987         printf("Number of forwarding cores set to %u\n",
2988                (unsigned int) nb_fwd_lcores);
2989 }
2990
2991 void
2992 set_fwd_ports_list(unsigned int *portlist, unsigned int nb_pt)
2993 {
2994         unsigned int i;
2995         portid_t port_id;
2996         int record_now;
2997
2998         record_now = 0;
2999  again:
3000         for (i = 0; i < nb_pt; i++) {
3001                 port_id = (portid_t) portlist[i];
3002                 if (port_id_is_invalid(port_id, ENABLED_WARN))
3003                         return;
3004                 if (record_now)
3005                         fwd_ports_ids[i] = port_id;
3006         }
3007         if (record_now == 0) {
3008                 record_now = 1;
3009                 goto again;
3010         }
3011         nb_cfg_ports = (portid_t) nb_pt;
3012         if (nb_fwd_ports != (portid_t) nb_pt) {
3013                 printf("previous number of forwarding ports %u - changed to "
3014                        "number of configured ports %u\n",
3015                        (unsigned int) nb_fwd_ports, nb_pt);
3016                 nb_fwd_ports = (portid_t) nb_pt;
3017         }
3018 }
3019
3020 /**
3021  * Parse the user input and obtain the list of forwarding ports
3022  *
3023  * @param[in] list
3024  *   String containing the user input. User can specify
3025  *   in these formats 1,3,5 or 1-3 or 1-2,5 or 3,5-6.
3026  *   For example, if the user wants to use all the available
3027  *   4 ports in his system, then the input can be 0-3 or 0,1,2,3.
3028  *   If the user wants to use only the ports 1,2 then the input
3029  *   is 1,2.
3030  *   valid characters are '-' and ','
3031  * @param[out] values
3032  *   This array will be filled with a list of port IDs
3033  *   based on the user input
3034  *   Note that duplicate entries are discarded and only the first
3035  *   count entries in this array are port IDs and all the rest
3036  *   will contain default values
3037  * @param[in] maxsize
3038  *   This parameter denotes 2 things
3039  *   1) Number of elements in the values array
3040  *   2) Maximum value of each element in the values array
3041  * @return
3042  *   On success, returns total count of parsed port IDs
3043  *   On failure, returns 0
3044  */
3045 static unsigned int
3046 parse_port_list(const char *list, unsigned int *values, unsigned int maxsize)
3047 {
3048         unsigned int count = 0;
3049         char *end = NULL;
3050         int min, max;
3051         int value, i;
3052         unsigned int marked[maxsize];
3053
3054         if (list == NULL || values == NULL)
3055                 return 0;
3056
3057         for (i = 0; i < (int)maxsize; i++)
3058                 marked[i] = 0;
3059
3060         min = INT_MAX;
3061
3062         do {
3063                 /*Remove the blank spaces if any*/
3064                 while (isblank(*list))
3065                         list++;
3066                 if (*list == '\0')
3067                         break;
3068                 errno = 0;
3069                 value = strtol(list, &end, 10);
3070                 if (errno || end == NULL)
3071                         return 0;
3072                 if (value < 0 || value >= (int)maxsize)
3073                         return 0;
3074                 while (isblank(*end))
3075                         end++;
3076                 if (*end == '-' && min == INT_MAX) {
3077                         min = value;
3078                 } else if ((*end == ',') || (*end == '\0')) {
3079                         max = value;
3080                         if (min == INT_MAX)
3081                                 min = value;
3082                         for (i = min; i <= max; i++) {
3083                                 if (count < maxsize) {
3084                                         if (marked[i])
3085                                                 continue;
3086                                         values[count] = i;
3087                                         marked[i] = 1;
3088                                         count++;
3089                                 }
3090                         }
3091                         min = INT_MAX;
3092                 } else
3093                         return 0;
3094                 list = end + 1;
3095         } while (*end != '\0');
3096
3097         return count;
3098 }
3099
3100 void
3101 parse_fwd_portlist(const char *portlist)
3102 {
3103         unsigned int portcount;
3104         unsigned int portindex[RTE_MAX_ETHPORTS];
3105         unsigned int i, valid_port_count = 0;
3106
3107         portcount = parse_port_list(portlist, portindex, RTE_MAX_ETHPORTS);
3108         if (!portcount)
3109                 rte_exit(EXIT_FAILURE, "Invalid fwd port list\n");
3110
3111         /*
3112          * Here we verify the validity of the ports
3113          * and thereby calculate the total number of
3114          * valid ports
3115          */
3116         for (i = 0; i < portcount && i < RTE_DIM(portindex); i++) {
3117                 if (rte_eth_dev_is_valid_port(portindex[i])) {
3118                         portindex[valid_port_count] = portindex[i];
3119                         valid_port_count++;
3120                 }
3121         }
3122
3123         set_fwd_ports_list(portindex, valid_port_count);
3124 }
3125
3126 void
3127 set_fwd_ports_mask(uint64_t portmask)
3128 {
3129         unsigned int portlist[64];
3130         unsigned int nb_pt;
3131         unsigned int i;
3132
3133         if (portmask == 0) {
3134                 printf("Invalid NULL mask of ports\n");
3135                 return;
3136         }
3137         nb_pt = 0;
3138         RTE_ETH_FOREACH_DEV(i) {
3139                 if (! ((uint64_t)(1ULL << i) & portmask))
3140                         continue;
3141                 portlist[nb_pt++] = i;
3142         }
3143         set_fwd_ports_list(portlist, nb_pt);
3144 }
3145
3146 void
3147 set_fwd_ports_number(uint16_t nb_pt)
3148 {
3149         if (nb_pt > nb_cfg_ports) {
3150                 printf("nb fwd ports %u > %u (number of configured "
3151                        "ports) - ignored\n",
3152                        (unsigned int) nb_pt, (unsigned int) nb_cfg_ports);
3153                 return;
3154         }
3155         nb_fwd_ports = (portid_t) nb_pt;
3156         printf("Number of forwarding ports set to %u\n",
3157                (unsigned int) nb_fwd_ports);
3158 }
3159
3160 int
3161 port_is_forwarding(portid_t port_id)
3162 {
3163         unsigned int i;
3164
3165         if (port_id_is_invalid(port_id, ENABLED_WARN))
3166                 return -1;
3167
3168         for (i = 0; i < nb_fwd_ports; i++) {
3169                 if (fwd_ports_ids[i] == port_id)
3170                         return 1;
3171         }
3172
3173         return 0;
3174 }
3175
3176 void
3177 set_nb_pkt_per_burst(uint16_t nb)
3178 {
3179         if (nb > MAX_PKT_BURST) {
3180                 printf("nb pkt per burst: %u > %u (maximum packet per burst) "
3181                        " ignored\n",
3182                        (unsigned int) nb, (unsigned int) MAX_PKT_BURST);
3183                 return;
3184         }
3185         nb_pkt_per_burst = nb;
3186         printf("Number of packets per burst set to %u\n",
3187                (unsigned int) nb_pkt_per_burst);
3188 }
3189
3190 static const char *
3191 tx_split_get_name(enum tx_pkt_split split)
3192 {
3193         uint32_t i;
3194
3195         for (i = 0; i != RTE_DIM(tx_split_name); i++) {
3196                 if (tx_split_name[i].split == split)
3197                         return tx_split_name[i].name;
3198         }
3199         return NULL;
3200 }
3201
3202 void
3203 set_tx_pkt_split(const char *name)
3204 {
3205         uint32_t i;
3206
3207         for (i = 0; i != RTE_DIM(tx_split_name); i++) {
3208                 if (strcmp(tx_split_name[i].name, name) == 0) {
3209                         tx_pkt_split = tx_split_name[i].split;
3210                         return;
3211                 }
3212         }
3213         printf("unknown value: \"%s\"\n", name);
3214 }
3215
3216 int
3217 parse_fec_mode(const char *name, uint32_t *mode)
3218 {
3219         uint8_t i;
3220
3221         for (i = 0; i < RTE_DIM(fec_mode_name); i++) {
3222                 if (strcmp(fec_mode_name[i].name, name) == 0) {
3223                         *mode = RTE_ETH_FEC_MODE_TO_CAPA(fec_mode_name[i].mode);
3224                         return 0;
3225                 }
3226         }
3227         return -1;
3228 }
3229
3230 void
3231 show_fec_capability(unsigned int num, struct rte_eth_fec_capa *speed_fec_capa)
3232 {
3233         unsigned int i, j;
3234
3235         printf("FEC capabilities:\n");
3236
3237         for (i = 0; i < num; i++) {
3238                 printf("%s : ",
3239                         rte_eth_link_speed_to_str(speed_fec_capa[i].speed));
3240
3241                 for (j = RTE_ETH_FEC_AUTO; j < RTE_DIM(fec_mode_name); j++) {
3242                         if (RTE_ETH_FEC_MODE_TO_CAPA(j) &
3243                                                 speed_fec_capa[i].capa)
3244                                 printf("%s ", fec_mode_name[j].name);
3245                 }
3246                 printf("\n");
3247         }
3248 }
3249
3250 void
3251 show_tx_pkt_segments(void)
3252 {
3253         uint32_t i, n;
3254         const char *split;
3255
3256         n = tx_pkt_nb_segs;
3257         split = tx_split_get_name(tx_pkt_split);
3258
3259         printf("Number of segments: %u\n", n);
3260         printf("Segment sizes: ");
3261         for (i = 0; i != n - 1; i++)
3262                 printf("%hu,", tx_pkt_seg_lengths[i]);
3263         printf("%hu\n", tx_pkt_seg_lengths[i]);
3264         printf("Split packet: %s\n", split);
3265 }
3266
3267 static bool
3268 nb_segs_is_invalid(unsigned int nb_segs)
3269 {
3270         uint16_t ring_size;
3271         uint16_t queue_id;
3272         uint16_t port_id;
3273         int ret;
3274
3275         RTE_ETH_FOREACH_DEV(port_id) {
3276                 for (queue_id = 0; queue_id < nb_txq; queue_id++) {
3277                         ret = get_tx_ring_size(port_id, queue_id, &ring_size);
3278
3279                         if (ret)
3280                                 return true;
3281
3282                         if (ring_size < nb_segs) {
3283                                 printf("nb segments per TX packets=%u >= "
3284                                        "TX queue(%u) ring_size=%u - ignored\n",
3285                                        nb_segs, queue_id, ring_size);
3286                                 return true;
3287                         }
3288                 }
3289         }
3290
3291         return false;
3292 }
3293
3294 void
3295 set_tx_pkt_segments(unsigned *seg_lengths, unsigned nb_segs)
3296 {
3297         uint16_t tx_pkt_len;
3298         unsigned i;
3299
3300         if (nb_segs_is_invalid(nb_segs))
3301                 return;
3302
3303         /*
3304          * Check that each segment length is greater or equal than
3305          * the mbuf data sise.
3306          * Check also that the total packet length is greater or equal than the
3307          * size of an empty UDP/IP packet (sizeof(struct rte_ether_hdr) +
3308          * 20 + 8).
3309          */
3310         tx_pkt_len = 0;
3311         for (i = 0; i < nb_segs; i++) {
3312                 if (seg_lengths[i] > (unsigned) mbuf_data_size) {
3313                         printf("length[%u]=%u > mbuf_data_size=%u - give up\n",
3314                                i, seg_lengths[i], (unsigned) mbuf_data_size);
3315                         return;
3316                 }
3317                 tx_pkt_len = (uint16_t)(tx_pkt_len + seg_lengths[i]);
3318         }
3319         if (tx_pkt_len < (sizeof(struct rte_ether_hdr) + 20 + 8)) {
3320                 printf("total packet length=%u < %d - give up\n",
3321                                 (unsigned) tx_pkt_len,
3322                                 (int)(sizeof(struct rte_ether_hdr) + 20 + 8));
3323                 return;
3324         }
3325
3326         for (i = 0; i < nb_segs; i++)
3327                 tx_pkt_seg_lengths[i] = (uint16_t) seg_lengths[i];
3328
3329         tx_pkt_length  = tx_pkt_len;
3330         tx_pkt_nb_segs = (uint8_t) nb_segs;
3331 }
3332
3333 void
3334 show_tx_pkt_times(void)
3335 {
3336         printf("Interburst gap: %u\n", tx_pkt_times_inter);
3337         printf("Intraburst gap: %u\n", tx_pkt_times_intra);
3338 }
3339
3340 void
3341 set_tx_pkt_times(unsigned int *tx_times)
3342 {
3343         uint16_t port_id;
3344         int offload_found = 0;
3345         int offset;
3346         int flag;
3347
3348         static const struct rte_mbuf_dynfield desc_offs = {
3349                 .name = RTE_MBUF_DYNFIELD_TIMESTAMP_NAME,
3350                 .size = sizeof(uint64_t),
3351                 .align = __alignof__(uint64_t),
3352         };
3353         static const struct rte_mbuf_dynflag desc_flag = {
3354                 .name = RTE_MBUF_DYNFLAG_TX_TIMESTAMP_NAME,
3355         };
3356
3357         RTE_ETH_FOREACH_DEV(port_id) {
3358                 struct rte_eth_dev_info dev_info = { 0 };
3359                 int ret;
3360
3361                 ret = rte_eth_dev_info_get(port_id, &dev_info);
3362                 if (ret == 0 && dev_info.tx_offload_capa &
3363                                 DEV_TX_OFFLOAD_SEND_ON_TIMESTAMP) {
3364                         offload_found = 1;
3365                         break;
3366                 }
3367         }
3368         if (!offload_found) {
3369                 printf("No device supporting Tx timestamp scheduling found, "
3370                        "dynamic flag and field not registered\n");
3371                 return;
3372         }
3373         offset = rte_mbuf_dynfield_register(&desc_offs);
3374         if (offset < 0 && rte_errno != EEXIST)
3375                 printf("Dynamic timestamp field registration error: %d",
3376                        rte_errno);
3377         flag = rte_mbuf_dynflag_register(&desc_flag);
3378         if (flag < 0 && rte_errno != EEXIST)
3379                 printf("Dynamic timestamp flag registration error: %d",
3380                        rte_errno);
3381         tx_pkt_times_inter = tx_times[0];
3382         tx_pkt_times_intra = tx_times[1];
3383 }
3384
3385 void
3386 setup_gro(const char *onoff, portid_t port_id)
3387 {
3388         if (!rte_eth_dev_is_valid_port(port_id)) {
3389                 printf("invalid port id %u\n", port_id);
3390                 return;
3391         }
3392         if (test_done == 0) {
3393                 printf("Before enable/disable GRO,"
3394                                 " please stop forwarding first\n");
3395                 return;
3396         }
3397         if (strcmp(onoff, "on") == 0) {
3398                 if (gro_ports[port_id].enable != 0) {
3399                         printf("Port %u has enabled GRO. Please"
3400                                         " disable GRO first\n", port_id);
3401                         return;
3402                 }
3403                 if (gro_flush_cycles == GRO_DEFAULT_FLUSH_CYCLES) {
3404                         gro_ports[port_id].param.gro_types = RTE_GRO_TCP_IPV4;
3405                         gro_ports[port_id].param.max_flow_num =
3406                                 GRO_DEFAULT_FLOW_NUM;
3407                         gro_ports[port_id].param.max_item_per_flow =
3408                                 GRO_DEFAULT_ITEM_NUM_PER_FLOW;
3409                 }
3410                 gro_ports[port_id].enable = 1;
3411         } else {
3412                 if (gro_ports[port_id].enable == 0) {
3413                         printf("Port %u has disabled GRO\n", port_id);
3414                         return;
3415                 }
3416                 gro_ports[port_id].enable = 0;
3417         }
3418 }
3419
3420 void
3421 setup_gro_flush_cycles(uint8_t cycles)
3422 {
3423         if (test_done == 0) {
3424                 printf("Before change flush interval for GRO,"
3425                                 " please stop forwarding first.\n");
3426                 return;
3427         }
3428
3429         if (cycles > GRO_MAX_FLUSH_CYCLES || cycles <
3430                         GRO_DEFAULT_FLUSH_CYCLES) {
3431                 printf("The flushing cycle be in the range"
3432                                 " of 1 to %u. Revert to the default"
3433                                 " value %u.\n",
3434                                 GRO_MAX_FLUSH_CYCLES,
3435                                 GRO_DEFAULT_FLUSH_CYCLES);
3436                 cycles = GRO_DEFAULT_FLUSH_CYCLES;
3437         }
3438
3439         gro_flush_cycles = cycles;
3440 }
3441
3442 void
3443 show_gro(portid_t port_id)
3444 {
3445         struct rte_gro_param *param;
3446         uint32_t max_pkts_num;
3447
3448         param = &gro_ports[port_id].param;
3449
3450         if (!rte_eth_dev_is_valid_port(port_id)) {
3451                 printf("Invalid port id %u.\n", port_id);
3452                 return;
3453         }
3454         if (gro_ports[port_id].enable) {
3455                 printf("GRO type: TCP/IPv4\n");
3456                 if (gro_flush_cycles == GRO_DEFAULT_FLUSH_CYCLES) {
3457                         max_pkts_num = param->max_flow_num *
3458                                 param->max_item_per_flow;
3459                 } else
3460                         max_pkts_num = MAX_PKT_BURST * GRO_MAX_FLUSH_CYCLES;
3461                 printf("Max number of packets to perform GRO: %u\n",
3462                                 max_pkts_num);
3463                 printf("Flushing cycles: %u\n", gro_flush_cycles);
3464         } else
3465                 printf("Port %u doesn't enable GRO.\n", port_id);
3466 }
3467
3468 void
3469 setup_gso(const char *mode, portid_t port_id)
3470 {
3471         if (!rte_eth_dev_is_valid_port(port_id)) {
3472                 printf("invalid port id %u\n", port_id);
3473                 return;
3474         }
3475         if (strcmp(mode, "on") == 0) {
3476                 if (test_done == 0) {
3477                         printf("before enabling GSO,"
3478                                         " please stop forwarding first\n");
3479                         return;
3480                 }
3481                 gso_ports[port_id].enable = 1;
3482         } else if (strcmp(mode, "off") == 0) {
3483                 if (test_done == 0) {
3484                         printf("before disabling GSO,"
3485                                         " please stop forwarding first\n");
3486                         return;
3487                 }
3488                 gso_ports[port_id].enable = 0;
3489         }
3490 }
3491
3492 char*
3493 list_pkt_forwarding_modes(void)
3494 {
3495         static char fwd_modes[128] = "";
3496         const char *separator = "|";
3497         struct fwd_engine *fwd_eng;
3498         unsigned i = 0;
3499
3500         if (strlen (fwd_modes) == 0) {
3501                 while ((fwd_eng = fwd_engines[i++]) != NULL) {
3502                         strncat(fwd_modes, fwd_eng->fwd_mode_name,
3503                                         sizeof(fwd_modes) - strlen(fwd_modes) - 1);
3504                         strncat(fwd_modes, separator,
3505                                         sizeof(fwd_modes) - strlen(fwd_modes) - 1);
3506                 }
3507                 fwd_modes[strlen(fwd_modes) - strlen(separator)] = '\0';
3508         }
3509
3510         return fwd_modes;
3511 }
3512
3513 char*
3514 list_pkt_forwarding_retry_modes(void)
3515 {
3516         static char fwd_modes[128] = "";
3517         const char *separator = "|";
3518         struct fwd_engine *fwd_eng;
3519         unsigned i = 0;
3520
3521         if (strlen(fwd_modes) == 0) {
3522                 while ((fwd_eng = fwd_engines[i++]) != NULL) {
3523                         if (fwd_eng == &rx_only_engine)
3524                                 continue;
3525                         strncat(fwd_modes, fwd_eng->fwd_mode_name,
3526                                         sizeof(fwd_modes) -
3527                                         strlen(fwd_modes) - 1);
3528                         strncat(fwd_modes, separator,
3529                                         sizeof(fwd_modes) -
3530                                         strlen(fwd_modes) - 1);
3531                 }
3532                 fwd_modes[strlen(fwd_modes) - strlen(separator)] = '\0';
3533         }
3534
3535         return fwd_modes;
3536 }
3537
3538 void
3539 set_pkt_forwarding_mode(const char *fwd_mode_name)
3540 {
3541         struct fwd_engine *fwd_eng;
3542         unsigned i;
3543
3544         i = 0;
3545         while ((fwd_eng = fwd_engines[i]) != NULL) {
3546                 if (! strcmp(fwd_eng->fwd_mode_name, fwd_mode_name)) {
3547                         printf("Set %s packet forwarding mode%s\n",
3548                                fwd_mode_name,
3549                                retry_enabled == 0 ? "" : " with retry");
3550                         cur_fwd_eng = fwd_eng;
3551                         return;
3552                 }
3553                 i++;
3554         }
3555         printf("Invalid %s packet forwarding mode\n", fwd_mode_name);
3556 }
3557
3558 void
3559 add_rx_dump_callbacks(portid_t portid)
3560 {
3561         struct rte_eth_dev_info dev_info;
3562         uint16_t queue;
3563         int ret;
3564
3565         if (port_id_is_invalid(portid, ENABLED_WARN))
3566                 return;
3567
3568         ret = eth_dev_info_get_print_err(portid, &dev_info);
3569         if (ret != 0)
3570                 return;
3571
3572         for (queue = 0; queue < dev_info.nb_rx_queues; queue++)
3573                 if (!ports[portid].rx_dump_cb[queue])
3574                         ports[portid].rx_dump_cb[queue] =
3575                                 rte_eth_add_rx_callback(portid, queue,
3576                                         dump_rx_pkts, NULL);
3577 }
3578
3579 void
3580 add_tx_dump_callbacks(portid_t portid)
3581 {
3582         struct rte_eth_dev_info dev_info;
3583         uint16_t queue;
3584         int ret;
3585
3586         if (port_id_is_invalid(portid, ENABLED_WARN))
3587                 return;
3588
3589         ret = eth_dev_info_get_print_err(portid, &dev_info);
3590         if (ret != 0)
3591                 return;
3592
3593         for (queue = 0; queue < dev_info.nb_tx_queues; queue++)
3594                 if (!ports[portid].tx_dump_cb[queue])
3595                         ports[portid].tx_dump_cb[queue] =
3596                                 rte_eth_add_tx_callback(portid, queue,
3597                                                         dump_tx_pkts, NULL);
3598 }
3599
3600 void
3601 remove_rx_dump_callbacks(portid_t portid)
3602 {
3603         struct rte_eth_dev_info dev_info;
3604         uint16_t queue;
3605         int ret;
3606
3607         if (port_id_is_invalid(portid, ENABLED_WARN))
3608                 return;
3609
3610         ret = eth_dev_info_get_print_err(portid, &dev_info);
3611         if (ret != 0)
3612                 return;
3613
3614         for (queue = 0; queue < dev_info.nb_rx_queues; queue++)
3615                 if (ports[portid].rx_dump_cb[queue]) {
3616                         rte_eth_remove_rx_callback(portid, queue,
3617                                 ports[portid].rx_dump_cb[queue]);
3618                         ports[portid].rx_dump_cb[queue] = NULL;
3619                 }
3620 }
3621
3622 void
3623 remove_tx_dump_callbacks(portid_t portid)
3624 {
3625         struct rte_eth_dev_info dev_info;
3626         uint16_t queue;
3627         int ret;
3628
3629         if (port_id_is_invalid(portid, ENABLED_WARN))
3630                 return;
3631
3632         ret = eth_dev_info_get_print_err(portid, &dev_info);
3633         if (ret != 0)
3634                 return;
3635
3636         for (queue = 0; queue < dev_info.nb_tx_queues; queue++)
3637                 if (ports[portid].tx_dump_cb[queue]) {
3638                         rte_eth_remove_tx_callback(portid, queue,
3639                                 ports[portid].tx_dump_cb[queue]);
3640                         ports[portid].tx_dump_cb[queue] = NULL;
3641                 }
3642 }
3643
3644 void
3645 configure_rxtx_dump_callbacks(uint16_t verbose)
3646 {
3647         portid_t portid;
3648
3649 #ifndef RTE_ETHDEV_RXTX_CALLBACKS
3650                 TESTPMD_LOG(ERR, "setting rxtx callbacks is not enabled\n");
3651                 return;
3652 #endif
3653
3654         RTE_ETH_FOREACH_DEV(portid)
3655         {
3656                 if (verbose == 1 || verbose > 2)
3657                         add_rx_dump_callbacks(portid);
3658                 else
3659                         remove_rx_dump_callbacks(portid);
3660                 if (verbose >= 2)
3661                         add_tx_dump_callbacks(portid);
3662                 else
3663                         remove_tx_dump_callbacks(portid);
3664         }
3665 }
3666
3667 void
3668 set_verbose_level(uint16_t vb_level)
3669 {
3670         printf("Change verbose level from %u to %u\n",
3671                (unsigned int) verbose_level, (unsigned int) vb_level);
3672         verbose_level = vb_level;
3673         configure_rxtx_dump_callbacks(verbose_level);
3674 }
3675
3676 void
3677 vlan_extend_set(portid_t port_id, int on)
3678 {
3679         int diag;
3680         int vlan_offload;
3681         uint64_t port_rx_offloads = ports[port_id].dev_conf.rxmode.offloads;
3682
3683         if (port_id_is_invalid(port_id, ENABLED_WARN))
3684                 return;
3685
3686         vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
3687
3688         if (on) {
3689                 vlan_offload |= ETH_VLAN_EXTEND_OFFLOAD;
3690                 port_rx_offloads |= DEV_RX_OFFLOAD_VLAN_EXTEND;
3691         } else {
3692                 vlan_offload &= ~ETH_VLAN_EXTEND_OFFLOAD;
3693                 port_rx_offloads &= ~DEV_RX_OFFLOAD_VLAN_EXTEND;
3694         }
3695
3696         diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload);
3697         if (diag < 0) {
3698                 printf("rx_vlan_extend_set(port_pi=%d, on=%d) failed "
3699                "diag=%d\n", port_id, on, diag);
3700                 return;
3701         }
3702         ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads;
3703 }
3704
3705 void
3706 rx_vlan_strip_set(portid_t port_id, int on)
3707 {
3708         int diag;
3709         int vlan_offload;
3710         uint64_t port_rx_offloads = ports[port_id].dev_conf.rxmode.offloads;
3711
3712         if (port_id_is_invalid(port_id, ENABLED_WARN))
3713                 return;
3714
3715         vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
3716
3717         if (on) {
3718                 vlan_offload |= ETH_VLAN_STRIP_OFFLOAD;
3719                 port_rx_offloads |= DEV_RX_OFFLOAD_VLAN_STRIP;
3720         } else {
3721                 vlan_offload &= ~ETH_VLAN_STRIP_OFFLOAD;
3722                 port_rx_offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP;
3723         }
3724
3725         diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload);
3726         if (diag < 0) {
3727                 printf("rx_vlan_strip_set(port_pi=%d, on=%d) failed "
3728                "diag=%d\n", port_id, on, diag);
3729                 return;
3730         }
3731         ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads;
3732 }
3733
3734 void
3735 rx_vlan_strip_set_on_queue(portid_t port_id, uint16_t queue_id, int on)
3736 {
3737         int diag;
3738
3739         if (port_id_is_invalid(port_id, ENABLED_WARN))
3740                 return;
3741
3742         diag = rte_eth_dev_set_vlan_strip_on_queue(port_id, queue_id, on);
3743         if (diag < 0)
3744                 printf("rx_vlan_strip_set_on_queue(port_pi=%d, queue_id=%d, on=%d) failed "
3745                "diag=%d\n", port_id, queue_id, on, diag);
3746 }
3747
3748 void
3749 rx_vlan_filter_set(portid_t port_id, int on)
3750 {
3751         int diag;
3752         int vlan_offload;
3753         uint64_t port_rx_offloads = ports[port_id].dev_conf.rxmode.offloads;
3754
3755         if (port_id_is_invalid(port_id, ENABLED_WARN))
3756                 return;
3757
3758         vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
3759
3760         if (on) {
3761                 vlan_offload |= ETH_VLAN_FILTER_OFFLOAD;
3762                 port_rx_offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
3763         } else {
3764                 vlan_offload &= ~ETH_VLAN_FILTER_OFFLOAD;
3765                 port_rx_offloads &= ~DEV_RX_OFFLOAD_VLAN_FILTER;
3766         }
3767
3768         diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload);
3769         if (diag < 0) {
3770                 printf("rx_vlan_filter_set(port_pi=%d, on=%d) failed "
3771                "diag=%d\n", port_id, on, diag);
3772                 return;
3773         }
3774         ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads;
3775 }
3776
3777 void
3778 rx_vlan_qinq_strip_set(portid_t port_id, int on)
3779 {
3780         int diag;
3781         int vlan_offload;
3782         uint64_t port_rx_offloads = ports[port_id].dev_conf.rxmode.offloads;
3783
3784         if (port_id_is_invalid(port_id, ENABLED_WARN))
3785                 return;
3786
3787         vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
3788
3789         if (on) {
3790                 vlan_offload |= ETH_QINQ_STRIP_OFFLOAD;
3791                 port_rx_offloads |= DEV_RX_OFFLOAD_QINQ_STRIP;
3792         } else {
3793                 vlan_offload &= ~ETH_QINQ_STRIP_OFFLOAD;
3794                 port_rx_offloads &= ~DEV_RX_OFFLOAD_QINQ_STRIP;
3795         }
3796
3797         diag = rte_eth_dev_set_vlan_offload(port_id, vlan_offload);
3798         if (diag < 0) {
3799                 printf("%s(port_pi=%d, on=%d) failed "
3800                "diag=%d\n", __func__, port_id, on, diag);
3801                 return;
3802         }
3803         ports[port_id].dev_conf.rxmode.offloads = port_rx_offloads;
3804 }
3805
3806 int
3807 rx_vft_set(portid_t port_id, uint16_t vlan_id, int on)
3808 {
3809         int diag;
3810
3811         if (port_id_is_invalid(port_id, ENABLED_WARN))
3812                 return 1;
3813         if (vlan_id_is_invalid(vlan_id))
3814                 return 1;
3815         diag = rte_eth_dev_vlan_filter(port_id, vlan_id, on);
3816         if (diag == 0)
3817                 return 0;
3818         printf("rte_eth_dev_vlan_filter(port_pi=%d, vlan_id=%d, on=%d) failed "
3819                "diag=%d\n",
3820                port_id, vlan_id, on, diag);
3821         return -1;
3822 }
3823
3824 void
3825 rx_vlan_all_filter_set(portid_t port_id, int on)
3826 {
3827         uint16_t vlan_id;
3828
3829         if (port_id_is_invalid(port_id, ENABLED_WARN))
3830                 return;
3831         for (vlan_id = 0; vlan_id < 4096; vlan_id++) {
3832                 if (rx_vft_set(port_id, vlan_id, on))
3833                         break;
3834         }
3835 }
3836
3837 void
3838 vlan_tpid_set(portid_t port_id, enum rte_vlan_type vlan_type, uint16_t tp_id)
3839 {
3840         int diag;
3841
3842         if (port_id_is_invalid(port_id, ENABLED_WARN))
3843                 return;
3844
3845         diag = rte_eth_dev_set_vlan_ether_type(port_id, vlan_type, tp_id);
3846         if (diag == 0)
3847                 return;
3848
3849         printf("tx_vlan_tpid_set(port_pi=%d, vlan_type=%d, tpid=%d) failed "
3850                "diag=%d\n",
3851                port_id, vlan_type, tp_id, diag);
3852 }
3853
3854 void
3855 tx_vlan_set(portid_t port_id, uint16_t vlan_id)
3856 {
3857         struct rte_eth_dev_info dev_info;
3858         int ret;
3859
3860         if (vlan_id_is_invalid(vlan_id))
3861                 return;
3862
3863         if (ports[port_id].dev_conf.txmode.offloads &
3864             DEV_TX_OFFLOAD_QINQ_INSERT) {
3865                 printf("Error, as QinQ has been enabled.\n");
3866                 return;
3867         }
3868
3869         ret = eth_dev_info_get_print_err(port_id, &dev_info);
3870         if (ret != 0)
3871                 return;
3872
3873         if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_VLAN_INSERT) == 0) {
3874                 printf("Error: vlan insert is not supported by port %d\n",
3875                         port_id);
3876                 return;
3877         }
3878
3879         tx_vlan_reset(port_id);
3880         ports[port_id].dev_conf.txmode.offloads |= DEV_TX_OFFLOAD_VLAN_INSERT;
3881         ports[port_id].tx_vlan_id = vlan_id;
3882 }
3883
3884 void
3885 tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer)
3886 {
3887         struct rte_eth_dev_info dev_info;
3888         int ret;
3889
3890         if (vlan_id_is_invalid(vlan_id))
3891                 return;
3892         if (vlan_id_is_invalid(vlan_id_outer))
3893                 return;
3894
3895         ret = eth_dev_info_get_print_err(port_id, &dev_info);
3896         if (ret != 0)
3897                 return;
3898
3899         if ((dev_info.tx_offload_capa & DEV_TX_OFFLOAD_QINQ_INSERT) == 0) {
3900                 printf("Error: qinq insert not supported by port %d\n",
3901                         port_id);
3902                 return;
3903         }
3904
3905         tx_vlan_reset(port_id);
3906         ports[port_id].dev_conf.txmode.offloads |= (DEV_TX_OFFLOAD_VLAN_INSERT |
3907                                                     DEV_TX_OFFLOAD_QINQ_INSERT);
3908         ports[port_id].tx_vlan_id = vlan_id;
3909         ports[port_id].tx_vlan_id_outer = vlan_id_outer;
3910 }
3911
3912 void
3913 tx_vlan_reset(portid_t port_id)
3914 {
3915         ports[port_id].dev_conf.txmode.offloads &=
3916                                 ~(DEV_TX_OFFLOAD_VLAN_INSERT |
3917                                   DEV_TX_OFFLOAD_QINQ_INSERT);
3918         ports[port_id].tx_vlan_id = 0;
3919         ports[port_id].tx_vlan_id_outer = 0;
3920 }
3921
3922 void
3923 tx_vlan_pvid_set(portid_t port_id, uint16_t vlan_id, int on)
3924 {
3925         if (port_id_is_invalid(port_id, ENABLED_WARN))
3926                 return;
3927
3928         rte_eth_dev_set_vlan_pvid(port_id, vlan_id, on);
3929 }
3930
3931 void
3932 set_qmap(portid_t port_id, uint8_t is_rx, uint16_t queue_id, uint8_t map_value)
3933 {
3934         uint16_t i;
3935         uint8_t existing_mapping_found = 0;
3936
3937         if (port_id_is_invalid(port_id, ENABLED_WARN))
3938                 return;
3939
3940         if (is_rx ? (rx_queue_id_is_invalid(queue_id)) : (tx_queue_id_is_invalid(queue_id)))
3941                 return;
3942
3943         if (map_value >= RTE_ETHDEV_QUEUE_STAT_CNTRS) {
3944                 printf("map_value not in required range 0..%d\n",
3945                                 RTE_ETHDEV_QUEUE_STAT_CNTRS - 1);
3946                 return;
3947         }
3948
3949         if (!is_rx) { /*then tx*/
3950                 for (i = 0; i < nb_tx_queue_stats_mappings; i++) {
3951                         if ((tx_queue_stats_mappings[i].port_id == port_id) &&
3952                             (tx_queue_stats_mappings[i].queue_id == queue_id)) {
3953                                 tx_queue_stats_mappings[i].stats_counter_id = map_value;
3954                                 existing_mapping_found = 1;
3955                                 break;
3956                         }
3957                 }
3958                 if (!existing_mapping_found) { /* A new additional mapping... */
3959                         tx_queue_stats_mappings[nb_tx_queue_stats_mappings].port_id = port_id;
3960                         tx_queue_stats_mappings[nb_tx_queue_stats_mappings].queue_id = queue_id;
3961                         tx_queue_stats_mappings[nb_tx_queue_stats_mappings].stats_counter_id = map_value;
3962                         nb_tx_queue_stats_mappings++;
3963                 }
3964         }
3965         else { /*rx*/
3966                 for (i = 0; i < nb_rx_queue_stats_mappings; i++) {
3967                         if ((rx_queue_stats_mappings[i].port_id == port_id) &&
3968                             (rx_queue_stats_mappings[i].queue_id == queue_id)) {
3969                                 rx_queue_stats_mappings[i].stats_counter_id = map_value;
3970                                 existing_mapping_found = 1;
3971                                 break;
3972                         }
3973                 }
3974                 if (!existing_mapping_found) { /* A new additional mapping... */
3975                         rx_queue_stats_mappings[nb_rx_queue_stats_mappings].port_id = port_id;
3976                         rx_queue_stats_mappings[nb_rx_queue_stats_mappings].queue_id = queue_id;
3977                         rx_queue_stats_mappings[nb_rx_queue_stats_mappings].stats_counter_id = map_value;
3978                         nb_rx_queue_stats_mappings++;
3979                 }
3980         }
3981 }
3982
3983 void
3984 set_xstats_hide_zero(uint8_t on_off)
3985 {
3986         xstats_hide_zero = on_off;
3987 }
3988
3989 void
3990 set_record_core_cycles(uint8_t on_off)
3991 {
3992         record_core_cycles = on_off;
3993 }
3994
3995 void
3996 set_record_burst_stats(uint8_t on_off)
3997 {
3998         record_burst_stats = on_off;
3999 }
4000
4001 static inline void
4002 print_fdir_mask(struct rte_eth_fdir_masks *mask)
4003 {
4004         printf("\n    vlan_tci: 0x%04x", rte_be_to_cpu_16(mask->vlan_tci_mask));
4005
4006         if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL)
4007                 printf(", mac_addr: 0x%02x, tunnel_type: 0x%01x,"
4008                         " tunnel_id: 0x%08x",
4009                         mask->mac_addr_byte_mask, mask->tunnel_type_mask,
4010                         rte_be_to_cpu_32(mask->tunnel_id_mask));
4011         else if (fdir_conf.mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
4012                 printf(", src_ipv4: 0x%08x, dst_ipv4: 0x%08x",
4013                         rte_be_to_cpu_32(mask->ipv4_mask.src_ip),
4014                         rte_be_to_cpu_32(mask->ipv4_mask.dst_ip));
4015
4016                 printf("\n    src_port: 0x%04x, dst_port: 0x%04x",
4017                         rte_be_to_cpu_16(mask->src_port_mask),
4018                         rte_be_to_cpu_16(mask->dst_port_mask));
4019
4020                 printf("\n    src_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x",
4021                         rte_be_to_cpu_32(mask->ipv6_mask.src_ip[0]),
4022                         rte_be_to_cpu_32(mask->ipv6_mask.src_ip[1]),
4023                         rte_be_to_cpu_32(mask->ipv6_mask.src_ip[2]),
4024                         rte_be_to_cpu_32(mask->ipv6_mask.src_ip[3]));
4025
4026                 printf("\n    dst_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x",
4027                         rte_be_to_cpu_32(mask->ipv6_mask.dst_ip[0]),
4028                         rte_be_to_cpu_32(mask->ipv6_mask.dst_ip[1]),
4029                         rte_be_to_cpu_32(mask->ipv6_mask.dst_ip[2]),
4030                         rte_be_to_cpu_32(mask->ipv6_mask.dst_ip[3]));
4031         }
4032
4033         printf("\n");
4034 }
4035
4036 static inline void
4037 print_fdir_flex_payload(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num)
4038 {
4039         struct rte_eth_flex_payload_cfg *cfg;
4040         uint32_t i, j;
4041
4042         for (i = 0; i < flex_conf->nb_payloads; i++) {
4043                 cfg = &flex_conf->flex_set[i];
4044                 if (cfg->type == RTE_ETH_RAW_PAYLOAD)
4045                         printf("\n    RAW:  ");
4046                 else if (cfg->type == RTE_ETH_L2_PAYLOAD)
4047                         printf("\n    L2_PAYLOAD:  ");
4048                 else if (cfg->type == RTE_ETH_L3_PAYLOAD)
4049                         printf("\n    L3_PAYLOAD:  ");
4050                 else if (cfg->type == RTE_ETH_L4_PAYLOAD)
4051                         printf("\n    L4_PAYLOAD:  ");
4052                 else
4053                         printf("\n    UNKNOWN PAYLOAD(%u):  ", cfg->type);
4054                 for (j = 0; j < num; j++)
4055                         printf("  %-5u", cfg->src_offset[j]);
4056         }
4057         printf("\n");
4058 }
4059
4060 static char *
4061 flowtype_to_str(uint16_t flow_type)
4062 {
4063         struct flow_type_info {
4064                 char str[32];
4065                 uint16_t ftype;
4066         };
4067
4068         uint8_t i;
4069         static struct flow_type_info flowtype_str_table[] = {
4070                 {"raw", RTE_ETH_FLOW_RAW},
4071                 {"ipv4", RTE_ETH_FLOW_IPV4},
4072                 {"ipv4-frag", RTE_ETH_FLOW_FRAG_IPV4},
4073                 {"ipv4-tcp", RTE_ETH_FLOW_NONFRAG_IPV4_TCP},
4074                 {"ipv4-udp", RTE_ETH_FLOW_NONFRAG_IPV4_UDP},
4075                 {"ipv4-sctp", RTE_ETH_FLOW_NONFRAG_IPV4_SCTP},
4076                 {"ipv4-other", RTE_ETH_FLOW_NONFRAG_IPV4_OTHER},
4077                 {"ipv6", RTE_ETH_FLOW_IPV6},
4078                 {"ipv6-frag", RTE_ETH_FLOW_FRAG_IPV6},
4079                 {"ipv6-tcp", RTE_ETH_FLOW_NONFRAG_IPV6_TCP},
4080                 {"ipv6-udp", RTE_ETH_FLOW_NONFRAG_IPV6_UDP},
4081                 {"ipv6-sctp", RTE_ETH_FLOW_NONFRAG_IPV6_SCTP},
4082                 {"ipv6-other", RTE_ETH_FLOW_NONFRAG_IPV6_OTHER},
4083                 {"l2_payload", RTE_ETH_FLOW_L2_PAYLOAD},
4084                 {"port", RTE_ETH_FLOW_PORT},
4085                 {"vxlan", RTE_ETH_FLOW_VXLAN},
4086                 {"geneve", RTE_ETH_FLOW_GENEVE},
4087                 {"nvgre", RTE_ETH_FLOW_NVGRE},
4088                 {"vxlan-gpe", RTE_ETH_FLOW_VXLAN_GPE},
4089         };
4090
4091         for (i = 0; i < RTE_DIM(flowtype_str_table); i++) {
4092                 if (flowtype_str_table[i].ftype == flow_type)
4093                         return flowtype_str_table[i].str;
4094         }
4095
4096         return NULL;
4097 }
4098
4099 static inline void
4100 print_fdir_flex_mask(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num)
4101 {
4102         struct rte_eth_fdir_flex_mask *mask;
4103         uint32_t i, j;
4104         char *p;
4105
4106         for (i = 0; i < flex_conf->nb_flexmasks; i++) {
4107                 mask = &flex_conf->flex_mask[i];
4108                 p = flowtype_to_str(mask->flow_type);
4109                 printf("\n    %s:\t", p ? p : "unknown");
4110                 for (j = 0; j < num; j++)
4111                         printf(" %02x", mask->mask[j]);
4112         }
4113         printf("\n");
4114 }
4115
4116 static inline void
4117 print_fdir_flow_type(uint32_t flow_types_mask)
4118 {
4119         int i;
4120         char *p;
4121
4122         for (i = RTE_ETH_FLOW_UNKNOWN; i < RTE_ETH_FLOW_MAX; i++) {
4123                 if (!(flow_types_mask & (1 << i)))
4124                         continue;
4125                 p = flowtype_to_str(i);
4126                 if (p)
4127                         printf(" %s", p);
4128                 else
4129                         printf(" unknown");
4130         }
4131         printf("\n");
4132 }
4133
4134 static int
4135 get_fdir_info(portid_t port_id, struct rte_eth_fdir_info *fdir_info,
4136                     struct rte_eth_fdir_stats *fdir_stat)
4137 {
4138         int ret;
4139
4140         ret = rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_FDIR);
4141         if (!ret) {
4142                 rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR,
4143                                RTE_ETH_FILTER_INFO, fdir_info);
4144                 rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR,
4145                                RTE_ETH_FILTER_STATS, fdir_stat);
4146                 return 0;
4147         }
4148
4149 #ifdef RTE_LIBRTE_I40E_PMD
4150         if (ret == -ENOTSUP) {
4151                 ret = rte_pmd_i40e_get_fdir_info(port_id, fdir_info);
4152                 if (!ret)
4153                         ret = rte_pmd_i40e_get_fdir_stats(port_id, fdir_stat);
4154         }
4155 #endif
4156 #ifdef RTE_LIBRTE_IXGBE_PMD
4157         if (ret == -ENOTSUP) {
4158                 ret = rte_pmd_ixgbe_get_fdir_info(port_id, fdir_info);
4159                 if (!ret)
4160                         ret = rte_pmd_ixgbe_get_fdir_stats(port_id, fdir_stat);
4161         }
4162 #endif
4163         switch (ret) {
4164         case 0:
4165                 break;
4166         case -ENOTSUP:
4167                 printf("\n FDIR is not supported on port %-2d\n",
4168                         port_id);
4169                 break;
4170         default:
4171                 printf("programming error: (%s)\n", strerror(-ret));
4172                 break;
4173         }
4174         return ret;
4175 }
4176
4177 void
4178 fdir_get_infos(portid_t port_id)
4179 {
4180         struct rte_eth_fdir_stats fdir_stat;
4181         struct rte_eth_fdir_info fdir_info;
4182
4183         static const char *fdir_stats_border = "########################";
4184
4185         if (port_id_is_invalid(port_id, ENABLED_WARN))
4186                 return;
4187
4188         memset(&fdir_info, 0, sizeof(fdir_info));
4189         memset(&fdir_stat, 0, sizeof(fdir_stat));
4190         if (get_fdir_info(port_id, &fdir_info, &fdir_stat))
4191                 return;
4192
4193         printf("\n  %s FDIR infos for port %-2d     %s\n",
4194                fdir_stats_border, port_id, fdir_stats_border);
4195         printf("  MODE: ");
4196         if (fdir_info.mode == RTE_FDIR_MODE_PERFECT)
4197                 printf("  PERFECT\n");
4198         else if (fdir_info.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN)
4199                 printf("  PERFECT-MAC-VLAN\n");
4200         else if (fdir_info.mode == RTE_FDIR_MODE_PERFECT_TUNNEL)
4201                 printf("  PERFECT-TUNNEL\n");
4202         else if (fdir_info.mode == RTE_FDIR_MODE_SIGNATURE)
4203                 printf("  SIGNATURE\n");
4204         else
4205                 printf("  DISABLE\n");
4206         if (fdir_info.mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN
4207                 && fdir_info.mode != RTE_FDIR_MODE_PERFECT_TUNNEL) {
4208                 printf("  SUPPORTED FLOW TYPE: ");
4209                 print_fdir_flow_type(fdir_info.flow_types_mask[0]);
4210         }
4211         printf("  FLEX PAYLOAD INFO:\n");
4212         printf("  max_len:       %-10"PRIu32"  payload_limit: %-10"PRIu32"\n"
4213                "  payload_unit:  %-10"PRIu32"  payload_seg:   %-10"PRIu32"\n"
4214                "  bitmask_unit:  %-10"PRIu32"  bitmask_num:   %-10"PRIu32"\n",
4215                 fdir_info.max_flexpayload, fdir_info.flex_payload_limit,
4216                 fdir_info.flex_payload_unit,
4217                 fdir_info.max_flex_payload_segment_num,
4218                 fdir_info.flex_bitmask_unit, fdir_info.max_flex_bitmask_num);
4219         printf("  MASK: ");
4220         print_fdir_mask(&fdir_info.mask);
4221         if (fdir_info.flex_conf.nb_payloads > 0) {
4222                 printf("  FLEX PAYLOAD SRC OFFSET:");
4223                 print_fdir_flex_payload(&fdir_info.flex_conf, fdir_info.max_flexpayload);
4224         }
4225         if (fdir_info.flex_conf.nb_flexmasks > 0) {
4226                 printf("  FLEX MASK CFG:");
4227                 print_fdir_flex_mask(&fdir_info.flex_conf, fdir_info.max_flexpayload);
4228         }
4229         printf("  guarant_count: %-10"PRIu32"  best_count:    %"PRIu32"\n",
4230                fdir_stat.guarant_cnt, fdir_stat.best_cnt);
4231         printf("  guarant_space: %-10"PRIu32"  best_space:    %"PRIu32"\n",
4232                fdir_info.guarant_spc, fdir_info.best_spc);
4233         printf("  collision:     %-10"PRIu32"  free:          %"PRIu32"\n"
4234                "  maxhash:       %-10"PRIu32"  maxlen:        %"PRIu32"\n"
4235                "  add:           %-10"PRIu64"  remove:        %"PRIu64"\n"
4236                "  f_add:         %-10"PRIu64"  f_remove:      %"PRIu64"\n",
4237                fdir_stat.collision, fdir_stat.free,
4238                fdir_stat.maxhash, fdir_stat.maxlen,
4239                fdir_stat.add, fdir_stat.remove,
4240                fdir_stat.f_add, fdir_stat.f_remove);
4241         printf("  %s############################%s\n",
4242                fdir_stats_border, fdir_stats_border);
4243 }
4244
4245 void
4246 fdir_set_flex_mask(portid_t port_id, struct rte_eth_fdir_flex_mask *cfg)
4247 {
4248         struct rte_port *port;
4249         struct rte_eth_fdir_flex_conf *flex_conf;
4250         int i, idx = 0;
4251
4252         port = &ports[port_id];
4253         flex_conf = &port->dev_conf.fdir_conf.flex_conf;
4254         for (i = 0; i < RTE_ETH_FLOW_MAX; i++) {
4255                 if (cfg->flow_type == flex_conf->flex_mask[i].flow_type) {
4256                         idx = i;
4257                         break;
4258                 }
4259         }
4260         if (i >= RTE_ETH_FLOW_MAX) {
4261                 if (flex_conf->nb_flexmasks < RTE_DIM(flex_conf->flex_mask)) {
4262                         idx = flex_conf->nb_flexmasks;
4263                         flex_conf->nb_flexmasks++;
4264                 } else {
4265                         printf("The flex mask table is full. Can not set flex"
4266                                 " mask for flow_type(%u).", cfg->flow_type);
4267                         return;
4268                 }
4269         }
4270         rte_memcpy(&flex_conf->flex_mask[idx],
4271                          cfg,
4272                          sizeof(struct rte_eth_fdir_flex_mask));
4273 }
4274
4275 void
4276 fdir_set_flex_payload(portid_t port_id, struct rte_eth_flex_payload_cfg *cfg)
4277 {
4278         struct rte_port *port;
4279         struct rte_eth_fdir_flex_conf *flex_conf;
4280         int i, idx = 0;
4281
4282         port = &ports[port_id];
4283         flex_conf = &port->dev_conf.fdir_conf.flex_conf;
4284         for (i = 0; i < RTE_ETH_PAYLOAD_MAX; i++) {
4285                 if (cfg->type == flex_conf->flex_set[i].type) {
4286                         idx = i;
4287                         break;
4288                 }
4289         }
4290         if (i >= RTE_ETH_PAYLOAD_MAX) {
4291                 if (flex_conf->nb_payloads < RTE_DIM(flex_conf->flex_set)) {
4292                         idx = flex_conf->nb_payloads;
4293                         flex_conf->nb_payloads++;
4294                 } else {
4295                         printf("The flex payload table is full. Can not set"
4296                                 " flex payload for type(%u).", cfg->type);
4297                         return;
4298                 }
4299         }
4300         rte_memcpy(&flex_conf->flex_set[idx],
4301                          cfg,
4302                          sizeof(struct rte_eth_flex_payload_cfg));
4303
4304 }
4305
4306 void
4307 set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on)
4308 {
4309 #ifdef RTE_LIBRTE_IXGBE_PMD
4310         int diag;
4311
4312         if (is_rx)
4313                 diag = rte_pmd_ixgbe_set_vf_rx(port_id, vf, on);
4314         else
4315                 diag = rte_pmd_ixgbe_set_vf_tx(port_id, vf, on);
4316
4317         if (diag == 0)
4318                 return;
4319         printf("rte_pmd_ixgbe_set_vf_%s for port_id=%d failed diag=%d\n",
4320                         is_rx ? "rx" : "tx", port_id, diag);
4321         return;
4322 #endif
4323         printf("VF %s setting not supported for port %d\n",
4324                         is_rx ? "Rx" : "Tx", port_id);
4325         RTE_SET_USED(vf);
4326         RTE_SET_USED(on);
4327 }
4328
4329 int
4330 set_queue_rate_limit(portid_t port_id, uint16_t queue_idx, uint16_t rate)
4331 {
4332         int diag;
4333         struct rte_eth_link link;
4334         int ret;
4335
4336         if (port_id_is_invalid(port_id, ENABLED_WARN))
4337                 return 1;
4338         ret = eth_link_get_nowait_print_err(port_id, &link);
4339         if (ret < 0)
4340                 return 1;
4341         if (link.link_speed != ETH_SPEED_NUM_UNKNOWN &&
4342             rate > link.link_speed) {
4343                 printf("Invalid rate value:%u bigger than link speed: %u\n",
4344                         rate, link.link_speed);
4345                 return 1;
4346         }
4347         diag = rte_eth_set_queue_rate_limit(port_id, queue_idx, rate);
4348         if (diag == 0)
4349                 return diag;
4350         printf("rte_eth_set_queue_rate_limit for port_id=%d failed diag=%d\n",
4351                 port_id, diag);
4352         return diag;
4353 }
4354
4355 int
4356 set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk)
4357 {
4358         int diag = -ENOTSUP;
4359
4360         RTE_SET_USED(vf);
4361         RTE_SET_USED(rate);
4362         RTE_SET_USED(q_msk);
4363
4364 #ifdef RTE_LIBRTE_IXGBE_PMD
4365         if (diag == -ENOTSUP)
4366                 diag = rte_pmd_ixgbe_set_vf_rate_limit(port_id, vf, rate,
4367                                                        q_msk);
4368 #endif
4369 #ifdef RTE_LIBRTE_BNXT_PMD
4370         if (diag == -ENOTSUP)
4371                 diag = rte_pmd_bnxt_set_vf_rate_limit(port_id, vf, rate, q_msk);
4372 #endif
4373         if (diag == 0)
4374                 return diag;
4375
4376         printf("set_vf_rate_limit for port_id=%d failed diag=%d\n",
4377                 port_id, diag);
4378         return diag;
4379 }
4380
4381 /*
4382  * Functions to manage the set of filtered Multicast MAC addresses.
4383  *
4384  * A pool of filtered multicast MAC addresses is associated with each port.
4385  * The pool is allocated in chunks of MCAST_POOL_INC multicast addresses.
4386  * The address of the pool and the number of valid multicast MAC addresses
4387  * recorded in the pool are stored in the fields "mc_addr_pool" and
4388  * "mc_addr_nb" of the "rte_port" data structure.
4389  *
4390  * The function "rte_eth_dev_set_mc_addr_list" of the PMDs API imposes
4391  * to be supplied a contiguous array of multicast MAC addresses.
4392  * To comply with this constraint, the set of multicast addresses recorded
4393  * into the pool are systematically compacted at the beginning of the pool.
4394  * Hence, when a multicast address is removed from the pool, all following
4395  * addresses, if any, are copied back to keep the set contiguous.
4396  */
4397 #define MCAST_POOL_INC 32
4398
4399 static int
4400 mcast_addr_pool_extend(struct rte_port *port)
4401 {
4402         struct rte_ether_addr *mc_pool;
4403         size_t mc_pool_size;
4404
4405         /*
4406          * If a free entry is available at the end of the pool, just
4407          * increment the number of recorded multicast addresses.
4408          */
4409         if ((port->mc_addr_nb % MCAST_POOL_INC) != 0) {
4410                 port->mc_addr_nb++;
4411                 return 0;
4412         }
4413
4414         /*
4415          * [re]allocate a pool with MCAST_POOL_INC more entries.
4416          * The previous test guarantees that port->mc_addr_nb is a multiple
4417          * of MCAST_POOL_INC.
4418          */
4419         mc_pool_size = sizeof(struct rte_ether_addr) * (port->mc_addr_nb +
4420                                                     MCAST_POOL_INC);
4421         mc_pool = (struct rte_ether_addr *) realloc(port->mc_addr_pool,
4422                                                 mc_pool_size);
4423         if (mc_pool == NULL) {
4424                 printf("allocation of pool of %u multicast addresses failed\n",
4425                        port->mc_addr_nb + MCAST_POOL_INC);
4426                 return -ENOMEM;
4427         }
4428
4429         port->mc_addr_pool = mc_pool;
4430         port->mc_addr_nb++;
4431         return 0;
4432
4433 }
4434
4435 static void
4436 mcast_addr_pool_append(struct rte_port *port, struct rte_ether_addr *mc_addr)
4437 {
4438         if (mcast_addr_pool_extend(port) != 0)
4439                 return;
4440         rte_ether_addr_copy(mc_addr, &port->mc_addr_pool[port->mc_addr_nb - 1]);
4441 }
4442
4443 static void
4444 mcast_addr_pool_remove(struct rte_port *port, uint32_t addr_idx)
4445 {
4446         port->mc_addr_nb--;
4447         if (addr_idx == port->mc_addr_nb) {
4448                 /* No need to recompact the set of multicast addressses. */
4449                 if (port->mc_addr_nb == 0) {
4450                         /* free the pool of multicast addresses. */
4451                         free(port->mc_addr_pool);
4452                         port->mc_addr_pool = NULL;
4453                 }
4454                 return;
4455         }
4456         memmove(&port->mc_addr_pool[addr_idx],
4457                 &port->mc_addr_pool[addr_idx + 1],
4458                 sizeof(struct rte_ether_addr) * (port->mc_addr_nb - addr_idx));
4459 }
4460
4461 static int
4462 eth_port_multicast_addr_list_set(portid_t port_id)
4463 {
4464         struct rte_port *port;
4465         int diag;
4466
4467         port = &ports[port_id];
4468         diag = rte_eth_dev_set_mc_addr_list(port_id, port->mc_addr_pool,
4469                                             port->mc_addr_nb);
4470         if (diag < 0)
4471                 printf("rte_eth_dev_set_mc_addr_list(port=%d, nb=%u) failed. diag=%d\n",
4472                         port_id, port->mc_addr_nb, diag);
4473
4474         return diag;
4475 }
4476
4477 void
4478 mcast_addr_add(portid_t port_id, struct rte_ether_addr *mc_addr)
4479 {
4480         struct rte_port *port;
4481         uint32_t i;
4482
4483         if (port_id_is_invalid(port_id, ENABLED_WARN))
4484                 return;
4485
4486         port = &ports[port_id];
4487
4488         /*
4489          * Check that the added multicast MAC address is not already recorded
4490          * in the pool of multicast addresses.
4491          */
4492         for (i = 0; i < port->mc_addr_nb; i++) {
4493                 if (rte_is_same_ether_addr(mc_addr, &port->mc_addr_pool[i])) {
4494                         printf("multicast address already filtered by port\n");
4495                         return;
4496                 }
4497         }
4498
4499         mcast_addr_pool_append(port, mc_addr);
4500         if (eth_port_multicast_addr_list_set(port_id) < 0)
4501                 /* Rollback on failure, remove the address from the pool */
4502                 mcast_addr_pool_remove(port, i);
4503 }
4504
4505 void
4506 mcast_addr_remove(portid_t port_id, struct rte_ether_addr *mc_addr)
4507 {
4508         struct rte_port *port;
4509         uint32_t i;
4510
4511         if (port_id_is_invalid(port_id, ENABLED_WARN))
4512                 return;
4513
4514         port = &ports[port_id];
4515
4516         /*
4517          * Search the pool of multicast MAC addresses for the removed address.
4518          */
4519         for (i = 0; i < port->mc_addr_nb; i++) {
4520                 if (rte_is_same_ether_addr(mc_addr, &port->mc_addr_pool[i]))
4521                         break;
4522         }
4523         if (i == port->mc_addr_nb) {
4524                 printf("multicast address not filtered by port %d\n", port_id);
4525                 return;
4526         }
4527
4528         mcast_addr_pool_remove(port, i);
4529         if (eth_port_multicast_addr_list_set(port_id) < 0)
4530                 /* Rollback on failure, add the address back into the pool */
4531                 mcast_addr_pool_append(port, mc_addr);
4532 }
4533
4534 void
4535 port_dcb_info_display(portid_t port_id)
4536 {
4537         struct rte_eth_dcb_info dcb_info;
4538         uint16_t i;
4539         int ret;
4540         static const char *border = "================";
4541
4542         if (port_id_is_invalid(port_id, ENABLED_WARN))
4543                 return;
4544
4545         ret = rte_eth_dev_get_dcb_info(port_id, &dcb_info);
4546         if (ret) {
4547                 printf("\n Failed to get dcb infos on port %-2d\n",
4548                         port_id);
4549                 return;
4550         }
4551         printf("\n  %s DCB infos for port %-2d  %s\n", border, port_id, border);
4552         printf("  TC NUMBER: %d\n", dcb_info.nb_tcs);
4553         printf("\n  TC :        ");
4554         for (i = 0; i < dcb_info.nb_tcs; i++)
4555                 printf("\t%4d", i);
4556         printf("\n  Priority :  ");
4557         for (i = 0; i < dcb_info.nb_tcs; i++)
4558                 printf("\t%4d", dcb_info.prio_tc[i]);
4559         printf("\n  BW percent :");
4560         for (i = 0; i < dcb_info.nb_tcs; i++)
4561                 printf("\t%4d%%", dcb_info.tc_bws[i]);
4562         printf("\n  RXQ base :  ");
4563         for (i = 0; i < dcb_info.nb_tcs; i++)
4564                 printf("\t%4d", dcb_info.tc_queue.tc_rxq[0][i].base);
4565         printf("\n  RXQ number :");
4566         for (i = 0; i < dcb_info.nb_tcs; i++)
4567                 printf("\t%4d", dcb_info.tc_queue.tc_rxq[0][i].nb_queue);
4568         printf("\n  TXQ base :  ");
4569         for (i = 0; i < dcb_info.nb_tcs; i++)
4570                 printf("\t%4d", dcb_info.tc_queue.tc_txq[0][i].base);
4571         printf("\n  TXQ number :");
4572         for (i = 0; i < dcb_info.nb_tcs; i++)
4573                 printf("\t%4d", dcb_info.tc_queue.tc_txq[0][i].nb_queue);
4574         printf("\n");
4575 }
4576
4577 uint8_t *
4578 open_file(const char *file_path, uint32_t *size)
4579 {
4580         int fd = open(file_path, O_RDONLY);
4581         off_t pkg_size;
4582         uint8_t *buf = NULL;
4583         int ret = 0;
4584         struct stat st_buf;
4585
4586         if (size)
4587                 *size = 0;
4588
4589         if (fd == -1) {
4590                 printf("%s: Failed to open %s\n", __func__, file_path);
4591                 return buf;
4592         }
4593
4594         if ((fstat(fd, &st_buf) != 0) || (!S_ISREG(st_buf.st_mode))) {
4595                 close(fd);
4596                 printf("%s: File operations failed\n", __func__);
4597                 return buf;
4598         }
4599
4600         pkg_size = st_buf.st_size;
4601         if (pkg_size < 0) {
4602                 close(fd);
4603                 printf("%s: File operations failed\n", __func__);
4604                 return buf;
4605         }
4606
4607         buf = (uint8_t *)malloc(pkg_size);
4608         if (!buf) {
4609                 close(fd);
4610                 printf("%s: Failed to malloc memory\n", __func__);
4611                 return buf;
4612         }
4613
4614         ret = read(fd, buf, pkg_size);
4615         if (ret < 0) {
4616                 close(fd);
4617                 printf("%s: File read operation failed\n", __func__);
4618                 close_file(buf);
4619                 return NULL;
4620         }
4621
4622         if (size)
4623                 *size = pkg_size;
4624
4625         close(fd);
4626
4627         return buf;
4628 }
4629
4630 int
4631 save_file(const char *file_path, uint8_t *buf, uint32_t size)
4632 {
4633         FILE *fh = fopen(file_path, "wb");
4634
4635         if (fh == NULL) {
4636                 printf("%s: Failed to open %s\n", __func__, file_path);
4637                 return -1;
4638         }
4639
4640         if (fwrite(buf, 1, size, fh) != size) {
4641                 fclose(fh);
4642                 printf("%s: File write operation failed\n", __func__);
4643                 return -1;
4644         }
4645
4646         fclose(fh);
4647
4648         return 0;
4649 }
4650
4651 int
4652 close_file(uint8_t *buf)
4653 {
4654         if (buf) {
4655                 free((void *)buf);
4656                 return 0;
4657         }
4658
4659         return -1;
4660 }
4661
4662 void
4663 port_queue_region_info_display(portid_t port_id, void *buf)
4664 {
4665 #ifdef RTE_LIBRTE_I40E_PMD
4666         uint16_t i, j;
4667         struct rte_pmd_i40e_queue_regions *info =
4668                 (struct rte_pmd_i40e_queue_regions *)buf;
4669         static const char *queue_region_info_stats_border = "-------";
4670
4671         if (!info->queue_region_number)
4672                 printf("there is no region has been set before");
4673
4674         printf("\n      %s All queue region info for port=%2d %s",
4675                         queue_region_info_stats_border, port_id,
4676                         queue_region_info_stats_border);
4677         printf("\n      queue_region_number: %-14u \n",
4678                         info->queue_region_number);
4679
4680         for (i = 0; i < info->queue_region_number; i++) {
4681                 printf("\n      region_id: %-14u queue_number: %-14u "
4682                         "queue_start_index: %-14u \n",
4683                         info->region[i].region_id,
4684                         info->region[i].queue_num,
4685                         info->region[i].queue_start_index);
4686
4687                 printf("  user_priority_num is  %-14u :",
4688                                         info->region[i].user_priority_num);
4689                 for (j = 0; j < info->region[i].user_priority_num; j++)
4690                         printf(" %-14u ", info->region[i].user_priority[j]);
4691
4692                 printf("\n      flowtype_num is  %-14u :",
4693                                 info->region[i].flowtype_num);
4694                 for (j = 0; j < info->region[i].flowtype_num; j++)
4695                         printf(" %-14u ", info->region[i].hw_flowtype[j]);
4696         }
4697 #else
4698         RTE_SET_USED(port_id);
4699         RTE_SET_USED(buf);
4700 #endif
4701
4702         printf("\n\n");
4703 }
4704
4705 void
4706 show_macs(portid_t port_id)
4707 {
4708         char buf[RTE_ETHER_ADDR_FMT_SIZE];
4709         struct rte_eth_dev_info dev_info;
4710         struct rte_ether_addr *addr;
4711         uint32_t i, num_macs = 0;
4712         struct rte_eth_dev *dev;
4713
4714         dev = &rte_eth_devices[port_id];
4715
4716         rte_eth_dev_info_get(port_id, &dev_info);
4717
4718         for (i = 0; i < dev_info.max_mac_addrs; i++) {
4719                 addr = &dev->data->mac_addrs[i];
4720
4721                 /* skip zero address */
4722                 if (rte_is_zero_ether_addr(addr))
4723                         continue;
4724
4725                 num_macs++;
4726         }
4727
4728         printf("Number of MAC address added: %d\n", num_macs);
4729
4730         for (i = 0; i < dev_info.max_mac_addrs; i++) {
4731                 addr = &dev->data->mac_addrs[i];
4732
4733                 /* skip zero address */
4734                 if (rte_is_zero_ether_addr(addr))
4735                         continue;
4736
4737                 rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, addr);
4738                 printf("  %s\n", buf);
4739         }
4740 }
4741
4742 void
4743 show_mcast_macs(portid_t port_id)
4744 {
4745         char buf[RTE_ETHER_ADDR_FMT_SIZE];
4746         struct rte_ether_addr *addr;
4747         struct rte_port *port;
4748         uint32_t i;
4749
4750         port = &ports[port_id];
4751
4752         printf("Number of Multicast MAC address added: %d\n", port->mc_addr_nb);
4753
4754         for (i = 0; i < port->mc_addr_nb; i++) {
4755                 addr = &port->mc_addr_pool[i];
4756
4757                 rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, addr);
4758                 printf("  %s\n", buf);
4759         }
4760 }