Hi, Ferrruh,
        All is fixed in v10, please check it out, thanks.

在 2021/4/17 0:30, Ferruh Yigit 写道:
On 4/16/2021 2:52 AM, Min Hu (Connor) wrote:
This patch adds multi-process support for testpmd.
The test cmd example as follows:
the primary cmd:
./dpdk-testpmd -a xxx --proc-type=auto -l 0-1 -- -i \
--rxq=4 --txq=4 --num-procs=2 --proc-id=0

the secondary cmd:
./dpdk-testpmd -a xxx --proc-type=auto -l 2-3 -- -i \
--rxq=4 --txq=4 --num-procs=2 --proc-id=1


Hi Connor,

Thanks for the update. +Anatoly as multi-process maintainer, and ethdev maintainers.

Signed-off-by: Min Hu (Connor) <humi...@huawei.com>
Signed-off-by: Lijun Ou <ouli...@huawei.com>
Acked-by: Xiaoyun Li <xiaoyun...@intel.com>
Acked-by: Ajit Khaparde <ajit.khapa...@broadcom.com>
---
v9:
* Updated release notes and rst doc.
* Deleted deprecated codes.
* move macro and variable.

v8:
* Added warning info about queue numbers and process numbers.

v7:
* Fixed compiling error for unexpected unindent.

v6:
* Add rte flow description for multiple process.

v5:
* Fixed run_app.rst for multiple process description.
* Fix compiling error.

v4:
* Fixed minimum vlaue of Rxq or Txq in doc.

v3:
* Fixed compiling error using gcc10.0.

v2:
* Added document for this patch.
---
  app/test-pmd/cmdline.c                 |   6 ++
  app/test-pmd/config.c                  |  14 ++++-
  app/test-pmd/parameters.c              |  12 ++++
  app/test-pmd/testpmd.c                 | 108 +++++++++++++++++++++++----------
  app/test-pmd/testpmd.h                 |   3 +
  doc/guides/rel_notes/release_21_05.rst |   1 +
  doc/guides/testpmd_app_ug/run_app.rst  |  86 ++++++++++++++++++++++++++
  7 files changed, 196 insertions(+), 34 deletions(-)

diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
index 5bf1497..e465824 100644
--- a/app/test-pmd/cmdline.c
+++ b/app/test-pmd/cmdline.c
@@ -5354,6 +5354,12 @@ cmd_set_flush_rx_parsed(void *parsed_result,
          __rte_unused void *data)
  {
      struct cmd_set_flush_rx *res = parsed_result;
+
+    if (num_procs > 1 && (strcmp(res->mode, "on") == 0)) {
+        printf("multi-process doesn't support to flush rx queues.\n");
+        return;
+    }
+
      no_flush_rx = (uint8_t)((strcmp(res->mode, "on") == 0) ? 0 : 1);
  }
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 40b2b29..c982c87 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -2860,6 +2860,8 @@ rss_fwd_config_setup(void)
      queueid_t  rxq;
      queueid_t  nb_q;
      streamid_t  sm_id;
+    int start;
+    int end;
      nb_q = nb_rxq;
      if (nb_q > nb_txq)
@@ -2877,7 +2879,15 @@ rss_fwd_config_setup(void)
      init_fwd_streams();
      setup_fwd_config_of_each_lcore(&cur_fwd_config);
-    rxp = 0; rxq = 0;
+
+    if (proc_id > 0 && nb_q % num_procs)
+        printf("Warning! queue numbers should be multiple of "
+            "processes, or packet loss will happen.\n");
+
+    start = proc_id * nb_q / num_procs;
+    end = start + nb_q / num_procs;
+    rxp = 0;
+    rxq = start;

Can you put some comment above, on what/why is done, something similar to you already put into the documentation?

      for (sm_id = 0; sm_id < cur_fwd_config.nb_fwd_streams; sm_id++) {
          struct fwd_stream *fs;
@@ -2894,6 +2904,8 @@ rss_fwd_config_setup(void)
              continue;
          rxp = 0;
          rxq++;
+        if (rxq >= end)
+            rxq = start;
      }
  }
diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c
index f3954c1..d86cc21 100644
--- a/app/test-pmd/parameters.c
+++ b/app/test-pmd/parameters.c
@@ -508,6 +508,9 @@ parse_link_speed(int n)
  void
  launch_args_parse(int argc, char** argv)
  {
+#define PARAM_PROC_ID "proc-id"
+#define PARAM_NUM_PROCS "num-procs"
+
      int n, opt;
      char **argvopt;
      int opt_idx;
@@ -625,6 +628,8 @@ launch_args_parse(int argc, char** argv)
          { "rx-mq-mode",                 1, 0, 0 },
          { "record-core-cycles",         0, 0, 0 },
          { "record-burst-stats",         0, 0, 0 },
+        { PARAM_NUM_PROCS,              1, 0, 0 },
+        { PARAM_PROC_ID,                1, 0, 0 },
          { 0, 0, 0, 0 },
      };
@@ -1391,6 +1396,13 @@ launch_args_parse(int argc, char** argv)
                  record_core_cycles = 1;
              if (!strcmp(lgopts[opt_idx].name, "record-burst-stats"))
                  record_burst_stats = 1;
+

To be consistent for rest, this empty line can be removed.

+            if (strncmp(lgopts[opt_idx].name,
+                    PARAM_NUM_PROCS, 9) == 0)
+                num_procs = atoi(optarg);
+            if (strncmp(lgopts[opt_idx].name,
+                    PARAM_PROC_ID, 7) == 0)
+                proc_id = atoi(optarg);
              break;
          case 'h':
              usage(argv[0]);
diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c
index 96d2e0f..01d0d82 100644
--- a/app/test-pmd/testpmd.c
+++ b/app/test-pmd/testpmd.c
@@ -518,6 +518,16 @@ enum rte_eth_rx_mq_mode rx_mq_mode = ETH_MQ_RX_VMDQ_DCB_RSS;
   */
  uint32_t eth_link_speed;
+/*
+ * Id of the current process.
+ */

Can you please add more info, like this being related to the primary/secondary process support and used to configure the queues to be polled.

+int proc_id;
+
+/*
+ * Number of processes.
+ */
+unsigned int num_procs = 1;
+

Ditto.

<...>

@@ -2511,21 +2537,28 @@ start_port(portid_t pid)
                  return -1;
              }
              /* configure port */
-            diag = rte_eth_dev_configure(pi, nb_rxq + nb_hairpinq,
+            if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+                diag = rte_eth_dev_configure(pi,
+                             nb_rxq + nb_hairpinq,
                               nb_txq + nb_hairpinq,
                               &(port->dev_conf));
-            if (diag != 0) {
-                if (rte_atomic16_cmpset(&(port->port_status),
-                RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0)
-                    printf("Port %d can not be set back "
-                            "to stopped\n", pi);
-                printf("Fail to configure port %d\n", pi);
-                /* try to reconfigure port next time */
-                port->need_reconfig = 1;
-                return -1;
+                if (diag != 0) {
+                    if (rte_atomic16_cmpset(
+                            &(port->port_status),
+                            RTE_PORT_HANDLING,
+                            RTE_PORT_STOPPED) == 0)
+                        printf("Port %d can not be set "
+                               "back to stopped\n", pi);
+                    printf("Fail to configure port %d\n",
+                        pi);
+                    /* try to reconfigure port next time */
+                    port->need_reconfig = 1;
+                    return -1;
+                }

Just an idea,
I am a little worried about the complexity this new process type checks are added to the multiple locations. What do you think hiding process type checks behind new functions, like:
eth_dev_configure_mp(...) {
   if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
     return rte_eth_dev_configure(..)
   }
   return 0;
}

and replace it with 'rte_eth_dev_configure()':

  -diag = rte_eth_dev_configure(...)
  +diag = eth_dev_configure_mp(...)

Do you think does this help reducing the complexity added by the multi-process support?

              }
          }
-        if (port->need_reconfig_queues > 0) {
+        if (port->need_reconfig_queues > 0 &&
+            rte_eal_process_type() == RTE_PROC_PRIMARY) {

According our coding convention, we don't allign with paranthesis but put double tabs.

And what about creating an inline function for primary process check, like is_proc_primary(), that may help.

              port->need_reconfig_queues = 0;
              /* setup tx queues */
              for (qi = 0; qi < nb_txq; qi++) {
@@ -2626,17 +2659,20 @@ start_port(portid_t pid)
          cnt_pi++;
          /* start port */
-        diag = rte_eth_dev_start(pi);
-        if (diag < 0) {
-            printf("Fail to start port %d: %s\n", pi,
-                   rte_strerror(-diag));
+        if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
+            diag = rte_eth_dev_start(pi);
+            if (diag < 0) {
+                printf("Fail to start port %d: %s\n", pi,
+                       rte_strerror(-diag));
-            /* Fail to setup rx queue, return */
-            if (rte_atomic16_cmpset(&(port->port_status),
+                /* Fail to setup rx queue, return */
+                if (rte_atomic16_cmpset(&(port->port_status),
                  RTE_PORT_HANDLING, RTE_PORT_STOPPED) == 0)

Syntax is wrong here after change, but if you go with above idea to hide process type check within functions, you won't need to change these lines at all.

<...>

@@ -3885,8 +3925,10 @@ main(int argc, char** argv)
          }
      }
-    if (!no_device_start && start_port(RTE_PORT_ALL) != 0)
+    if (!no_device_start && start_port(RTE_PORT_ALL) != 0) {
+        pmd_test_exit();

Why need to add 'pmd_test_exit()' for the multi-process support, if there is a special case, please add comment for it.


.

Reply via email to