@@ -293,13 +293,15 @@ 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 [-pmd core_id] name \
- [study_cnt]
+ [study_cnt] [-recirc]
-The above command has two optional parameters: ``study_cnt`` and ``core_id``.
-The ``core_id`` sets a particular packet parsing 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.
+The above command has three optional parameters: ``study_cnt``, ``core_id``
+and ``-inner``. The ``core_id`` sets a particular packet parsing 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. The fourth
+parameter ``-recirc`` acts like flag which indicates to MFEX to use optimized
+MFEX inner for processing tunneled inner packets.
Also user can select the ``study`` implementation which studies the traffic for
a specific number of packets by applying all available implementations of
@@ -321,3 +323,8 @@ following command::
``scalar`` can be selected on core ``3`` by the following command::
$ ovs-appctl dpif-netdev/miniflow-parser-set -pmd 3 scalar
+
+``study`` can be selected with packet count and explicit PMD selection along
+with the ``recirc`` by following command::
+
+ $ ovs-appctl dpif-netdev/miniflow-parser-set -pmd 3 study 1024 -recirc
@@ -33,6 +33,9 @@ VLOG_DEFINE_THIS_MODULE(dpif_netdev_extract);
/* Variable to hold the default MFEX implementation. */
static ATOMIC(miniflow_extract_func) default_mfex_func;
+/* Variable to hold the default MFEX inner implementation. */
+static ATOMIC(miniflow_extract_func) default_mfex_inner_func;
+
/* Implementations of available extract options and
* the implementations are always in order of preference.
*/
@@ -141,16 +144,31 @@ dp_mfex_impl_get_default(void)
return return_func;
}
+miniflow_extract_func
+dp_mfex_inner_impl_get_default(void)
+{
+ miniflow_extract_func return_func;
+ atomic_uintptr_t *mfex_func = (void *)&default_mfex_inner_func;
+
+ atomic_read_relaxed(mfex_func, (uintptr_t *) &return_func);
+
+ return return_func;
+}
+
int
-dp_mfex_impl_set_default_by_name(const char *name)
+dp_mfex_impl_set_default_by_name(const char *name, bool mfex_inner)
{
miniflow_extract_func new_default;
atomic_uintptr_t *mfex_func = (void *)&default_mfex_func;
+ atomic_uintptr_t *mfex_inner_func = (void *)&default_mfex_inner_func;
int err = dp_mfex_impl_get_by_name(name, &new_default);
if (!err) {
atomic_store_relaxed(mfex_func, (uintptr_t) new_default);
+ if (mfex_inner) {
+ atomic_store_relaxed(mfex_inner_func, (uintptr_t) new_default);
+ }
}
return err;
@@ -178,6 +196,10 @@ dp_mfex_impl_get(struct ds *reply, struct dp_netdev_pmd_thread **pmd_list,
if (pmd->miniflow_extract_opt == mfex_impls[i].extract_func) {
ds_put_format(reply, "%u,", pmd->core_id);
}
+ if (pmd->miniflow_extract_inner_opt ==
+ mfex_impls[i].extract_func) {
+ ds_put_format(reply, "%u,", pmd->core_id);
+ }
}
ds_chomp(reply, ',');
@@ -128,8 +128,12 @@ dp_mfex_impl_get_by_name(const char *name, miniflow_extract_func *out_func);
* overridden at runtime. */
miniflow_extract_func dp_mfex_impl_get_default(void);
+/* Returns the default MFEX which is first ./configure selected, but can be
+ * overridden at runtime. */
+miniflow_extract_func dp_mfex_inner_impl_get_default(void);
+
/* Overrides the default MFEX with the user set MFEX. */
-int dp_mfex_impl_set_default_by_name(const char *name);
+int dp_mfex_impl_set_default_by_name(const char *name, bool mfex_inner);
/* Retrieve the array of miniflow implementations for iteration. */
struct dpif_miniflow_extract_impl *
@@ -176,6 +180,8 @@ mfex_study_traffic(struct dp_packet_batch *packets,
int
mfex_set_study_pkt_cnt(uint32_t pkt_cmp_count, const char *name);
+void dp_mfex_inner_impl_set_default(void);
+
/* AVX512 MFEX Probe and Implementations functions. */
#ifdef __x86_64__
int32_t mfex_avx512_probe(void);
@@ -133,6 +133,9 @@ struct dp_netdev_pmd_thread {
/* Function pointer to call for miniflow_extract() functionality. */
ATOMIC(miniflow_extract_func) miniflow_extract_opt;
+ /* Function pointer to call for miniflow_extract() inner functionality. */
+ ATOMIC(miniflow_extract_func) miniflow_extract_inner_opt;
+
struct seq *reload_seq;
uint64_t last_reload_seq;
@@ -1222,6 +1222,7 @@ dpif_miniflow_extract_impl_set(struct unixctl_conn *conn, int argc,
struct ds reply = DS_EMPTY_INITIALIZER;
bool pmd_thread_update_done = false;
bool mfex_name_is_study = false;
+ bool mfex_inner_is_set = false;
const char *mfex_name = NULL;
const char *reply_str = NULL;
struct shash_node *node;
@@ -1260,6 +1261,10 @@ dpif_miniflow_extract_impl_set(struct unixctl_conn *conn, int argc,
argc -= 1;
argv += 1;
+ } else if (strcmp("-recirc", argv[1]) == 0) {
+ mfex_inner_is_set = true;
+ 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) ||
@@ -1301,7 +1306,7 @@ dpif_miniflow_extract_impl_set(struct unixctl_conn *conn, int argc,
* 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);
+ err = dp_mfex_impl_set_default_by_name(mfex_name, mfex_inner_is_set);
if (err == -ENODEV) {
ds_put_format(&reply,
"Error: miniflow extract not available due to CPU"
@@ -1318,6 +1323,7 @@ dpif_miniflow_extract_impl_set(struct unixctl_conn *conn, int argc,
/* Get the desired MFEX function pointer and error check its usage. */
miniflow_extract_func mfex_func = NULL;
+ miniflow_extract_func mfex_inner_func = NULL;
err = dp_mfex_impl_get_by_name(mfex_name, &mfex_func);
if (err) {
if (err == -ENODEV) {
@@ -1332,6 +1338,7 @@ dpif_miniflow_extract_impl_set(struct unixctl_conn *conn, int argc,
goto error;
}
+ mfex_inner_func = mfex_func;
/* Apply the MFEX pointer to each pmd thread in each netdev, filtering
* by the users "-pmd" argument if required.
*/
@@ -1358,6 +1365,8 @@ dpif_miniflow_extract_impl_set(struct unixctl_conn *conn, int argc,
pmd_thread_update_done = true;
atomic_store_relaxed(&pmd->miniflow_extract_opt, mfex_func);
+ atomic_store_relaxed(&pmd->miniflow_extract_inner_opt,
+ mfex_inner_func);
};
free(pmd_list);
@@ -1629,8 +1638,8 @@ dpif_netdev_init(void)
NULL);
unixctl_command_register("dpif-netdev/miniflow-parser-set",
"[-pmd core] miniflow_implementation_name"
- " [study_pkt_cnt]",
- 1, 5, dpif_miniflow_extract_impl_set,
+ " [study_pkt_cnt] [-recirc]",
+ 1, 6, dpif_miniflow_extract_impl_set,
NULL);
unixctl_command_register("dpif-netdev/miniflow-parser-get", "",
0, 0, dpif_miniflow_extract_impl_get,
@@ -7470,6 +7479,12 @@ dp_netdev_configure_pmd(struct dp_netdev_pmd_thread *pmd, struct dp_netdev *dp,
/* Init default miniflow_extract function */
atomic_init(&pmd->miniflow_extract_opt, dp_mfex_impl_get_default());
+ /* Init default miniflow_extract function */
+ miniflow_extract_func mfex_inner_func = dp_mfex_impl_get_default();
+ atomic_uintptr_t *pmd_func_mfex_inner =
+ (void *)&pmd->miniflow_extract_inner_opt;
+ atomic_store_relaxed(pmd_func_mfex_inner, (uintptr_t) mfex_inner_func);
+
/* init the 'flow_cache' since there is no
* actual thread created for NON_PMD_CORE_ID. */
if (core_id == NON_PMD_CORE_ID) {