forked from openvswitch/ovs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dpif-netdev-lookup-autovalidator.c
109 lines (94 loc) · 4.27 KB
/
dpif-netdev-lookup-autovalidator.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*
* 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;
}