mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 18:07:40 +00:00
110 lines
4.3 KiB
C
110 lines
4.3 KiB
C
|
/*
|
||
|
* Copyright (c) 2020 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.h"
|
||
|
#include "dpif-netdev-lookup.h"
|
||
|
#include "openvswitch/vlog.h"
|
||
|
|
||
|
VLOG_DEFINE_THIS_MODULE(dpif_lookup_autovalidator);
|
||
|
|
||
|
/* This file implements an automated validator for subtable search
|
||
|
* implementations. It compares the results of the generic scalar search result
|
||
|
* with ISA optimized implementations.
|
||
|
*
|
||
|
* Note the goal is *NOT* to test the *specialized* versions of subtables, as
|
||
|
* the compiler performs the specialization - and we rely on the correctness of
|
||
|
* the compiler to not break those specialized variants.
|
||
|
*
|
||
|
* The goal is to ensure identical results of the different implementations,
|
||
|
* despite that the implementations may have different methods to get those
|
||
|
* results.
|
||
|
*
|
||
|
* Example: AVX-512 ISA uses different instructions and algorithm to the scalar
|
||
|
* implementation, however the results (rules[] output) must be the same.
|
||
|
*/
|
||
|
|
||
|
dpcls_subtable_lookup_func
|
||
|
dpcls_subtable_autovalidator_probe(uint32_t u0 OVS_UNUSED,
|
||
|
uint32_t u1 OVS_UNUSED);
|
||
|
|
||
|
static uint32_t
|
||
|
dpcls_subtable_autovalidator(struct dpcls_subtable *subtable,
|
||
|
uint32_t keys_map,
|
||
|
const struct netdev_flow_key *keys[],
|
||
|
struct dpcls_rule **rules_good)
|
||
|
{
|
||
|
const uint32_t u0_bit_count = subtable->mf_bits_set_unit0;
|
||
|
const uint32_t u1_bit_count = subtable->mf_bits_set_unit1;
|
||
|
|
||
|
/* Scalar generic - the "known correct" version. */
|
||
|
dpcls_subtable_lookup_func lookup_good;
|
||
|
lookup_good = dpcls_subtable_generic_probe(u0_bit_count, u1_bit_count);
|
||
|
|
||
|
/* Run actual scalar implementation to get known good results. */
|
||
|
uint32_t matches_good = lookup_good(subtable, keys_map, keys, rules_good);
|
||
|
|
||
|
struct dpcls_subtable_lookup_info_t *lookup_funcs;
|
||
|
int32_t lookup_func_count = dpcls_subtable_lookup_info_get(&lookup_funcs);
|
||
|
if (lookup_func_count < 0) {
|
||
|
VLOG_ERR("failed to get lookup subtable function implementations\n");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* Ensure the autovalidator is the 0th item in the lookup_funcs array. */
|
||
|
ovs_assert(lookup_funcs[0].probe(0, 0) == dpcls_subtable_autovalidator);
|
||
|
|
||
|
/* Now compare all other implementations against known good results.
|
||
|
* Note we start iterating from array[1], as 0 is the autotester itself.
|
||
|
*/
|
||
|
for (int i = 1; i < lookup_func_count; i++) {
|
||
|
dpcls_subtable_lookup_func lookup_func;
|
||
|
lookup_func = lookup_funcs[i].probe(u0_bit_count,
|
||
|
u1_bit_count);
|
||
|
|
||
|
/* If its probe returns a function, then test it. */
|
||
|
if (lookup_func) {
|
||
|
struct dpcls_rule *rules_test[NETDEV_MAX_BURST];
|
||
|
size_t rules_size = sizeof(struct dpcls_rule *) * NETDEV_MAX_BURST;
|
||
|
memset(rules_test, 0, rules_size);
|
||
|
uint32_t matches_test = lookup_func(subtable, keys_map, keys,
|
||
|
rules_test);
|
||
|
|
||
|
/* Ensure same packets matched against subtable. */
|
||
|
if (matches_good != matches_test) {
|
||
|
VLOG_ERR("matches_good 0x%x != matches_test 0x%x in func %s\n",
|
||
|
matches_good, matches_test, lookup_funcs[i].name);
|
||
|
}
|
||
|
|
||
|
/* Ensure rules matched are the same for scalar / others. */
|
||
|
int j;
|
||
|
ULLONG_FOR_EACH_1 (j, matches_test) {
|
||
|
ovs_assert(rules_good[j] == rules_test[j]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return matches_good;
|
||
|
}
|
||
|
|
||
|
dpcls_subtable_lookup_func
|
||
|
dpcls_subtable_autovalidator_probe(uint32_t u0 OVS_UNUSED,
|
||
|
uint32_t u1 OVS_UNUSED)
|
||
|
{
|
||
|
/* Always return the same validator tester, it works for all subtables. */
|
||
|
return dpcls_subtable_autovalidator;
|
||
|
}
|