On Thu, Jul 15, 2021 at 09:36:12PM +0530, kumar Amber wrote:
> From: Kumar Amber <kumar.am...@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.am...@intel.com>
> 
> ---
> v14:
> - fix logging format and  xmas ordering
> v13:
> - reowrked the set command as per discussion
> - fixed the atomic set in study
> - added bool for handling study mfex to simplify logic and command output
> - fixed double space in variable declaration and removed static
> v12:
> - re-work the set command to sweep
> - inlcude fixes to study.c and doc changes
> v11:
> - include comments from Eelco
> - reworked set command as per discussion
> v10:
> - fix review comments Eelco
> v9:
> - fix review comments Flavio
> 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 |  38 +++++-
>  lib/dpif-netdev-extract-study.c      |  26 +++-
>  lib/dpif-netdev-private-extract.h    |   9 ++
>  lib/dpif-netdev.c                    | 175 ++++++++++++++++++++++-----
>  4 files changed, 216 insertions(+), 32 deletions(-)
> 
> diff --git a/Documentation/topics/dpdk/bridge.rst 
> b/Documentation/topics/dpdk/bridge.rst
> index a47153495..8c500c504 100644
> --- a/Documentation/topics/dpdk/bridge.rst
> +++ b/Documentation/topics/dpdk/bridge.rst
> @@ -284,12 +284,46 @@ 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.
> +The core_id sets a particular miniflow extract function to a specific
> +pmd thread on the core. The third parameter study_cnt, which is specific
> +to study and ignored by other implementations, means how many packets
> +are needed to choose the best implementation.
>  
>  Also user can select the study implementation which studies the traffic for
>  a specific number of packets by applying all available implementations of
>  miniflow extract and then chooses the one with the most optimal result for
> -that traffic pattern.
> +that traffic pattern. The user can optionally provide an packet count
> +[study_cnt] 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 
> user.
> +
> +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 first 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 should not be provided for any implementation other
> +than study ::
> +
> +    $ 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 02b709f8b..4340c9eee 100644
> --- a/lib/dpif-netdev-extract-study.c
> +++ b/lib/dpif-netdev-extract-study.c
> @@ -25,7 +25,7 @@
>  
>  VLOG_DEFINE_THIS_MODULE(dpif_mfex_extract_study);
>  
> -static atomic_uint32_t mfex_study_pkts_count = 0;
> +static atomic_uint32_t mfex_study_pkts_count = MFEX_MAX_PKT_COUNT;
>  
>  /* Struct to hold miniflow study stats. */
>  struct study_stats {
> @@ -48,6 +48,25 @@ mfex_study_get_study_stats_ptr(void)
>      return stats;
>  }
>  
> +int
> +mfex_set_study_pkt_cnt(uint32_t pkt_cmp_count, const char *name)
> +{
> +    struct dpif_miniflow_extract_impl *miniflow_funcs;
> +    miniflow_funcs = dpif_mfex_impl_info_get();
> +
> +    /* If the packet count is set and implementation called is study then
> +     * set packet counter to requested number else return -EINVAL.
> +     */
> +    if ((strcmp(miniflow_funcs[MFEX_IMPL_STUDY].name, name) == 0) &&
> +        (pkt_cmp_count != 0)) {
> +
> +        atomic_store_relaxed(&mfex_study_pkts_count, pkt_cmp_count);
> +        return 0;
> +    }
> +
> +    return -EINVAL;
> +}
> +
>  uint32_t
>  mfex_study_traffic(struct dp_packet_batch *packets,
>                     struct netdev_flow_key *keys,
> @@ -86,7 +105,10 @@ 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_PKT_COUNT) {
> +    uint32_t study_cnt_pkts;
> +    atomic_read_relaxed(&mfex_study_pkts_count, &study_cnt_pkts);
> +
> +    if (stats->pkt_count >= study_cnt_pkts) {
>          uint32_t best_func_index = MFEX_IMPL_START_IDX;
>          uint32_t max_hits = 0;
>          for (int i = MFEX_IMPL_START_IDX; i < MFEX_IMPL_MAX; i++) {
> diff --git a/lib/dpif-netdev-private-extract.h 
> b/lib/dpif-netdev-private-extract.h
> index 9c03a1aa0..b93fecbbc 100644
> --- a/lib/dpif-netdev-private-extract.h
> +++ b/lib/dpif-netdev-private-extract.h
> @@ -151,4 +151,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.
> + */
> +int
> +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 707bf85c0..585b9500c 100644
> --- a/lib/dpif-netdev.c
> +++ b/lib/dpif-netdev.c
> @@ -1076,36 +1076,127 @@ dpif_miniflow_extract_impl_get(struct unixctl_conn 
> *conn, int argc OVS_UNUSED,
>  }
>  
>  static void
> -dpif_miniflow_extract_impl_set(struct unixctl_conn *conn, int argc 
> OVS_UNUSED,
> +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.
> +    /* This command takes some optional and mandatory arguments. The function
> +     * here first parses all of the options, saving results in local 
> variables.
> +     * Then the parsed values are acted on.
>       */
> -    const char *mfex_name = argv[1];
> +    unsigned int pmd_thread_to_change = NON_PMD_CORE_ID;
> +    unsigned int study_count = MFEX_MAX_PKT_COUNT;
> +    struct ds reply = DS_EMPTY_INITIALIZER;
> +    bool pmd_thread_update_done = false;
> +    bool mfex_name_is_study = false;
> +    const char *mfex_name = NULL;
> +    const char *reply_str = NULL;
>      struct shash_node *node;
> +    int err;
> +
> +    while (argc > 1) {
> +        /* Optional argument "-pmd" limits the commands actions to just this
> +         * PMD thread.
> +         */
> +        if ((!strcmp(argv[1], "-pmd") && !mfex_name)) {
> +            if (argc < 3) {
> +                ds_put_format(&reply,
> +                   "Error: -pmd option requires a thread id argument.\n");
> +                goto error;
> +            }
> +
> +            /* Ensure argument can be parsed to an integer. */
> +            if (!str_to_uint(argv[2], 10, &pmd_thread_to_change) ||
> +                    (pmd_thread_to_change == NON_PMD_CORE_ID)) {
> +                ds_put_format(&reply,
> +                  "Error: miniflow extract parser not changed, PMD thread"
> +                  " passed is not valid: '%s'. Pass a valid pmd thread 
> ID.\n",
> +                  argv[2]);
> +                goto error;
> +            }
> +
> +            argc -= 2;
> +            argv += 2;
> +
> +        } else if (!mfex_name) {
> +            /* Name of MFEX impl requested by user. */
> +            mfex_name = argv[1];
> +            mfex_name_is_study = strcmp("study", mfex_name) == 0;
> +            argc -= 1;
> +            argv += 1;
> +
> +        /* If name is study and more args exist, parse study_count value. */
> +        } else if (mfex_name && mfex_name_is_study) {
> +            if (!str_to_uint(argv[1], 10, &study_count) ||
> +                    (study_count == 0)) {
> +                ds_put_format(&reply,
> +                    "Error: Invalid study_pkt_cnt value: %s.\n", argv[1]);

Ian flagged this one, but there is another missing spot below.

> +                goto error;
> +            }
> +
> +            argc -= 1;
> +            argv += 1;
> +        } else {
> +            ds_put_format(&reply, "Error: unknown argument %s.\n", argv[1]);
> +                goto error;
> +            break;
> +        }
> +    }
> +
> +    /* Ensure user passed an MFEX name. */
> +    if (!mfex_name) {
> +        ds_put_format(&reply, "Error: no miniflow extract name provided. "
> +                "Output of miniflow-parser-get shows implementation 
> list.\n");
> +        goto error;
> +    }
>  
> -    int err = dp_mfex_impl_set_default_by_name(mfex_name);
> +    /* If the MFEX name is "study", set the study packet count. */
> +    if (mfex_name_is_study) {
> +        err = mfex_set_study_pkt_cnt(study_count, mfex_name);
> +        if (err) {
> +            ds_put_format(&reply, "Error: failed to set study count %d for"
> +                          " miniflow extract implementation %s.\n",
> +                          study_count, mfex_name);
> +            goto error;
> +        }
> +    }
>  
> +    /* Set the default MFEX impl only if the command was applied to all PMD
> +     * threads. If a PMD thread was selected, do NOT update the default.
> +     */
> +    if (pmd_thread_to_change == NON_PMD_CORE_ID) {
> +        err = dp_mfex_impl_set_default_by_name(mfex_name);
> +        if (err == -ENODEV) {
> +            ds_put_format(&reply,
> +              "Miniflow extract not available due to CPU ISA requirements: 
> %s",
> +              mfex_name);

Here. Error: miniflow extract...

AppVeyor is ok, notice no regression, study works and selects the
correct traffic profile for UDP and TCP, testsuite ok, dpdk
testsuite ok.

Acked-by: Flavio Leitner <f...@sysclose.org>



> +            goto error;
> +        } else if (err) {
> +            ds_put_format(&reply,
> +              "Error: unknown miniflow extract implementation %s.",
> +              mfex_name);
> +            goto error;
> +        }
> +    }
> +
> +    /* Get the desired MFEX function pointer and error check its usage. */
> +    miniflow_extract_func mfex_func = NULL;
> +    err = dp_mfex_impl_get_by_name(mfex_name, &mfex_func);
>      if (err) {
> -        struct ds reply = DS_EMPTY_INITIALIZER;
> -        char *error_desc = NULL;
> -        if (err == -EINVAL) {
> -            error_desc = "Unknown miniflow extract implementation:";
> -        } else if (err == -ENOENT) {
> -            error_desc = "Miniflow extract implementation doesn't exist:";
> -        } else if (err == -ENODEV) {
> -            error_desc = "Miniflow extract implementation not available:";
> +        if (err == -ENODEV) {
> +            ds_put_format(&reply,
> +              "Error: miniflow extract not available due to CPU ISA "
> +              "requirements: %s", mfex_name);
>          } else {
> -            error_desc = "Miniflow extract implementation Error:";
> +            ds_put_format(&reply,
> +               "Error: unknown miniflow extract implementation %s.",
> +               mfex_name);
>          }
> -        ds_put_format(&reply, "%s %s.\n", error_desc, 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;
> +        goto error;
>      }
>  
> +    /* Apply the MFEX pointer to each pmd thread in each netdev, filtering
> +     * by the users "-pmd" argument if required.
> +     */
>      ovs_mutex_lock(&dp_netdev_mutex);
>  
>      SHASH_FOR_EACH (node, &dp_netdevs) {
> @@ -1114,7 +1205,6 @@ dpif_miniflow_extract_impl_set(struct unixctl_conn 
> *conn, int argc OVS_UNUSED,
>          size_t n;
>  
>          sorted_poll_thread_list(dp, &pmd_list, &n);
> -        miniflow_extract_func default_func = dp_mfex_impl_get_default();
>  
>          for (size_t i = 0; i < n; i++) {
>              struct dp_netdev_pmd_thread *pmd = pmd_list[i];
> @@ -1122,23 +1212,51 @@ dpif_miniflow_extract_impl_set(struct unixctl_conn 
> *conn, int argc OVS_UNUSED,
>                  continue;
>              }
>  
> -            /* Initialize MFEX function pointer to the newly configured
> -             * default. */
> +            /* If -pmd specified, skip all other pmd threads. */
> +            if ((pmd_thread_to_change != NON_PMD_CORE_ID) &&
> +                    (pmd->core_id != pmd_thread_to_change)) {
> +                continue;
> +            }
> +
> +            pmd_thread_update_done = true;
>              atomic_uintptr_t *pmd_func = (void *) &pmd->miniflow_extract_opt;
> -            atomic_store_relaxed(pmd_func, (uintptr_t) default_func);
> +            atomic_store_relaxed(pmd_func, (uintptr_t) mfex_func);
>          };
>      }
>  
>      ovs_mutex_unlock(&dp_netdev_mutex);
>  
> +    /* If PMD thread was specified, but it wasn't found, return error. */
> +    if (pmd_thread_to_change != NON_PMD_CORE_ID && !pmd_thread_update_done) {
> +        ds_put_format(&reply,
> +                      "Error: miniflow extract parser not changed, "
> +                      "PMD thread %d not in use, pass a valid pmd"
> +                      " thread ID.\n", pmd_thread_to_change);
> +        goto error;
> +    }
> +
>      /* Reply with success to command. */
> -    struct ds reply = DS_EMPTY_INITIALIZER;
> -    ds_put_format(&reply, "Miniflow Extract implementation set to %s",
> +    ds_put_format(&reply, "Miniflow extract implementation set to %s",
>                    mfex_name);
> -    const char *reply_str = ds_cstr(&reply);
> +    if (pmd_thread_to_change != NON_PMD_CORE_ID) {
> +        ds_put_format(&reply, ", on pmd thread %d", pmd_thread_to_change);
> +    }
> +    if (mfex_name_is_study) {
> +        ds_put_format(&reply, ", studying %d packets", study_count);
> +    }
> +    ds_put_format(&reply, ".\n");
> +
> +    reply_str = ds_cstr(&reply);
>      VLOG_INFO("%s", reply_str);
>      unixctl_command_reply(conn, reply_str);
>      ds_destroy(&reply);
> +    return;
> +
> +error:
> +    reply_str = ds_cstr(&reply);
> +    VLOG_ERR("%s", reply_str);
> +    unixctl_command_reply_error(conn, reply_str);
> +    ds_destroy(&reply);
>  }
>  
>  static void
> @@ -1371,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
> 

-- 
fbl
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to