remove extra parentheses in return statement
[dpdk.git] / app / test-pmd / config.c
index 69a83c2..0062484 100644 (file)
@@ -79,7 +79,6 @@
 #include <rte_memcpy.h>
 #include <rte_memzone.h>
 #include <rte_launch.h>
-#include <rte_tailq.h>
 #include <rte_eal.h>
 #include <rte_per_lcore.h>
 #include <rte_lcore.h>
 
 #include "testpmd.h"
 
-static const char *flowtype_str[RTE_ETH_FLOW_TYPE_MAX] = {
-       NULL,
-       "udp4",
-       "tcp4",
-       "sctp4",
-       "ip4",
-       "ip4-frag",
-       "udp6",
-       "tcp6",
-       "sctp6",
-       "ip6",
-       "ip6-frag",
+static char *flowtype_to_str(uint16_t flow_type);
+
+static const struct {
+       enum tx_pkt_split split;
+       const char *name;
+} tx_split_name[] = {
+       {
+               .split = TX_PKT_SPLIT_OFF,
+               .name = "off",
+       },
+       {
+               .split = TX_PKT_SPLIT_ON,
+               .name = "on",
+       },
+       {
+               .split = TX_PKT_SPLIT_RND,
+               .name = "rand",
+       },
+};
+
+struct rss_type_info {
+       char str[32];
+       uint64_t rss_type;
+};
+
+static const struct rss_type_info rss_type_table[] = {
+       { "ipv4", ETH_RSS_IPV4 },
+       { "ipv4-frag", ETH_RSS_FRAG_IPV4 },
+       { "ipv4-tcp", ETH_RSS_NONFRAG_IPV4_TCP },
+       { "ipv4-udp", ETH_RSS_NONFRAG_IPV4_UDP },
+       { "ipv4-sctp", ETH_RSS_NONFRAG_IPV4_SCTP },
+       { "ipv4-other", ETH_RSS_NONFRAG_IPV4_OTHER },
+       { "ipv6", ETH_RSS_IPV6 },
+       { "ipv6-frag", ETH_RSS_FRAG_IPV6 },
+       { "ipv6-tcp", ETH_RSS_NONFRAG_IPV6_TCP },
+       { "ipv6-udp", ETH_RSS_NONFRAG_IPV6_UDP },
+       { "ipv6-sctp", ETH_RSS_NONFRAG_IPV6_SCTP },
+       { "ipv6-other", ETH_RSS_NONFRAG_IPV6_OTHER },
+       { "l2-payload", ETH_RSS_L2_PAYLOAD },
+       { "ipv6-ex", ETH_RSS_IPV6_EX },
+       { "ipv6-tcp-ex", ETH_RSS_IPV6_TCP_EX },
+       { "ipv6-udp-ex", ETH_RSS_IPV6_UDP_EX },
 };
 
 static void
@@ -124,11 +153,15 @@ nic_stats_display(portid_t port_id)
        struct rte_eth_stats stats;
        struct rte_port *port = &ports[port_id];
        uint8_t i;
+       portid_t pid;
 
        static const char *nic_stats_border = "########################";
 
-       if (port_id >= nb_ports) {
-               printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
+       if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+               printf("Valid port range is [0");
+               FOREACH_PORT(pid, ports)
+                       printf(", %d", pid);
+               printf("]\n");
                return;
        }
        rte_eth_stats_get(port_id, &stats);
@@ -139,9 +172,7 @@ nic_stats_display(portid_t port_id)
                printf("  RX-packets: %-10"PRIu64" RX-missed: %-10"PRIu64" RX-bytes:  "
                       "%-"PRIu64"\n",
                       stats.ipackets, stats.imissed, stats.ibytes);
-               printf("  RX-badcrc:  %-10"PRIu64" RX-badlen: %-10"PRIu64" RX-errors: "
-                      "%-"PRIu64"\n",
-                      stats.ibadcrc, stats.ibadlen, stats.ierrors);
+               printf("  RX-errors: %-"PRIu64"\n", stats.ierrors);
                printf("  RX-nombuf:  %-10"PRIu64"\n",
                       stats.rx_nombuf);
                printf("  TX-packets: %-10"PRIu64" TX-errors: %-10"PRIu64" TX-bytes:  "
@@ -152,9 +183,7 @@ nic_stats_display(portid_t port_id)
                printf("  RX-packets:              %10"PRIu64"    RX-errors: %10"PRIu64
                       "    RX-bytes: %10"PRIu64"\n",
                       stats.ipackets, stats.ierrors, stats.ibytes);
-               printf("  RX-badcrc:               %10"PRIu64"    RX-badlen: %10"PRIu64
-                      "  RX-errors:  %10"PRIu64"\n",
-                      stats.ibadcrc, stats.ibadlen, stats.ierrors);
+               printf("  RX-errors:  %10"PRIu64"\n", stats.ierrors);
                printf("  RX-nombuf:               %10"PRIu64"\n",
                       stats.rx_nombuf);
                printf("  TX-packets:              %10"PRIu64"    TX-errors: %10"PRIu64
@@ -162,12 +191,6 @@ nic_stats_display(portid_t port_id)
                       stats.opackets, stats.oerrors, stats.obytes);
        }
 
-       /* stats fdir */
-       if (fdir_conf.mode != RTE_FDIR_MODE_NONE)
-               printf("  Fdirmiss:   %-10"PRIu64" Fdirmatch: %-10"PRIu64"\n",
-                      stats.fdirmiss,
-                      stats.fdirmatch);
-
        if (port->rx_queue_stats_mapping_enabled) {
                printf("\n");
                for (i = 0; i < RTE_ETHDEV_QUEUE_STAT_CNTRS; i++) {
@@ -186,14 +209,6 @@ nic_stats_display(portid_t port_id)
                }
        }
 
-       /* Display statistics of XON/XOFF pause frames, if any. */
-       if ((stats.tx_pause_xon  | stats.rx_pause_xon |
-            stats.tx_pause_xoff | stats.rx_pause_xoff) > 0) {
-               printf("  RX-XOFF:    %-10"PRIu64" RX-XON:    %-10"PRIu64"\n",
-                      stats.rx_pause_xoff, stats.rx_pause_xon);
-               printf("  TX-XOFF:    %-10"PRIu64" TX-XON:    %-10"PRIu64"\n",
-                      stats.tx_pause_xoff, stats.tx_pause_xon);
-       }
        printf("  %s############################%s\n",
               nic_stats_border, nic_stats_border);
 }
@@ -201,8 +216,13 @@ nic_stats_display(portid_t port_id)
 void
 nic_stats_clear(portid_t port_id)
 {
-       if (port_id >= nb_ports) {
-               printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
+       portid_t pid;
+
+       if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+               printf("Valid port range is [0");
+               FOREACH_PORT(pid, ports)
+                       printf(", %d", pid);
+               printf("]\n");
                return;
        }
        rte_eth_stats_reset(port_id);
@@ -249,11 +269,15 @@ nic_stats_mapping_display(portid_t port_id)
 {
        struct rte_port *port = &ports[port_id];
        uint16_t i;
+       portid_t pid;
 
        static const char *nic_stats_mapping_border = "########################";
 
-       if (port_id >= nb_ports) {
-               printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
+       if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+               printf("Valid port range is [0");
+               FOREACH_PORT(pid, ports)
+                       printf(", %d", pid);
+               printf("]\n");
                return;
        }
 
@@ -292,6 +316,69 @@ nic_stats_mapping_display(portid_t port_id)
               nic_stats_mapping_border, nic_stats_mapping_border);
 }
 
+void
+rx_queue_infos_display(portid_t port_id, uint16_t queue_id)
+{
+       struct rte_eth_rxq_info qinfo;
+       int32_t rc;
+       static const char *info_border = "*********************";
+
+       rc = rte_eth_rx_queue_info_get(port_id, queue_id, &qinfo);
+       if (rc != 0) {
+               printf("Failed to retrieve information for port: %hhu, "
+                       "RX queue: %hu\nerror desc: %s(%d)\n",
+                       port_id, queue_id, strerror(-rc), rc);
+               return;
+       }
+
+       printf("\n%s Infos for port %-2u, RX queue %-2u %s",
+              info_border, port_id, queue_id, info_border);
+
+       printf("\nMempool: %s", (qinfo.mp == NULL) ? "NULL" : qinfo.mp->name);
+       printf("\nRX prefetch threshold: %hhu", qinfo.conf.rx_thresh.pthresh);
+       printf("\nRX host threshold: %hhu", qinfo.conf.rx_thresh.hthresh);
+       printf("\nRX writeback threshold: %hhu", qinfo.conf.rx_thresh.wthresh);
+       printf("\nRX free threshold: %hu", qinfo.conf.rx_free_thresh);
+       printf("\nRX drop packets: %s",
+               (qinfo.conf.rx_drop_en != 0) ? "on" : "off");
+       printf("\nRX deferred start: %s",
+               (qinfo.conf.rx_deferred_start != 0) ? "on" : "off");
+       printf("\nRX scattered packets: %s",
+               (qinfo.scattered_rx != 0) ? "on" : "off");
+       printf("\nNumber of RXDs: %hu", qinfo.nb_desc);
+       printf("\n");
+}
+
+void
+tx_queue_infos_display(portid_t port_id, uint16_t queue_id)
+{
+       struct rte_eth_txq_info qinfo;
+       int32_t rc;
+       static const char *info_border = "*********************";
+
+       rc = rte_eth_tx_queue_info_get(port_id, queue_id, &qinfo);
+       if (rc != 0) {
+               printf("Failed to retrieve information for port: %hhu, "
+                       "TX queue: %hu\nerror desc: %s(%d)\n",
+                       port_id, queue_id, strerror(-rc), rc);
+               return;
+       }
+
+       printf("\n%s Infos for port %-2u, TX queue %-2u %s",
+              info_border, port_id, queue_id, info_border);
+
+       printf("\nTX prefetch threshold: %hhu", qinfo.conf.tx_thresh.pthresh);
+       printf("\nTX host threshold: %hhu", qinfo.conf.tx_thresh.hthresh);
+       printf("\nTX writeback threshold: %hhu", qinfo.conf.tx_thresh.wthresh);
+       printf("\nTX RS threshold: %hu", qinfo.conf.tx_rs_thresh);
+       printf("\nTX free threshold: %hu", qinfo.conf.tx_free_thresh);
+       printf("\nTX flags: %#x", qinfo.conf.txq_flags);
+       printf("\nTX deferred start: %s",
+               (qinfo.conf.tx_deferred_start != 0) ? "on" : "off");
+       printf("\nNumber of TXDs: %hu", qinfo.nb_desc);
+       printf("\n");
+}
+
 void
 port_infos_display(portid_t port_id)
 {
@@ -302,9 +389,13 @@ port_infos_display(portid_t port_id)
        int vlan_offload;
        struct rte_mempool * mp;
        static const char *info_border = "*********************";
+       portid_t pid;
 
-       if (port_id >= nb_ports) {
-               printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
+       if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+               printf("Valid port range is [0");
+               FOREACH_PORT(pid, ports)
+                       printf(", %d", pid);
+               printf("]\n");
                return;
        }
        port = &ports[port_id];
@@ -357,16 +448,53 @@ port_infos_display(portid_t port_id)
 
        memset(&dev_info, 0, sizeof(dev_info));
        rte_eth_dev_info_get(port_id, &dev_info);
+       if (dev_info.hash_key_size > 0)
+               printf("Hash key size in bytes: %u\n", dev_info.hash_key_size);
        if (dev_info.reta_size > 0)
                printf("Redirection table size: %u\n", dev_info.reta_size);
+       if (!dev_info.flow_type_rss_offloads)
+               printf("No flow type is supported.\n");
+       else {
+               uint16_t i;
+               char *p;
+
+               printf("Supported flow types:\n");
+               for (i = RTE_ETH_FLOW_UNKNOWN + 1; i < RTE_ETH_FLOW_MAX;
+                                                               i++) {
+                       if (!(dev_info.flow_type_rss_offloads & (1ULL << i)))
+                               continue;
+                       p = flowtype_to_str(i);
+                       printf("  %s\n", (p ? p : "unknown"));
+               }
+       }
+
+       printf("Max possible RX queues: %u\n", dev_info.max_rx_queues);
+       printf("Max possible number of RXDs per queue: %hu\n",
+               dev_info.rx_desc_lim.nb_max);
+       printf("Min possible number of RXDs per queue: %hu\n",
+               dev_info.rx_desc_lim.nb_min);
+       printf("RXDs number alignment: %hu\n", dev_info.rx_desc_lim.nb_align);
+
+       printf("Max possible TX queues: %u\n", dev_info.max_tx_queues);
+       printf("Max possible number of TXDs per queue: %hu\n",
+               dev_info.tx_desc_lim.nb_max);
+       printf("Min possible number of TXDs per queue: %hu\n",
+               dev_info.tx_desc_lim.nb_min);
+       printf("TXDs number alignment: %hu\n", dev_info.tx_desc_lim.nb_align);
 }
 
 int
-port_id_is_invalid(portid_t port_id)
+port_id_is_invalid(portid_t port_id, enum print_warning warning)
 {
-       if (port_id < nb_ports)
+       if (port_id == (portid_t)RTE_PORT_ALL)
+               return 0;
+
+       if (port_id < RTE_MAX_ETHPORTS && ports[port_id].enabled)
                return 0;
-       printf("Invalid port %d (must be < nb_ports=%d)\n", port_id, nb_ports);
+
+       if (warning == ENABLED_WARN)
+               printf("Invalid port %d\n", port_id);
+
        return 1;
 }
 
@@ -425,7 +553,7 @@ port_reg_bit_display(portid_t port_id, uint32_t reg_off, uint8_t bit_x)
        uint32_t reg_v;
 
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
        if (port_reg_off_is_invalid(port_id, reg_off))
                return;
@@ -444,7 +572,7 @@ port_reg_bit_field_display(portid_t port_id, uint32_t reg_off,
        uint8_t  l_bit;
        uint8_t  h_bit;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
        if (port_reg_off_is_invalid(port_id, reg_off))
                return;
@@ -471,7 +599,7 @@ port_reg_display(portid_t port_id, uint32_t reg_off)
 {
        uint32_t reg_v;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
        if (port_reg_off_is_invalid(port_id, reg_off))
                return;
@@ -485,7 +613,7 @@ port_reg_bit_set(portid_t port_id, uint32_t reg_off, uint8_t bit_pos,
 {
        uint32_t reg_v;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
        if (port_reg_off_is_invalid(port_id, reg_off))
                return;
@@ -513,7 +641,7 @@ port_reg_bit_field_set(portid_t port_id, uint32_t reg_off,
        uint8_t  l_bit;
        uint8_t  h_bit;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
        if (port_reg_off_is_invalid(port_id, reg_off))
                return;
@@ -547,7 +675,7 @@ port_reg_bit_field_set(portid_t port_id, uint32_t reg_off,
 void
 port_reg_set(portid_t port_id, uint32_t reg_off, uint32_t reg_v)
 {
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
        if (port_reg_off_is_invalid(port_id, reg_off))
                return;
@@ -560,7 +688,7 @@ port_mtu_set(portid_t port_id, uint16_t mtu)
 {
        int diag;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
        diag = rte_eth_dev_set_mtu(port_id, mtu);
        if (diag == 0)
@@ -622,7 +750,7 @@ ring_dma_zone_lookup(const char *ring_name, uint8_t port_id, uint16_t q_id)
                printf("%s ring memory zoneof (port %d, queue %d) not"
                       "found (zone name = %s\n",
                       ring_name, port_id, q_id, mz_name);
-       return (mz);
+       return mz;
 }
 
 union igb_ring_dword {
@@ -723,7 +851,7 @@ rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id)
 {
        const struct rte_memzone *rx_mz;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
        if (rx_queue_id_is_invalid(rxq_id))
                return;
@@ -740,7 +868,7 @@ tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id)
 {
        const struct rte_memzone *tx_mz;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
        if (tx_queue_id_is_invalid(txq_id))
                return;
@@ -774,18 +902,23 @@ rxtx_config_display(void)
                printf("  packet len=%u - nb packet segments=%d\n",
                                (unsigned)tx_pkt_length, (int) tx_pkt_nb_segs);
 
+       struct rte_eth_rxconf *rx_conf = &ports[0].rx_conf;
+       struct rte_eth_txconf *tx_conf = &ports[0].tx_conf;
+
        printf("  nb forwarding cores=%d - nb forwarding ports=%d\n",
               nb_fwd_lcores, nb_fwd_ports);
        printf("  RX queues=%d - RX desc=%d - RX free threshold=%d\n",
-              nb_rxq, nb_rxd, rx_free_thresh);
+              nb_rxq, nb_rxd, rx_conf->rx_free_thresh);
        printf("  RX threshold registers: pthresh=%d hthresh=%d wthresh=%d\n",
-              rx_thresh.pthresh, rx_thresh.hthresh, rx_thresh.wthresh);
+              rx_conf->rx_thresh.pthresh, rx_conf->rx_thresh.hthresh,
+              rx_conf->rx_thresh.wthresh);
        printf("  TX queues=%d - TX desc=%d - TX free threshold=%d\n",
-              nb_txq, nb_txd, tx_free_thresh);
+              nb_txq, nb_txd, tx_conf->tx_free_thresh);
        printf("  TX threshold registers: pthresh=%d hthresh=%d wthresh=%d\n",
-              tx_thresh.pthresh, tx_thresh.hthresh, tx_thresh.wthresh);
+              tx_conf->tx_thresh.pthresh, tx_conf->tx_thresh.hthresh,
+              tx_conf->tx_thresh.wthresh);
        printf("  TX RS bit threshold=%d - TXQ flags=0x%"PRIx32"\n",
-              tx_rs_thresh, txq_flags);
+              tx_conf->tx_rs_thresh, tx_conf->txq_flags);
 }
 
 void
@@ -796,7 +929,7 @@ port_rss_reta_info(portid_t port_id,
        uint16_t i, idx, shift;
        int ret;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
 
        ret = rte_eth_dev_rss_reta_query(port_id, reta_conf, nb_entries);
@@ -820,18 +953,26 @@ port_rss_reta_info(portid_t port_id,
  * key of the port.
  */
 void
-port_rss_hash_conf_show(portid_t port_id, int show_rss_key)
+port_rss_hash_conf_show(portid_t port_id, char rss_info[], int show_rss_key)
 {
        struct rte_eth_rss_conf rss_conf;
-       uint8_t rss_key[10 * 4];
+       uint8_t rss_key[10 * 4] = "";
        uint64_t rss_hf;
        uint8_t i;
        int diag;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
+
+       rss_conf.rss_hf = 0;
+       for (i = 0; i < RTE_DIM(rss_type_table); i++) {
+               if (!strcmp(rss_info, rss_type_table[i].str))
+                       rss_conf.rss_hf = rss_type_table[i].rss_type;
+       }
+
        /* Get RSS hash key if asked to display it */
        rss_conf.rss_key = (show_rss_key) ? rss_key : NULL;
+       rss_conf.rss_key_len = sizeof(rss_key);
        diag = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf);
        if (diag != 0) {
                switch (diag) {
@@ -853,24 +994,10 @@ port_rss_hash_conf_show(portid_t port_id, int show_rss_key)
                return;
        }
        printf("RSS functions:\n ");
-       if (rss_hf & ETH_RSS_IPV4)
-               printf("ip4");
-       if (rss_hf & ETH_RSS_IPV4_TCP)
-               printf(" tcp4");
-       if (rss_hf & ETH_RSS_IPV4_UDP)
-               printf(" udp4");
-       if (rss_hf & ETH_RSS_IPV6)
-               printf(" ip6");
-       if (rss_hf & ETH_RSS_IPV6_EX)
-               printf(" ip6-ex");
-       if (rss_hf & ETH_RSS_IPV6_TCP)
-               printf(" tcp6");
-       if (rss_hf & ETH_RSS_IPV6_TCP_EX)
-               printf(" tcp6-ex");
-       if (rss_hf & ETH_RSS_IPV6_UDP)
-               printf(" udp6");
-       if (rss_hf & ETH_RSS_IPV6_UDP_EX)
-               printf(" udp6-ex");
+       for (i = 0; i < RTE_DIM(rss_type_table); i++) {
+               if (rss_hf & rss_type_table[i].rss_type)
+                       printf("%s ", rss_type_table[i].str);
+       }
        printf("\n");
        if (!show_rss_key)
                return;
@@ -881,12 +1008,20 @@ port_rss_hash_conf_show(portid_t port_id, int show_rss_key)
 }
 
 void
-port_rss_hash_key_update(portid_t port_id, uint8_t *hash_key)
+port_rss_hash_key_update(portid_t port_id, char rss_type[], uint8_t *hash_key,
+                        uint hash_key_len)
 {
        struct rte_eth_rss_conf rss_conf;
        int diag;
+       unsigned int i;
 
        rss_conf.rss_key = NULL;
+       rss_conf.rss_key_len = hash_key_len;
+       rss_conf.rss_hf = 0;
+       for (i = 0; i < RTE_DIM(rss_type_table); i++) {
+               if (!strcmp(rss_type_table[i].str, rss_type))
+                       rss_conf.rss_hf = rss_type_table[i].rss_type;
+       }
        diag = rte_eth_dev_rss_hash_conf_get(port_id, &rss_conf);
        if (diag == 0) {
                rss_conf.rss_key = hash_key;
@@ -1087,113 +1222,89 @@ rss_fwd_config_setup(void)
        }
 }
 
-/*
- * In DCB and VT on,the mapping of 128 receive queues to 128 transmit queues.
- */
-static void
-dcb_rxq_2_txq_mapping(queueid_t rxq, queueid_t *txq)
-{
-       if(dcb_q_mapping == DCB_4_TCS_Q_MAPPING) {
-
-               if (rxq < 32)
-                       /* tc0: 0-31 */
-                       *txq = rxq;
-               else if (rxq < 64) {
-                       /* tc1: 64-95 */
-                       *txq =  (uint16_t)(rxq + 32);
-               }
-               else {
-                       /* tc2: 96-111;tc3:112-127 */
-                       *txq =  (uint16_t)(rxq/2 + 64);
-               }
-       }
-       else {
-               if (rxq < 16)
-                       /* tc0 mapping*/
-                       *txq = rxq;
-               else if (rxq < 32) {
-                       /* tc1 mapping*/
-                        *txq = (uint16_t)(rxq + 16);
-               }
-               else if (rxq < 64) {
-                       /*tc2,tc3 mapping */
-                       *txq =  (uint16_t)(rxq + 32);
-               }
-               else {
-                       /* tc4,tc5,tc6 and tc7 mapping */
-                       *txq =  (uint16_t)(rxq/2 + 64);
-               }
-       }
-}
-
 /**
- * For the DCB forwarding test, each core is assigned on every port multi-transmit
- * queue.
+ * For the DCB forwarding test, each core is assigned on each traffic class.
  *
  * Each core is assigned a multi-stream, each stream being composed of
  * a RX queue to poll on a RX port for input messages, associated with
- * a TX queue of a TX port where to send forwarded packets.
- * All packets received on the RX queue of index "RxQj" of the RX port "RxPi"
- * are sent on the TX queue "TxQl" of the TX port "TxPk" according to the two
- * following rules:
- * In VT mode,
- *    - TxPk = (RxPi + 1) if RxPi is even, (RxPi - 1) if RxPi is odd
- *    - TxQl = RxQj
- * In non-VT mode,
- *    - TxPk = (RxPi + 1) if RxPi is even, (RxPi - 1) if RxPi is odd
- *    There is a mapping of RxQj to TxQl to be required,and the mapping was implemented
- *    in dcb_rxq_2_txq_mapping function.
+ * a TX queue of a TX port where to send forwarded packets. All RX and
+ * TX queues are mapping to the same traffic class.
+ * If VMDQ and DCB co-exist, each traffic class on different POOLs share
+ * the same core
  */
 static void
 dcb_fwd_config_setup(void)
 {
-       portid_t   rxp;
-       portid_t   txp;
-       queueid_t  rxq;
-       queueid_t  nb_q;
+       struct rte_eth_dcb_info rxp_dcb_info, txp_dcb_info;
+       portid_t txp, rxp = 0;
+       queueid_t txq, rxq = 0;
        lcoreid_t  lc_id;
-       uint16_t sm_id;
-
-       nb_q = nb_rxq;
+       uint16_t nb_rx_queue, nb_tx_queue;
+       uint16_t i, j, k, sm_id = 0;
+       uint8_t tc = 0;
 
        cur_fwd_config.nb_fwd_lcores = (lcoreid_t) nb_fwd_lcores;
        cur_fwd_config.nb_fwd_ports = nb_fwd_ports;
        cur_fwd_config.nb_fwd_streams =
-               (streamid_t) (nb_q * cur_fwd_config.nb_fwd_ports);
+               (streamid_t) (nb_rxq * cur_fwd_config.nb_fwd_ports);
 
        /* reinitialize forwarding streams */
        init_fwd_streams();
+       sm_id = 0;
+       txp = 1;
+       /* get the dcb info on the first RX and TX ports */
+       (void)rte_eth_dev_get_dcb_info(fwd_ports_ids[rxp], &rxp_dcb_info);
+       (void)rte_eth_dev_get_dcb_info(fwd_ports_ids[txp], &txp_dcb_info);
 
-       setup_fwd_config_of_each_lcore(&cur_fwd_config);
-       rxp = 0; rxq = 0;
        for (lc_id = 0; lc_id < cur_fwd_config.nb_fwd_lcores; lc_id++) {
-               /* a fwd core can run multi-streams */
-               for (sm_id = 0; sm_id < fwd_lcores[lc_id]->stream_nb; sm_id++)
-               {
-                       struct fwd_stream *fs;
-                       fs = fwd_streams[fwd_lcores[lc_id]->stream_idx + sm_id];
-                       if ((rxp & 0x1) == 0)
-                               txp = (portid_t) (rxp + 1);
-                       else
-                               txp = (portid_t) (rxp - 1);
-                       fs->rx_port = fwd_ports_ids[rxp];
-                       fs->rx_queue = rxq;
-                       fs->tx_port = fwd_ports_ids[txp];
-                       if (dcb_q_mapping == DCB_VT_Q_MAPPING)
-                               fs->tx_queue = rxq;
-                       else
-                               dcb_rxq_2_txq_mapping(rxq, &fs->tx_queue);
-                       fs->peer_addr = fs->tx_port;
-                       rxq = (queueid_t) (rxq + 1);
-                       if (rxq < nb_q)
-                               continue;
-                       rxq = 0;
-                       if (numa_support && (nb_fwd_ports <= (nb_ports >> 1)))
-                               rxp = (portid_t)
-                                       (rxp + ((nb_ports >> 1) / nb_fwd_ports));
-                       else
-                               rxp = (portid_t) (rxp + 1);
+               fwd_lcores[lc_id]->stream_nb = 0;
+               fwd_lcores[lc_id]->stream_idx = sm_id;
+               for (i = 0; i < ETH_MAX_VMDQ_POOL; i++) {
+                       /* if the nb_queue is zero, means this tc is
+                        * not enabled on the POOL
+                        */
+                       if (rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue == 0)
+                               break;
+                       k = fwd_lcores[lc_id]->stream_nb +
+                               fwd_lcores[lc_id]->stream_idx;
+                       rxq = rxp_dcb_info.tc_queue.tc_rxq[i][tc].base;
+                       txq = txp_dcb_info.tc_queue.tc_txq[i][tc].base;
+                       nb_rx_queue = txp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue;
+                       nb_tx_queue = txp_dcb_info.tc_queue.tc_txq[i][tc].nb_queue;
+                       for (j = 0; j < nb_rx_queue; j++) {
+                               struct fwd_stream *fs;
+
+                               fs = fwd_streams[k + j];
+                               fs->rx_port = fwd_ports_ids[rxp];
+                               fs->rx_queue = rxq + j;
+                               fs->tx_port = fwd_ports_ids[txp];
+                               fs->tx_queue = txq + j % nb_tx_queue;
+                               fs->peer_addr = fs->tx_port;
+                       }
+                       fwd_lcores[lc_id]->stream_nb +=
+                               rxp_dcb_info.tc_queue.tc_rxq[i][tc].nb_queue;
                }
+               sm_id = (streamid_t) (sm_id + fwd_lcores[lc_id]->stream_nb);
+
+               tc++;
+               if (tc < rxp_dcb_info.nb_tcs)
+                       continue;
+               /* Restart from TC 0 on next RX port */
+               tc = 0;
+               if (numa_support && (nb_fwd_ports <= (nb_ports >> 1)))
+                       rxp = (portid_t)
+                               (rxp + ((nb_ports >> 1) / nb_fwd_ports));
+               else
+                       rxp++;
+               if (rxp >= nb_fwd_ports)
+                       return;
+               /* get the dcb information on next RX and TX ports */
+               if ((rxp & 0x1) == 0)
+                       txp = (portid_t) (rxp + 1);
+               else
+                       txp = (portid_t) (rxp - 1);
+               rte_eth_dev_get_dcb_info(fwd_ports_ids[rxp], &rxp_dcb_info);
+               rte_eth_dev_get_dcb_info(fwd_ports_ids[txp], &txp_dcb_info);
        }
 }
 
@@ -1237,7 +1348,7 @@ icmp_echo_config_setup(void)
                        fs->rx_port = fwd_ports_ids[rxp];
                        fs->rx_queue = rxq;
                        fs->tx_port = fs->rx_port;
-                       fs->tx_queue = lc_id;
+                       fs->tx_queue = rxq;
                        fs->peer_addr = fs->tx_port;
                        if (verbose_level > 0)
                                printf("  stream=%d port=%d rxq=%d txq=%d\n",
@@ -1313,10 +1424,6 @@ pkt_fwd_config_display(struct fwd_config *cfg)
 void
 fwd_config_display(void)
 {
-       if((dcb_config) && (nb_fwd_lcores == 1)) {
-               printf("In DCB mode,the nb forwarding cores should be larger than 1\n");
-               return;
-       }
        fwd_config_setup();
        pkt_fwd_config_display(&cur_fwd_config);
 }
@@ -1406,12 +1513,8 @@ set_fwd_ports_list(unsigned int *portlist, unsigned int nb_pt)
  again:
        for (i = 0; i < nb_pt; i++) {
                port_id = (portid_t) portlist[i];
-               if (port_id >= nb_ports) {
-                       printf("Invalid port id %u >= %u\n",
-                              (unsigned int) port_id,
-                              (unsigned int) nb_ports);
+               if (port_id_is_invalid(port_id, ENABLED_WARN))
                        return;
-               }
                if (record_now)
                        fwd_ports_ids[i] = port_id;
        }
@@ -1440,7 +1543,7 @@ set_fwd_ports_mask(uint64_t portmask)
                return;
        }
        nb_pt = 0;
-       for (i = 0; i < 64; i++) {
+       for (i = 0; i < (unsigned)RTE_MIN(64, RTE_MAX_ETHPORTS); i++) {
                if (! ((uint64_t)(1ULL << i) & portmask))
                        continue;
                portlist[nb_pt++] = i;
@@ -1476,6 +1579,49 @@ set_nb_pkt_per_burst(uint16_t nb)
               (unsigned int) nb_pkt_per_burst);
 }
 
+static const char *
+tx_split_get_name(enum tx_pkt_split split)
+{
+       uint32_t i;
+
+       for (i = 0; i != RTE_DIM(tx_split_name); i++) {
+               if (tx_split_name[i].split == split)
+                       return tx_split_name[i].name;
+       }
+       return NULL;
+}
+
+void
+set_tx_pkt_split(const char *name)
+{
+       uint32_t i;
+
+       for (i = 0; i != RTE_DIM(tx_split_name); i++) {
+               if (strcmp(tx_split_name[i].name, name) == 0) {
+                       tx_pkt_split = tx_split_name[i].split;
+                       return;
+               }
+       }
+       printf("unknown value: \"%s\"\n", name);
+}
+
+void
+show_tx_pkt_segments(void)
+{
+       uint32_t i, n;
+       const char *split;
+
+       n = tx_pkt_nb_segs;
+       split = tx_split_get_name(tx_pkt_split);
+
+       printf("Number of segments: %u\n", n);
+       printf("Segment sizes: ");
+       for (i = 0; i != n - 1; i++)
+               printf("%hu,", tx_pkt_seg_lengths[i]);
+       printf("%hu\n", tx_pkt_seg_lengths[i]);
+       printf("Split packet: %s\n", split);
+}
+
 void
 set_tx_pkt_segments(unsigned *seg_lengths, unsigned nb_segs)
 {
@@ -1569,7 +1715,7 @@ vlan_extend_set(portid_t port_id, int on)
        int diag;
        int vlan_offload;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
 
        vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
@@ -1591,7 +1737,7 @@ rx_vlan_strip_set(portid_t port_id, int on)
        int diag;
        int vlan_offload;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
 
        vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
@@ -1612,7 +1758,7 @@ rx_vlan_strip_set_on_queue(portid_t port_id, uint16_t queue_id, int on)
 {
        int diag;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
 
        diag = rte_eth_dev_set_vlan_strip_on_queue(port_id, queue_id, on);
@@ -1627,7 +1773,7 @@ rx_vlan_filter_set(portid_t port_id, int on)
        int diag;
        int vlan_offload;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
 
        vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
@@ -1643,21 +1789,22 @@ rx_vlan_filter_set(portid_t port_id, int on)
               "diag=%d\n", port_id, on, diag);
 }
 
-void
+int
 rx_vft_set(portid_t port_id, uint16_t vlan_id, int on)
 {
        int diag;
 
-       if (port_id_is_invalid(port_id))
-               return;
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
+               return 1;
        if (vlan_id_is_invalid(vlan_id))
-               return;
+               return 1;
        diag = rte_eth_dev_vlan_filter(port_id, vlan_id, on);
        if (diag == 0)
-               return;
+               return 0;
        printf("rte_eth_dev_vlan_filter(port_pi=%d, vlan_id=%d, on=%d) failed "
               "diag=%d\n",
               port_id, vlan_id, on, diag);
+       return -1;
 }
 
 void
@@ -1665,17 +1812,19 @@ rx_vlan_all_filter_set(portid_t port_id, int on)
 {
        uint16_t vlan_id;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
-       for (vlan_id = 0; vlan_id < 4096; vlan_id++)
-               rx_vft_set(port_id, vlan_id, on);
+       for (vlan_id = 0; vlan_id < 4096; vlan_id++) {
+               if (rx_vft_set(port_id, vlan_id, on))
+                       break;
+       }
 }
 
 void
 vlan_tpid_set(portid_t port_id, uint16_t tp_id)
 {
        int diag;
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
 
        diag = rte_eth_dev_set_vlan_ether_type(port_id, tp_id);
@@ -1690,26 +1839,45 @@ vlan_tpid_set(portid_t port_id, uint16_t tp_id)
 void
 tx_vlan_set(portid_t port_id, uint16_t vlan_id)
 {
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
        if (vlan_id_is_invalid(vlan_id))
                return;
+       tx_vlan_reset(port_id);
        ports[port_id].tx_ol_flags |= TESTPMD_TX_OFFLOAD_INSERT_VLAN;
        ports[port_id].tx_vlan_id = vlan_id;
 }
 
+void
+tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer)
+{
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
+               return;
+       if (vlan_id_is_invalid(vlan_id))
+               return;
+       if (vlan_id_is_invalid(vlan_id_outer))
+               return;
+       tx_vlan_reset(port_id);
+       ports[port_id].tx_ol_flags |= TESTPMD_TX_OFFLOAD_INSERT_QINQ;
+       ports[port_id].tx_vlan_id = vlan_id;
+       ports[port_id].tx_vlan_id_outer = vlan_id_outer;
+}
+
 void
 tx_vlan_reset(portid_t port_id)
 {
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
-       ports[port_id].tx_ol_flags &= ~TESTPMD_TX_OFFLOAD_INSERT_VLAN;
+       ports[port_id].tx_ol_flags &= ~(TESTPMD_TX_OFFLOAD_INSERT_VLAN |
+                               TESTPMD_TX_OFFLOAD_INSERT_QINQ);
+       ports[port_id].tx_vlan_id = 0;
+       ports[port_id].tx_vlan_id_outer = 0;
 }
 
 void
 tx_vlan_pvid_set(portid_t port_id, uint16_t vlan_id, int on)
 {
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
 
        rte_eth_dev_set_vlan_pvid(port_id, vlan_id, on);
@@ -1721,7 +1889,7 @@ set_qmap(portid_t port_id, uint8_t is_rx, uint16_t queue_id, uint8_t map_value)
        uint16_t i;
        uint8_t existing_mapping_found = 0;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
 
        if (is_rx ? (rx_queue_id_is_invalid(queue_id)) : (tx_queue_id_is_invalid(queue_id)))
@@ -1767,69 +1935,45 @@ set_qmap(portid_t port_id, uint8_t is_rx, uint16_t queue_id, uint8_t map_value)
        }
 }
 
-void
-fdir_add_signature_filter(portid_t port_id, uint8_t queue_id,
-                         struct rte_fdir_filter *fdir_filter)
-{
-       int diag;
-
-       if (port_id_is_invalid(port_id))
-               return;
-
-       diag = rte_eth_dev_fdir_add_signature_filter(port_id, fdir_filter,
-                                                    queue_id);
-       if (diag == 0)
-               return;
-
-       printf("rte_eth_dev_fdir_add_signature_filter for port_id=%d failed "
-              "diag=%d\n", port_id, diag);
-}
-
-void
-fdir_update_signature_filter(portid_t port_id, uint8_t queue_id,
-                            struct rte_fdir_filter *fdir_filter)
-{
-       int diag;
-
-       if (port_id_is_invalid(port_id))
-               return;
-
-       diag = rte_eth_dev_fdir_update_signature_filter(port_id, fdir_filter,
-                                                       queue_id);
-       if (diag == 0)
-               return;
-
-       printf("rte_eth_dev_fdir_update_signature_filter for port_id=%d failed "
-              "diag=%d\n", port_id, diag);
-}
-
-void
-fdir_remove_signature_filter(portid_t port_id,
-                            struct rte_fdir_filter *fdir_filter)
+static inline void
+print_fdir_mask(struct rte_eth_fdir_masks *mask)
 {
-       int diag;
+       printf("\n    vlan_tci: 0x%04x, ", mask->vlan_tci_mask);
 
-       if (port_id_is_invalid(port_id))
-               return;
-
-       diag = rte_eth_dev_fdir_remove_signature_filter(port_id, fdir_filter);
-       if (diag == 0)
-               return;
+       if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN)
+               printf("mac_addr: 0x%02x", mask->mac_addr_byte_mask);
+       else if (fdir_conf.mode == RTE_FDIR_MODE_PERFECT_TUNNEL)
+               printf("mac_addr: 0x%02x, tunnel_type: 0x%01x, tunnel_id: 0x%08x",
+                       mask->mac_addr_byte_mask, mask->tunnel_type_mask,
+                       mask->tunnel_id_mask);
+       else {
+               printf("src_ipv4: 0x%08x, dst_ipv4: 0x%08x,"
+                       " src_port: 0x%04x, dst_port: 0x%04x",
+                       mask->ipv4_mask.src_ip, mask->ipv4_mask.dst_ip,
+                       mask->src_port_mask, mask->dst_port_mask);
 
-       printf("rte_eth_dev_fdir_add_signature_filter for port_id=%d failed "
-              "diag=%d\n", port_id, diag);
+               printf("\n    src_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x,"
+                       " dst_ipv6: 0x%08x,0x%08x,0x%08x,0x%08x",
+                       mask->ipv6_mask.src_ip[0], mask->ipv6_mask.src_ip[1],
+                       mask->ipv6_mask.src_ip[2], mask->ipv6_mask.src_ip[3],
+                       mask->ipv6_mask.dst_ip[0], mask->ipv6_mask.dst_ip[1],
+                       mask->ipv6_mask.dst_ip[2], mask->ipv6_mask.dst_ip[3]);
+       }
 
+       printf("\n");
 }
 
 static inline void
-print_fdir_flex_payload(struct rte_eth_fdir_flex_conf *flex_conf)
+print_fdir_flex_payload(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num)
 {
        struct rte_eth_flex_payload_cfg *cfg;
-       int i, j;
+       uint32_t i, j;
 
        for (i = 0; i < flex_conf->nb_payloads; i++) {
                cfg = &flex_conf->flex_set[i];
-               if (cfg->type == RTE_ETH_L2_PAYLOAD)
+               if (cfg->type == RTE_ETH_RAW_PAYLOAD)
+                       printf("\n    RAW:  ");
+               else if (cfg->type == RTE_ETH_L2_PAYLOAD)
                        printf("\n    L2_PAYLOAD:  ");
                else if (cfg->type == RTE_ETH_L3_PAYLOAD)
                        printf("\n    L3_PAYLOAD:  ");
@@ -1837,22 +1981,58 @@ print_fdir_flex_payload(struct rte_eth_fdir_flex_conf *flex_conf)
                        printf("\n    L4_PAYLOAD:  ");
                else
                        printf("\n    UNKNOWN PAYLOAD(%u):  ", cfg->type);
-               for (j = 0; j < RTE_ETH_FDIR_MAX_FLEXLEN; j++)
+               for (j = 0; j < num; j++)
                        printf("  %-5u", cfg->src_offset[j]);
        }
        printf("\n");
 }
 
+static char *
+flowtype_to_str(uint16_t flow_type)
+{
+       struct flow_type_info {
+               char str[32];
+               uint16_t ftype;
+       };
+
+       uint8_t i;
+       static struct flow_type_info flowtype_str_table[] = {
+               {"raw", RTE_ETH_FLOW_RAW},
+               {"ipv4", RTE_ETH_FLOW_IPV4},
+               {"ipv4-frag", RTE_ETH_FLOW_FRAG_IPV4},
+               {"ipv4-tcp", RTE_ETH_FLOW_NONFRAG_IPV4_TCP},
+               {"ipv4-udp", RTE_ETH_FLOW_NONFRAG_IPV4_UDP},
+               {"ipv4-sctp", RTE_ETH_FLOW_NONFRAG_IPV4_SCTP},
+               {"ipv4-other", RTE_ETH_FLOW_NONFRAG_IPV4_OTHER},
+               {"ipv6", RTE_ETH_FLOW_IPV6},
+               {"ipv6-frag", RTE_ETH_FLOW_FRAG_IPV6},
+               {"ipv6-tcp", RTE_ETH_FLOW_NONFRAG_IPV6_TCP},
+               {"ipv6-udp", RTE_ETH_FLOW_NONFRAG_IPV6_UDP},
+               {"ipv6-sctp", RTE_ETH_FLOW_NONFRAG_IPV6_SCTP},
+               {"ipv6-other", RTE_ETH_FLOW_NONFRAG_IPV6_OTHER},
+               {"l2_payload", RTE_ETH_FLOW_L2_PAYLOAD},
+       };
+
+       for (i = 0; i < RTE_DIM(flowtype_str_table); i++) {
+               if (flowtype_str_table[i].ftype == flow_type)
+                       return flowtype_str_table[i].str;
+       }
+
+       return NULL;
+}
+
 static inline void
-print_fdir_flex_mask(struct rte_eth_fdir_flex_conf *flex_conf)
+print_fdir_flex_mask(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num)
 {
        struct rte_eth_fdir_flex_mask *mask;
-       int i, j;
+       uint32_t i, j;
+       char *p;
 
        for (i = 0; i < flex_conf->nb_flexmasks; i++) {
                mask = &flex_conf->flex_mask[i];
-               printf("\n    %s:\t", flowtype_str[mask->flow_type]);
-               for (j = 0; j < RTE_ETH_FDIR_MAX_FLEXLEN; j++)
+               p = flowtype_to_str(mask->flow_type);
+               printf("\n    %s:\t", p ? p : "unknown");
+               for (j = 0; j < num; j++)
                        printf(" %02x", mask->mask[j]);
        }
        printf("\n");
@@ -1861,13 +2041,17 @@ print_fdir_flex_mask(struct rte_eth_fdir_flex_conf *flex_conf)
 static inline void
 print_fdir_flow_type(uint32_t flow_types_mask)
 {
-       int i = 0;
+       int i;
+       char *p;
 
-       for (i = RTE_ETH_FLOW_TYPE_UDPV4;
-            i <= RTE_ETH_FLOW_TYPE_FRAG_IPV6;
-            i++) {
-               if (flow_types_mask & (1 << i))
-                       printf(" %s", flowtype_str[i]);
+       for (i = RTE_ETH_FLOW_UNKNOWN; i < RTE_ETH_FLOW_MAX; i++) {
+               if (!(flow_types_mask & (1 << i)))
+                       continue;
+               p = flowtype_to_str(i);
+               if (p)
+                       printf(" %s", p);
+               else
+                       printf(" unknown");
        }
        printf("\n");
 }
@@ -1881,30 +2065,12 @@ fdir_get_infos(portid_t port_id)
 
        static const char *fdir_stats_border = "########################";
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
        ret = rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_FDIR);
        if (ret < 0) {
-               /* use the old fdir APIs to get info */
-               struct rte_eth_fdir fdir;
-               memset(&fdir, 0, sizeof(fdir));
-               ret = rte_eth_dev_fdir_get_infos(port_id, &fdir);
-               if (ret < 0) {
-                       printf("\n getting fdir info fails on port %-2d\n",
-                               port_id);
-                       return;
-               }
-               printf("\n  %s FDIR infos for port %-2d     %s\n",
-                       fdir_stats_border, port_id, fdir_stats_border);
-               printf("  collision: %-10"PRIu64"  free:     %"PRIu64"\n"
-                      "  maxhash:   %-10"PRIu64"  maxlen:   %"PRIu64"\n"
-                      "  add:       %-10"PRIu64"  remove:   %"PRIu64"\n"
-                      "  f_add:     %-10"PRIu64"  f_remove: %"PRIu64"\n",
-                      (uint64_t)(fdir.collision), (uint64_t)(fdir.free),
-                      (uint64_t)(fdir.maxhash), (uint64_t)(fdir.maxlen),
-                      fdir.add, fdir.remove, fdir.f_add, fdir.f_remove);
-               printf("  %s############################%s\n",
-                      fdir_stats_border, fdir_stats_border);
+               printf("\n FDIR is not supported on port %-2d\n",
+                       port_id);
                return;
        }
 
@@ -1918,13 +2084,20 @@ fdir_get_infos(portid_t port_id)
               fdir_stats_border, port_id, fdir_stats_border);
        printf("  MODE: ");
        if (fdir_info.mode == RTE_FDIR_MODE_PERFECT)
-                       printf("  PERFECT\n");
+               printf("  PERFECT\n");
+       else if (fdir_info.mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN)
+               printf("  PERFECT-MAC-VLAN\n");
+       else if (fdir_info.mode == RTE_FDIR_MODE_PERFECT_TUNNEL)
+               printf("  PERFECT-TUNNEL\n");
        else if (fdir_info.mode == RTE_FDIR_MODE_SIGNATURE)
-                       printf("  SIGNATURE\n");
+               printf("  SIGNATURE\n");
        else
-                       printf("  DISABLE\n");
-       printf("  SUPPORTED FLOW TYPE: ");
-       print_fdir_flow_type(fdir_info.flow_types_mask[0]);
+               printf("  DISABLE\n");
+       if (fdir_info.mode != RTE_FDIR_MODE_PERFECT_MAC_VLAN
+               && fdir_info.mode != RTE_FDIR_MODE_PERFECT_TUNNEL) {
+               printf("  SUPPORTED FLOW TYPE: ");
+               print_fdir_flow_type(fdir_info.flow_types_mask[0]);
+       }
        printf("  FLEX PAYLOAD INFO:\n");
        printf("  max_len:       %-10"PRIu32"  payload_limit: %-10"PRIu32"\n"
               "  payload_unit:  %-10"PRIu32"  payload_seg:   %-10"PRIu32"\n"
@@ -1933,92 +2106,32 @@ fdir_get_infos(portid_t port_id)
                fdir_info.flex_payload_unit,
                fdir_info.max_flex_payload_segment_num,
                fdir_info.flex_bitmask_unit, fdir_info.max_flex_bitmask_num);
+       printf("  MASK: ");
+       print_fdir_mask(&fdir_info.mask);
        if (fdir_info.flex_conf.nb_payloads > 0) {
                printf("  FLEX PAYLOAD SRC OFFSET:");
-               print_fdir_flex_payload(&fdir_info.flex_conf);
+               print_fdir_flex_payload(&fdir_info.flex_conf, fdir_info.max_flexpayload);
        }
        if (fdir_info.flex_conf.nb_flexmasks > 0) {
                printf("  FLEX MASK CFG:");
-               print_fdir_flex_mask(&fdir_info.flex_conf);
+               print_fdir_flex_mask(&fdir_info.flex_conf, fdir_info.max_flexpayload);
        }
-       printf("  guarant_count: %-10"PRIu32"  best_count:    %-10"PRIu32"\n",
+       printf("  guarant_count: %-10"PRIu32"  best_count:    %"PRIu32"\n",
               fdir_stat.guarant_cnt, fdir_stat.best_cnt);
-       printf("  guarant_space: %-10"PRIu32"  best_space:    %-10"PRIu32"\n",
-              fdir_info.guarant_spc, fdir_info.guarant_spc);
+       printf("  guarant_space: %-10"PRIu32"  best_space:    %"PRIu32"\n",
+              fdir_info.guarant_spc, fdir_info.best_spc);
+       printf("  collision:     %-10"PRIu32"  free:          %"PRIu32"\n"
+              "  maxhash:       %-10"PRIu32"  maxlen:        %"PRIu32"\n"
+              "  add:           %-10"PRIu64"  remove:        %"PRIu64"\n"
+              "  f_add:         %-10"PRIu64"  f_remove:      %"PRIu64"\n",
+              fdir_stat.collision, fdir_stat.free,
+              fdir_stat.maxhash, fdir_stat.maxlen,
+              fdir_stat.add, fdir_stat.remove,
+              fdir_stat.f_add, fdir_stat.f_remove);
        printf("  %s############################%s\n",
               fdir_stats_border, fdir_stats_border);
 }
 
-void
-fdir_add_perfect_filter(portid_t port_id, uint16_t soft_id, uint8_t queue_id,
-                       uint8_t drop, struct rte_fdir_filter *fdir_filter)
-{
-       int diag;
-
-       if (port_id_is_invalid(port_id))
-               return;
-
-       diag = rte_eth_dev_fdir_add_perfect_filter(port_id, fdir_filter,
-                                                  soft_id, queue_id, drop);
-       if (diag == 0)
-               return;
-
-       printf("rte_eth_dev_fdir_add_perfect_filter for port_id=%d failed "
-              "diag=%d\n", port_id, diag);
-}
-
-void
-fdir_update_perfect_filter(portid_t port_id, uint16_t soft_id, uint8_t queue_id,
-                          uint8_t drop, struct rte_fdir_filter *fdir_filter)
-{
-       int diag;
-
-       if (port_id_is_invalid(port_id))
-               return;
-
-       diag = rte_eth_dev_fdir_update_perfect_filter(port_id, fdir_filter,
-                                                     soft_id, queue_id, drop);
-       if (diag == 0)
-               return;
-
-       printf("rte_eth_dev_fdir_update_perfect_filter for port_id=%d failed "
-              "diag=%d\n", port_id, diag);
-}
-
-void
-fdir_remove_perfect_filter(portid_t port_id, uint16_t soft_id,
-                          struct rte_fdir_filter *fdir_filter)
-{
-       int diag;
-
-       if (port_id_is_invalid(port_id))
-               return;
-
-       diag = rte_eth_dev_fdir_remove_perfect_filter(port_id, fdir_filter,
-                                                     soft_id);
-       if (diag == 0)
-               return;
-
-       printf("rte_eth_dev_fdir_update_perfect_filter for port_id=%d failed "
-              "diag=%d\n", port_id, diag);
-}
-
-void
-fdir_set_masks(portid_t port_id, struct rte_fdir_masks *fdir_masks)
-{
-       int diag;
-
-       if (port_id_is_invalid(port_id))
-               return;
-
-       diag = rte_eth_dev_fdir_set_masks(port_id, fdir_masks);
-       if (diag == 0)
-               return;
-
-       printf("rte_eth_dev_set_masks_filter for port_id=%d failed "
-              "diag=%d\n", port_id, diag);
-}
-
 void
 fdir_set_flex_mask(portid_t port_id, struct rte_eth_fdir_flex_mask *cfg)
 {
@@ -2028,13 +2141,13 @@ fdir_set_flex_mask(portid_t port_id, struct rte_eth_fdir_flex_mask *cfg)
 
        port = &ports[port_id];
        flex_conf = &port->dev_conf.fdir_conf.flex_conf;
-       for (i = 0; i < RTE_ETH_FLOW_TYPE_MAX; i++) {
+       for (i = 0; i < RTE_ETH_FLOW_MAX; i++) {
                if (cfg->flow_type == flex_conf->flex_mask[i].flow_type) {
                        idx = i;
                        break;
                }
        }
-       if (i >= RTE_ETH_FLOW_TYPE_MAX) {
+       if (i >= RTE_ETH_FLOW_MAX) {
                if (flex_conf->nb_flexmasks < RTE_DIM(flex_conf->flex_mask)) {
                        idx = flex_conf->nb_flexmasks;
                        flex_conf->nb_flexmasks++;
@@ -2085,7 +2198,7 @@ set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on)
 {
        int diag;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
        if (is_rx)
                diag = rte_eth_dev_set_vf_rx(port_id,vf,on);
@@ -2107,7 +2220,7 @@ set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, uint64_t vf_mask, uint8_t on)
 {
        int diag;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
        if (vlan_id_is_invalid(vlan_id))
                return;
@@ -2124,7 +2237,7 @@ set_queue_rate_limit(portid_t port_id, uint16_t queue_idx, uint16_t rate)
        int diag;
        struct rte_eth_link link;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return 1;
        rte_eth_link_get_nowait(port_id, &link);
        if (rate > link.link_speed) {
@@ -2149,7 +2262,7 @@ set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk)
        if (q_msk == 0)
                return 0;
 
-       if (port_id_is_invalid(port_id))
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return 1;
        rte_eth_link_get_nowait(port_id, &link);
        if (rate > link.link_speed) {
@@ -2165,150 +2278,187 @@ set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk)
        return diag;
 }
 
-void
-get_ethertype_filter(uint8_t port_id, uint16_t index)
+/*
+ * Functions to manage the set of filtered Multicast MAC addresses.
+ *
+ * A pool of filtered multicast MAC addresses is associated with each port.
+ * The pool is allocated in chunks of MCAST_POOL_INC multicast addresses.
+ * The address of the pool and the number of valid multicast MAC addresses
+ * recorded in the pool are stored in the fields "mc_addr_pool" and
+ * "mc_addr_nb" of the "rte_port" data structure.
+ *
+ * The function "rte_eth_dev_set_mc_addr_list" of the PMDs API imposes
+ * to be supplied a contiguous array of multicast MAC addresses.
+ * To comply with this constraint, the set of multicast addresses recorded
+ * into the pool are systematically compacted at the beginning of the pool.
+ * Hence, when a multicast address is removed from the pool, all following
+ * addresses, if any, are copied back to keep the set contiguous.
+ */
+#define MCAST_POOL_INC 32
+
+static int
+mcast_addr_pool_extend(struct rte_port *port)
 {
-       struct rte_ethertype_filter filter;
-       int ret = 0;
-       uint16_t rx_queue;
+       struct ether_addr *mc_pool;
+       size_t mc_pool_size;
 
-       memset(&filter, 0, sizeof(filter));
-       ret = rte_eth_dev_get_ethertype_filter(port_id, index,
-                               &filter, &rx_queue);
-       if (ret < 0) {
-               if (ret == (-ENOENT))
-                       printf("filter[%d] is not enabled\n", index);
-               else
-                       printf("get ethertype filter fails(%s)\n", strerror(-ret));
-               return;
-       } else {
-               printf("filter[%d]:\n", index);
-               printf("    ethertype:  0x%04x\n",
-                       rte_le_to_cpu_32(filter.ethertype));
-               printf("    priority: %s, %d\n",
-                       filter.priority_en ? "enable" : "disable",
-                       filter.priority);
-               printf("    queue: %d\n", rx_queue);
+       /*
+        * If a free entry is available at the end of the pool, just
+        * increment the number of recorded multicast addresses.
+        */
+       if ((port->mc_addr_nb % MCAST_POOL_INC) != 0) {
+               port->mc_addr_nb++;
+               return 0;
        }
-}
 
-void
-get_syn_filter(uint8_t port_id)
-{
-       struct rte_syn_filter filter;
-       int ret = 0;
-       uint16_t rx_queue;
+       /*
+        * [re]allocate a pool with MCAST_POOL_INC more entries.
+        * The previous test guarantees that port->mc_addr_nb is a multiple
+        * of MCAST_POOL_INC.
+        */
+       mc_pool_size = sizeof(struct ether_addr) * (port->mc_addr_nb +
+                                                   MCAST_POOL_INC);
+       mc_pool = (struct ether_addr *) realloc(port->mc_addr_pool,
+                                               mc_pool_size);
+       if (mc_pool == NULL) {
+               printf("allocation of pool of %u multicast addresses failed\n",
+                      port->mc_addr_nb + MCAST_POOL_INC);
+               return -ENOMEM;
+       }
+
+       port->mc_addr_pool = mc_pool;
+       port->mc_addr_nb++;
+       return 0;
 
-       memset(&filter, 0, sizeof(filter));
-       ret = rte_eth_dev_get_syn_filter(port_id, &filter, &rx_queue);
+}
 
-       if (ret < 0) {
-               if (ret == (-ENOENT))
-                       printf("syn filter is not enabled\n");
-               else
-                       printf("get syn filter fails(%s)\n", strerror(-ret));
+static void
+mcast_addr_pool_remove(struct rte_port *port, uint32_t addr_idx)
+{
+       port->mc_addr_nb--;
+       if (addr_idx == port->mc_addr_nb) {
+               /* No need to recompact the set of multicast addressses. */
+               if (port->mc_addr_nb == 0) {
+                       /* free the pool of multicast addresses. */
+                       free(port->mc_addr_pool);
+                       port->mc_addr_pool = NULL;
+               }
                return;
        }
-       printf("syn filter: priority: %s, queue: %d\n",
-               filter.hig_pri ? "high" : "low",
-               rx_queue);
+       memmove(&port->mc_addr_pool[addr_idx],
+               &port->mc_addr_pool[addr_idx + 1],
+               sizeof(struct ether_addr) * (port->mc_addr_nb - addr_idx));
 }
-void
-get_2tuple_filter(uint8_t port_id, uint16_t index)
+
+static void
+eth_port_multicast_addr_list_set(uint8_t port_id)
 {
-       struct rte_2tuple_filter filter;
-       int ret = 0;
-       uint16_t rx_queue;
+       struct rte_port *port;
+       int diag;
 
-       memset(&filter, 0, sizeof(filter));
-       ret = rte_eth_dev_get_2tuple_filter(port_id, index,
-                               &filter, &rx_queue);
-       if (ret < 0) {
-               if (ret == (-ENOENT))
-                       printf("filter[%d] is not enabled\n", index);
-               else
-                       printf("get 2tuple filter fails(%s)\n", strerror(-ret));
+       port = &ports[port_id];
+       diag = rte_eth_dev_set_mc_addr_list(port_id, port->mc_addr_pool,
+                                           port->mc_addr_nb);
+       if (diag == 0)
                return;
-       } else {
-               printf("filter[%d]:\n", index);
-               printf("    Destination Port:     0x%04x    mask: %d\n",
-                       rte_be_to_cpu_16(filter.dst_port),
-                       filter.dst_port_mask ? 0 : 1);
-               printf("    protocol:  0x%02x     mask:%d     tcp_flags: 0x%02x\n",
-                       filter.protocol, filter.protocol_mask ? 0 : 1,
-                       filter.tcp_flags);
-               printf("    priority: %d    queue: %d\n",
-                       filter.priority, rx_queue);
-       }
+       printf("rte_eth_dev_set_mc_addr_list(port=%d, nb=%u) failed. diag=%d\n",
+              port->mc_addr_nb, port_id, -diag);
 }
 
 void
-get_5tuple_filter(uint8_t port_id, uint16_t index)
+mcast_addr_add(uint8_t port_id, struct ether_addr *mc_addr)
 {
-       struct rte_5tuple_filter filter;
-       int ret = 0;
-       uint16_t rx_queue;
+       struct rte_port *port;
+       uint32_t i;
 
-       memset(&filter, 0, sizeof(filter));
-       ret = rte_eth_dev_get_5tuple_filter(port_id, index,
-                               &filter, &rx_queue);
-       if (ret < 0) {
-               if (ret == (-ENOENT))
-                       printf("filter[%d] is not enabled\n", index);
-               else
-                       printf("get 5tuple filter fails(%s)\n", strerror(-ret));
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
-       } else {
-               printf("filter[%d]:\n", index);
-               printf("    Destination IP:  0x%08x    mask: %d\n",
-                       (unsigned)rte_be_to_cpu_32(filter.dst_ip),
-                       filter.dst_ip_mask ? 0 : 1);
-               printf("    Source IP:       0x%08x    mask: %d\n",
-                       (unsigned)rte_be_to_cpu_32(filter.src_ip),
-                       filter.src_ip_mask ? 0 : 1);
-               printf("    Destination Port:       0x%04x    mask: %d\n",
-                       rte_be_to_cpu_16(filter.dst_port),
-                       filter.dst_port_mask ? 0 : 1);
-               printf("    Source Port:       0x%04x    mask: %d\n",
-                       rte_be_to_cpu_16(filter.src_port),
-                       filter.src_port_mask ? 0 : 1);
-               printf("    protocol:           0x%02x    mask: %d\n",
-                       filter.protocol,
-                       filter.protocol_mask ? 0 : 1);
-               printf("    priority: %d    flags: 0x%02x    queue: %d\n",
-                       filter.priority, filter.tcp_flags, rx_queue);
+
+       port = &ports[port_id];
+
+       /*
+        * Check that the added multicast MAC address is not already recorded
+        * in the pool of multicast addresses.
+        */
+       for (i = 0; i < port->mc_addr_nb; i++) {
+               if (is_same_ether_addr(mc_addr, &port->mc_addr_pool[i])) {
+                       printf("multicast address already filtered by port\n");
+                       return;
+               }
        }
+
+       if (mcast_addr_pool_extend(port) != 0)
+               return;
+       ether_addr_copy(mc_addr, &port->mc_addr_pool[i]);
+       eth_port_multicast_addr_list_set(port_id);
 }
-void
-get_flex_filter(uint8_t port_id, uint16_t index)
 
+void
+mcast_addr_remove(uint8_t port_id, struct ether_addr *mc_addr)
 {
-       struct rte_flex_filter filter;
-       int ret = 0;
-       uint16_t rx_queue;
-       int i, j;
+       struct rte_port *port;
+       uint32_t i;
 
-       memset(&filter, 0, sizeof(filter));
-       ret = rte_eth_dev_get_flex_filter(port_id, index,
-                               &filter, &rx_queue);
-       if (ret < 0) {
-               if (ret == (-ENOENT))
-                       printf("filter[%d] is not enabled\n", index);
-               else
-                       printf("get flex filter fails(%s)\n", strerror(-ret));
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
                return;
-       } else {
-               printf("filter[%d]: ", index);
-               printf("\n    length: %d", filter.len);
-               printf("\n    dword[]: 0x");
-               for (i = 0; i < 32; i++)
-                       printf("%08x ", (unsigned)rte_be_to_cpu_32(filter.dwords[i]));
-               printf("\n    mask[]: 0b");
-               for (i = 0; i < 16; i++) {
-                       for (j = 0; j < 8; j++)
-                               printf("%c", (filter.mask[i] & (1 << j)) ? '1' : '0');
-               }
-               printf("\n    priority: %d    queue: %d\n",
-                       filter.priority, rx_queue);
+
+       port = &ports[port_id];
+
+       /*
+        * Search the pool of multicast MAC addresses for the removed address.
+        */
+       for (i = 0; i < port->mc_addr_nb; i++) {
+               if (is_same_ether_addr(mc_addr, &port->mc_addr_pool[i]))
+                       break;
        }
+       if (i == port->mc_addr_nb) {
+               printf("multicast address not filtered by port %d\n", port_id);
+               return;
+       }
+
+       mcast_addr_pool_remove(port, i);
+       eth_port_multicast_addr_list_set(port_id);
+}
+
+void
+port_dcb_info_display(uint8_t port_id)
+{
+       struct rte_eth_dcb_info dcb_info;
+       uint16_t i;
+       int ret;
+       static const char *border = "================";
+
+       if (port_id_is_invalid(port_id, ENABLED_WARN))
+               return;
+
+       ret = rte_eth_dev_get_dcb_info(port_id, &dcb_info);
+       if (ret) {
+               printf("\n Failed to get dcb infos on port %-2d\n",
+                       port_id);
+               return;
+       }
+       printf("\n  %s DCB infos for port %-2d  %s\n", border, port_id, border);
+       printf("  TC NUMBER: %d\n", dcb_info.nb_tcs);
+       printf("\n  TC :        ");
+       for (i = 0; i < dcb_info.nb_tcs; i++)
+               printf("\t%4d", i);
+       printf("\n  Priority :  ");
+       for (i = 0; i < dcb_info.nb_tcs; i++)
+               printf("\t%4d", dcb_info.prio_tc[i]);
+       printf("\n  BW percent :");
+       for (i = 0; i < dcb_info.nb_tcs; i++)
+               printf("\t%4d%%", dcb_info.tc_bws[i]);
+       printf("\n  RXQ base :  ");
+       for (i = 0; i < dcb_info.nb_tcs; i++)
+               printf("\t%4d", dcb_info.tc_queue.tc_rxq[0][i].base);
+       printf("\n  RXQ number :");
+       for (i = 0; i < dcb_info.nb_tcs; i++)
+               printf("\t%4d", dcb_info.tc_queue.tc_rxq[0][i].nb_queue);
+       printf("\n  TXQ base :  ");
+       for (i = 0; i < dcb_info.nb_tcs; i++)
+               printf("\t%4d", dcb_info.tc_queue.tc_txq[0][i].base);
+       printf("\n  TXQ number :");
+       for (i = 0; i < dcb_info.nb_tcs; i++)
+               printf("\t%4d", dcb_info.tc_queue.tc_txq[0][i].nb_queue);
+       printf("\n");
 }