Coverage Report

Created: 2025-07-01 06:50

/src/openvswitch/lib/dpif-netdev-lookup-autovalidator.c
Line
Count
Source (jump to first uncovered line)
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 "openvswitch/vlog.h"
21
22
VLOG_DEFINE_THIS_MODULE(dpif_lookup_autovalidator);
23
24
/* This file implements an automated validator for subtable search
25
 * implementations. It compares the results of the generic scalar search result
26
 * with ISA optimized implementations.
27
 *
28
 * Note the goal is *NOT* to test the *specialized* versions of subtables, as
29
 * the compiler performs the specialization - and we rely on the correctness of
30
 * the compiler to not break those specialized variants.
31
 *
32
 * The goal is to ensure identical results of the different implementations,
33
 * despite that the implementations may have different methods to get those
34
 * results.
35
 *
36
 * Example: AVX-512 ISA uses different instructions and algorithm to the scalar
37
 * implementation, however the results (rules[] output) must be the same.
38
 */
39
40
dpcls_subtable_lookup_func
41
dpcls_subtable_autovalidator_probe(uint32_t u0 OVS_UNUSED,
42
                                   uint32_t u1 OVS_UNUSED);
43
44
static uint32_t
45
dpcls_subtable_autovalidator(struct dpcls_subtable *subtable,
46
                             uint32_t keys_map,
47
                             const struct netdev_flow_key *keys[],
48
                             struct dpcls_rule **rules_good)
49
0
{
50
0
    const uint32_t u0_bit_count = subtable->mf_bits_set_unit0;
51
0
    const uint32_t u1_bit_count = subtable->mf_bits_set_unit1;
52
53
    /* Scalar generic - the "known correct" version. */
54
0
    dpcls_subtable_lookup_func lookup_good;
55
0
    lookup_good = dpcls_subtable_generic_probe(u0_bit_count, u1_bit_count);
56
57
    /* Run actual scalar implementation to get known good results. */
58
0
    uint32_t matches_good = lookup_good(subtable, keys_map, keys, rules_good);
59
60
0
    struct dpcls_subtable_lookup_info_t *lookup_funcs;
61
0
    int32_t lookup_func_count = dpcls_subtable_lookup_info_get(&lookup_funcs);
62
0
    if (lookup_func_count < 0) {
63
0
        VLOG_ERR("failed to get lookup subtable function implementations\n");
64
0
        return 0;
65
0
    }
66
67
    /* Ensure the autovalidator is the 0th item in the lookup_funcs array. */
68
0
    ovs_assert(lookup_funcs[0].probe(0, 0) == dpcls_subtable_autovalidator);
69
70
    /* Now compare all other implementations against known good results.
71
     * Note we start iterating from array[1], as 0 is the autotester itself.
72
     */
73
0
    for (int i = 1; i < lookup_func_count; i++) {
74
0
        dpcls_subtable_lookup_func lookup_func;
75
0
        lookup_func = lookup_funcs[i].probe(u0_bit_count,
76
0
                            u1_bit_count);
77
78
        /* If its probe returns a function, then test it. */
79
0
        if (lookup_func) {
80
0
            struct dpcls_rule *rules_test[NETDEV_MAX_BURST];
81
0
            size_t rules_size = sizeof(struct dpcls_rule *) * NETDEV_MAX_BURST;
82
0
            memset(rules_test, 0, rules_size);
83
0
            uint32_t matches_test = lookup_func(subtable, keys_map, keys,
84
0
                                                rules_test);
85
86
            /* Ensure same packets matched against subtable. */
87
0
            if (matches_good != matches_test) {
88
0
                VLOG_ERR("matches_good 0x%x != matches_test 0x%x in func %s\n",
89
0
                         matches_good, matches_test, lookup_funcs[i].name);
90
0
            }
91
92
            /* Ensure rules matched are the same for scalar / others. */
93
0
            int j;
94
0
            ULLONG_FOR_EACH_1 (j, matches_test) {
95
0
                ovs_assert(rules_good[j] == rules_test[j]);
96
0
            }
97
0
        }
98
0
    }
99
100
0
    return matches_good;
101
0
}
102
103
dpcls_subtable_lookup_func
104
dpcls_subtable_autovalidator_probe(uint32_t u0 OVS_UNUSED,
105
                                   uint32_t u1 OVS_UNUSED)
106
0
{
107
    /* Always return the same validator tester, it works for all subtables. */
108
0
    return dpcls_subtable_autovalidator;
109
0
}