summaryrefslogtreecommitdiff
path: root/lib/dpif-netdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dpif-netdev.c')
-rw-r--r--lib/dpif-netdev.c180
1 files changed, 152 insertions, 28 deletions
diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 707bf85c0..21d7714cc 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -1076,36 +1076,132 @@ 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]);
+ 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,
+ "Error: miniflow extract not available due to CPU"
+ " ISA requirements: %s",
+ mfex_name);
+ 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 +1210,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 +1217,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 +1494,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,