@@ -226,6 +226,14 @@ stats associated with the datapath.
Just like with the SIMD DPCLS feature above, SIMD can be applied to the DPIF to
improve performance.
+OVS provides multiple implementations of the DPIF. The available
+implementations can be listed with the following command ::
+
+ $ ovs-appctl dpif-netdev/dpif-impl-get
+ Available DPIF implementations:
+ dpif_scalar (pmds: none)
+ dpif_avx512 (pmds: 1,2,6,7)
+
By default, dpif_scalar is used. The DPIF implementation can be selected by
name ::
@@ -23,6 +23,7 @@ Post-v2.15.0
* Refactor lib/dpif-netdev.c to multiple header files.
* Add avx512 implementation of dpif which can process non recirculated
packets. It supports partial HWOL, EMC, SMC and DPCLS lookups.
+ * Add commands to get and set the dpif implementations.
- ovs-ctl:
* New option '--no-record-hostname' to disable hostname configuration
in ovsdb on startup.
@@ -79,6 +79,37 @@ dp_netdev_impl_get_default(void)
return default_dpif_func;
}
+void
+dp_netdev_impl_get(struct ds *reply, struct dp_netdev_pmd_thread **pmd_list,
+ size_t n)
+{
+ /* Add all dpif functions to reply string. */
+ ds_put_cstr(reply, "Available DPIF implementations:\n");
+
+ for (uint32_t i = 0; i < ARRAY_SIZE(dpif_impls); i++) {
+ ds_put_format(reply, " %s (pmds: ", dpif_impls[i].name);
+
+ for (size_t j = 0; j < n; j++) {
+ struct dp_netdev_pmd_thread *pmd = pmd_list[j];
+ if (pmd->core_id == NON_PMD_CORE_ID) {
+ continue;
+ }
+
+ if (pmd->netdev_input_func == dpif_impls[i].input_func) {
+ ds_put_format(reply, "%u,", pmd->core_id);
+ }
+ }
+
+ ds_chomp(reply, ',');
+
+ if (ds_last(reply) == ' ') {
+ ds_put_cstr(reply, "none");
+ }
+
+ ds_put_cstr(reply, ")\n");
+ }
+}
+
/* This function checks all available DPIF implementations, and selects the
* returns the function pointer to the one requested by "name".
*/
@@ -22,6 +22,7 @@
/* Forward declarations to avoid including files. */
struct dp_netdev_pmd_thread;
struct dp_packet_batch;
+struct ds;
/* Typedef for DPIF functions.
* Returns whether all packets were processed successfully.
@@ -48,6 +49,11 @@ struct dpif_netdev_impl_info_t {
const char *name;
};
+/* This function returns all available implementations to the caller. */
+void
+dp_netdev_impl_get(struct ds *reply, struct dp_netdev_pmd_thread **pmd_list,
+ size_t n);
+
/* Returns the default DPIF which is first ./configure selected, but can be
* overridden at runtime. */
dp_netdev_input_func dp_netdev_impl_get_default(void);
@@ -227,5 +227,8 @@ When this is the case, the above command prints the load-balancing information
of the bonds configured in datapath \fIdp\fR showing the interface associated
with each bucket (hash).
.
+.IP "\fBdpif-netdev/dpif-impl-get\fR
+Lists the DPIF implementations that are available.
+.
.IP "\fBdpif-netdev/dpif-impl-set\fR \fIdpif_impl\fR"
Sets the DPIF to be used to \fIdpif_impl\fR. By default "dpif_scalar" is used.
@@ -965,6 +965,29 @@ dpif_netdev_subtable_lookup_set(struct unixctl_conn *conn, int argc OVS_UNUSED,
ds_destroy(&reply);
}
+static void
+dpif_netdev_impl_get(struct unixctl_conn *conn, int argc OVS_UNUSED,
+ const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
+{
+ struct ds reply = DS_EMPTY_INITIALIZER;
+ struct shash_node *node;
+
+ ovs_mutex_lock(&dp_netdev_mutex);
+ SHASH_FOR_EACH (node, &dp_netdevs) {
+ struct dp_netdev_pmd_thread **pmd_list;
+ struct dp_netdev *dp = node->data;
+ size_t n;
+
+ /* Get PMD threads list, required to get the DPIF impl used by each PMD
+ * thread. */
+ sorted_poll_thread_list(dp, &pmd_list, &n);
+ dp_netdev_impl_get(&reply, pmd_list, n);
+ }
+ ovs_mutex_unlock(&dp_netdev_mutex);
+ unixctl_command_reply(conn, ds_cstr(&reply));
+ ds_destroy(&reply);
+}
+
static void
dpif_netdev_impl_set(struct unixctl_conn *conn, int argc OVS_UNUSED,
const char *argv[], void *aux OVS_UNUSED)
@@ -1251,6 +1274,9 @@ dpif_netdev_init(void)
"dpif_implementation_name",
1, 1, dpif_netdev_impl_set,
NULL);
+ unixctl_command_register("dpif-netdev/dpif-impl-get", "",
+ 0, 0, dpif_netdev_impl_get,
+ NULL);
return 0;
}