]> git.proxmox.com Git - mirror_ovs.git/blob - tests/oss-fuzz/miniflow_target.c
db-ctl-base: Add {in} and {not-in} set relational operators.
[mirror_ovs.git] / tests / oss-fuzz / miniflow_target.c
1 #include <config.h>
2 #include "classifier.h"
3 #include "fuzzer.h"
4 #include "dp-packet.h"
5 #include "flow.h"
6 #include "openvswitch/ofp-match.h"
7 #include "openvswitch/ofp-print.h"
8 #include "openvswitch/match.h"
9 #include "classifier-private.h"
10 #include "util.h"
11
12 /* Returns a copy of 'src'. The caller must eventually free the returned
13 * miniflow with free(). */
14 static struct miniflow *
15 miniflow_clone__(const struct miniflow *src)
16 {
17 struct miniflow *dst;
18 size_t data_size;
19
20 data_size = miniflow_alloc(&dst, 1, src);
21 miniflow_clone(dst, src, data_size / sizeof(uint64_t));
22 return dst;
23 }
24
25 /* Returns a hash value for 'flow', given 'basis'. */
26 static inline uint32_t
27 miniflow_hash__(const struct miniflow *flow, uint32_t basis)
28 {
29 const uint64_t *p = miniflow_get_values(flow);
30 size_t n_values = miniflow_n_values(flow);
31 struct flowmap hash_map = FLOWMAP_EMPTY_INITIALIZER;
32 uint32_t hash = basis;
33 size_t idx;
34
35 FLOWMAP_FOR_EACH_INDEX (idx, flow->map) {
36 uint64_t value = *p++;
37
38 if (value) {
39 hash = hash_add64(hash, value);
40 flowmap_set(&hash_map, idx, 1);
41 }
42 }
43 map_t map;
44 FLOWMAP_FOR_EACH_MAP (map, hash_map) {
45 hash = hash_add64(hash, map);
46 }
47
48 return hash_finish(hash, n_values);
49 }
50
51 #define FLOW_U32S (FLOW_U64S * 2)
52
53 static void
54 toggle_masked_flow_bits(struct flow *flow, const struct flow_wildcards *mask)
55 {
56 const uint32_t *mask_u32 = (const uint32_t *) &mask->masks;
57 uint32_t *flow_u32 = (uint32_t *) flow;
58 int i;
59
60 for (i = 0; i < FLOW_U32S; i++) {
61 if (mask_u32[i] != 0) {
62 uint32_t bit;
63
64 do {
65 bit = 1u << random_range(32);
66 } while (!(bit & mask_u32[i]));
67 flow_u32[i] ^= bit;
68 }
69 }
70 }
71
72 static void
73 wildcard_extra_bits(struct flow_wildcards *mask)
74 {
75 uint32_t *mask_u32 = (uint32_t *) &mask->masks;
76 int i;
77
78 for (i = 0; i < FLOW_U32S; i++) {
79 if (mask_u32[i] != 0) {
80 uint32_t bit;
81
82 do {
83 bit = 1u << random_range(32);
84 } while (!(bit & mask_u32[i]));
85 mask_u32[i] &= ~bit;
86 }
87 }
88 }
89
90 static void
91 test_miniflow(struct flow *flow)
92 {
93 struct miniflow *miniflow, *miniflow2, *miniflow3;
94 struct flow flow2, flow3;
95 struct flow_wildcards mask;
96 struct minimask *minimask;
97 int i;
98
99 const uint64_t *flow_u64 = (const uint64_t *) flow;
100
101 /* Convert flow to miniflow. */
102 miniflow = miniflow_create(flow);
103
104 /* Obtain miniflow hash. */
105 uint32_t hash = miniflow_hash_5tuple(miniflow, 0);
106 ignore(hash);
107
108 /* Check that the flow equals its miniflow. */
109 for (i = 0; i < FLOW_MAX_VLAN_HEADERS; i++) {
110 ovs_assert(miniflow_get_vid(miniflow, i) ==
111 vlan_tci_to_vid(flow->vlans[i].tci));
112 }
113 for (i = 0; i < FLOW_U64S; i++) {
114 ovs_assert(miniflow_get(miniflow, i) == flow_u64[i]);
115 }
116
117 /* Check that the miniflow equals itself. */
118 ovs_assert(miniflow_equal(miniflow, miniflow));
119
120 /* Convert miniflow back to flow and verify that it's the same. */
121 miniflow_expand(miniflow, &flow2);
122 ovs_assert(flow_equal(flow, &flow2));
123 /* Check that copying a miniflow works properly. */
124 miniflow2 = miniflow_clone__(miniflow);
125 ovs_assert(miniflow_equal(miniflow, miniflow2));
126 ovs_assert(miniflow_hash__(miniflow, 0) == miniflow_hash__(miniflow2, 0));
127 miniflow_expand(miniflow2, &flow3);
128 ovs_assert(flow_equal(flow, &flow3));
129
130 /* Check that masked matches work as expected for identical flows and
131 * miniflows. */
132 flow_wildcards_init_for_packet(&mask, flow);
133 /* Ensure that mask is not catchall just in case
134 * flow_wildcards_init_for_packet returns a catchall mask
135 */
136 uint64_t *mask_u64 = (uint64_t *) &mask.masks;
137 mask_u64[0] = 1;
138 ovs_assert(!flow_wildcards_is_catchall(&mask));
139 minimask = minimask_create(&mask);
140 ovs_assert(!minimask_is_catchall(minimask));
141 ovs_assert(miniflow_equal_in_minimask(miniflow, miniflow2, minimask));
142 ovs_assert(miniflow_equal_flow_in_minimask(miniflow, &flow2, minimask));
143 ovs_assert(miniflow_hash_in_minimask(miniflow, minimask, 0x12345678) ==
144 flow_hash_in_minimask(flow, minimask, 0x12345678));
145 ovs_assert(minimask_hash(minimask, 0) ==
146 miniflow_hash__(&minimask->masks, 0));
147
148 /* Check that masked matches work as expected for differing flows and
149 * miniflows. */
150 toggle_masked_flow_bits(&flow2, &mask);
151 ovs_assert(!miniflow_equal_flow_in_minimask(miniflow, &flow2, minimask));
152 miniflow3 = miniflow_create(&flow2);
153 ovs_assert(!miniflow_equal_in_minimask(miniflow, miniflow3, minimask));
154
155 free(miniflow);
156 free(miniflow2);
157 free(miniflow3);
158 free(minimask);
159 }
160
161 static void
162 test_minimask_has_extra(struct flow *flow)
163 {
164 struct flow_wildcards catchall;
165 struct minimask *minicatchall;
166
167 flow_wildcards_init_catchall(&catchall);
168 minicatchall = minimask_create(&catchall);
169 ovs_assert(minimask_is_catchall(minicatchall));
170
171 struct flow_wildcards mask;
172 struct minimask *minimask;
173
174 mask.masks = *flow;
175 minimask = minimask_create(&mask);
176 ovs_assert(!minimask_has_extra(minimask, minimask));
177 ovs_assert(minimask_has_extra(minicatchall, minimask)
178 == !minimask_is_catchall(minimask));
179 if (!minimask_is_catchall(minimask)) {
180 struct minimask *minimask2;
181
182 wildcard_extra_bits(&mask);
183 minimask2 = minimask_create(&mask);
184 ovs_assert(minimask_has_extra(minimask2, minimask));
185 ovs_assert(!minimask_has_extra(minimask, minimask2));
186 free(minimask2);
187 }
188
189 free(minimask);
190 free(minicatchall);
191 }
192
193 static void
194 test_minimask_combine(struct flow *flow)
195 {
196 struct flow_wildcards catchall;
197 struct minimask *minicatchall;
198
199 flow_wildcards_init_catchall(&catchall);
200 minicatchall = minimask_create(&catchall);
201 ovs_assert(minimask_is_catchall(minicatchall));
202
203 struct minimask *minimask, *minimask2;
204 struct flow_wildcards mask, mask2, combined, combined2;
205 struct {
206 struct minimask minicombined;
207 uint64_t storage[FLOW_U64S];
208 } m;
209 struct flow flow2;
210
211 memset(&flow2, 0, sizeof flow2);
212 mask.masks = *flow;
213 minimask = minimask_create(&mask);
214
215 minimask_combine(&m.minicombined, minimask, minicatchall, m.storage);
216 ovs_assert(minimask_is_catchall(&m.minicombined));
217
218 /* Create mask based on zero flow */
219 mask2.masks = flow2;
220 minimask2 = minimask_create(&mask2);
221
222 minimask_combine(&m.minicombined, minimask, minimask2, m.storage);
223 flow_wildcards_and(&combined, &mask, &mask2);
224 minimask_expand(&m.minicombined, &combined2);
225 ovs_assert(flow_wildcards_equal(&combined, &combined2));
226
227 free(minimask);
228 free(minimask2);
229
230 free(minicatchall);
231 }
232
233 int
234 LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
235 {
236 struct dp_packet packet;
237 struct flow flow;
238 dp_packet_use_const(&packet, data, size);
239 flow_extract(&packet, &flow);
240
241 /* Do miniflow tests. */
242 test_miniflow(&flow);
243 test_minimask_has_extra(&flow);
244 test_minimask_combine(&flow);
245
246 return 0;
247 }