The patch adds and re-uses the dpif set command to set the function pointers to be used to switch between different inner dpifs.
Signed-off-by: Kumar Amber <kumar.am...@intel.com> Signed-off-by: Cian Ferriter <cian.ferri...@intel.com> Co-authored-by: Cian Ferriter <cian.ferri...@intel.com> --- v3: - Add description to the dpif recirc function. - Fix use of return value to fall back to scalar dpif. --- --- lib/dpif-netdev-private-dpif.c | 57 +++++++++++++++++++++++++++----- lib/dpif-netdev-private-dpif.h | 18 ++++++++++ lib/dpif-netdev-private-thread.h | 3 ++ lib/dpif-netdev.c | 19 +++++++++-- 4 files changed, 87 insertions(+), 10 deletions(-) diff --git a/lib/dpif-netdev-private-dpif.c b/lib/dpif-netdev-private-dpif.c index 2dc51270a..96bfd4824 100644 --- a/lib/dpif-netdev-private-dpif.c +++ b/lib/dpif-netdev-private-dpif.c @@ -27,6 +27,8 @@ #include "util.h" VLOG_DEFINE_THIS_MODULE(dpif_netdev_impl); +#define DPIF_NETDEV_IMPL_AVX512_CHECK (__x86_64__ && HAVE_AVX512F \ + && HAVE_LD_AVX512_GOOD && __SSE4_2__) DEFINE_EXTERN_PER_THREAD_DATA(recirc_depth, 0); @@ -39,18 +41,21 @@ enum dpif_netdev_impl_info_idx { static struct dpif_netdev_impl_info_t dpif_impls[] = { /* The default scalar C code implementation. */ [DPIF_NETDEV_IMPL_SCALAR] = { .input_func = dp_netdev_input, + .recirc_func = dp_netdev_recirculate, .probe = NULL, .name = "dpif_scalar", }, #if (__x86_64__ && HAVE_AVX512F && HAVE_LD_AVX512_GOOD && __SSE4_2__) /* Only available on x86_64 bit builds with SSE 4.2 used for OVS core. */ [DPIF_NETDEV_IMPL_AVX512] = { .input_func = dp_netdev_input_avx512, + .recirc_func = dp_netdev_input_avx512_recirc, .probe = dp_netdev_input_avx512_probe, .name = "dpif_avx512", }, #endif }; static dp_netdev_input_func default_dpif_func; +static dp_netdev_recirc_func default_dpif_recirc_func; dp_netdev_input_func dp_netdev_impl_get_default(void) @@ -61,7 +66,7 @@ dp_netdev_impl_get_default(void) int dpif_idx = DPIF_NETDEV_IMPL_SCALAR; /* Configure-time overriding to run test suite on all implementations. */ -#if (__x86_64__ && HAVE_AVX512F && HAVE_LD_AVX512_GOOD && __SSE4_2__) +#if DPIF_NETDEV_IMPL_AVX512_CHECK #ifdef DPIF_AVX512_DEFAULT dp_netdev_input_func_probe probe; @@ -81,6 +86,35 @@ dp_netdev_impl_get_default(void) return default_dpif_func; } +dp_netdev_recirc_func +dp_netdev_recirc_impl_get_default(void) +{ + /* For the first call, this will be NULL. Compute the compile time default. + */ + if (!default_dpif_recirc_func) { + int dpif_idx = DPIF_NETDEV_IMPL_SCALAR; + +/* Configure-time overriding to run test suite on all implementations. */ +#if DPIF_NETDEV_IMPL_AVX512_CHECK +#ifdef DPIF_AVX512_DEFAULT + dp_netdev_input_func_probe probe; + + /* Check if the compiled default is compatible. */ + probe = dpif_impls[DPIF_NETDEV_IMPL_AVX512].probe; + if (!probe || !probe()) { + dpif_idx = DPIF_NETDEV_IMPL_AVX512; + } +#endif +#endif + + VLOG_INFO("Default re-circulate DPIF implementation is %s.\n", + dpif_impls[dpif_idx].name); + default_dpif_recirc_func = dpif_impls[dpif_idx].recirc_func; + } + + return default_dpif_recirc_func; +} + void dp_netdev_impl_get(struct ds *reply, struct dp_netdev_pmd_thread **pmd_list, size_t n) @@ -116,10 +150,12 @@ dp_netdev_impl_get(struct ds *reply, struct dp_netdev_pmd_thread **pmd_list, * returns the function pointer to the one requested by "name". */ static int32_t -dp_netdev_impl_get_by_name(const char *name, dp_netdev_input_func *out_func) +dp_netdev_impl_get_by_name(const char *name, dp_netdev_input_func *dpif_func, + dp_netdev_recirc_func *dpif_recirc_func) { ovs_assert(name); - ovs_assert(out_func); + ovs_assert(dpif_func); + ovs_assert(dpif_recirc_func); uint32_t i; @@ -129,11 +165,13 @@ dp_netdev_impl_get_by_name(const char *name, dp_netdev_input_func *out_func) if (dpif_impls[i].probe) { int probe_err = dpif_impls[i].probe(); if (probe_err) { - *out_func = NULL; + *dpif_func = NULL; + *dpif_recirc_func = NULL; return probe_err; } } - *out_func = dpif_impls[i].input_func; + *dpif_func = dpif_impls[i].input_func; + *dpif_recirc_func = dpif_impls[i].recirc_func; return 0; } } @@ -144,12 +182,15 @@ dp_netdev_impl_get_by_name(const char *name, dp_netdev_input_func *out_func) int32_t dp_netdev_impl_set_default_by_name(const char *name) { - dp_netdev_input_func new_default; + dp_netdev_input_func new_dpif_default; + dp_netdev_recirc_func new_dpif_recirc_default; - int32_t err = dp_netdev_impl_get_by_name(name, &new_default); + int32_t err = dp_netdev_impl_get_by_name(name, &new_dpif_default, + &new_dpif_recirc_default); if (!err) { - default_dpif_func = new_default; + default_dpif_func = new_dpif_default; + default_dpif_recirc_func = new_dpif_recirc_default; } return err; diff --git a/lib/dpif-netdev-private-dpif.h b/lib/dpif-netdev-private-dpif.h index 37908de9a..5dd1bd1de 100644 --- a/lib/dpif-netdev-private-dpif.h +++ b/lib/dpif-netdev-private-dpif.h @@ -36,6 +36,16 @@ typedef int32_t (*dp_netdev_input_func)(struct dp_netdev_pmd_thread *pmd, struct dp_packet_batch *packets, odp_port_t port_no); +/* Typedef for DPIF re-circulate functions. + * The implementation on success must handle the whole batch of packets. + * The implementation on failure must return the error code and also + * the batch of packets must be unchnaged. After failure, scalar dpif + * is called and is expected to handle packet processing thereafter. + * Returns 0 on sucess else returns error code on failure. + */ +typedef int32_t (*dp_netdev_recirc_func)(struct dp_netdev_pmd_thread *pmd, + struct dp_packet_batch *packets); + /* Probe a DPIF implementation. This allows the implementation to validate CPU * ISA availability. Returns -ENOTSUP if not available, returns 0 if valid to * use. @@ -46,6 +56,10 @@ typedef int32_t (*dp_netdev_input_func_probe)(void); struct dpif_netdev_impl_info_t { /* Function pointer to execute to have this DPIF implementation run. */ dp_netdev_input_func input_func; + + /* Function pointer to execute recirc DPIF implementation. */ + dp_netdev_recirc_func recirc_func; + /* Function pointer to execute to check the CPU ISA is available to run. If * not necessary, it must be set to NULL which implies that it is always * valid to use. */ @@ -63,6 +77,10 @@ dp_netdev_impl_get(struct ds *reply, struct dp_netdev_pmd_thread **pmd_list, * overridden at runtime. */ dp_netdev_input_func dp_netdev_impl_get_default(void); +/* Returns the default recirculate DPIF which is first ./configure selected, + * but can be overridden at runtime. */ +dp_netdev_recirc_func dp_netdev_recirc_impl_get_default(void); + /* Overrides the default DPIF with the user set DPIF. */ int32_t dp_netdev_impl_set_default_by_name(const char *name); diff --git a/lib/dpif-netdev-private-thread.h b/lib/dpif-netdev-private-thread.h index 4472b199d..bce91358b 100644 --- a/lib/dpif-netdev-private-thread.h +++ b/lib/dpif-netdev-private-thread.h @@ -124,6 +124,9 @@ struct dp_netdev_pmd_thread { /* Function pointer to call for dp_netdev_input() functionality. */ ATOMIC(dp_netdev_input_func) netdev_input_func; + /* Function pointer to call for dp_netdev_recirculate() functionality. */ + ATOMIC(dp_netdev_recirc_func) netdev_input_recirc_func; + /* Pointer for per-DPIF implementation scratch space. */ void *netdev_input_func_userdata; diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index ea95acde0..ef14325a9 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -1153,6 +1153,10 @@ dpif_netdev_impl_set(struct unixctl_conn *conn, int argc OVS_UNUSED, * default. */ atomic_store_relaxed(&pmd->netdev_input_func, dp_netdev_impl_get_default()); + /* Initialize recirc DPIF function pointer to the newly configured + * default. */ + atomic_store_relaxed(&pmd->netdev_input_recirc_func, + dp_netdev_recirc_impl_get_default()); }; free(pmd_list); @@ -7475,6 +7479,11 @@ dp_netdev_configure_pmd(struct dp_netdev_pmd_thread *pmd, struct dp_netdev *dp, /* Initialize DPIF function pointer to the default configured version. */ atomic_init(&pmd->netdev_input_func, dp_netdev_impl_get_default()); + /* Initialize recirculate DPIF function pointer to the default configured + * version. */ + atomic_init(&pmd->netdev_input_recirc_func, + dp_netdev_recirc_impl_get_default()); + /* Init default miniflow_extract function */ atomic_init(&pmd->miniflow_extract_opt, dp_mfex_impl_get_default()); @@ -8819,7 +8828,10 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_, } (*depth)++; - dp_netdev_recirculate(pmd, packets_); + int ret = pmd->netdev_input_recirc_func(pmd, packets_); + if (ret != 0) { + dp_netdev_recirculate(pmd, packets_); + } (*depth)--; return; } @@ -8891,7 +8903,10 @@ dp_execute_cb(void *aux_, struct dp_packet_batch *packets_, } (*depth)++; - dp_netdev_recirculate(pmd, packets_); + int ret = pmd->netdev_input_recirc_func(pmd, packets_); + if (ret != 0) { + dp_netdev_recirculate(pmd, packets_); + } (*depth)--; return; -- 2.25.1 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev