2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 18:07:40 +00:00
ovs/lib/dpif-netdev-private-dpif.c
Sunil Pai G b0e8668f38 dpif-netdev: Simplify AVX512 build time checks to enhance readability.
The preprocessor comparison string to check AVX512 capabilities are
lengthy and effecting user readability. Simpify this by aliasing the checks.

Suggested-by: Eelco Chaudron <echaudro@redhat.com>
Signed-off-by: Sunil Pai G <sunil.pai.g@intel.com>
Acked-by: Cian Ferriter <cian.ferriter@intel.com>
Signed-off-by: Ian Stokes <ian.stokes@intel.com>
2022-08-10 15:57:39 +01:00

172 lines
4.6 KiB
C

/*
* Copyright (c) 2021 Intel Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <config.h>
#include "dpif-netdev-private-dpif.h"
#include "dpif-netdev-private-thread.h"
#include <errno.h>
#include <string.h>
#include "cpu.h"
#include "openvswitch/dynamic-string.h"
#include "openvswitch/vlog.h"
#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__)
enum dpif_netdev_impl_info_idx {
DPIF_NETDEV_IMPL_SCALAR,
DPIF_NETDEV_IMPL_AVX512
};
#if DPIF_NETDEV_IMPL_AVX512_CHECK
static int32_t
dp_netdev_input_outer_avx512_probe(void)
{
if (!cpu_has_isa(OVS_CPU_ISA_X86_AVX512F)
|| !cpu_has_isa(OVS_CPU_ISA_X86_BMI2)) {
return -ENOTSUP;
}
return 0;
}
#endif
/* Actual list of implementations goes here. */
static struct dpif_netdev_impl_info_t dpif_impls[] = {
/* The default scalar C code implementation. */
[DPIF_NETDEV_IMPL_SCALAR] = { .input_func = dp_netdev_input,
.probe = NULL,
.name = "dpif_scalar", },
#if DPIF_NETDEV_IMPL_AVX512_CHECK
/* Only available on x86_64 bit builds with SSE 4.2 used for OVS core. */
[DPIF_NETDEV_IMPL_AVX512] = { .input_func = dp_netdev_input_outer_avx512,
.probe = dp_netdev_input_outer_avx512_probe,
.name = "dpif_avx512", },
#endif
};
static dp_netdev_input_func default_dpif_func;
dp_netdev_input_func
dp_netdev_impl_get_default(void)
{
/* For the first call, this will be NULL. Compute the compile time default.
*/
if (!default_dpif_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 DPIF implementation is %s.\n",
dpif_impls[dpif_idx].name);
default_dpif_func = dpif_impls[dpif_idx].input_func;
}
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".
*/
static int32_t
dp_netdev_impl_get_by_name(const char *name, dp_netdev_input_func *out_func)
{
ovs_assert(name);
ovs_assert(out_func);
uint32_t i;
for (i = 0; i < ARRAY_SIZE(dpif_impls); i++) {
if (strcmp(dpif_impls[i].name, name) == 0) {
/* Probe function is optional - so check it is set before exec. */
if (dpif_impls[i].probe) {
int probe_err = dpif_impls[i].probe();
if (probe_err) {
*out_func = NULL;
return probe_err;
}
}
*out_func = dpif_impls[i].input_func;
return 0;
}
}
return -EINVAL;
}
int32_t
dp_netdev_impl_set_default_by_name(const char *name)
{
dp_netdev_input_func new_default;
int32_t err = dp_netdev_impl_get_by_name(name, &new_default);
if (!err) {
default_dpif_func = new_default;
}
return err;
}