New upstream version 18.08
[deb_dpdk.git] / app / test-pmd / testpmd.c
index 4c0e258..ee48db2 100644 (file)
@@ -12,6 +12,7 @@
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <errno.h>
+#include <stdbool.h>
 
 #include <sys/queue.h>
 #include <sys/stat.h>
@@ -126,6 +127,8 @@ portid_t nb_ports;             /**< Number of probed ethernet ports. */
 struct fwd_lcore **fwd_lcores; /**< For all probed logical cores. */
 lcoreid_t nb_lcores;           /**< Number of probed logical cores. */
 
+portid_t ports_ids[RTE_MAX_ETHPORTS]; /**< Store all port ids. */
+
 /*
  * Test Forwarding Configuration.
  *    nb_fwd_lcores <= nb_cfg_lcores <= nb_lcores
@@ -154,9 +157,8 @@ struct fwd_engine * fwd_engines[] = {
        &tx_only_engine,
        &csum_fwd_engine,
        &icmp_echo_engine,
-#if defined RTE_LIBRTE_PMD_SOFTNIC && defined RTE_LIBRTE_SCHED
-       &softnic_tm_engine,
-       &softnic_tm_bypass_engine,
+#if defined RTE_LIBRTE_PMD_SOFTNIC
+       &softnic_fwd_engine,
 #endif
 #ifdef RTE_LIBRTE_IEEE1588
        &ieee1588_fwd_engine,
@@ -210,9 +212,10 @@ queueid_t nb_txq = 1; /**< Number of TX queues per port. */
 
 /*
  * Configurable number of RX/TX ring descriptors.
+ * Defaults are supplied by drivers via ethdev.
  */
-#define RTE_TEST_RX_DESC_DEFAULT 1024
-#define RTE_TEST_TX_DESC_DEFAULT 1024
+#define RTE_TEST_RX_DESC_DEFAULT 0
+#define RTE_TEST_TX_DESC_DEFAULT 0
 uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; /**< Number of RX descriptors. */
 uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; /**< Number of TX descriptors. */
 
@@ -284,6 +287,8 @@ uint8_t lsc_interrupt = 1; /* enabled by default */
  */
 uint8_t rmv_interrupt = 1; /* enabled by default */
 
+uint8_t hot_plug = 0; /**< hotplug disabled by default. */
+
 /*
  * Display or mask ether events
  * Default to all events except VF_MBOX
@@ -292,8 +297,13 @@ uint32_t event_print_mask = (UINT32_C(1) << RTE_ETH_EVENT_UNKNOWN) |
                            (UINT32_C(1) << RTE_ETH_EVENT_INTR_LSC) |
                            (UINT32_C(1) << RTE_ETH_EVENT_QUEUE_STATE) |
                            (UINT32_C(1) << RTE_ETH_EVENT_INTR_RESET) |
+                           (UINT32_C(1) << RTE_ETH_EVENT_IPSEC) |
                            (UINT32_C(1) << RTE_ETH_EVENT_MACSEC) |
                            (UINT32_C(1) << RTE_ETH_EVENT_INTR_RMV);
+/*
+ * Decide if all memory are locked for performance.
+ */
+int do_mlockall = 0;
 
 /*
  * NIC bypass mode configuration options.
@@ -325,7 +335,6 @@ lcoreid_t latencystats_lcore_id = -1;
 struct rte_eth_rxmode rx_mode = {
        .max_rx_pkt_len = ETHER_MAX_LEN, /**< Default maximum frame length. */
        .offloads = DEV_RX_OFFLOAD_CRC_STRIP,
-       .ignore_offload_bitfield = 1,
 };
 
 struct rte_eth_txmode tx_mode = {
@@ -337,7 +346,7 @@ struct rte_fdir_conf fdir_conf = {
        .pballoc = RTE_FDIR_PBALLOC_64K,
        .status = RTE_FDIR_REPORT_STATUS,
        .mask = {
-               .vlan_tci_mask = 0x0,
+               .vlan_tci_mask = 0xFFEF,
                .ipv4_mask     = {
                        .src_ip = 0xFFFFFFFF,
                        .dst_ip = 0xFFFFFFFF,
@@ -384,6 +393,38 @@ uint8_t bitrate_enabled;
 struct gro_status gro_ports[RTE_MAX_ETHPORTS];
 uint8_t gro_flush_cycles = GRO_DEFAULT_FLUSH_CYCLES;
 
+struct vxlan_encap_conf vxlan_encap_conf = {
+       .select_ipv4 = 1,
+       .select_vlan = 0,
+       .vni = "\x00\x00\x00",
+       .udp_src = 0,
+       .udp_dst = RTE_BE16(4789),
+       .ipv4_src = IPv4(127, 0, 0, 1),
+       .ipv4_dst = IPv4(255, 255, 255, 255),
+       .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
+               "\x00\x00\x00\x00\x00\x00\x00\x01",
+       .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
+               "\x00\x00\x00\x00\x00\x00\x11\x11",
+       .vlan_tci = 0,
+       .eth_src = "\x00\x00\x00\x00\x00\x00",
+       .eth_dst = "\xff\xff\xff\xff\xff\xff",
+};
+
+struct nvgre_encap_conf nvgre_encap_conf = {
+       .select_ipv4 = 1,
+       .select_vlan = 0,
+       .tni = "\x00\x00\x00",
+       .ipv4_src = IPv4(127, 0, 0, 1),
+       .ipv4_dst = IPv4(255, 255, 255, 255),
+       .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00"
+               "\x00\x00\x00\x00\x00\x00\x00\x01",
+       .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00"
+               "\x00\x00\x00\x00\x00\x00\x11\x11",
+       .vlan_tci = 0,
+       .eth_src = "\x00\x00\x00\x00\x00\x00",
+       .eth_dst = "\xff\xff\xff\xff\xff\xff",
+};
+
 /* Forward function declarations */
 static void map_port_queue_stats_mapping_registers(portid_t pi,
                                                   struct rte_port *port);
@@ -391,6 +432,12 @@ static void check_all_ports_link_status(uint32_t port_mask);
 static int eth_event_callback(portid_t port_id,
                              enum rte_eth_event_type type,
                              void *param, void *ret_param);
+static void eth_dev_event_callback(char *device_name,
+                               enum rte_dev_event_type type,
+                               void *param);
+static int eth_dev_event_callback_register(void);
+static int eth_dev_event_callback_unregister(void);
+
 
 /*
  * Check if all the ports are started.
@@ -656,6 +703,7 @@ init_config(void)
        uint8_t port_per_socket[RTE_MAX_NUMA_NODES];
        struct rte_gro_param gro_param;
        uint32_t gso_types;
+       int k;
 
        memset(port_per_socket,0,RTE_MAX_NUMA_NODES);
 
@@ -690,6 +738,11 @@ init_config(void)
                port->dev_conf.txmode = tx_mode;
                port->dev_conf.rxmode = rx_mode;
                rte_eth_dev_info_get(pid, &port->dev_info);
+
+               if (!(port->dev_info.rx_offload_capa &
+                                       DEV_RX_OFFLOAD_CRC_STRIP))
+                       port->dev_conf.rxmode.offloads &=
+                               ~DEV_RX_OFFLOAD_CRC_STRIP;
                if (!(port->dev_info.tx_offload_capa &
                      DEV_TX_OFFLOAD_MBUF_FAST_FREE))
                        port->dev_conf.txmode.offloads &=
@@ -707,6 +760,15 @@ init_config(void)
                        }
                }
 
+               /* Apply Rx offloads configuration */
+               for (k = 0; k < port->dev_info.max_rx_queues; k++)
+                       port->rx_conf[k].offloads =
+                               port->dev_conf.rxmode.offloads;
+               /* Apply Tx offloads configuration */
+               for (k = 0; k < port->dev_info.max_tx_queues; k++)
+                       port->tx_conf[k].offloads =
+                               port->dev_conf.txmode.offloads;
+
                /* set flag to initialize port/queue */
                port->need_reconfig = 1;
                port->need_reconfig_queues = 1;
@@ -747,7 +809,7 @@ init_config(void)
        init_port_config();
 
        gso_types = DEV_TX_OFFLOAD_TCP_TSO | DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
-               DEV_TX_OFFLOAD_GRE_TNL_TSO;
+               DEV_TX_OFFLOAD_GRE_TNL_TSO | DEV_TX_OFFLOAD_UDP_TSO;
        /*
         * Records which Mbuf pool to use by each logical core, if needed.
         */
@@ -786,6 +848,19 @@ init_config(void)
                                        "rte_gro_ctx_create() failed\n");
                }
        }
+
+#if defined RTE_LIBRTE_PMD_SOFTNIC
+       if (strcmp(cur_fwd_eng->fwd_mode_name, "softnic") == 0) {
+               RTE_ETH_FOREACH_DEV(pid) {
+                       port = &ports[pid];
+                       const char *driver = port->dev_info.driver_name;
+
+                       if (strcmp(driver, "net_softnic") == 0)
+                               port->softport.fwd_lcore_arg = fwd_lcores;
+               }
+       }
+#endif
+
 }
 
 
@@ -871,18 +946,23 @@ init_fwd_streams(void)
 
        /* init new */
        nb_fwd_streams = nb_fwd_streams_new;
-       fwd_streams = rte_zmalloc("testpmd: fwd_streams",
-               sizeof(struct fwd_stream *) * nb_fwd_streams, RTE_CACHE_LINE_SIZE);
-       if (fwd_streams == NULL)
-               rte_exit(EXIT_FAILURE, "rte_zmalloc(%d (struct fwd_stream *)) "
-                                               "failed\n", nb_fwd_streams);
+       if (nb_fwd_streams) {
+               fwd_streams = rte_zmalloc("testpmd: fwd_streams",
+                       sizeof(struct fwd_stream *) * nb_fwd_streams,
+                       RTE_CACHE_LINE_SIZE);
+               if (fwd_streams == NULL)
+                       rte_exit(EXIT_FAILURE, "rte_zmalloc(%d"
+                                " (struct fwd_stream *)) failed\n",
+                                nb_fwd_streams);
 
-       for (sm_id = 0; sm_id < nb_fwd_streams; sm_id++) {
-               fwd_streams[sm_id] = rte_zmalloc("testpmd: struct fwd_stream",
-                               sizeof(struct fwd_stream), RTE_CACHE_LINE_SIZE);
-               if (fwd_streams[sm_id] == NULL)
-                       rte_exit(EXIT_FAILURE, "rte_zmalloc(struct fwd_stream)"
-                                                               " failed\n");
+               for (sm_id = 0; sm_id < nb_fwd_streams; sm_id++) {
+                       fwd_streams[sm_id] = rte_zmalloc("testpmd:"
+                               " struct fwd_stream", sizeof(struct fwd_stream),
+                               RTE_CACHE_LINE_SIZE);
+                       if (fwd_streams[sm_id] == NULL)
+                               rte_exit(EXIT_FAILURE, "rte_zmalloc"
+                                        "(struct fwd_stream) failed\n");
+               }
        }
 
        return 0;
@@ -916,6 +996,9 @@ pkt_burst_stats_display(const char *rx_tx, struct pkt_burst_stats *pbs)
                        pktnb_stats[1] = pktnb_stats[0];
                        burst_stats[0] = nb_burst;
                        pktnb_stats[0] = nb_pkt;
+               } else if (nb_burst > burst_stats[1]) {
+                       burst_stats[1] = nb_burst;
+                       pktnb_stats[1] = nb_pkt;
                }
        }
        if (total_burst == 0)
@@ -1110,9 +1193,9 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
        uint64_t tics_per_1sec;
        uint64_t tics_datum;
        uint64_t tics_current;
-       uint8_t idx_port, cnt_ports;
+       uint16_t i, cnt_ports;
 
-       cnt_ports = rte_eth_dev_count();
+       cnt_ports = nb_ports;
        tics_datum = rte_rdtsc();
        tics_per_1sec = rte_get_timer_hz();
 #endif
@@ -1127,11 +1210,9 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd)
                        tics_current = rte_rdtsc();
                        if (tics_current - tics_datum >= tics_per_1sec) {
                                /* Periodic bitrate calculation */
-                               for (idx_port = 0;
-                                               idx_port < cnt_ports;
-                                               idx_port++)
+                               for (i = 0; i < cnt_ports; i++)
                                        rte_stats_bitrate_calc(bitrate_data,
-                                               idx_port);
+                                               ports_ids[i]);
                                tics_datum = tics_current;
                        }
                }
@@ -1201,6 +1282,31 @@ launch_packet_forwarding(lcore_function_t *pkt_fwd_on_lcore)
        }
 }
 
+/*
+ * Update the forward ports list.
+ */
+void
+update_fwd_ports(portid_t new_pid)
+{
+       unsigned int i;
+       unsigned int new_nb_fwd_ports = 0;
+       int move = 0;
+
+       for (i = 0; i < nb_fwd_ports; ++i) {
+               if (port_id_is_invalid(fwd_ports_ids[i], DISABLED_WARN))
+                       move = 1;
+               else if (move)
+                       fwd_ports_ids[new_nb_fwd_ports++] = fwd_ports_ids[i];
+               else
+                       new_nb_fwd_ports++;
+       }
+       if (new_pid < RTE_MAX_ETHPORTS)
+               fwd_ports_ids[new_nb_fwd_ports++] = new_pid;
+
+       nb_fwd_ports = new_nb_fwd_ports;
+       nb_cfg_ports = new_nb_fwd_ports;
+}
+
 /*
  * Launch packet forwarding configuration.
  */
@@ -1236,10 +1342,6 @@ start_packet_forwarding(int with_tx_first)
                return;
        }
 
-       if (init_fwd_streams() < 0) {
-               printf("Fail from init_fwd_streams()\n");
-               return;
-       }
 
        if(dcb_test) {
                for (i = 0; i < nb_fwd_ports; i++) {
@@ -1259,10 +1361,11 @@ start_packet_forwarding(int with_tx_first)
        }
        test_done = 0;
 
+       fwd_config_setup();
+
        if(!no_flush_rx)
                flush_fwd_rx_queues();
 
-       fwd_config_setup();
        pkt_fwd_config_display(&cur_fwd_config);
        rxtx_config_display();
 
@@ -1586,20 +1689,19 @@ start_port(portid_t pid)
                }
                if (port->need_reconfig_queues > 0) {
                        port->need_reconfig_queues = 0;
-                       port->tx_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE;
-                       /* Apply Tx offloads configuration */
-                       port->tx_conf.offloads = port->dev_conf.txmode.offloads;
                        /* setup tx queues */
                        for (qi = 0; qi < nb_txq; qi++) {
                                if ((numa_support) &&
                                        (txring_numa[pi] != NUMA_NO_CONFIG))
                                        diag = rte_eth_tx_queue_setup(pi, qi,
-                                               nb_txd,txring_numa[pi],
-                                               &(port->tx_conf));
+                                               port->nb_tx_desc[qi],
+                                               txring_numa[pi],
+                                               &(port->tx_conf[qi]));
                                else
                                        diag = rte_eth_tx_queue_setup(pi, qi,
-                                               nb_txd,port->socket_id,
-                                               &(port->tx_conf));
+                                               port->nb_tx_desc[qi],
+                                               port->socket_id,
+                                               &(port->tx_conf[qi]));
 
                                if (diag == 0)
                                        continue;
@@ -1610,15 +1712,14 @@ start_port(portid_t pid)
                                                        RTE_PORT_STOPPED) == 0)
                                        printf("Port %d can not be set back "
                                                        "to stopped\n", pi);
-                               printf("Fail to configure port %d tx queues\n", pi);
+                               printf("Fail to configure port %d tx queues\n",
+                                      pi);
                                /* try to reconfigure queues next time */
                                port->need_reconfig_queues = 1;
                                return -1;
                        }
-                       /* Apply Rx offloads configuration */
-                       port->rx_conf.offloads = port->dev_conf.rxmode.offloads;
-                       /* setup rx queues */
                        for (qi = 0; qi < nb_rxq; qi++) {
+                               /* setup rx queues */
                                if ((numa_support) &&
                                        (rxring_numa[pi] != NUMA_NO_CONFIG)) {
                                        struct rte_mempool * mp =
@@ -1632,8 +1733,10 @@ start_port(portid_t pid)
                                        }
 
                                        diag = rte_eth_rx_queue_setup(pi, qi,
-                                            nb_rxd,rxring_numa[pi],
-                                            &(port->rx_conf),mp);
+                                            port->nb_rx_desc[qi],
+                                            rxring_numa[pi],
+                                            &(port->rx_conf[qi]),
+                                            mp);
                                } else {
                                        struct rte_mempool *mp =
                                                mbuf_pool_find(port->socket_id);
@@ -1645,8 +1748,10 @@ start_port(portid_t pid)
                                                return -1;
                                        }
                                        diag = rte_eth_rx_queue_setup(pi, qi,
-                                            nb_rxd,port->socket_id,
-                                            &(port->rx_conf), mp);
+                                            port->nb_rx_desc[qi],
+                                            port->socket_id,
+                                            &(port->rx_conf[qi]),
+                                            mp);
                                }
                                if (diag == 0)
                                        continue;
@@ -1657,7 +1762,8 @@ start_port(portid_t pid)
                                                        RTE_PORT_STOPPED) == 0)
                                        printf("Port %d can not be set back "
                                                        "to stopped\n", pi);
-                               printf("Fail to configure port %d rx queues\n", pi);
+                               printf("Fail to configure port %d rx queues\n",
+                                      pi);
                                /* try to reconfigure queues next time */
                                port->need_reconfig_queues = 1;
                                return -1;
@@ -1853,6 +1959,39 @@ reset_port(portid_t pid)
        printf("Done\n");
 }
 
+static int
+eth_dev_event_callback_register(void)
+{
+       int ret;
+
+       /* register the device event callback */
+       ret = rte_dev_event_callback_register(NULL,
+               eth_dev_event_callback, NULL);
+       if (ret) {
+               printf("Failed to register device event callback\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+
+static int
+eth_dev_event_callback_unregister(void)
+{
+       int ret;
+
+       /* unregister the device event callback */
+       ret = rte_dev_event_callback_unregister(NULL,
+               eth_dev_event_callback, NULL);
+       if (ret < 0) {
+               printf("Failed to unregister device event callback\n");
+               return -1;
+       }
+
+       return 0;
+}
+
 void
 attach_port(char *identifier)
 {
@@ -1876,10 +2015,13 @@ attach_port(char *identifier)
        reconfig(pi, socket_id);
        rte_eth_promiscuous_enable(pi);
 
-       nb_ports = rte_eth_dev_count();
+       ports_ids[nb_ports] = pi;
+       nb_ports = rte_eth_dev_count_avail();
 
        ports[pi].port_status = RTE_PORT_STOPPED;
 
+       update_fwd_ports(pi);
+
        printf("Port %d is attached. Now total ports is %d\n", pi, nb_ports);
        printf("Done\n");
 }
@@ -1888,6 +2030,7 @@ void
 detach_port(portid_t port_id)
 {
        char name[RTE_ETH_NAME_MAX_LEN];
+       uint16_t i;
 
        printf("Detaching a port...\n");
 
@@ -1900,14 +2043,23 @@ detach_port(portid_t port_id)
                port_flow_flush(port_id);
 
        if (rte_eth_dev_detach(port_id, name)) {
-               TESTPMD_LOG(ERR, "Failed to detach port '%s'\n", name);
+               TESTPMD_LOG(ERR, "Failed to detach port %u\n", port_id);
                return;
        }
 
-       nb_ports = rte_eth_dev_count();
+       for (i = 0; i < nb_ports; i++) {
+               if (ports_ids[i] == port_id) {
+                       ports_ids[i] = ports_ids[nb_ports-1];
+                       ports_ids[nb_ports-1] = 0;
+                       break;
+               }
+       }
+       nb_ports = rte_eth_dev_count_avail();
+
+       update_fwd_ports(RTE_MAX_ETHPORTS);
 
-       printf("Port '%s' is detached. Now total ports is %d\n",
-                       name, nb_ports);
+       printf("Port %u is detached. Now total ports is %d\n",
+                       port_id, nb_ports);
        printf("Done\n");
        return;
 }
@@ -1915,7 +2067,9 @@ detach_port(portid_t port_id)
 void
 pmd_test_exit(void)
 {
+       struct rte_device *device;
        portid_t pt_id;
+       int ret;
 
        if (test_done == 0)
                stop_packet_forwarding();
@@ -1927,8 +2081,33 @@ pmd_test_exit(void)
                        fflush(stdout);
                        stop_port(pt_id);
                        close_port(pt_id);
+
+                       /*
+                        * This is a workaround to fix a virtio-user issue that
+                        * requires to call clean-up routine to remove existing
+                        * socket.
+                        * This workaround valid only for testpmd, needs a fix
+                        * valid for all applications.
+                        * TODO: Implement proper resource cleanup
+                        */
+                       device = rte_eth_devices[pt_id].device;
+                       if (device && !strcmp(device->driver->name, "net_virtio_user"))
+                               detach_port(pt_id);
                }
        }
+
+       if (hot_plug) {
+               ret = rte_dev_event_monitor_stop();
+               if (ret)
+                       RTE_LOG(ERR, EAL,
+                               "fail to stop device event monitor.");
+
+               ret = eth_dev_event_callback_unregister();
+               if (ret)
+                       RTE_LOG(ERR, EAL,
+                               "fail to unregister all event callbacks.");
+       }
+
        printf("\nBye...\n");
 }
 
@@ -1999,18 +2178,23 @@ check_all_ports_link_status(uint32_t port_mask)
 static void
 rmv_event_callback(void *arg)
 {
-       struct rte_eth_dev *dev;
+       int need_to_start = 0;
+       int org_no_link_check = no_link_check;
        portid_t port_id = (intptr_t)arg;
 
        RTE_ETH_VALID_PORTID_OR_RET(port_id);
-       dev = &rte_eth_devices[port_id];
 
+       if (!test_done && port_is_forwarding(port_id)) {
+               need_to_start = 1;
+               stop_packet_forwarding();
+       }
+       no_link_check = 1;
        stop_port(port_id);
+       no_link_check = org_no_link_check;
        close_port(port_id);
-       printf("removing device %s\n", dev->device->name);
-       if (rte_eal_dev_detach(dev->device))
-               TESTPMD_LOG(ERR, "Failed to detach device %s\n",
-                       dev->device->name);
+       detach_port(port_id);
+       if (need_to_start)
+               start_packet_forwarding(0);
 }
 
 /* This function is used by the interrupt thread */
@@ -2024,6 +2208,7 @@ eth_event_callback(portid_t port_id, enum rte_eth_event_type type, void *param,
                [RTE_ETH_EVENT_QUEUE_STATE] = "Queue state",
                [RTE_ETH_EVENT_INTR_RESET] = "Interrupt reset",
                [RTE_ETH_EVENT_VF_MBOX] = "VF Mbox",
+               [RTE_ETH_EVENT_IPSEC] = "IPsec",
                [RTE_ETH_EVENT_MACSEC] = "MACsec",
                [RTE_ETH_EVENT_INTR_RMV] = "device removal",
                [RTE_ETH_EVENT_NEW] = "device probed",
@@ -2059,6 +2244,37 @@ eth_event_callback(portid_t port_id, enum rte_eth_event_type type, void *param,
        return 0;
 }
 
+/* This function is used by the interrupt thread */
+static void
+eth_dev_event_callback(char *device_name, enum rte_dev_event_type type,
+                            __rte_unused void *arg)
+{
+       if (type >= RTE_DEV_EVENT_MAX) {
+               fprintf(stderr, "%s called upon invalid event %d\n",
+                       __func__, type);
+               fflush(stderr);
+       }
+
+       switch (type) {
+       case RTE_DEV_EVENT_REMOVE:
+               RTE_LOG(ERR, EAL, "The device: %s has been removed!\n",
+                       device_name);
+               /* TODO: After finish failure handle, begin to stop
+                * packet forward, stop port, close port, detach port.
+                */
+               break;
+       case RTE_DEV_EVENT_ADD:
+               RTE_LOG(ERR, EAL, "The device: %s has been added!\n",
+                       device_name);
+               /* TODO: After finish kernel driver binding,
+                * begin to attach port.
+                */
+               break;
+       default:
+               break;
+       }
+}
+
 static int
 set_tx_queue_stats_mapping_registers(portid_t port_id, struct rte_port *port)
 {
@@ -2140,39 +2356,51 @@ map_port_queue_stats_mapping_registers(portid_t pi, struct rte_port *port)
 static void
 rxtx_port_config(struct rte_port *port)
 {
-       port->rx_conf = port->dev_info.default_rxconf;
-       port->tx_conf = port->dev_info.default_txconf;
+       uint16_t qid;
+
+       for (qid = 0; qid < nb_rxq; qid++) {
+               port->rx_conf[qid] = port->dev_info.default_rxconf;
+
+               /* Check if any Rx parameters have been passed */
+               if (rx_pthresh != RTE_PMD_PARAM_UNSET)
+                       port->rx_conf[qid].rx_thresh.pthresh = rx_pthresh;
+
+               if (rx_hthresh != RTE_PMD_PARAM_UNSET)
+                       port->rx_conf[qid].rx_thresh.hthresh = rx_hthresh;
+
+               if (rx_wthresh != RTE_PMD_PARAM_UNSET)
+                       port->rx_conf[qid].rx_thresh.wthresh = rx_wthresh;
 
-       /* Check if any RX/TX parameters have been passed */
-       if (rx_pthresh != RTE_PMD_PARAM_UNSET)
-               port->rx_conf.rx_thresh.pthresh = rx_pthresh;
+               if (rx_free_thresh != RTE_PMD_PARAM_UNSET)
+                       port->rx_conf[qid].rx_free_thresh = rx_free_thresh;
 
-       if (rx_hthresh != RTE_PMD_PARAM_UNSET)
-               port->rx_conf.rx_thresh.hthresh = rx_hthresh;
+               if (rx_drop_en != RTE_PMD_PARAM_UNSET)
+                       port->rx_conf[qid].rx_drop_en = rx_drop_en;
 
-       if (rx_wthresh != RTE_PMD_PARAM_UNSET)
-               port->rx_conf.rx_thresh.wthresh = rx_wthresh;
+               port->nb_rx_desc[qid] = nb_rxd;
+       }
 
-       if (rx_free_thresh != RTE_PMD_PARAM_UNSET)
-               port->rx_conf.rx_free_thresh = rx_free_thresh;
+       for (qid = 0; qid < nb_txq; qid++) {
+               port->tx_conf[qid] = port->dev_info.default_txconf;
 
-       if (rx_drop_en != RTE_PMD_PARAM_UNSET)
-               port->rx_conf.rx_drop_en = rx_drop_en;
+               /* Check if any Tx parameters have been passed */
+               if (tx_pthresh != RTE_PMD_PARAM_UNSET)
+                       port->tx_conf[qid].tx_thresh.pthresh = tx_pthresh;
 
-       if (tx_pthresh != RTE_PMD_PARAM_UNSET)
-               port->tx_conf.tx_thresh.pthresh = tx_pthresh;
+               if (tx_hthresh != RTE_PMD_PARAM_UNSET)
+                       port->tx_conf[qid].tx_thresh.hthresh = tx_hthresh;
 
-       if (tx_hthresh != RTE_PMD_PARAM_UNSET)
-               port->tx_conf.tx_thresh.hthresh = tx_hthresh;
+               if (tx_wthresh != RTE_PMD_PARAM_UNSET)
+                       port->tx_conf[qid].tx_thresh.wthresh = tx_wthresh;
 
-       if (tx_wthresh != RTE_PMD_PARAM_UNSET)
-               port->tx_conf.tx_thresh.wthresh = tx_wthresh;
+               if (tx_rs_thresh != RTE_PMD_PARAM_UNSET)
+                       port->tx_conf[qid].tx_rs_thresh = tx_rs_thresh;
 
-       if (tx_rs_thresh != RTE_PMD_PARAM_UNSET)
-               port->tx_conf.tx_rs_thresh = tx_rs_thresh;
+               if (tx_free_thresh != RTE_PMD_PARAM_UNSET)
+                       port->tx_conf[qid].tx_free_thresh = tx_free_thresh;
 
-       if (tx_free_thresh != RTE_PMD_PARAM_UNSET)
-               port->tx_conf.tx_free_thresh = tx_free_thresh;
+               port->nb_tx_desc[qid] = nb_txd;
+       }
 }
 
 void
@@ -2184,9 +2412,11 @@ init_port_config(void)
        RTE_ETH_FOREACH_DEV(pid) {
                port = &ports[pid];
                port->dev_conf.fdir_conf = fdir_conf;
+               rte_eth_dev_info_get(pid, &port->dev_info);
                if (nb_rxq > 1) {
                        port->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL;
-                       port->dev_conf.rx_adv_conf.rss_conf.rss_hf = rss_hf;
+                       port->dev_conf.rx_adv_conf.rss_conf.rss_hf =
+                               rss_hf & port->dev_info.flow_type_rss_offloads;
                } else {
                        port->dev_conf.rx_adv_conf.rss_conf.rss_key = NULL;
                        port->dev_conf.rx_adv_conf.rss_conf.rss_hf = 0;
@@ -2216,17 +2446,6 @@ init_port_config(void)
                    (rte_eth_devices[pid].data->dev_flags &
                     RTE_ETH_DEV_INTR_RMV))
                        port->dev_conf.intr_conf.rmv = 1;
-
-#if defined RTE_LIBRTE_PMD_SOFTNIC && defined RTE_LIBRTE_SCHED
-               /* Detect softnic port */
-               if (!strcmp(port->dev_info.driver_name, "net_softnic")) {
-                       port->softnic_enable = 1;
-                       memset(&port->softport, 0, sizeof(struct softnic_port));
-
-                       if (!strcmp(cur_fwd_eng->fwd_mode_name, "tm"))
-                               port->softport.tm_flag = 1;
-               }
-#endif
        }
 }
 
@@ -2251,7 +2470,10 @@ uint8_t port_is_bonding_slave(portid_t slave_pid)
        struct rte_port *port;
 
        port = &ports[slave_pid];
-       return port->slave_flag;
+       if ((rte_eth_devices[slave_pid].data->dev_flags &
+           RTE_ETH_DEV_BONDED_SLAVE) || (port->slave_flag == 1))
+               return 1;
+       return 0;
 }
 
 const uint16_t vlan_tags[] = {
@@ -2262,12 +2484,14 @@ const uint16_t vlan_tags[] = {
 };
 
 static  int
-get_eth_dcb_conf(struct rte_eth_conf *eth_conf,
+get_eth_dcb_conf(portid_t pid, struct rte_eth_conf *eth_conf,
                 enum dcb_mode_enable dcb_mode,
                 enum rte_eth_nb_tcs num_tcs,
                 uint8_t pfc_en)
 {
        uint8_t i;
+       int32_t rc;
+       struct rte_eth_rss_conf rss_conf;
 
        /*
         * Builds up the correct configuration for dcb+vt based on the vlan tags array
@@ -2307,6 +2531,10 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf,
                struct rte_eth_dcb_tx_conf *tx_conf =
                                &eth_conf->tx_adv_conf.dcb_tx_conf;
 
+               rc = rte_eth_dev_rss_hash_conf_get(pid, &rss_conf);
+               if (rc != 0)
+                       return rc;
+
                rx_conf->nb_tcs = num_tcs;
                tx_conf->nb_tcs = num_tcs;
 
@@ -2314,8 +2542,9 @@ get_eth_dcb_conf(struct rte_eth_conf *eth_conf,
                        rx_conf->dcb_tc[i] = i % num_tcs;
                        tx_conf->dcb_tc[i] = i % num_tcs;
                }
+
                eth_conf->rxmode.mq_mode = ETH_MQ_RX_DCB_RSS;
-               eth_conf->rx_adv_conf.rss_conf.rss_hf = rss_hf;
+               eth_conf->rx_adv_conf.rss_conf = rss_conf;
                eth_conf->txmode.mq_mode = ETH_MQ_TX_DCB;
        }
 
@@ -2349,17 +2578,13 @@ init_port_dcb_config(portid_t pid,
        port_conf.txmode = rte_port->dev_conf.txmode;
 
        /*set configuration of DCB in vt mode and DCB in non-vt mode*/
-       retval = get_eth_dcb_conf(&port_conf, dcb_mode, num_tcs, pfc_en);
+       retval = get_eth_dcb_conf(pid, &port_conf, dcb_mode, num_tcs, pfc_en);
        if (retval < 0)
                return retval;
        port_conf.rxmode.offloads |= DEV_RX_OFFLOAD_VLAN_FILTER;
 
-       /**
-        * Write the configuration into the device.
-        * Set the numbers of RX & TX queues to 0, so
-        * the RX & TX queues will not be setup.
-        */
-       rte_eth_dev_configure(pid, 0, 0, &port_conf);
+       /* re-configure the device . */
+       rte_eth_dev_configure(pid, nb_rxq, nb_rxq, &port_conf);
 
        rte_eth_dev_info_get(pid, &rte_port->dev_info);
 
@@ -2474,8 +2699,10 @@ signal_handler(int signum)
 int
 main(int argc, char** argv)
 {
-       int  diag;
+       int diag;
        portid_t port_id;
+       uint16_t count;
+       int ret;
 
        signal(SIGINT, signal_handler);
        signal(SIGTERM, signal_handler);
@@ -2489,17 +2716,17 @@ main(int argc, char** argv)
                rte_panic("Cannot register log type");
        rte_log_set_level(testpmd_logtype, RTE_LOG_DEBUG);
 
-       if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
-               TESTPMD_LOG(NOTICE, "mlockall() failed with error \"%s\"\n",
-                       strerror(errno));
-       }
-
 #ifdef RTE_LIBRTE_PDUMP
        /* initialize packet capture framework */
        rte_pdump_init(NULL);
 #endif
 
-       nb_ports = (portid_t) rte_eth_dev_count();
+       count = 0;
+       RTE_ETH_FOREACH_DEV(port_id) {
+               ports_ids[count] = port_id;
+               count++;
+       }
+       nb_ports = (portid_t) count;
        if (nb_ports == 0)
                TESTPMD_LOG(WARNING, "No probed ethernet devices\n");
 
@@ -2519,11 +2746,23 @@ main(int argc, char** argv)
        latencystats_enabled = 0;
 #endif
 
+       /* on FreeBSD, mlockall() is disabled by default */
+#ifdef RTE_EXEC_ENV_BSDAPP
+       do_mlockall = 0;
+#else
+       do_mlockall = 1;
+#endif
+
        argc -= diag;
        argv += diag;
        if (argc > 1)
                launch_args_parse(argc, argv);
 
+       if (do_mlockall && mlockall(MCL_CURRENT | MCL_FUTURE)) {
+               TESTPMD_LOG(NOTICE, "mlockall() failed with error \"%s\"\n",
+                       strerror(errno));
+       }
+
        if (tx_first && interactive)
                rte_exit(EXIT_FAILURE, "--tx-first cannot be used on "
                                "interactive mode.\n");
@@ -2543,6 +2782,18 @@ main(int argc, char** argv)
                       nb_rxq, nb_txq);
 
        init_config();
+
+       if (hot_plug) {
+               /* enable hot plug monitoring */
+               ret = rte_dev_event_monitor_start();
+               if (ret) {
+                       rte_errno = EINVAL;
+                       return -1;
+               }
+               eth_dev_event_callback_register();
+
+       }
+
        if (start_port(RTE_PORT_ALL) != 0)
                rte_exit(EXIT_FAILURE, "Start ports failed\n");