This patch support measure RX burst cycles.
It stops only when all the injected packets are received.
It won't repeat re-send recevied packets.
Now it measures two situations, poll before/after xmit(w or w/o desc. cache 
conflict)

Usage Example:
1. Run unit test app in interactive mode
    app/test -c f -n 4 -- -i
2. Set stream control mode, by default is continuous
    set_rxtx_sc [continuous|poll_before_xmit|poll_after_xmit]
3. Run and wait for the result
    pmd_perf_autotest

Signed-off-by: Cunming Liang <cunming.liang at intel.com>
Acked-by: Bruce Richardson <bruce.richardson at intel.com>
---
 app/test/commands.c      |   43 +++++++++-
 app/test/test.h          |    1 +
 app/test/test_pmd_perf.c |  212 ++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 235 insertions(+), 21 deletions(-)

diff --git a/app/test/commands.c b/app/test/commands.c
index 7c5d812..92a17ed 100644
--- a/app/test/commands.c
+++ b/app/test/commands.c
@@ -310,8 +310,6 @@ cmdline_parse_inst_t cmd_quit = {

 /****************/

-/****************/
-
 struct cmd_set_rxtx_result {
        cmdline_fixed_string_t set;
        cmdline_fixed_string_t mode;
@@ -346,8 +344,6 @@ cmdline_parse_inst_t cmd_set_rxtx = {

 /****************/

-/****************/
-
 struct cmd_set_rxtx_anchor {
        cmdline_fixed_string_t set;
        cmdline_fixed_string_t type;
@@ -384,6 +380,44 @@ cmdline_parse_inst_t cmd_set_rxtx_anchor = {

 /****************/

+/* for stream control */
+struct cmd_set_rxtx_sc {
+       cmdline_fixed_string_t set;
+       cmdline_fixed_string_t type;
+};
+
+static void
+cmd_set_rxtx_sc_parsed(void *parsed_result,
+                          struct cmdline *cl,
+                          __attribute__((unused)) void *data)
+{
+       struct cmd_set_rxtx_sc *res = parsed_result;
+       if (test_set_rxtx_sc(res->type) < 0)
+               cmdline_printf(cl, "Cannot find such stream control\n");
+}
+
+cmdline_parse_token_string_t cmd_set_rxtx_sc_set =
+       TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_sc, set,
+                                "set_rxtx_sc");
+
+cmdline_parse_token_string_t cmd_set_rxtx_sc_type =
+       TOKEN_STRING_INITIALIZER(struct cmd_set_rxtx_sc, type, NULL);
+
+cmdline_parse_inst_t cmd_set_rxtx_sc = {
+       .f = cmd_set_rxtx_sc_parsed,  /* function to call */
+       .data = NULL,      /* 2nd arg of func */
+       .help_str = "set rxtx stream control: "
+                       "set_rxtx_sc <type>",
+       .tokens = {        /* token list, NULL terminated */
+               (void *)&cmd_set_rxtx_sc_set,
+               (void *)&cmd_set_rxtx_sc_type,
+               NULL,
+       },
+};
+
+/****************/
+
+
 cmdline_parse_ctx_t main_ctx[] = {
        (cmdline_parse_inst_t *)&cmd_autotest,
        (cmdline_parse_inst_t *)&cmd_dump,
@@ -392,6 +426,7 @@ cmdline_parse_ctx_t main_ctx[] = {
        (cmdline_parse_inst_t *)&cmd_quit,
        (cmdline_parse_inst_t *)&cmd_set_rxtx,
        (cmdline_parse_inst_t *)&cmd_set_rxtx_anchor,
+       (cmdline_parse_inst_t *)&cmd_set_rxtx_sc,
        NULL,
 };

diff --git a/app/test/test.h b/app/test/test.h
index 68ae4bf..bd44a7f 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -142,6 +142,7 @@ int test_mp_secondary(void);
 int test_ivshmem(void);
 int test_set_rxtx_conf(cmdline_fixed_string_t mode);
 int test_set_rxtx_anchor(cmdline_fixed_string_t type);
+int test_set_rxtx_sc(cmdline_fixed_string_t type);

 typedef int (test_callback)(void);
 TAILQ_HEAD(test_commands_list, test_command);
diff --git a/app/test/test_pmd_perf.c b/app/test/test_pmd_perf.c
index a6d6ea7..f3da599 100644
--- a/app/test/test_pmd_perf.c
+++ b/app/test/test_pmd_perf.c
@@ -39,6 +39,8 @@
 #include <rte_cycles.h>
 #include <rte_ethdev.h>
 #include <rte_byteorder.h>
+#include <rte_atomic.h>
+#include <rte_malloc.h>
 #include "packet_burst_generator.h"
 #include "test.h"

@@ -73,13 +75,15 @@
 #define TX_HTHRESH 0  /**< Default values of TX host threshold reg. */
 #define TX_WTHRESH 0  /**< Default values of TX write-back threshold reg. */

+#define MAX_TRAFFIC_BURST              2048

 #define NB_MBUF RTE_MAX(                                               \
-         (unsigned)(nb_ports*nb_rx_queue*RTE_TEST_RX_DESC_DEFAULT +    \
-          nb_ports*nb_lcores*MAX_PKT_BURST +                           \
-          nb_ports*nb_tx_queue*RTE_TEST_TX_DESC_DEFAULT +              \
-          nb_lcores*MEMPOOL_CACHE_SIZE),                               \
-         (unsigned)8192)
+               (unsigned)(nb_ports*nb_rx_queue*nb_rxd +                \
+                          nb_ports*nb_lcores*MAX_PKT_BURST +           \
+                          nb_ports*nb_tx_queue*nb_txd +                \
+                          nb_lcores*MEMPOOL_CACHE_SIZE +               \
+                          nb_ports*MAX_TRAFFIC_BURST),                 \
+                       (unsigned)8192)


 static struct rte_mempool *mbufpool[NB_SOCKETS];
@@ -147,6 +151,14 @@ struct lcore_conf lcore_conf[RTE_MAX_LCORE];

 static uint64_t link_mbps;

+enum {
+       SC_CONTINUOUS = 0,
+       SC_BURST_POLL_FIRST,
+       SC_BURST_XMIT_FIRST,
+};
+
+static uint32_t sc_flag;
+
 /* Check the link status of all ports in up to 3s, and print them finally */
 static void
 check_all_ports_link_status(uint8_t port_num, uint32_t port_mask)
@@ -361,8 +373,7 @@ signal_handler(int signum)
                stats_display(0);
 }

-#define MAX_TRAFIC_BURST                (4096)
-struct rte_mbuf *tx_burst[MAX_TRAFIC_BURST];
+struct rte_mbuf **tx_burst;

 uint64_t (*do_measure)(struct lcore_conf *conf,
                       struct rte_mbuf *pkts_burst[],
@@ -503,7 +514,7 @@ main_loop(__rte_unused void *args)
        if (conf->status != LCORE_USED)
                return 0;

-       pkt_per_port =  MAX_TRAFIC_BURST / conf->nb_ports;
+       pkt_per_port = MAX_TRAFFIC_BURST;

        int idx = 0;
        for (i = 0; i < conf->nb_ports; i++) {
@@ -554,12 +565,135 @@ main_loop(__rte_unused void *args)
        return 0;
 }

+rte_atomic64_t start;
+
+static inline int
+poll_burst(void *args)
+{
+#define MAX_IDLE           (1000)
+       unsigned lcore_id;
+       struct rte_mbuf **pkts_burst;
+       uint64_t diff_tsc, cur_tsc;
+       uint16_t next[RTE_MAX_ETHPORTS];
+       struct lcore_conf *conf;
+       uint32_t pkt_per_port = *((uint32_t *)args);
+       unsigned i, portid, nb_rx = 0;
+       uint64_t total;
+       uint64_t timeout = MAX_IDLE;
+
+       lcore_id = rte_lcore_id();
+       conf = &lcore_conf[lcore_id];
+       if (conf->status != LCORE_USED)
+               return 0;
+
+       total = pkt_per_port * conf->nb_ports;
+       printf("start to receive total expect %ld\n", total);
+
+       pkts_burst = (struct rte_mbuf **)
+               rte_calloc_socket("poll_burst",
+                                 total, sizeof(void *),
+                                 CACHE_LINE_SIZE, conf->socketid);
+       if (!pkts_burst)
+               return -1;
+
+       for (i = 0; i < conf->nb_ports; i++) {
+               portid = conf->portlist[i];
+               next[portid] = i * pkt_per_port;
+       }
+
+       while (!rte_atomic64_read(&start))
+               ;
+
+       cur_tsc = rte_rdtsc();
+       while (total) {
+               for (i = 0; i < conf->nb_ports; i++) {
+                       portid = conf->portlist[i];
+                       nb_rx = rte_eth_rx_burst((uint8_t) portid, 0,
+                                                &pkts_burst[next[portid]],
+                                                MAX_PKT_BURST);
+                       if (unlikely(nb_rx == 0)) {
+                               timeout--;
+                               if (unlikely(timeout == 0))
+                                       goto timeout;
+                               continue;
+                       }
+                       next[portid] += nb_rx;
+                       total -= nb_rx;
+               }
+       }
+timeout:
+       diff_tsc = rte_rdtsc() - cur_tsc;
+
+       printf("%ld packets lost, IDLE %ld times\n", total, MAX_IDLE - timeout);
+
+       /* clean up */
+       total = pkt_per_port * conf->nb_ports - total;
+       for (i = 0; i < total; i++)
+               rte_pktmbuf_free(pkts_burst[i]);
+
+       rte_free(pkts_burst);
+
+       return diff_tsc / total;
+}
+
+static int
+exec_burst(uint32_t flags, int lcore)
+{
+       unsigned i, portid, nb_tx = 0;
+       struct lcore_conf *conf;
+       uint32_t pkt_per_port;
+       int num, idx = 0;
+       int diff_tsc;
+
+       conf = &lcore_conf[lcore];
+
+       pkt_per_port = MAX_TRAFFIC_BURST;
+       num = pkt_per_port;
+
+       rte_atomic64_init(&start);
+
+       /* start polling thread, but not actually poll yet */
+       rte_eal_remote_launch(poll_burst,
+                             (void *)&pkt_per_port, lcore);
+
+       /* Only when polling first */
+       if (flags == SC_BURST_POLL_FIRST)
+               rte_atomic64_set(&start, 1);
+
+       /* start xmit */
+       while (num) {
+               nb_tx = RTE_MIN(MAX_PKT_BURST, num);
+               for (i = 0; i < conf->nb_ports; i++) {
+                       portid = conf->portlist[i];
+                       rte_eth_tx_burst(portid, 0,
+                                        &tx_burst[idx], nb_tx);
+                       idx += nb_tx;
+               }
+               num -= nb_tx;
+       }
+
+       sleep(5);
+
+       /* only when polling second  */
+       if (flags == SC_BURST_XMIT_FIRST)
+               rte_atomic64_set(&start, 1);
+
+       /* wait for polling finished */
+       diff_tsc = rte_eal_wait_lcore(lcore);
+       if (diff_tsc < 0)
+               return -1;
+
+       printf("Result: %d cycles per packet\n", diff_tsc);
+
+       return 0;
+}
+
 static int
 test_pmd_perf(void)
 {
        uint16_t nb_ports, num, nb_lcores, slave_id = (uint16_t)-1;
-       uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
-       uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
+       uint16_t nb_rxd = MAX_TRAFFIC_BURST;
+       uint16_t nb_txd = MAX_TRAFFIC_BURST;
        uint16_t portid;
        uint16_t nb_rx_queue = 1, nb_tx_queue = 1;
        int socketid = -1;
@@ -587,6 +721,12 @@ test_pmd_perf(void)

        init_mbufpool(NB_MBUF);

+       if (sc_flag == SC_CONTINUOUS) {
+               nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
+               nb_txd = RTE_TEST_TX_DESC_DEFAULT;
+       }
+       printf("CONFIG RXD=%d TXD=%d\n", nb_rxd, nb_txd);
+
        reset_count();
        num = 0;
        for (portid = 0; portid < nb_ports; portid++) {
@@ -651,15 +791,34 @@ test_pmd_perf(void)
        }
        check_all_ports_link_status(nb_ports, RTE_PORT_ALL);

-       init_traffic(mbufpool[socketid], tx_burst, MAX_TRAFIC_BURST);
+       if (tx_burst == NULL) {
+               tx_burst = (struct rte_mbuf **)
+                       rte_calloc_socket("tx_buff",
+                                         MAX_TRAFFIC_BURST * nb_ports,
+                                         sizeof(void *),
+                                         CACHE_LINE_SIZE, socketid);
+               if (!tx_burst)
+                       return -1;
+       }

-       /* do both rxtx by default */
-       if (NULL == do_measure)
-               do_measure = measure_rxtx;
+       init_traffic(mbufpool[socketid],
+                    tx_burst, MAX_TRAFFIC_BURST * nb_ports);

-       rte_eal_remote_launch(main_loop, NULL, slave_id);
-       if (rte_eal_wait_lcore(slave_id) < 0)
-               return -1;
+       printf("Generate %d packets @socket %d\n",
+              MAX_TRAFFIC_BURST * nb_ports, socketid);
+
+       if (sc_flag == SC_CONTINUOUS) {
+               /* do both rxtx by default */
+               if (NULL == do_measure)
+                       do_measure = measure_rxtx;
+
+               rte_eal_remote_launch(main_loop, NULL, slave_id);
+
+               if (rte_eal_wait_lcore(slave_id) < 0)
+                       return -1;
+       } else if (sc_flag == SC_BURST_POLL_FIRST ||
+                  sc_flag == SC_BURST_XMIT_FIRST)
+               exec_burst(sc_flag, slave_id);

        /* port tear down */
        for (portid = 0; portid < nb_ports; portid++) {
@@ -736,6 +895,25 @@ test_set_rxtx_anchor(cmdline_fixed_string_t type)
        return -1;
 }

+int
+test_set_rxtx_sc(cmdline_fixed_string_t type)
+{
+       printf("stream control switch to %s\n", type);
+
+       if (!strcmp(type, "continuous")) {
+               sc_flag = SC_CONTINUOUS;
+               return 0;
+       } else if (!strcmp(type, "poll_before_xmit")) {
+               sc_flag = SC_BURST_POLL_FIRST;
+               return 0;
+       } else if (!strcmp(type, "poll_after_xmit")) {
+               sc_flag = SC_BURST_XMIT_FIRST;
+               return 0;
+       }
+
+       return -1;
+}
+
 static struct test_command pmd_perf_cmd = {
        .command = "pmd_perf_autotest",
        .callback = test_pmd_perf,
-- 
1.7.4.1

Reply via email to