diff --git a/Documentation/topics/dpdk/bridge.rst b/Documentation/topics/dpdk/bridge.rst index 06d1f943c..2d0850836 100644 --- a/Documentation/topics/dpdk/bridge.rst +++ b/Documentation/topics/dpdk/bridge.rst @@ -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 :: diff --git a/NEWS b/NEWS index 2625cabc8..471f3a1a2 100644 --- a/NEWS +++ b/NEWS @@ -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. diff --git a/lib/dpif-netdev-private-dpif.c b/lib/dpif-netdev-private-dpif.c index a05a82fa1..84d4ec156 100644 --- a/lib/dpif-netdev-private-dpif.c +++ b/lib/dpif-netdev-private-dpif.c @@ -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". */ diff --git a/lib/dpif-netdev-private-dpif.h b/lib/dpif-netdev-private-dpif.h index 7880647ad..0da639c55 100644 --- a/lib/dpif-netdev-private-dpif.h +++ b/lib/dpif-netdev-private-dpif.h @@ -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); diff --git a/lib/dpif-netdev-unixctl.man b/lib/dpif-netdev-unixctl.man index 76cc949f9..5f9256215 100644 --- a/lib/dpif-netdev-unixctl.man +++ b/lib/dpif-netdev-unixctl.man @@ -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. diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 6cdeb93de..f7b2163bf 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -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; }