4a49932ddf6022e68d451542bdae645228991e4c
[cascardo/ovs.git] / tests / test-classifier.c
1 /*
2  * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
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 /* "White box" tests for classifier.
18  *
19  * With very few exceptions, these tests obtain complete coverage of every
20  * basic block and every branch in the classifier implementation, e.g. a clean
21  * report from "gcov -b".  (Covering the exceptions would require finding
22  * collisions in the hash function used for flow data, etc.)
23  *
24  * This test should receive a clean report from "valgrind --leak-check=full":
25  * it frees every heap block that it allocates.
26  */
27
28 #include <config.h>
29 #undef NDEBUG
30 #include "classifier.h"
31 #include <assert.h>
32 #include <errno.h>
33 #include <limits.h>
34 #include "byte-order.h"
35 #include "classifier-private.h"
36 #include "command-line.h"
37 #include "flow.h"
38 #include "ofp-util.h"
39 #include "ovstest.h"
40 #include "packets.h"
41 #include "random.h"
42 #include "unaligned.h"
43 #include "util.h"
44
45 static bool versioned = false;
46
47 /* Fields in a rule. */
48 #define CLS_FIELDS                        \
49     /*        struct flow    all-caps */  \
50     /*        member name    name     */  \
51     /*        -----------    -------- */  \
52     CLS_FIELD(tunnel.tun_id, TUN_ID)      \
53     CLS_FIELD(metadata,      METADATA)    \
54     CLS_FIELD(nw_src,        NW_SRC)      \
55     CLS_FIELD(nw_dst,        NW_DST)      \
56     CLS_FIELD(in_port,       IN_PORT)     \
57     CLS_FIELD(vlan_tci,      VLAN_TCI)    \
58     CLS_FIELD(dl_type,       DL_TYPE)     \
59     CLS_FIELD(tp_src,        TP_SRC)      \
60     CLS_FIELD(tp_dst,        TP_DST)      \
61     CLS_FIELD(dl_src,        DL_SRC)      \
62     CLS_FIELD(dl_dst,        DL_DST)      \
63     CLS_FIELD(nw_proto,      NW_PROTO)    \
64     CLS_FIELD(nw_tos,        NW_DSCP)
65
66 /* Field indexes.
67  *
68  * (These are also indexed into struct classifier's 'tables' array.) */
69 enum {
70 #define CLS_FIELD(MEMBER, NAME) CLS_F_IDX_##NAME,
71     CLS_FIELDS
72 #undef CLS_FIELD
73     CLS_N_FIELDS
74 };
75
76 /* Field information. */
77 struct cls_field {
78     int ofs;                    /* Offset in struct flow. */
79     int len;                    /* Length in bytes. */
80     const char *name;           /* Name (for debugging). */
81 };
82
83 static const struct cls_field cls_fields[CLS_N_FIELDS] = {
84 #define CLS_FIELD(MEMBER, NAME)                 \
85     { offsetof(struct flow, MEMBER),            \
86       sizeof ((struct flow *)0)->MEMBER,        \
87       #NAME },
88     CLS_FIELDS
89 #undef CLS_FIELD
90 };
91
92 struct test_rule {
93     struct ovs_list list_node;
94     int aux;                    /* Auxiliary data. */
95     struct cls_rule cls_rule;   /* Classifier rule data. */
96 };
97
98 static struct test_rule *
99 test_rule_from_cls_rule(const struct cls_rule *rule)
100 {
101     return rule ? CONTAINER_OF(rule, struct test_rule, cls_rule) : NULL;
102 }
103
104 static void
105 test_rule_destroy(struct test_rule *rule)
106 {
107     if (rule) {
108         cls_rule_destroy(&rule->cls_rule);
109         free(rule);
110     }
111 }
112
113 static struct test_rule *make_rule(int wc_fields, int priority, int value_pat);
114 static void free_rule(struct test_rule *);
115 static struct test_rule *clone_rule(const struct test_rule *);
116
117 /* Trivial (linear) classifier. */
118 struct tcls {
119     size_t n_rules;
120     size_t allocated_rules;
121     struct test_rule **rules;
122 };
123
124 static void
125 tcls_init(struct tcls *tcls)
126 {
127     tcls->n_rules = 0;
128     tcls->allocated_rules = 0;
129     tcls->rules = NULL;
130 }
131
132 static void
133 tcls_destroy(struct tcls *tcls)
134 {
135     if (tcls) {
136         size_t i;
137
138         for (i = 0; i < tcls->n_rules; i++) {
139             test_rule_destroy(tcls->rules[i]);
140         }
141         free(tcls->rules);
142     }
143 }
144
145 static bool
146 tcls_is_empty(const struct tcls *tcls)
147 {
148     return tcls->n_rules == 0;
149 }
150
151 static struct test_rule *
152 tcls_insert(struct tcls *tcls, const struct test_rule *rule)
153 {
154     size_t i;
155
156     for (i = 0; i < tcls->n_rules; i++) {
157         const struct cls_rule *pos = &tcls->rules[i]->cls_rule;
158         if (cls_rule_equal(pos, &rule->cls_rule)) {
159             /* Exact match. */
160             ovsrcu_postpone(free_rule, tcls->rules[i]);
161             tcls->rules[i] = clone_rule(rule);
162             return tcls->rules[i];
163         } else if (pos->priority < rule->cls_rule.priority) {
164             break;
165         }
166     }
167
168     if (tcls->n_rules >= tcls->allocated_rules) {
169         tcls->rules = x2nrealloc(tcls->rules, &tcls->allocated_rules,
170                                  sizeof *tcls->rules);
171     }
172     if (i != tcls->n_rules) {
173         memmove(&tcls->rules[i + 1], &tcls->rules[i],
174                 sizeof *tcls->rules * (tcls->n_rules - i));
175     }
176     tcls->rules[i] = clone_rule(rule);
177     tcls->n_rules++;
178     return tcls->rules[i];
179 }
180
181 static void
182 tcls_remove(struct tcls *cls, const struct test_rule *rule)
183 {
184     size_t i;
185
186     for (i = 0; i < cls->n_rules; i++) {
187         struct test_rule *pos = cls->rules[i];
188         if (pos == rule) {
189             test_rule_destroy(pos);
190
191             memmove(&cls->rules[i], &cls->rules[i + 1],
192                     sizeof *cls->rules * (cls->n_rules - i - 1));
193
194             cls->n_rules--;
195             return;
196         }
197     }
198     OVS_NOT_REACHED();
199 }
200
201 static bool
202 match(const struct cls_rule *wild_, const struct flow *fixed)
203 {
204     struct match wild;
205     int f_idx;
206
207     minimatch_expand(&wild_->match, &wild);
208     for (f_idx = 0; f_idx < CLS_N_FIELDS; f_idx++) {
209         bool eq;
210
211         if (f_idx == CLS_F_IDX_NW_SRC) {
212             eq = !((fixed->nw_src ^ wild.flow.nw_src)
213                    & wild.wc.masks.nw_src);
214         } else if (f_idx == CLS_F_IDX_NW_DST) {
215             eq = !((fixed->nw_dst ^ wild.flow.nw_dst)
216                    & wild.wc.masks.nw_dst);
217         } else if (f_idx == CLS_F_IDX_TP_SRC) {
218             eq = !((fixed->tp_src ^ wild.flow.tp_src)
219                    & wild.wc.masks.tp_src);
220         } else if (f_idx == CLS_F_IDX_TP_DST) {
221             eq = !((fixed->tp_dst ^ wild.flow.tp_dst)
222                    & wild.wc.masks.tp_dst);
223         } else if (f_idx == CLS_F_IDX_DL_SRC) {
224             eq = eth_addr_equal_except(fixed->dl_src, wild.flow.dl_src,
225                                        wild.wc.masks.dl_src);
226         } else if (f_idx == CLS_F_IDX_DL_DST) {
227             eq = eth_addr_equal_except(fixed->dl_dst, wild.flow.dl_dst,
228                                        wild.wc.masks.dl_dst);
229         } else if (f_idx == CLS_F_IDX_VLAN_TCI) {
230             eq = !((fixed->vlan_tci ^ wild.flow.vlan_tci)
231                    & wild.wc.masks.vlan_tci);
232         } else if (f_idx == CLS_F_IDX_TUN_ID) {
233             eq = !((fixed->tunnel.tun_id ^ wild.flow.tunnel.tun_id)
234                    & wild.wc.masks.tunnel.tun_id);
235         } else if (f_idx == CLS_F_IDX_METADATA) {
236             eq = !((fixed->metadata ^ wild.flow.metadata)
237                    & wild.wc.masks.metadata);
238         } else if (f_idx == CLS_F_IDX_NW_DSCP) {
239             eq = !((fixed->nw_tos ^ wild.flow.nw_tos) &
240                    (wild.wc.masks.nw_tos & IP_DSCP_MASK));
241         } else if (f_idx == CLS_F_IDX_NW_PROTO) {
242             eq = !((fixed->nw_proto ^ wild.flow.nw_proto)
243                    & wild.wc.masks.nw_proto);
244         } else if (f_idx == CLS_F_IDX_DL_TYPE) {
245             eq = !((fixed->dl_type ^ wild.flow.dl_type)
246                    & wild.wc.masks.dl_type);
247         } else if (f_idx == CLS_F_IDX_IN_PORT) {
248             eq = !((fixed->in_port.ofp_port
249                     ^ wild.flow.in_port.ofp_port)
250                    & wild.wc.masks.in_port.ofp_port);
251         } else {
252             OVS_NOT_REACHED();
253         }
254
255         if (!eq) {
256             return false;
257         }
258     }
259     return true;
260 }
261
262 static struct cls_rule *
263 tcls_lookup(const struct tcls *cls, const struct flow *flow)
264 {
265     size_t i;
266
267     for (i = 0; i < cls->n_rules; i++) {
268         struct test_rule *pos = cls->rules[i];
269         if (match(&pos->cls_rule, flow)) {
270             return &pos->cls_rule;
271         }
272     }
273     return NULL;
274 }
275
276 static void
277 tcls_delete_matches(struct tcls *cls, const struct cls_rule *target)
278 {
279     size_t i;
280
281     for (i = 0; i < cls->n_rules; ) {
282         struct test_rule *pos = cls->rules[i];
283         if (!minimask_has_extra(pos->cls_rule.match.mask,
284                                 target->match.mask)) {
285             struct flow flow;
286
287             miniflow_expand(pos->cls_rule.match.flow, &flow);
288             if (match(target, &flow)) {
289                 tcls_remove(cls, pos);
290                 continue;
291             }
292         }
293         i++;
294     }
295 }
296 \f
297 static ovs_be32 nw_src_values[] = { CONSTANT_HTONL(0xc0a80001),
298                                     CONSTANT_HTONL(0xc0a04455) };
299 static ovs_be32 nw_dst_values[] = { CONSTANT_HTONL(0xc0a80002),
300                                     CONSTANT_HTONL(0xc0a04455) };
301 static ovs_be64 tun_id_values[] = {
302     0,
303     CONSTANT_HTONLL(UINT64_C(0xfedcba9876543210)) };
304 static ovs_be64 metadata_values[] = {
305     0,
306     CONSTANT_HTONLL(UINT64_C(0xfedcba9876543210)) };
307 static ofp_port_t in_port_values[] = { OFP_PORT_C(1), OFPP_LOCAL };
308 static ovs_be16 vlan_tci_values[] = { CONSTANT_HTONS(101), CONSTANT_HTONS(0) };
309 static ovs_be16 dl_type_values[]
310             = { CONSTANT_HTONS(ETH_TYPE_IP), CONSTANT_HTONS(ETH_TYPE_ARP) };
311 static ovs_be16 tp_src_values[] = { CONSTANT_HTONS(49362),
312                                     CONSTANT_HTONS(80) };
313 static ovs_be16 tp_dst_values[] = { CONSTANT_HTONS(6667), CONSTANT_HTONS(22) };
314 static uint8_t dl_src_values[][ETH_ADDR_LEN] = {
315                                       { 0x00, 0x02, 0xe3, 0x0f, 0x80, 0xa4 },
316                                       { 0x5e, 0x33, 0x7f, 0x5f, 0x1e, 0x99 } };
317 static uint8_t dl_dst_values[][ETH_ADDR_LEN] = {
318                                       { 0x4a, 0x27, 0x71, 0xae, 0x64, 0xc1 },
319                                       { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
320 static uint8_t nw_proto_values[] = { IPPROTO_TCP, IPPROTO_ICMP };
321 static uint8_t nw_dscp_values[] = { 48, 0 };
322
323 static void *values[CLS_N_FIELDS][2];
324
325 static void
326 init_values(void)
327 {
328     values[CLS_F_IDX_TUN_ID][0] = &tun_id_values[0];
329     values[CLS_F_IDX_TUN_ID][1] = &tun_id_values[1];
330
331     values[CLS_F_IDX_METADATA][0] = &metadata_values[0];
332     values[CLS_F_IDX_METADATA][1] = &metadata_values[1];
333
334     values[CLS_F_IDX_IN_PORT][0] = &in_port_values[0];
335     values[CLS_F_IDX_IN_PORT][1] = &in_port_values[1];
336
337     values[CLS_F_IDX_VLAN_TCI][0] = &vlan_tci_values[0];
338     values[CLS_F_IDX_VLAN_TCI][1] = &vlan_tci_values[1];
339
340     values[CLS_F_IDX_DL_SRC][0] = dl_src_values[0];
341     values[CLS_F_IDX_DL_SRC][1] = dl_src_values[1];
342
343     values[CLS_F_IDX_DL_DST][0] = dl_dst_values[0];
344     values[CLS_F_IDX_DL_DST][1] = dl_dst_values[1];
345
346     values[CLS_F_IDX_DL_TYPE][0] = &dl_type_values[0];
347     values[CLS_F_IDX_DL_TYPE][1] = &dl_type_values[1];
348
349     values[CLS_F_IDX_NW_SRC][0] = &nw_src_values[0];
350     values[CLS_F_IDX_NW_SRC][1] = &nw_src_values[1];
351
352     values[CLS_F_IDX_NW_DST][0] = &nw_dst_values[0];
353     values[CLS_F_IDX_NW_DST][1] = &nw_dst_values[1];
354
355     values[CLS_F_IDX_NW_PROTO][0] = &nw_proto_values[0];
356     values[CLS_F_IDX_NW_PROTO][1] = &nw_proto_values[1];
357
358     values[CLS_F_IDX_NW_DSCP][0] = &nw_dscp_values[0];
359     values[CLS_F_IDX_NW_DSCP][1] = &nw_dscp_values[1];
360
361     values[CLS_F_IDX_TP_SRC][0] = &tp_src_values[0];
362     values[CLS_F_IDX_TP_SRC][1] = &tp_src_values[1];
363
364     values[CLS_F_IDX_TP_DST][0] = &tp_dst_values[0];
365     values[CLS_F_IDX_TP_DST][1] = &tp_dst_values[1];
366 }
367
368 #define N_NW_SRC_VALUES ARRAY_SIZE(nw_src_values)
369 #define N_NW_DST_VALUES ARRAY_SIZE(nw_dst_values)
370 #define N_TUN_ID_VALUES ARRAY_SIZE(tun_id_values)
371 #define N_METADATA_VALUES ARRAY_SIZE(metadata_values)
372 #define N_IN_PORT_VALUES ARRAY_SIZE(in_port_values)
373 #define N_VLAN_TCI_VALUES ARRAY_SIZE(vlan_tci_values)
374 #define N_DL_TYPE_VALUES ARRAY_SIZE(dl_type_values)
375 #define N_TP_SRC_VALUES ARRAY_SIZE(tp_src_values)
376 #define N_TP_DST_VALUES ARRAY_SIZE(tp_dst_values)
377 #define N_DL_SRC_VALUES ARRAY_SIZE(dl_src_values)
378 #define N_DL_DST_VALUES ARRAY_SIZE(dl_dst_values)
379 #define N_NW_PROTO_VALUES ARRAY_SIZE(nw_proto_values)
380 #define N_NW_DSCP_VALUES ARRAY_SIZE(nw_dscp_values)
381
382 #define N_FLOW_VALUES (N_NW_SRC_VALUES *        \
383                        N_NW_DST_VALUES *        \
384                        N_TUN_ID_VALUES *        \
385                        N_IN_PORT_VALUES *       \
386                        N_VLAN_TCI_VALUES *       \
387                        N_DL_TYPE_VALUES *       \
388                        N_TP_SRC_VALUES *        \
389                        N_TP_DST_VALUES *        \
390                        N_DL_SRC_VALUES *        \
391                        N_DL_DST_VALUES *        \
392                        N_NW_PROTO_VALUES *      \
393                        N_NW_DSCP_VALUES)
394
395 static unsigned int
396 get_value(unsigned int *x, unsigned n_values)
397 {
398     unsigned int rem = *x % n_values;
399     *x /= n_values;
400     return rem;
401 }
402
403 static void
404 compare_classifiers(struct classifier *cls, size_t n_invisible_rules,
405                     cls_version_t version, struct tcls *tcls)
406 {
407     static const int confidence = 500;
408     unsigned int i;
409
410     assert(classifier_count(cls) == tcls->n_rules + n_invisible_rules);
411     for (i = 0; i < confidence; i++) {
412         const struct cls_rule *cr0, *cr1, *cr2;
413         struct flow flow;
414         struct flow_wildcards wc;
415         unsigned int x;
416
417         flow_wildcards_init_catchall(&wc);
418         x = random_range(N_FLOW_VALUES);
419         memset(&flow, 0, sizeof flow);
420         flow.nw_src = nw_src_values[get_value(&x, N_NW_SRC_VALUES)];
421         flow.nw_dst = nw_dst_values[get_value(&x, N_NW_DST_VALUES)];
422         flow.tunnel.tun_id = tun_id_values[get_value(&x, N_TUN_ID_VALUES)];
423         flow.metadata = metadata_values[get_value(&x, N_METADATA_VALUES)];
424         flow.in_port.ofp_port = in_port_values[get_value(&x,
425                                                    N_IN_PORT_VALUES)];
426         flow.vlan_tci = vlan_tci_values[get_value(&x, N_VLAN_TCI_VALUES)];
427         flow.dl_type = dl_type_values[get_value(&x, N_DL_TYPE_VALUES)];
428         flow.tp_src = tp_src_values[get_value(&x, N_TP_SRC_VALUES)];
429         flow.tp_dst = tp_dst_values[get_value(&x, N_TP_DST_VALUES)];
430         memcpy(flow.dl_src, dl_src_values[get_value(&x, N_DL_SRC_VALUES)],
431                ETH_ADDR_LEN);
432         memcpy(flow.dl_dst, dl_dst_values[get_value(&x, N_DL_DST_VALUES)],
433                ETH_ADDR_LEN);
434         flow.nw_proto = nw_proto_values[get_value(&x, N_NW_PROTO_VALUES)];
435         flow.nw_tos = nw_dscp_values[get_value(&x, N_NW_DSCP_VALUES)];
436
437         /* This assertion is here to suppress a GCC 4.9 array-bounds warning */
438         ovs_assert(cls->n_tries <= CLS_MAX_TRIES);
439
440         cr0 = classifier_lookup(cls, version, &flow, &wc);
441         cr1 = tcls_lookup(tcls, &flow);
442         assert((cr0 == NULL) == (cr1 == NULL));
443         if (cr0 != NULL) {
444             const struct test_rule *tr0 = test_rule_from_cls_rule(cr0);
445             const struct test_rule *tr1 = test_rule_from_cls_rule(cr1);
446
447             assert(cls_rule_equal(cr0, cr1));
448             assert(tr0->aux == tr1->aux);
449
450             /* Make sure the rule should have been visible. */
451             assert(cr0->cls_match);
452             assert(cls_match_visible_in_version(cr0->cls_match, version));
453         }
454         cr2 = classifier_lookup(cls, version, &flow, NULL);
455         assert(cr2 == cr0);
456     }
457 }
458
459 static void
460 destroy_classifier(struct classifier *cls)
461 {
462     struct test_rule *rule;
463
464     classifier_defer(cls);
465     CLS_FOR_EACH (rule, cls_rule, cls) {
466         if (classifier_remove(cls, &rule->cls_rule)) {
467             ovsrcu_postpone(free_rule, rule);
468         }
469     }
470     classifier_destroy(cls);
471 }
472
473 static void
474 pvector_verify(const struct pvector *pvec)
475 {
476     void *ptr OVS_UNUSED;
477     int prev_priority = INT_MAX;
478
479     PVECTOR_FOR_EACH (ptr, pvec) {
480         int priority = cursor__.vector[cursor__.entry_idx].priority;
481         if (priority > prev_priority) {
482             ovs_abort(0, "Priority vector is out of order (%u > %u)",
483                       priority, prev_priority);
484         }
485         prev_priority = priority;
486     }
487 }
488
489 static unsigned int
490 trie_verify(const rcu_trie_ptr *trie, unsigned int ofs, unsigned int n_bits)
491 {
492     const struct trie_node *node = ovsrcu_get(struct trie_node *, trie);
493
494     if (node) {
495         assert(node->n_rules == 0 || node->n_bits > 0);
496         ofs += node->n_bits;
497         assert((ofs > 0 || (ofs == 0 && node->n_bits == 0)) && ofs <= n_bits);
498
499         return node->n_rules
500             + trie_verify(&node->edges[0], ofs, n_bits)
501             + trie_verify(&node->edges[1], ofs, n_bits);
502     }
503     return 0;
504 }
505
506 static void
507 verify_tries(struct classifier *cls)
508     OVS_NO_THREAD_SAFETY_ANALYSIS
509 {
510     unsigned int n_rules = 0;
511     int i;
512
513     for (i = 0; i < cls->n_tries; i++) {
514         n_rules += trie_verify(&cls->tries[i].root, 0,
515                                cls->tries[i].field->n_bits);
516     }
517     assert(n_rules <= cls->n_rules);
518 }
519
520 static void
521 check_tables(const struct classifier *cls, int n_tables, int n_rules,
522              int n_dups, int n_invisible, cls_version_t version)
523     OVS_NO_THREAD_SAFETY_ANALYSIS
524 {
525     const struct cls_subtable *table;
526     struct test_rule *test_rule;
527     int found_tables = 0;
528     int found_tables_with_visible_rules = 0;
529     int found_rules = 0;
530     int found_dups = 0;
531     int found_invisible = 0;
532     int found_visible_but_removable = 0;
533     int found_rules2 = 0;
534
535     pvector_verify(&cls->subtables);
536     CMAP_FOR_EACH (table, cmap_node, &cls->subtables_map) {
537         const struct cls_match *head;
538         int max_priority = INT_MIN;
539         unsigned int max_count = 0;
540         bool found = false;
541         bool found_visible_rules = false;
542         const struct cls_subtable *iter;
543
544         /* Locate the subtable from 'subtables'. */
545         PVECTOR_FOR_EACH (iter, &cls->subtables) {
546             if (iter == table) {
547                 if (found) {
548                     ovs_abort(0, "Subtable %p duplicated in 'subtables'.",
549                               table);
550                 }
551                 found = true;
552             }
553         }
554         if (!found) {
555             ovs_abort(0, "Subtable %p not found from 'subtables'.", table);
556         }
557
558         assert(!cmap_is_empty(&table->rules));
559         assert(trie_verify(&table->ports_trie, 0, table->ports_mask_len)
560                == (table->ports_mask_len ? cmap_count(&table->rules) : 0));
561
562         found_tables++;
563
564         CMAP_FOR_EACH (head, cmap_node, &table->rules) {
565             int prev_priority = INT_MAX;
566             cls_version_t prev_version = 0;
567             const struct cls_match *rule, *prev;
568             bool found_visible_rules_in_list = false;
569
570             assert(head->priority <= table->max_priority);
571
572             if (head->priority > max_priority) {
573                 max_priority = head->priority;
574                 max_count = 0;
575             }
576
577             FOR_EACH_RULE_IN_LIST_PROTECTED(rule, prev, head) {
578                 cls_version_t rule_version;
579                 const struct cls_rule *found_rule;
580
581                 /* Priority may not increase. */
582                 assert(rule->priority <= prev_priority);
583
584                 if (rule->priority == max_priority) {
585                     ++max_count;
586                 }
587
588                 /* Count invisible rules and visible duplicates. */
589                 if (!cls_match_visible_in_version(rule, version)) {
590                     found_invisible++;
591                 } else {
592                     if (cls_match_is_eventually_invisible(rule)) {
593                         found_visible_but_removable++;
594                     }
595                     if (found_visible_rules_in_list) {
596                         found_dups++;
597                     }
598                     found_visible_rules_in_list = true;
599                     found_visible_rules = true;
600                 }
601
602                 /* Rule must be visible in the version it was inserted. */
603                 rule_version = rule->add_version;
604                 assert(cls_match_visible_in_version(rule, rule_version));
605
606                 /* We should always find the latest version of the rule,
607                  * unless all rules have been marked for removal.
608                  * Later versions must always be later in the list. */
609                 found_rule = classifier_find_rule_exactly(cls, rule->cls_rule,
610                                                           rule_version);
611                 if (found_rule && found_rule != rule->cls_rule) {
612
613                     assert(found_rule->priority == rule->priority);
614
615                     /* Found rule may not have a lower version. */
616                     assert(found_rule->cls_match->add_version >= rule_version);
617
618                     /* This rule must not be visible in the found rule's
619                      * version. */
620                     assert(!cls_match_visible_in_version(
621                                rule, found_rule->cls_match->add_version));
622                 }
623
624                 if (rule->priority == prev_priority) {
625                     /* Exact duplicate rule may not have a lower version. */
626                     assert(rule_version >= prev_version);
627
628                     /* Previous rule must not be visible in rule's version. */
629                     assert(!cls_match_visible_in_version(prev, rule_version));
630                 }
631
632                 prev_priority = rule->priority;
633                 prev_version = rule_version;
634                 found_rules++;
635             }
636         }
637
638         if (found_visible_rules) {
639             found_tables_with_visible_rules++;
640         }
641
642         assert(table->max_priority == max_priority);
643         assert(table->max_count == max_count);
644     }
645
646     assert(found_tables == cmap_count(&cls->subtables_map));
647     assert(found_tables == pvector_count(&cls->subtables));
648     assert(n_tables == -1 || n_tables == found_tables_with_visible_rules);
649     assert(n_rules == -1 || found_rules == n_rules + found_invisible);
650     assert(n_dups == -1 || found_dups == n_dups);
651     assert(found_invisible == n_invisible);
652
653     CLS_FOR_EACH (test_rule, cls_rule, cls) {
654         found_rules2++;
655     }
656     /* Iteration does not see removable rules. */
657     assert(found_rules
658            == found_rules2 + found_visible_but_removable + found_invisible);
659 }
660
661 static struct test_rule *
662 make_rule(int wc_fields, int priority, int value_pat)
663 {
664     const struct cls_field *f;
665     struct test_rule *rule;
666     struct match match;
667
668     match_init_catchall(&match);
669     for (f = &cls_fields[0]; f < &cls_fields[CLS_N_FIELDS]; f++) {
670         int f_idx = f - cls_fields;
671         int value_idx = (value_pat & (1u << f_idx)) != 0;
672         memcpy((char *) &match.flow + f->ofs,
673                values[f_idx][value_idx], f->len);
674
675         if (f_idx == CLS_F_IDX_NW_SRC) {
676             match.wc.masks.nw_src = OVS_BE32_MAX;
677         } else if (f_idx == CLS_F_IDX_NW_DST) {
678             match.wc.masks.nw_dst = OVS_BE32_MAX;
679         } else if (f_idx == CLS_F_IDX_TP_SRC) {
680             match.wc.masks.tp_src = OVS_BE16_MAX;
681         } else if (f_idx == CLS_F_IDX_TP_DST) {
682             match.wc.masks.tp_dst = OVS_BE16_MAX;
683         } else if (f_idx == CLS_F_IDX_DL_SRC) {
684             memset(match.wc.masks.dl_src, 0xff, ETH_ADDR_LEN);
685         } else if (f_idx == CLS_F_IDX_DL_DST) {
686             memset(match.wc.masks.dl_dst, 0xff, ETH_ADDR_LEN);
687         } else if (f_idx == CLS_F_IDX_VLAN_TCI) {
688             match.wc.masks.vlan_tci = OVS_BE16_MAX;
689         } else if (f_idx == CLS_F_IDX_TUN_ID) {
690             match.wc.masks.tunnel.tun_id = OVS_BE64_MAX;
691         } else if (f_idx == CLS_F_IDX_METADATA) {
692             match.wc.masks.metadata = OVS_BE64_MAX;
693         } else if (f_idx == CLS_F_IDX_NW_DSCP) {
694             match.wc.masks.nw_tos |= IP_DSCP_MASK;
695         } else if (f_idx == CLS_F_IDX_NW_PROTO) {
696             match.wc.masks.nw_proto = UINT8_MAX;
697         } else if (f_idx == CLS_F_IDX_DL_TYPE) {
698             match.wc.masks.dl_type = OVS_BE16_MAX;
699         } else if (f_idx == CLS_F_IDX_IN_PORT) {
700             match.wc.masks.in_port.ofp_port = u16_to_ofp(UINT16_MAX);
701         } else {
702             OVS_NOT_REACHED();
703         }
704     }
705
706     rule = xzalloc(sizeof *rule);
707     cls_rule_init(&rule->cls_rule, &match, wc_fields
708                   ? (priority == INT_MIN ? priority + 1 :
709                      priority == INT_MAX ? priority - 1 : priority)
710                   : 0);
711     return rule;
712 }
713
714 static struct test_rule *
715 clone_rule(const struct test_rule *src)
716 {
717     struct test_rule *dst;
718
719     dst = xmalloc(sizeof *dst);
720     dst->aux = src->aux;
721     cls_rule_clone(&dst->cls_rule, &src->cls_rule);
722     return dst;
723 }
724
725 static void
726 free_rule(struct test_rule *rule)
727 {
728     cls_rule_destroy(&rule->cls_rule);
729     free(rule);
730 }
731
732 static void
733 shuffle(int *p, size_t n)
734 {
735     for (; n > 1; n--, p++) {
736         int *q = &p[random_range(n)];
737         int tmp = *p;
738         *p = *q;
739         *q = tmp;
740     }
741 }
742
743 static void
744 shuffle_u32s(uint32_t *p, size_t n)
745 {
746     for (; n > 1; n--, p++) {
747         uint32_t *q = &p[random_range(n)];
748         uint32_t tmp = *p;
749         *p = *q;
750         *q = tmp;
751     }
752 }
753 \f
754 /* Classifier tests. */
755
756 static enum mf_field_id trie_fields[2] = {
757     MFF_IPV4_DST, MFF_IPV4_SRC
758 };
759
760 static void
761 set_prefix_fields(struct classifier *cls)
762 {
763     verify_tries(cls);
764     classifier_set_prefix_fields(cls, trie_fields, ARRAY_SIZE(trie_fields));
765     verify_tries(cls);
766 }
767
768 /* Tests an empty classifier. */
769 static void
770 test_empty(struct ovs_cmdl_context *ctx OVS_UNUSED)
771 {
772     struct classifier cls;
773     struct tcls tcls;
774
775     classifier_init(&cls, flow_segment_u64s);
776     set_prefix_fields(&cls);
777     tcls_init(&tcls);
778     assert(classifier_is_empty(&cls));
779     assert(tcls_is_empty(&tcls));
780     compare_classifiers(&cls, 0, CLS_MIN_VERSION, &tcls);
781     classifier_destroy(&cls);
782     tcls_destroy(&tcls);
783 }
784
785 /* Destroys a null classifier. */
786 static void
787 test_destroy_null(struct ovs_cmdl_context *ctx OVS_UNUSED)
788 {
789     classifier_destroy(NULL);
790 }
791
792 /* Tests classification with one rule at a time. */
793 static void
794 test_single_rule(struct ovs_cmdl_context *ctx OVS_UNUSED)
795 {
796     unsigned int wc_fields;     /* Hilarious. */
797
798     for (wc_fields = 0; wc_fields < (1u << CLS_N_FIELDS); wc_fields++) {
799         struct classifier cls;
800         struct test_rule *rule, *tcls_rule;
801         struct tcls tcls;
802
803         rule = make_rule(wc_fields,
804                          hash_bytes(&wc_fields, sizeof wc_fields, 0), 0);
805         classifier_init(&cls, flow_segment_u64s);
806         set_prefix_fields(&cls);
807         tcls_init(&tcls);
808         tcls_rule = tcls_insert(&tcls, rule);
809
810         classifier_insert(&cls, &rule->cls_rule, CLS_MIN_VERSION, NULL, 0);
811         compare_classifiers(&cls, 0, CLS_MIN_VERSION, &tcls);
812         check_tables(&cls, 1, 1, 0, 0, CLS_MIN_VERSION);
813
814         classifier_remove(&cls, &rule->cls_rule);
815         tcls_remove(&tcls, tcls_rule);
816         assert(classifier_is_empty(&cls));
817         assert(tcls_is_empty(&tcls));
818         compare_classifiers(&cls, 0, CLS_MIN_VERSION, &tcls);
819
820         ovsrcu_postpone(free_rule, rule);
821         classifier_destroy(&cls);
822         tcls_destroy(&tcls);
823     }
824 }
825
826 /* Tests replacing one rule by another. */
827 static void
828 test_rule_replacement(struct ovs_cmdl_context *ctx OVS_UNUSED)
829 {
830     unsigned int wc_fields;
831
832     for (wc_fields = 0; wc_fields < (1u << CLS_N_FIELDS); wc_fields++) {
833         struct classifier cls;
834         struct test_rule *rule1;
835         struct test_rule *rule2;
836         struct tcls tcls;
837
838         rule1 = make_rule(wc_fields, OFP_DEFAULT_PRIORITY, UINT_MAX);
839         rule2 = make_rule(wc_fields, OFP_DEFAULT_PRIORITY, UINT_MAX);
840         rule2->aux += 5;
841         rule2->aux += 5;
842
843         classifier_init(&cls, flow_segment_u64s);
844         set_prefix_fields(&cls);
845         tcls_init(&tcls);
846         tcls_insert(&tcls, rule1);
847         classifier_insert(&cls, &rule1->cls_rule, CLS_MIN_VERSION, NULL, 0);
848         compare_classifiers(&cls, 0, CLS_MIN_VERSION, &tcls);
849         check_tables(&cls, 1, 1, 0, 0, CLS_MIN_VERSION);
850         tcls_destroy(&tcls);
851
852         tcls_init(&tcls);
853         tcls_insert(&tcls, rule2);
854
855         assert(test_rule_from_cls_rule(
856                    classifier_replace(&cls, &rule2->cls_rule, CLS_MIN_VERSION,
857                                       NULL, 0)) == rule1);
858         ovsrcu_postpone(free_rule, rule1);
859         compare_classifiers(&cls, 0, CLS_MIN_VERSION, &tcls);
860         check_tables(&cls, 1, 1, 0, 0, CLS_MIN_VERSION);
861         classifier_defer(&cls);
862         classifier_remove(&cls, &rule2->cls_rule);
863
864         tcls_destroy(&tcls);
865         destroy_classifier(&cls);
866     }
867 }
868
869 static int
870 factorial(int n_items)
871 {
872     int n, i;
873
874     n = 1;
875     for (i = 2; i <= n_items; i++) {
876         n *= i;
877     }
878     return n;
879 }
880
881 static void
882 swap(int *a, int *b)
883 {
884     int tmp = *a;
885     *a = *b;
886     *b = tmp;
887 }
888
889 static void
890 reverse(int *a, int n)
891 {
892     int i;
893
894     for (i = 0; i < n / 2; i++) {
895         int j = n - (i + 1);
896         swap(&a[i], &a[j]);
897     }
898 }
899
900 static bool
901 next_permutation(int *a, int n)
902 {
903     int k;
904
905     for (k = n - 2; k >= 0; k--) {
906         if (a[k] < a[k + 1]) {
907             int l;
908
909             for (l = n - 1; ; l--) {
910                 if (a[l] > a[k]) {
911                     swap(&a[k], &a[l]);
912                     reverse(a + (k + 1), n - (k + 1));
913                     return true;
914                 }
915             }
916         }
917     }
918     return false;
919 }
920
921 /* Tests classification with rules that have the same matching criteria. */
922 static void
923 test_many_rules_in_one_list (struct ovs_cmdl_context *ctx OVS_UNUSED)
924 {
925     enum { N_RULES = 3 };
926     int n_pris;
927
928     for (n_pris = N_RULES; n_pris >= 1; n_pris--) {
929         int ops[N_RULES * 2];
930         int pris[N_RULES];
931         int n_permutations;
932         int i;
933
934         pris[0] = 0;
935         for (i = 1; i < N_RULES; i++) {
936             pris[i] = pris[i - 1] + (n_pris > i);
937         }
938
939         for (i = 0; i < N_RULES * 2; i++) {
940             ops[i] = i / 2;
941         }
942
943         n_permutations = 0;
944         do {
945             struct test_rule *rules[N_RULES];
946             struct test_rule *tcls_rules[N_RULES];
947             int pri_rules[N_RULES];
948             struct classifier cls;
949             struct tcls tcls;
950             cls_version_t version = CLS_MIN_VERSION;
951             size_t n_invisible_rules = 0;
952
953             n_permutations++;
954
955             for (i = 0; i < N_RULES; i++) {
956                 rules[i] = make_rule(456, pris[i], 0);
957                 tcls_rules[i] = NULL;
958                 pri_rules[i] = -1;
959             }
960
961             classifier_init(&cls, flow_segment_u64s);
962             set_prefix_fields(&cls);
963             tcls_init(&tcls);
964
965             for (i = 0; i < ARRAY_SIZE(ops); i++) {
966                 struct test_rule *displaced_rule = NULL;
967                 struct cls_rule *removable_rule = NULL;
968                 int j = ops[i];
969                 int m, n;
970
971                 if (!tcls_rules[j]) {
972                     tcls_rules[j] = tcls_insert(&tcls, rules[j]);
973                     if (versioned) {
974                         /* Insert the new rule in the next version. */
975                         ++version;
976
977                         displaced_rule = test_rule_from_cls_rule(
978                             classifier_find_rule_exactly(&cls,
979                                                          &rules[j]->cls_rule,
980                                                          version));
981                         if (displaced_rule) {
982                             /* Mark the old rule for removal after the current
983                              * version. */
984                             cls_rule_make_invisible_in_version(
985                                 &displaced_rule->cls_rule, version);
986                             n_invisible_rules++;
987                             removable_rule = &displaced_rule->cls_rule;
988                         }
989                         classifier_insert(&cls, &rules[j]->cls_rule, version,
990                                           NULL, 0);
991                     } else {
992                         displaced_rule = test_rule_from_cls_rule(
993                             classifier_replace(&cls, &rules[j]->cls_rule,
994                                                version, NULL, 0));
995                     }
996                     if (pri_rules[pris[j]] >= 0) {
997                         int k = pri_rules[pris[j]];
998                         assert(displaced_rule != NULL);
999                         assert(displaced_rule != rules[j]);
1000                         assert(pris[j] == displaced_rule->cls_rule.priority);
1001                         tcls_rules[k] = NULL;
1002                     } else {
1003                         assert(displaced_rule == NULL);
1004                     }
1005                     pri_rules[pris[j]] = j;
1006                 } else {
1007                     if (versioned) {
1008                         /* Mark the rule for removal after the current
1009                          * version. */
1010                         ++version;
1011                         cls_rule_make_invisible_in_version(
1012                             &rules[j]->cls_rule, version);
1013                         n_invisible_rules++;
1014                         removable_rule = &rules[j]->cls_rule;
1015                     } else {
1016                         classifier_remove(&cls, &rules[j]->cls_rule);
1017                     }
1018                     tcls_remove(&tcls, tcls_rules[j]);
1019                     tcls_rules[j] = NULL;
1020                     pri_rules[pris[j]] = -1;
1021                 }
1022                 compare_classifiers(&cls, n_invisible_rules, version, &tcls);
1023                 n = 0;
1024                 for (m = 0; m < N_RULES; m++) {
1025                     n += tcls_rules[m] != NULL;
1026                 }
1027                 check_tables(&cls, n > 0, n, n - 1, n_invisible_rules,
1028                              version);
1029
1030                 if (versioned && removable_rule) {
1031                     /* Removable rule is no longer visible. */
1032                     assert(removable_rule->cls_match);
1033                     assert(!cls_match_visible_in_version(
1034                                removable_rule->cls_match, version));
1035                     classifier_remove(&cls, removable_rule);
1036                     n_invisible_rules--;
1037                 }
1038             }
1039
1040             classifier_defer(&cls);
1041             for (i = 0; i < N_RULES; i++) {
1042                 if (classifier_remove(&cls, &rules[i]->cls_rule)) {
1043                     ovsrcu_postpone(free_rule, rules[i]);
1044                 }
1045             }
1046             classifier_destroy(&cls);
1047             tcls_destroy(&tcls);
1048         } while (next_permutation(ops, ARRAY_SIZE(ops)));
1049         assert(n_permutations == (factorial(N_RULES * 2) >> N_RULES));
1050     }
1051 }
1052
1053 static int
1054 count_ones(unsigned long int x)
1055 {
1056     int n = 0;
1057
1058     while (x) {
1059         x = zero_rightmost_1bit(x);
1060         n++;
1061     }
1062
1063     return n;
1064 }
1065
1066 static bool
1067 array_contains(int *array, int n, int value)
1068 {
1069     int i;
1070
1071     for (i = 0; i < n; i++) {
1072         if (array[i] == value) {
1073             return true;
1074         }
1075     }
1076
1077     return false;
1078 }
1079
1080 /* Tests classification with two rules at a time that fall into the same
1081  * table but different lists. */
1082 static void
1083 test_many_rules_in_one_table(struct ovs_cmdl_context *ctx OVS_UNUSED)
1084 {
1085     int iteration;
1086
1087     for (iteration = 0; iteration < 50; iteration++) {
1088         enum { N_RULES = 20 };
1089         struct test_rule *rules[N_RULES];
1090         struct test_rule *tcls_rules[N_RULES];
1091         struct classifier cls;
1092         struct tcls tcls;
1093         cls_version_t version = CLS_MIN_VERSION;
1094         size_t n_invisible_rules = 0;
1095         int value_pats[N_RULES];
1096         int value_mask;
1097         int wcf;
1098         int i;
1099
1100         do {
1101             wcf = random_uint32() & ((1u << CLS_N_FIELDS) - 1);
1102             value_mask = ~wcf & ((1u << CLS_N_FIELDS) - 1);
1103         } while ((1 << count_ones(value_mask)) < N_RULES);
1104
1105         classifier_init(&cls, flow_segment_u64s);
1106         set_prefix_fields(&cls);
1107         tcls_init(&tcls);
1108
1109         for (i = 0; i < N_RULES; i++) {
1110             int priority = random_range(INT_MAX);
1111
1112             do {
1113                 value_pats[i] = random_uint32() & value_mask;
1114             } while (array_contains(value_pats, i, value_pats[i]));
1115
1116             ++version;
1117             rules[i] = make_rule(wcf, priority, value_pats[i]);
1118             tcls_rules[i] = tcls_insert(&tcls, rules[i]);
1119
1120             classifier_insert(&cls, &rules[i]->cls_rule, version, NULL, 0);
1121             compare_classifiers(&cls, n_invisible_rules, version, &tcls);
1122
1123             check_tables(&cls, 1, i + 1, 0, n_invisible_rules, version);
1124         }
1125
1126         for (i = 0; i < N_RULES; i++) {
1127             tcls_remove(&tcls, tcls_rules[i]);
1128             if (versioned) {
1129                 /* Mark the rule for removal after the current version. */
1130                 ++version;
1131                 cls_rule_make_invisible_in_version(&rules[i]->cls_rule,
1132                                                    version);
1133                 n_invisible_rules++;
1134             } else {
1135                 classifier_remove(&cls, &rules[i]->cls_rule);
1136             }
1137             compare_classifiers(&cls, n_invisible_rules, version, &tcls);
1138             check_tables(&cls, i < N_RULES - 1, N_RULES - (i + 1), 0,
1139                          n_invisible_rules, version);
1140             if (!versioned) {
1141                 ovsrcu_postpone(free_rule, rules[i]);
1142             }
1143         }
1144
1145         if (versioned) {
1146             for (i = 0; i < N_RULES; i++) {
1147                 classifier_remove(&cls, &rules[i]->cls_rule);
1148                 n_invisible_rules--;
1149
1150                 compare_classifiers(&cls, n_invisible_rules, version, &tcls);
1151                 check_tables(&cls, 0, 0, 0, n_invisible_rules, version);
1152                 ovsrcu_postpone(free_rule, rules[i]);
1153             }
1154         }
1155
1156         classifier_destroy(&cls);
1157         tcls_destroy(&tcls);
1158     }
1159 }
1160
1161 /* Tests classification with many rules at a time that fall into random lists
1162  * in 'n' tables. */
1163 static void
1164 test_many_rules_in_n_tables(int n_tables)
1165 {
1166     enum { MAX_RULES = 50 };
1167     int wcfs[10];
1168     int iteration;
1169     int i;
1170
1171     assert(n_tables < 10);
1172     for (i = 0; i < n_tables; i++) {
1173         do {
1174             wcfs[i] = random_uint32() & ((1u << CLS_N_FIELDS) - 1);
1175         } while (array_contains(wcfs, i, wcfs[i]));
1176     }
1177
1178     for (iteration = 0; iteration < 30; iteration++) {
1179         int priorities[MAX_RULES];
1180         struct classifier cls;
1181         struct tcls tcls;
1182         cls_version_t version = CLS_MIN_VERSION;
1183         size_t n_invisible_rules = 0;
1184         struct ovs_list list = OVS_LIST_INITIALIZER(&list);
1185
1186         random_set_seed(iteration + 1);
1187         for (i = 0; i < MAX_RULES; i++) {
1188             priorities[i] = (i * 129) & INT_MAX;
1189         }
1190         shuffle(priorities, ARRAY_SIZE(priorities));
1191
1192         classifier_init(&cls, flow_segment_u64s);
1193         set_prefix_fields(&cls);
1194         tcls_init(&tcls);
1195
1196         for (i = 0; i < MAX_RULES; i++) {
1197             struct test_rule *rule;
1198             int priority = priorities[i];
1199             int wcf = wcfs[random_range(n_tables)];
1200             int value_pat = random_uint32() & ((1u << CLS_N_FIELDS) - 1);
1201             rule = make_rule(wcf, priority, value_pat);
1202             tcls_insert(&tcls, rule);
1203             classifier_insert(&cls, &rule->cls_rule, version, NULL, 0);
1204             compare_classifiers(&cls, n_invisible_rules, version, &tcls);
1205             check_tables(&cls, -1, i + 1, -1, n_invisible_rules, version);
1206         }
1207
1208         while (classifier_count(&cls) - n_invisible_rules > 0) {
1209             struct test_rule *target;
1210             struct test_rule *rule;
1211             size_t n_removable_rules = 0;
1212
1213             target = clone_rule(tcls.rules[random_range(tcls.n_rules)]);
1214
1215             CLS_FOR_EACH_TARGET (rule, cls_rule, &cls, &target->cls_rule,
1216                                  version) {
1217                 if (versioned) {
1218                     /* Mark the rule for removal after the current version. */
1219                     cls_rule_make_invisible_in_version(&rule->cls_rule,
1220                                                        version + 1);
1221                     n_removable_rules++;
1222                     compare_classifiers(&cls, n_invisible_rules, version,
1223                                         &tcls);
1224                     check_tables(&cls, -1, -1, -1, n_invisible_rules, version);
1225
1226                     list_push_back(&list, &rule->list_node);
1227                 } else if (classifier_remove(&cls, &rule->cls_rule)) {
1228                     ovsrcu_postpone(free_rule, rule);
1229                 }
1230             }
1231
1232             ++version;
1233             n_invisible_rules += n_removable_rules;
1234
1235             tcls_delete_matches(&tcls, &target->cls_rule);
1236             free_rule(target);
1237
1238             compare_classifiers(&cls, n_invisible_rules, version, &tcls);
1239             check_tables(&cls, -1, -1, -1, n_invisible_rules, version);
1240         }
1241         if (versioned) {
1242             struct test_rule *rule;
1243
1244             /* Remove rules that are no longer visible. */
1245             LIST_FOR_EACH_POP (rule, list_node, &list) {
1246                 classifier_remove(&cls, &rule->cls_rule);
1247                 n_invisible_rules--;
1248
1249                 compare_classifiers(&cls, n_invisible_rules, version,
1250                                     &tcls);
1251                 check_tables(&cls, -1, -1, -1, n_invisible_rules, version);
1252             }
1253         }
1254
1255         destroy_classifier(&cls);
1256         tcls_destroy(&tcls);
1257     }
1258 }
1259
1260 static void
1261 test_many_rules_in_two_tables(struct ovs_cmdl_context *ctx OVS_UNUSED)
1262 {
1263     test_many_rules_in_n_tables(2);
1264 }
1265
1266 static void
1267 test_many_rules_in_five_tables(struct ovs_cmdl_context *ctx OVS_UNUSED)
1268 {
1269     test_many_rules_in_n_tables(5);
1270 }
1271 \f
1272 /* Miniflow tests. */
1273
1274 static uint32_t
1275 random_value(void)
1276 {
1277     static const uint32_t values[] =
1278         { 0xffffffff, 0xaaaaaaaa, 0x55555555, 0x80000000,
1279           0x00000001, 0xface0000, 0x00d00d1e, 0xdeadbeef };
1280
1281     return values[random_range(ARRAY_SIZE(values))];
1282 }
1283
1284 static bool
1285 choose(unsigned int n, unsigned int *idxp)
1286 {
1287     if (*idxp < n) {
1288         return true;
1289     } else {
1290         *idxp -= n;
1291         return false;
1292     }
1293 }
1294
1295 #define FLOW_U32S (FLOW_U64S * 2)
1296
1297 static bool
1298 init_consecutive_values(int n_consecutive, struct flow *flow,
1299                         unsigned int *idxp)
1300 {
1301     uint32_t *flow_u32 = (uint32_t *) flow;
1302
1303     if (choose(FLOW_U32S - n_consecutive + 1, idxp)) {
1304         int i;
1305
1306         for (i = 0; i < n_consecutive; i++) {
1307             flow_u32[*idxp + i] = random_value();
1308         }
1309         return true;
1310     } else {
1311         return false;
1312     }
1313 }
1314
1315 static bool
1316 next_random_flow(struct flow *flow, unsigned int idx)
1317 {
1318     uint32_t *flow_u32 = (uint32_t *) flow;
1319     int i;
1320
1321     memset(flow, 0, sizeof *flow);
1322
1323     /* Empty flow. */
1324     if (choose(1, &idx)) {
1325         return true;
1326     }
1327
1328     /* All flows with a small number of consecutive nonzero values. */
1329     for (i = 1; i <= 4; i++) {
1330         if (init_consecutive_values(i, flow, &idx)) {
1331             return true;
1332         }
1333     }
1334
1335     /* All flows with a large number of consecutive nonzero values. */
1336     for (i = FLOW_U32S - 4; i <= FLOW_U32S; i++) {
1337         if (init_consecutive_values(i, flow, &idx)) {
1338             return true;
1339         }
1340     }
1341
1342     /* All flows with exactly two nonconsecutive nonzero values. */
1343     if (choose((FLOW_U32S - 1) * (FLOW_U32S - 2) / 2, &idx)) {
1344         int ofs1;
1345
1346         for (ofs1 = 0; ofs1 < FLOW_U32S - 2; ofs1++) {
1347             int ofs2;
1348
1349             for (ofs2 = ofs1 + 2; ofs2 < FLOW_U32S; ofs2++) {
1350                 if (choose(1, &idx)) {
1351                     flow_u32[ofs1] = random_value();
1352                     flow_u32[ofs2] = random_value();
1353                     return true;
1354                 }
1355             }
1356         }
1357         OVS_NOT_REACHED();
1358     }
1359
1360     /* 16 randomly chosen flows with N >= 3 nonzero values. */
1361     if (choose(16 * (FLOW_U32S - 4), &idx)) {
1362         int n = idx / 16 + 3;
1363         int i;
1364
1365         for (i = 0; i < n; i++) {
1366             flow_u32[i] = random_value();
1367         }
1368         shuffle_u32s(flow_u32, FLOW_U32S);
1369
1370         return true;
1371     }
1372
1373     return false;
1374 }
1375
1376 static void
1377 any_random_flow(struct flow *flow)
1378 {
1379     static unsigned int max;
1380     if (!max) {
1381         while (next_random_flow(flow, max)) {
1382             max++;
1383         }
1384     }
1385
1386     next_random_flow(flow, random_range(max));
1387 }
1388
1389 static void
1390 toggle_masked_flow_bits(struct flow *flow, const struct flow_wildcards *mask)
1391 {
1392     const uint32_t *mask_u32 = (const uint32_t *) &mask->masks;
1393     uint32_t *flow_u32 = (uint32_t *) flow;
1394     int i;
1395
1396     for (i = 0; i < FLOW_U32S; i++) {
1397         if (mask_u32[i] != 0) {
1398             uint32_t bit;
1399
1400             do {
1401                 bit = 1u << random_range(32);
1402             } while (!(bit & mask_u32[i]));
1403             flow_u32[i] ^= bit;
1404         }
1405     }
1406 }
1407
1408 static void
1409 wildcard_extra_bits(struct flow_wildcards *mask)
1410 {
1411     uint32_t *mask_u32 = (uint32_t *) &mask->masks;
1412     int i;
1413
1414     for (i = 0; i < FLOW_U32S; i++) {
1415         if (mask_u32[i] != 0) {
1416             uint32_t bit;
1417
1418             do {
1419                 bit = 1u << random_range(32);
1420             } while (!(bit & mask_u32[i]));
1421             mask_u32[i] &= ~bit;
1422         }
1423     }
1424 }
1425
1426 /* Returns a copy of 'src'.  The caller must eventually free the returned
1427  * miniflow with free(). */
1428 static struct miniflow *
1429 miniflow_clone__(const struct miniflow *src)
1430 {
1431     struct miniflow *dst;
1432     size_t data_size;
1433
1434     data_size = miniflow_alloc(&dst, 1, src);
1435     miniflow_clone(dst, src, data_size / sizeof(uint64_t));
1436     return dst;
1437 }
1438
1439 /* Returns a hash value for 'flow', given 'basis'. */
1440 static inline uint32_t
1441 miniflow_hash__(const struct miniflow *flow, uint32_t basis)
1442 {
1443     const uint64_t *values = miniflow_get_values(flow);
1444     const uint64_t *p = values;
1445     uint32_t hash = basis;
1446     uint64_t hash_tnl_map = 0, hash_pkt_map = 0;
1447     uint64_t map;
1448
1449     for (map = flow->tnl_map; map; map = zero_rightmost_1bit(map)) {
1450         if (*p) {
1451             hash = hash_add64(hash, *p);
1452             hash_tnl_map |= rightmost_1bit(map);
1453         }
1454         p++;
1455     }
1456     for (map = flow->pkt_map; map; map = zero_rightmost_1bit(map)) {
1457         if (*p) {
1458             hash = hash_add64(hash, *p);
1459             hash_pkt_map |= rightmost_1bit(map);
1460         }
1461         p++;
1462     }
1463     hash = hash_add64(hash, hash_tnl_map);
1464     hash = hash_add64(hash, hash_pkt_map);
1465
1466     return hash_finish(hash, p - values);
1467 }
1468
1469 static void
1470 test_miniflow(struct ovs_cmdl_context *ctx OVS_UNUSED)
1471 {
1472     struct flow flow;
1473     unsigned int idx;
1474
1475     random_set_seed(0xb3faca38);
1476     for (idx = 0; next_random_flow(&flow, idx); idx++) {
1477         const uint64_t *flow_u64 = (const uint64_t *) &flow;
1478         struct miniflow *miniflow, *miniflow2, *miniflow3;
1479         struct flow flow2, flow3;
1480         struct flow_wildcards mask;
1481         struct minimask *minimask;
1482         int i;
1483
1484         /* Convert flow to miniflow. */
1485         miniflow = miniflow_create(&flow);
1486
1487         /* Check that the flow equals its miniflow. */
1488         assert(miniflow_get_vid(miniflow) == vlan_tci_to_vid(flow.vlan_tci));
1489         for (i = 0; i < FLOW_U64S; i++) {
1490             assert(miniflow_get(miniflow, i) == flow_u64[i]);
1491         }
1492
1493         /* Check that the miniflow equals itself. */
1494         assert(miniflow_equal(miniflow, miniflow));
1495
1496         /* Convert miniflow back to flow and verify that it's the same. */
1497         miniflow_expand(miniflow, &flow2);
1498         assert(flow_equal(&flow, &flow2));
1499
1500         /* Check that copying a miniflow works properly. */
1501         miniflow2 = miniflow_clone__(miniflow);
1502         assert(miniflow_equal(miniflow, miniflow2));
1503         assert(miniflow_hash__(miniflow, 0) == miniflow_hash__(miniflow2, 0));
1504         miniflow_expand(miniflow2, &flow3);
1505         assert(flow_equal(&flow, &flow3));
1506
1507         /* Check that masked matches work as expected for identical flows and
1508          * miniflows. */
1509         do {
1510             next_random_flow(&mask.masks, 1);
1511         } while (flow_wildcards_is_catchall(&mask));
1512         minimask = minimask_create(&mask);
1513         assert(minimask_is_catchall(minimask)
1514                == flow_wildcards_is_catchall(&mask));
1515         assert(miniflow_equal_in_minimask(miniflow, miniflow2, minimask));
1516         assert(miniflow_equal_flow_in_minimask(miniflow, &flow2, minimask));
1517         assert(miniflow_hash_in_minimask(miniflow, minimask, 0x12345678) ==
1518                flow_hash_in_minimask(&flow, minimask, 0x12345678));
1519         assert(minimask_hash(minimask, 0) ==
1520                miniflow_hash__(&minimask->masks, 0));
1521
1522         /* Check that masked matches work as expected for differing flows and
1523          * miniflows. */
1524         toggle_masked_flow_bits(&flow2, &mask);
1525         assert(!miniflow_equal_flow_in_minimask(miniflow, &flow2, minimask));
1526         miniflow3 = miniflow_create(&flow2);
1527         assert(!miniflow_equal_in_minimask(miniflow, miniflow3, minimask));
1528
1529         /* Clean up. */
1530         free(miniflow);
1531         free(miniflow2);
1532         free(miniflow3);
1533         free(minimask);
1534     }
1535 }
1536
1537 static void
1538 test_minimask_has_extra(struct ovs_cmdl_context *ctx OVS_UNUSED)
1539 {
1540     struct flow_wildcards catchall;
1541     struct minimask *minicatchall;
1542     struct flow flow;
1543     unsigned int idx;
1544
1545     flow_wildcards_init_catchall(&catchall);
1546     minicatchall = minimask_create(&catchall);
1547     assert(minimask_is_catchall(minicatchall));
1548
1549     random_set_seed(0x2ec7905b);
1550     for (idx = 0; next_random_flow(&flow, idx); idx++) {
1551         struct flow_wildcards mask;
1552         struct minimask *minimask;
1553
1554         mask.masks = flow;
1555         minimask = minimask_create(&mask);
1556         assert(!minimask_has_extra(minimask, minimask));
1557         assert(minimask_has_extra(minicatchall, minimask)
1558                == !minimask_is_catchall(minimask));
1559         if (!minimask_is_catchall(minimask)) {
1560             struct minimask *minimask2;
1561
1562             wildcard_extra_bits(&mask);
1563             minimask2 = minimask_create(&mask);
1564             assert(minimask_has_extra(minimask2, minimask));
1565             assert(!minimask_has_extra(minimask, minimask2));
1566             free(minimask2);
1567         }
1568
1569         free(minimask);
1570     }
1571
1572     free(minicatchall);
1573 }
1574
1575 static void
1576 test_minimask_combine(struct ovs_cmdl_context *ctx OVS_UNUSED)
1577 {
1578     struct flow_wildcards catchall;
1579     struct minimask *minicatchall;
1580     struct flow flow;
1581     unsigned int idx;
1582
1583     flow_wildcards_init_catchall(&catchall);
1584     minicatchall = minimask_create(&catchall);
1585     assert(minimask_is_catchall(minicatchall));
1586
1587     random_set_seed(0x181bf0cd);
1588     for (idx = 0; next_random_flow(&flow, idx); idx++) {
1589         struct minimask *minimask, *minimask2;
1590         struct flow_wildcards mask, mask2, combined, combined2;
1591         struct {
1592             struct minimask minicombined;
1593             uint64_t storage[FLOW_U64S];
1594         } m;
1595         struct flow flow2;
1596
1597         mask.masks = flow;
1598         minimask = minimask_create(&mask);
1599
1600         minimask_combine(&m.minicombined, minimask, minicatchall, m.storage);
1601         assert(minimask_is_catchall(&m.minicombined));
1602
1603         any_random_flow(&flow2);
1604         mask2.masks = flow2;
1605         minimask2 = minimask_create(&mask2);
1606
1607         minimask_combine(&m.minicombined, minimask, minimask2, m.storage);
1608         flow_wildcards_and(&combined, &mask, &mask2);
1609         minimask_expand(&m.minicombined, &combined2);
1610         assert(flow_wildcards_equal(&combined, &combined2));
1611
1612         free(minimask);
1613         free(minimask2);
1614     }
1615
1616     free(minicatchall);
1617 }
1618 \f
1619 static const struct ovs_cmdl_command commands[] = {
1620     /* Classifier tests. */
1621     {"empty", NULL, 0, 0, test_empty},
1622     {"destroy-null", NULL, 0, 0, test_destroy_null},
1623     {"single-rule", NULL, 0, 0, test_single_rule},
1624     {"rule-replacement", NULL, 0, 0, test_rule_replacement},
1625     {"many-rules-in-one-list", NULL, 0, 1, test_many_rules_in_one_list},
1626     {"many-rules-in-one-table", NULL, 0, 1, test_many_rules_in_one_table},
1627     {"many-rules-in-two-tables", NULL, 0, 0, test_many_rules_in_two_tables},
1628     {"many-rules-in-five-tables", NULL, 0, 0, test_many_rules_in_five_tables},
1629
1630     /* Miniflow and minimask tests. */
1631     {"miniflow", NULL, 0, 0, test_miniflow},
1632     {"minimask_has_extra", NULL, 0, 0, test_minimask_has_extra},
1633     {"minimask_combine", NULL, 0, 0, test_minimask_combine},
1634
1635     {NULL, NULL, 0, 0, NULL},
1636 };
1637
1638 static void
1639 test_classifier_main(int argc, char *argv[])
1640 {
1641     struct ovs_cmdl_context ctx = {
1642         .argc = argc - 1,
1643         .argv = argv + 1,
1644     };
1645     set_program_name(argv[0]);
1646
1647     if (argc > 1 && !strcmp(argv[1], "--versioned")) {
1648         versioned = true;
1649         ctx.argc--;
1650         ctx.argv++;
1651     }
1652
1653     init_values();
1654     ovs_cmdl_run_command(&ctx, commands);
1655 }
1656
1657 OVSTEST_REGISTER("test-classifier", test_classifier_main);