]> git.proxmox.com Git - mirror_ovs.git/blame - lib/dpif-netdev-lookup-autovalidator.c
cirrus: Use FreeBSD 12.2.
[mirror_ovs.git] / lib / dpif-netdev-lookup-autovalidator.c
CommitLineData
e90e115a
HH
1/*
2 * Copyright (c) 2020 Intel Corporation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <config.h>
18#include "dpif-netdev.h"
19#include "dpif-netdev-lookup.h"
20#include "dpif-netdev-private.h"
21#include "openvswitch/vlog.h"
22
23VLOG_DEFINE_THIS_MODULE(dpif_lookup_autovalidator);
24
25/* This file implements an automated validator for subtable search
26 * implementations. It compares the results of the generic scalar search result
27 * with ISA optimized implementations.
28 *
29 * Note the goal is *NOT* to test the *specialized* versions of subtables, as
30 * the compiler performs the specialization - and we rely on the correctness of
31 * the compiler to not break those specialized variants.
32 *
33 * The goal is to ensure identical results of the different implementations,
34 * despite that the implementations may have different methods to get those
35 * results.
36 *
37 * Example: AVX-512 ISA uses different instructions and algorithm to the scalar
38 * implementation, however the results (rules[] output) must be the same.
39 */
40
41dpcls_subtable_lookup_func
42dpcls_subtable_autovalidator_probe(uint32_t u0 OVS_UNUSED,
43 uint32_t u1 OVS_UNUSED);
44
45static uint32_t
46dpcls_subtable_autovalidator(struct dpcls_subtable *subtable,
47 uint32_t keys_map,
48 const struct netdev_flow_key *keys[],
49 struct dpcls_rule **rules_good)
50{
51 const uint32_t u0_bit_count = subtable->mf_bits_set_unit0;
52 const uint32_t u1_bit_count = subtable->mf_bits_set_unit1;
53
54 /* Scalar generic - the "known correct" version. */
55 dpcls_subtable_lookup_func lookup_good;
56 lookup_good = dpcls_subtable_generic_probe(u0_bit_count, u1_bit_count);
57
58 /* Run actual scalar implementation to get known good results. */
59 uint32_t matches_good = lookup_good(subtable, keys_map, keys, rules_good);
60
61 struct dpcls_subtable_lookup_info_t *lookup_funcs;
62 int32_t lookup_func_count = dpcls_subtable_lookup_info_get(&lookup_funcs);
63 if (lookup_func_count < 0) {
64 VLOG_ERR("failed to get lookup subtable function implementations\n");
65 return 0;
66 }
67
68 /* Ensure the autovalidator is the 0th item in the lookup_funcs array. */
69 ovs_assert(lookup_funcs[0].probe(0, 0) == dpcls_subtable_autovalidator);
70
71 /* Now compare all other implementations against known good results.
72 * Note we start iterating from array[1], as 0 is the autotester itself.
73 */
74 for (int i = 1; i < lookup_func_count; i++) {
75 dpcls_subtable_lookup_func lookup_func;
76 lookup_func = lookup_funcs[i].probe(u0_bit_count,
77 u1_bit_count);
78
79 /* If its probe returns a function, then test it. */
80 if (lookup_func) {
81 struct dpcls_rule *rules_test[NETDEV_MAX_BURST];
82 size_t rules_size = sizeof(struct dpcls_rule *) * NETDEV_MAX_BURST;
83 memset(rules_test, 0, rules_size);
84 uint32_t matches_test = lookup_func(subtable, keys_map, keys,
85 rules_test);
86
87 /* Ensure same packets matched against subtable. */
88 if (matches_good != matches_test) {
89 VLOG_ERR("matches_good 0x%x != matches_test 0x%x in func %s\n",
90 matches_good, matches_test, lookup_funcs[i].name);
91 }
92
93 /* Ensure rules matched are the same for scalar / others. */
94 int j;
95 ULLONG_FOR_EACH_1 (j, matches_test) {
96 ovs_assert(rules_good[j] == rules_test[j]);
97 }
98 }
99 }
100
101 return matches_good;
102}
103
104dpcls_subtable_lookup_func
105dpcls_subtable_autovalidator_probe(uint32_t u0 OVS_UNUSED,
106 uint32_t u1 OVS_UNUSED)
107{
108 /* Always return the same validator tester, it works for all subtables. */
109 return dpcls_subtable_autovalidator;
110}