2 * Copyright (c) 2020 Intel Corporation.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "dpif-netdev.h"
19 #include "dpif-netdev-lookup.h"
20 #include "dpif-netdev-private.h"
21 #include "openvswitch/vlog.h"
23 VLOG_DEFINE_THIS_MODULE(dpif_lookup_autovalidator
);
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.
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.
33 * The goal is to ensure identical results of the different implementations,
34 * despite that the implementations may have different methods to get those
37 * Example: AVX-512 ISA uses different instructions and algorithm to the scalar
38 * implementation, however the results (rules[] output) must be the same.
41 dpcls_subtable_lookup_func
42 dpcls_subtable_autovalidator_probe(uint32_t u0 OVS_UNUSED
,
43 uint32_t u1 OVS_UNUSED
);
46 dpcls_subtable_autovalidator(struct dpcls_subtable
*subtable
,
48 const struct netdev_flow_key
*keys
[],
49 struct dpcls_rule
**rules_good
)
51 const uint32_t u0_bit_count
= subtable
->mf_bits_set_unit0
;
52 const uint32_t u1_bit_count
= subtable
->mf_bits_set_unit1
;
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
);
58 /* Run actual scalar implementation to get known good results. */
59 uint32_t matches_good
= lookup_good(subtable
, keys_map
, keys
, rules_good
);
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");
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
);
71 /* Now compare all other implementations against known good results.
72 * Note we start iterating from array[1], as 0 is the autotester itself.
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
,
79 /* If its probe returns a function, then test it. */
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
,
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
);
93 /* Ensure rules matched are the same for scalar / others. */
95 ULLONG_FOR_EACH_1 (j
, matches_test
) {
96 ovs_assert(rules_good
[j
] == rules_test
[j
]);
104 dpcls_subtable_lookup_func
105 dpcls_subtable_autovalidator_probe(uint32_t u0 OVS_UNUSED
,
106 uint32_t u1 OVS_UNUSED
)
108 /* Always return the same validator tester, it works for all subtables. */
109 return dpcls_subtable_autovalidator
;