[ovs-dev] [v7 06/12] dpif-netdev: Add packet count and core id paramters for study

kumar Amber kumar.amber at intel.com
Thu Jul 8 14:10:46 UTC 2021


From: Kumar Amber <kumar.amber at intel.com>

This commit introduces additional command line paramter
for mfex study function. If user provides additional packet out
it is used in study to compare minimum packets which must be processed
else a default value is choosen.
Also introduces a third paramter for choosing a particular pmd core.

$ ovs-appctl dpif-netdev/miniflow-parser-set study 500 3

Signed-off-by: Kumar Amber <kumar.amber at intel.com>

---
v7:
- change the command paramters for core_id and study_pkt_cnt
v5:
- fix review comments(Ian, Flavio, Eelco)
- introucde pmd core id parameter
---
---
 Documentation/topics/dpdk/bridge.rst |  39 +++++++-
 lib/dpif-netdev-extract-study.c      |  26 ++++-
 lib/dpif-netdev-private-extract.c    |   2 +-
 lib/dpif-netdev-private-extract.h    |   9 ++
 lib/dpif-netdev.c                    | 138 +++++++++++++++++++++++++--
 5 files changed, 200 insertions(+), 14 deletions(-)

diff --git a/Documentation/topics/dpdk/bridge.rst b/Documentation/topics/dpdk/bridge.rst
index 4db416ddd..8ed810f34 100644
--- a/Documentation/topics/dpdk/bridge.rst
+++ b/Documentation/topics/dpdk/bridge.rst
@@ -284,12 +284,47 @@ command also shows whether the CPU supports each implementation ::
 
 An implementation can be selected manually by the following command ::
 
-    $ ovs-appctl dpif-netdev/miniflow-parser-set study
+    $ ovs-appctl dpif-netdev/miniflow-parser-set [-pmd core_id] [name]
+                                                 [study_cnt]
+
+The above command has two optional parameters study_cnt and core_id which can
+be set optionally. The first parameter core_id to set a particular miniflow
+extract function to a specific pmd thread on the core. Third parameter
+study_cnt is specific to study where how many packets needed to choose best
+implementation can be provided.. In case of any other implementation other
+than study third parameter [study_cnt] can pe provided with any arbitatry
+number and is ignored.
 
 Also user can select the study implementation which studies the traffic for
 a specific number of packets by applying all available implementaions of
 miniflow extract and than chooses the one with most optimal result for that
-traffic pattern.
+traffic pattern. A user can also provide an additional packet count parameter
+which is the minimum number of packets that OVS must study before choosing an
+optimal implementation. If no packet count is provided, then the default value,
+128 is chosen. Also, as there is no synchronization point between threads, one
+PMD thread might still be running a previous round, and can now decide on
+earlier data.
+
+The per packet count is a global value, and parallel `study()` executions with
+differing packet counts will use the most recent count value provided by usser.
+
+Study can be selected with packet count by the following command ::
+
+    $ ovs-appctl dpif-netdev/miniflow-parser-set study 1024
+
+Study can be selected with packet count and explicit PMD selection
+by the following command ::
+
+    $ ovs-appctl dpif-netdev/miniflow-parser-set -pmd 3 study 1024
+
+In the above command the last parameter is the CORE ID of the PMD
+thread and this can also be used to explicitly set the miniflow
+extraction function pointer on different PMD threads.
+
+Scalar can be selected on core 3 by the following command where
+study count can be put as any arbitary number or left blank::
+
+    $ ovs-appctl dpif-netdev/miniflow-parser-set -pmd 3 scalar
 
 Miniflow Extract Validation
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/lib/dpif-netdev-extract-study.c b/lib/dpif-netdev-extract-study.c
index f14464b2b..d29523db0 100644
--- a/lib/dpif-netdev-extract-study.c
+++ b/lib/dpif-netdev-extract-study.c
@@ -28,7 +28,7 @@ VLOG_DEFINE_THIS_MODULE(dpif_mfex_extract_study);
 /* Max count of packets to be compared. */
 #define MFEX_MAX_COUNT (128)
 
-static uint32_t mfex_study_pkts_count = 0;
+static uint32_t mfex_study_pkts_count = MFEX_MAX_COUNT;
 
 /* Struct to hold miniflow study stats. */
 struct study_stats {
@@ -51,6 +51,28 @@ mfex_study_get_study_stats_ptr(void)
     return stats;
 }
 
+uint32_t mfex_set_study_pkt_cnt(uint32_t pkt_cmp_count,
+                                const char *name)
+{
+    struct dpif_miniflow_extract_impl *miniflow_funcs;
+    dpif_mfex_impl_info_get(&miniflow_funcs);
+
+    /* If the packet count is set and implementation called is study then
+     * set packet counter to requested number else set the packet counter
+     * to default number.
+     */
+    if ((strcmp(miniflow_funcs[MFEX_IMPL_STUDY].name, name) == 0) &&
+        (pkt_cmp_count != 0)) {
+
+        atomic_uintptr_t *study_pck_cnt = (void *)&mfex_study_pkts_count;
+        atomic_store_relaxed(study_pck_cnt, (uintptr_t) pkt_cmp_count );
+
+        return 0;
+    }
+
+    return -EINVAL;
+}
+
 uint32_t
 mfex_study_traffic(struct dp_packet_batch *packets,
                    struct netdev_flow_key *keys,
@@ -93,7 +115,7 @@ mfex_study_traffic(struct dp_packet_batch *packets,
     /* Choose the best implementation after a minimum packets have been
      * processed.
      */
-    if (stats->pkt_count >= MFEX_MAX_COUNT) {
+    if (stats->pkt_count >= mfex_study_pkts_count) {
         uint32_t best_func_index = MFEX_IMPL_START_IDX;
         uint32_t max_hits = 0;
         for (int i = MFEX_IMPL_START_IDX; i < impl_count; i++) {
diff --git a/lib/dpif-netdev-private-extract.c b/lib/dpif-netdev-private-extract.c
index be8c69408..f3d593d39 100644
--- a/lib/dpif-netdev-private-extract.c
+++ b/lib/dpif-netdev-private-extract.c
@@ -122,7 +122,7 @@ dp_mfex_impl_get(struct ds *reply, struct dp_netdev_pmd_thread **pmd_list,
 
     for (int i = 0; i < ARRAY_SIZE(mfex_impls); i++) {
 
-        ds_put_format(reply, "  %s (available: %s)(pmds: ",
+        ds_put_format(reply, "  %s (available: %s, pmds: ",
                       mfex_impls[i].name, mfex_impls[i].available ?
                       "True" : "False");
 
diff --git a/lib/dpif-netdev-private-extract.h b/lib/dpif-netdev-private-extract.h
index 802496cb9..bea532115 100644
--- a/lib/dpif-netdev-private-extract.h
+++ b/lib/dpif-netdev-private-extract.h
@@ -146,4 +146,13 @@ mfex_study_traffic(struct dp_packet_batch *packets,
                    uint32_t keys_size, odp_port_t in_port,
                    struct dp_netdev_pmd_thread *pmd_handle);
 
+/* Sets the packet count from user to the stats for use in
+ * study function to match against the classified packets to choose
+ * the optimal implementation.
+ * On error, returns EINVAL.
+ * On success, returns 0.
+ */
+uint32_t mfex_set_study_pkt_cnt(uint32_t pkt_cmp_count,
+                                const char *name);
+
 #endif /* MFEX_AVX512_EXTRACT */
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index b416dc80c..87156fc69 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -1079,17 +1079,49 @@ static void
 dpif_miniflow_extract_impl_set(struct unixctl_conn *conn, int argc,
                      const char *argv[], void *aux OVS_UNUSED)
 {
-    /* This function requires just one parameter, the miniflow name.
+    /* A First optional paramter PMD thread ID can be also provided which
+     * allows users to set miniflow implementation on a particular pmd.
+     * The second paramter is the name of the function and if -pmd corr_id
+     * is not provided this is the first paramter and only mandatory one.
+     * The third and last one is the study-cnt which is only provided for
+     * study function to set the packet count.
      */
-    const char *mfex_name = argv[1];
+    const char *mfex_name = NULL;
     struct shash_node *node;
+    bool pmd_core_param_set = false;
+    struct ds reply = DS_EMPTY_INITIALIZER;
+
+    if (strcmp("-pmd", argv[1]) == 0) {
+        mfex_name = argv[3];
+        pmd_core_param_set = true;
+    } else {
+        mfex_name = argv[1];
+    }
+
+    uint32_t pmd_thread_specified = 0;
+    uint32_t pmd_thread_to_change = 0;
+    uint32_t pmd_thread_update_ok = 0;
+
+    if (pmd_core_param_set) {
+        if (str_to_uint(argv[2], 10, &pmd_thread_to_change)) {
+            pmd_thread_specified = 1;
+        } else {
+            /* argv[2] isn't even a uint. return without changing anything. */
+            ds_put_format(&reply,
+                 "Error: Miniflow parser not changed, PMD thread argument"
+                 " passed is not valid: '%s'. Pass a valid pmd thread ID.\n",
+                 argv[2]);
+            const char *reply_str = ds_cstr(&reply);
+            VLOG_INFO("%s", reply_str);
+            unixctl_command_reply_error(conn, reply_str);
+            ds_destroy(&reply);
+            return;
+        }
+    }
 
-    ovs_mutex_lock(&dp_netdev_mutex);
     int err = dp_mfex_impl_set_default_by_name(mfex_name);
 
     if (err) {
-        ovs_mutex_unlock(&dp_netdev_mutex);
-        struct ds reply = DS_EMPTY_INITIALIZER;
         char *error_desc = NULL;
         if (err == -EINVAL) {
             error_desc = "Unknown miniflow extract implementation:";
@@ -1106,6 +1138,66 @@ dpif_miniflow_extract_impl_set(struct unixctl_conn *conn, int argc,
         return;
     }
 
+    /* argv[4] is optional packet count, which user can provide along with
+     * study function to set the minimum packet that must be matched in order
+     * to choose the optimal function. */
+    uint32_t pkt_cmp_count = 0;
+    uint32_t study_ret = 0;
+
+    if (argc == 5) {
+        if (str_to_uint(argv[4], 10, &pkt_cmp_count)) {
+            study_ret = mfex_set_study_pkt_cnt(pkt_cmp_count, mfex_name);
+
+            if (study_ret == -EINVAL) {
+                ds_put_format(&reply, "The study_pkt_cnt option is not valid"
+                              " for the %s implementation.\n",
+                              mfex_name);
+                const char *reply_str = ds_cstr(&reply);
+                unixctl_command_reply_error(conn, reply_str);
+                VLOG_INFO("%s", reply_str);
+                ds_destroy(&reply);
+                return;
+            }
+        } else {
+            ds_put_format(&reply, "Invalid study_pkt_cnt value: : %s.\n",
+                          argv[4]);
+            const char *reply_str = ds_cstr(&reply);
+            unixctl_command_reply_error(conn, reply_str);
+            VLOG_INFO("%s", reply_str);
+            ds_destroy(&reply);
+            return;
+        }
+    } else if ((!pmd_core_param_set) && (argc == 3)) {
+        if (str_to_uint(argv[2], 10, &pkt_cmp_count)) {
+            study_ret = mfex_set_study_pkt_cnt(pkt_cmp_count, mfex_name);
+
+            if (study_ret == -EINVAL) {
+                ds_put_format(&reply, "The study_pkt_cnt option is not valid"
+                              " for the %s implementation.\n",
+                              mfex_name);
+                const char *reply_str = ds_cstr(&reply);
+                unixctl_command_reply_error(conn, reply_str);
+                VLOG_INFO("%s", reply_str);
+                ds_destroy(&reply);
+                return;
+            }
+        } else {
+            ds_put_format(&reply, "Invalid study_pkt_cnt value: %s.\n",
+                          argv[2]);
+            const char *reply_str = ds_cstr(&reply);
+            unixctl_command_reply_error(conn, reply_str);
+            VLOG_INFO("%s", reply_str);
+            ds_destroy(&reply);
+            return;
+        }
+    } else {
+        /* Default packet compare count when packets count not provided. */
+        study_ret = mfex_set_study_pkt_cnt(0, mfex_name);
+
+    }
+
+    ovs_mutex_lock(&dp_netdev_mutex);
+
     SHASH_FOR_EACH (node, &dp_netdevs) {
         struct dp_netdev *dp = node->data;
 
@@ -1122,8 +1214,14 @@ dpif_miniflow_extract_impl_set(struct unixctl_conn *conn, int argc,
                 continue;
             }
 
+            if ((pmd_thread_specified) &&
+                (pmd->core_id != pmd_thread_to_change)) {
+                continue;
+            }
+
             /* Initialize MFEX function pointer to the newly configured
              * default. */
+            pmd_thread_update_ok = 1;
             atomic_uintptr_t *pmd_func = (void *) &pmd->miniflow_extract_opt;
             atomic_store_relaxed(pmd_func, (uintptr_t) default_func);
         };
@@ -1131,9 +1229,30 @@ dpif_miniflow_extract_impl_set(struct unixctl_conn *conn, int argc,
 
     ovs_mutex_unlock(&dp_netdev_mutex);
 
+    /* If PMD thread was specified, but it wasn't found, return error. */
+    if (pmd_thread_specified && !pmd_thread_update_ok) {
+        ds_put_format(&reply,
+             "Error: Miniflow parser not changed, PMD thread %d not in use,"
+             " pass a valid pmd thread ID.\n",
+             pmd_thread_to_change);
+        const char *reply_str = ds_cstr(&reply);
+        VLOG_INFO("%s", reply_str);
+        unixctl_command_reply_error(conn, reply_str);
+        ds_destroy(&reply);
+        return;
+    }
+
     /* Reply with success to command. */
-    struct ds reply = DS_EMPTY_INITIALIZER;
-    ds_put_format(&reply, "Miniflow implementation set to %s.\n", mfex_name);
+    ds_put_format(&reply, "Miniflow implementation set to %s", mfex_name);
+    if (pmd_thread_specified) {
+        ds_put_format(&reply, ", on pmd thread %d", pmd_thread_to_change);
+    }
+    if (study_ret == 0) {
+        ds_put_format(&reply, ", studying %d packets", pkt_cmp_count);
+    }
+
+    ds_put_format(&reply, ".\n");
+
     const char *reply_str = ds_cstr(&reply);
     VLOG_INFO("%s", reply_str);
     unixctl_command_reply(conn, reply_str);
@@ -1370,8 +1489,9 @@ dpif_netdev_init(void)
                              0, 0, dpif_netdev_impl_get,
                              NULL);
     unixctl_command_register("dpif-netdev/miniflow-parser-set",
-                             "miniflow_implementation_name",
-                             1, 1, dpif_miniflow_extract_impl_set,
+                             "[-pmd core] miniflow_implementation_name"
+                             " [study_pkt_cnt]",
+                             1, 5, dpif_miniflow_extract_impl_set,
                              NULL);
     unixctl_command_register("dpif-netdev/miniflow-parser-get", "",
                              0, 0, dpif_miniflow_extract_impl_get,
-- 
2.25.1



More information about the dev mailing list