app/testpmd: add port reset command
[dpdk.git] / app / test-pmd / testpmd.c
index a7bad73..e097ee0 100644 (file)
@@ -90,6 +90,7 @@
 #ifdef RTE_LIBRTE_LATENCY_STATS
 #include <rte_latencystats.h>
 #endif
+#include <rte_gro.h>
 
 #include "testpmd.h"
 
@@ -181,7 +182,7 @@ uint32_t burst_tx_retry_num = BURST_TX_RETRIES;
 uint16_t mbuf_data_size = DEFAULT_MBUF_DATA_SIZE; /**< Mbuf data space size. */
 uint32_t param_total_num_mbufs = 0;  /**< number of mbufs in all pools - if
                                       * specified on command-line. */
-
+uint16_t stats_period; /**< Period to show statistics (disabled by default) */
 /*
  * Configuration of packet segments used by the "txonly" processing engine.
  */
@@ -270,6 +271,11 @@ uint16_t port_topology = PORT_TOPOLOGY_PAIRED; /* Ports are paired by default */
  */
 uint8_t no_flush_rx = 0; /* flush by default */
 
+/*
+ * Flow API isolated mode.
+ */
+uint8_t flow_isolate_all;
+
 /*
  * Avoids to check link status when starting/stopping a port.
  */
@@ -379,6 +385,8 @@ lcoreid_t bitrate_lcore_id;
 uint8_t bitrate_enabled;
 #endif
 
+struct gro_status gro_ports[RTE_MAX_ETHPORTS];
+
 /* Forward function declarations */
 static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port);
 static void check_all_ports_link_status(uint32_t port_mask);
@@ -1426,6 +1434,15 @@ start_port(portid_t pid)
                if (port->need_reconfig > 0) {
                        port->need_reconfig = 0;
 
+                       if (flow_isolate_all) {
+                               int ret = port_flow_isolate(pi, 1);
+                               if (ret) {
+                                       printf("Failed to apply isolated"
+                                              " mode on port %d\n", pi);
+                                       return -1;
+                               }
+                       }
+
                        printf("Configuring Port %d (socket %u)\n", pi,
                                        port->socket_id);
                        /* configure port */
@@ -1665,6 +1682,47 @@ close_port(portid_t pid)
        printf("Done\n");
 }
 
+void
+reset_port(portid_t pid)
+{
+       int diag;
+       portid_t pi;
+       struct rte_port *port;
+
+       if (port_id_is_invalid(pid, ENABLED_WARN))
+               return;
+
+       printf("Resetting ports...\n");
+
+       RTE_ETH_FOREACH_DEV(pi) {
+               if (pid != pi && pid != (portid_t)RTE_PORT_ALL)
+                       continue;
+
+               if (port_is_forwarding(pi) != 0 && test_done == 0) {
+                       printf("Please remove port %d from forwarding "
+                              "configuration.\n", pi);
+                       continue;
+               }
+
+               if (port_is_bonding_slave(pi)) {
+                       printf("Please remove port %d from bonded device.\n",
+                              pi);
+                       continue;
+               }
+
+               diag = rte_eth_dev_reset(pi);
+               if (diag == 0) {
+                       port = &ports[pi];
+                       port->need_reconfig = 1;
+                       port->need_reconfig_queues = 1;
+               } else {
+                       printf("Failed to reset port %d. diag=%d\n", pi, diag);
+               }
+       }
+
+       printf("Done\n");
+}
+
 void
 attach_port(char *identifier)
 {
@@ -1711,8 +1769,10 @@ detach_port(uint8_t port_id)
        if (ports[port_id].flow_list)
                port_flow_flush(port_id);
 
-       if (rte_eth_dev_detach(port_id, name))
+       if (rte_eth_dev_detach(port_id, name)) {
+               RTE_LOG(ERR, USER1, "Failed to detach port '%s'\n", name);
                return;
+       }
 
        nb_ports = rte_eth_dev_count();
 
@@ -1810,23 +1870,17 @@ static void
 rmv_event_callback(void *arg)
 {
        struct rte_eth_dev *dev;
-       struct rte_devargs *da;
-       char name[32] = "";
        uint8_t port_id = (intptr_t)arg;
 
        RTE_ETH_VALID_PORTID_OR_RET(port_id);
        dev = &rte_eth_devices[port_id];
-       da = dev->device->devargs;
 
        stop_port(port_id);
        close_port(port_id);
-       if (da->type == RTE_DEVTYPE_VIRTUAL)
-               snprintf(name, sizeof(name), "%s", da->virt.drv_name);
-       else if (da->type == RTE_DEVTYPE_WHITELISTED_PCI)
-               rte_pci_device_name(&da->pci.addr, name, sizeof(name));
-       printf("removing device %s\n", name);
-       rte_eal_dev_detach(dev->device);
-       dev->state = RTE_ETH_DEV_UNUSED;
+       printf("removing device %s\n", dev->device->name);
+       if (rte_eal_dev_detach(dev->device))
+               RTE_LOG(ERR, USER1, "Failed to detach device %s\n",
+                       dev->device->name);
 }
 
 /* This function is used by the interrupt thread */
@@ -2235,6 +2289,21 @@ force_quit(void)
        prompt_exit();
 }
 
+static void
+print_stats(void)
+{
+       uint8_t i;
+       const char clr[] = { 27, '[', '2', 'J', '\0' };
+       const char top_left[] = { 27, '[', '1', ';', '1', 'H', '\0' };
+
+       /* Clear screen and move to top left */
+       printf("%s%s", clr, top_left);
+
+       printf("\nPort statistics ====================================");
+       for (i = 0; i < cur_fwd_config.nb_fwd_ports; i++)
+               nic_stats_display(fwd_ports_ids[i]);
+}
+
 static void
 signal_handler(int signum)
 {
@@ -2301,6 +2370,13 @@ main(int argc, char** argv)
        if (tx_first && interactive)
                rte_exit(EXIT_FAILURE, "--tx-first cannot be used on "
                                "interactive mode.\n");
+
+       if (tx_first && lsc_interrupt) {
+               printf("Warning: lsc_interrupt needs to be off when "
+                               " using tx_first. Disabling.\n");
+               lsc_interrupt = 0;
+       }
+
        if (!nb_rxq && !nb_txq)
                printf("Warning: Either rx or tx queues should be non-zero\n");
 
@@ -2361,6 +2437,28 @@ main(int argc, char** argv)
 
                printf("No commandline core given, start packet forwarding\n");
                start_packet_forwarding(tx_first);
+               if (stats_period != 0) {
+                       uint64_t prev_time = 0, cur_time, diff_time = 0;
+                       uint64_t timer_period;
+
+                       /* Convert to number of cycles */
+                       timer_period = stats_period * rte_get_timer_hz();
+
+                       while (1) {
+                               cur_time = rte_get_timer_cycles();
+                               diff_time += cur_time - prev_time;
+
+                               if (diff_time >= timer_period) {
+                                       print_stats();
+                                       /* Reset the timer */
+                                       diff_time = 0;
+                               }
+                               /* Sleep to avoid unnecessary checks */
+                               prev_time = cur_time;
+                               sleep(1);
+                       }
+               }
+
                printf("Press enter to exit\n");
                rc = read(0, &c, 1);
                pmd_test_exit();