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