42f026ff9d859b15766edd9e1293d6bdfeb0dc1c
[sliver-openvswitch.git] / lib / classifier.c
1 /*
2  * Copyright (c) 2009, 2010 Nicira Networks.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18 #include "classifier.h"
19 #include <assert.h>
20 #include <errno.h>
21 #include <netinet/in.h>
22 #include "dynamic-string.h"
23 #include "flow.h"
24 #include "hash.h"
25 #include "packets.h"
26
27 static struct cls_table *find_table(const struct classifier *,
28                                     const struct flow_wildcards *);
29 static struct cls_table *insert_table(struct classifier *,
30                                       const struct flow_wildcards *);
31
32 static struct cls_table *classifier_first_table(const struct classifier *);
33 static struct cls_table *classifier_next_table(const struct classifier *,
34                                                const struct cls_table *);
35 static void destroy_table(struct classifier *, struct cls_table *);
36
37 static bool should_include(const struct cls_table *, int include);
38
39 static struct cls_rule *find_match(const struct cls_table *,
40                                    const struct flow *);
41 static struct cls_rule *find_equal(struct cls_table *, const struct flow *,
42                                    uint32_t hash);
43 static struct cls_rule *insert_rule(struct cls_table *, struct cls_rule *);
44
45 static bool flow_equal_except(const struct flow *, const struct flow *,
46                                 const struct flow_wildcards *);
47 static void zero_wildcards(struct flow *, const struct flow_wildcards *);
48
49 /* Iterates RULE over HEAD and all of the cls_rules on HEAD->list. */
50 #define FOR_EACH_RULE_IN_LIST(RULE, HEAD)                               \
51     for ((RULE) = (HEAD); (RULE) != NULL; (RULE) = next_rule_in_list(RULE))
52 #define FOR_EACH_RULE_IN_LIST_SAFE(RULE, NEXT, HEAD)                    \
53     for ((RULE) = (HEAD);                                               \
54          (RULE) != NULL && ((NEXT) = next_rule_in_list(RULE), true);    \
55          (RULE) = (NEXT))
56
57 static struct cls_rule *next_rule_in_list(struct cls_rule *);
58
59 static struct cls_table *
60 cls_table_from_hmap_node(const struct hmap_node *node)
61 {
62     return node ? CONTAINER_OF(node, struct cls_table, hmap_node) : NULL;
63 }
64
65 static struct cls_rule *
66 cls_rule_from_hmap_node(const struct hmap_node *node)
67 {
68     return node ? CONTAINER_OF(node, struct cls_rule, hmap_node) : NULL;
69 }
70
71 /* Returns the cls_table within 'cls' that has no wildcards, or NULL if there
72  * is none.  */
73 struct cls_table *
74 classifier_exact_table(const struct classifier *cls)
75 {
76     struct flow_wildcards exact_wc;
77     flow_wildcards_init_exact(&exact_wc);
78     return find_table(cls, &exact_wc);
79 }
80
81 /* Returns the first rule in 'table', or a null pointer if 'table' is NULL. */
82 struct cls_rule *
83 cls_table_first_rule(const struct cls_table *table)
84 {
85     return table ? cls_rule_from_hmap_node(hmap_first(&table->rules)) : NULL;
86 }
87
88 /* Returns the next rule in 'table' following 'rule', or a null pointer if
89  * 'rule' is the last rule in 'table'. */
90 struct cls_rule *
91 cls_table_next_rule(const struct cls_table *table, const struct cls_rule *rule)
92 {
93     struct cls_rule *next
94         = CONTAINER_OF(rule->list.next, struct cls_rule, hmap_node);
95
96     return (next->priority < rule->priority
97             ? next
98             : cls_rule_from_hmap_node(hmap_next(&table->rules,
99                                                 &next->hmap_node)));
100 }
101
102 static void
103 cls_rule_init__(struct cls_rule *rule,
104                 const struct flow *flow, uint32_t wildcards)
105 {
106     rule->flow = *flow;
107     flow_wildcards_init(&rule->wc, wildcards);
108     cls_rule_zero_wildcards(rule);
109 }
110
111 /* Converts the flow in 'flow' into a cls_rule in 'rule', with the given
112  * 'wildcards' and 'priority'.*/
113 void
114 cls_rule_from_flow(const struct flow *flow, uint32_t wildcards,
115                    unsigned int priority, struct cls_rule *rule)
116 {
117     cls_rule_init__(rule, flow, wildcards);
118     rule->priority = priority;
119 }
120
121 /* Converts the ofp_match in 'match' (with format 'flow_format', one of NXFF_*)
122  * into a cls_rule in 'rule', with the given 'priority'.  'cookie' is used
123  * when 'flow_format' is NXFF_TUN_ID_FROM_COOKIE. */
124 void
125 cls_rule_from_match(const struct ofp_match *match, unsigned int priority,
126                     int flow_format, uint64_t cookie,
127                     struct cls_rule *rule)
128 {
129     uint32_t wildcards;
130     struct flow flow;
131
132     flow_from_match(match, flow_format, cookie, &flow, &wildcards);
133     cls_rule_init__(rule, &flow, wildcards);
134     rule->priority = rule->wc.wildcards ? priority : UINT16_MAX;
135 }
136
137 /* For each bit or field wildcarded in 'rule', sets the corresponding bit or
138  * field in 'flow' to all-0-bits.  It is important to maintain this invariant
139  * in a clr_rule that might be inserted into a classifier.
140  *
141  * It is never necessary to call this function directly for a cls_rule that is
142  * initialized or modified only by cls_rule_*() functions.  It is useful to
143  * restore the invariant in a cls_rule whose 'wc' member is modified by hand.
144  */
145 void
146 cls_rule_zero_wildcards(struct cls_rule *rule)
147 {
148     zero_wildcards(&rule->flow, &rule->wc);
149 }
150
151 /* Converts 'rule' to a string and returns the string.  The caller must free
152  * the string (with free()). */
153 char *
154 cls_rule_to_string(const struct cls_rule *rule)
155 {
156     struct ds s = DS_EMPTY_INITIALIZER;
157     ds_put_format(&s, "wildcards=%x priority=%u ",
158                   rule->wc.wildcards, rule->priority);
159     flow_format(&s, &rule->flow);
160     return ds_cstr(&s);
161 }
162
163 /* Prints cls_rule 'rule', for debugging.
164  *
165  * (The output could be improved and expanded, but this was good enough to
166  * debug the classifier.) */
167 void
168 cls_rule_print(const struct cls_rule *rule)
169 {
170     printf("wildcards=%x priority=%u ", rule->wc.wildcards, rule->priority);
171     flow_print(stdout, &rule->flow);
172     putc('\n', stdout);
173 }
174 \f
175 /* Initializes 'cls' as a classifier that initially contains no classification
176  * rules. */
177 void
178 classifier_init(struct classifier *cls)
179 {
180     cls->n_rules = 0;
181     hmap_init(&cls->tables);
182 }
183
184 /* Destroys 'cls'.  Rules within 'cls', if any, are not freed; this is the
185  * caller's responsibility. */
186 void
187 classifier_destroy(struct classifier *cls)
188 {
189     if (cls) {
190         struct cls_table *table, *next_table;
191
192         HMAP_FOR_EACH_SAFE (table, next_table, hmap_node, &cls->tables) {
193             hmap_destroy(&table->rules);
194             hmap_remove(&cls->tables, &table->hmap_node);
195             free(table);
196         }
197         hmap_destroy(&cls->tables);
198     }
199 }
200
201 /* Returns true if 'cls' contains no classification rules, false otherwise. */
202 bool
203 classifier_is_empty(const struct classifier *cls)
204 {
205     return cls->n_rules == 0;
206 }
207
208 /* Returns the number of rules in 'classifier'. */
209 int
210 classifier_count(const struct classifier *cls)
211 {
212     return cls->n_rules;
213 }
214
215 /* Returns the number of rules in 'classifier' that have no wildcards. */
216 int
217 classifier_count_exact(const struct classifier *cls)
218 {
219     struct cls_table *exact_table = classifier_exact_table(cls);
220     return exact_table ? exact_table->n_table_rules : 0;
221 }
222
223 /* Inserts 'rule' into 'cls'.  Until 'rule' is removed from 'cls', the caller
224  * must not modify or free it.
225  *
226  * If 'cls' already contains an identical rule (including wildcards, values of
227  * fixed fields, and priority), replaces the old rule by 'rule' and returns the
228  * rule that was replaced.  The caller takes ownership of the returned rule and
229  * is thus responsible for freeing it, etc., as necessary.
230  *
231  * Returns NULL if 'cls' does not contain a rule with an identical key, after
232  * inserting the new rule.  In this case, no rules are displaced by the new
233  * rule, even rules that cannot have any effect because the new rule matches a
234  * superset of their flows and has higher priority. */
235 struct cls_rule *
236 classifier_insert(struct classifier *cls, struct cls_rule *rule)
237 {
238     struct cls_rule *old_rule;
239     struct cls_table *table;
240
241     table = find_table(cls, &rule->wc);
242     if (!table) {
243         table = insert_table(cls, &rule->wc);
244     }
245
246     old_rule = insert_rule(table, rule);
247     if (!old_rule) {
248         table->n_table_rules++;
249         cls->n_rules++;
250     }
251     return old_rule;
252 }
253
254 /* Removes 'rule' from 'cls'.  It is the caller's responsibility to free
255  * 'rule', if this is desirable. */
256 void
257 classifier_remove(struct classifier *cls, struct cls_rule *rule)
258 {
259     struct cls_rule *head;
260     struct cls_table *table;
261
262     table = find_table(cls, &rule->wc);
263     head = find_equal(table, &rule->flow, rule->hmap_node.hash);
264     if (head != rule) {
265         list_remove(&rule->list);
266     } else if (list_is_empty(&rule->list)) {
267         hmap_remove(&table->rules, &rule->hmap_node);
268     } else {
269         struct cls_rule *next = CONTAINER_OF(rule->list.next,
270                                              struct cls_rule, list);
271
272         list_remove(&rule->list);
273         hmap_replace(&table->rules, &rule->hmap_node, &next->hmap_node);
274     }
275
276     if (--table->n_table_rules == 0 && !table->n_refs) {
277         destroy_table(cls, table);
278     }
279
280     cls->n_rules--;
281 }
282
283 /* Finds and returns the highest-priority rule in 'cls' that matches 'flow'.
284  * Returns a null pointer if no rules in 'cls' match 'flow'.  If multiple rules
285  * of equal priority match 'flow', returns one arbitrarily.
286  *
287  * 'include' is a combination of CLS_INC_* values that specify tables to
288  * include in the search. */
289 struct cls_rule *
290 classifier_lookup(const struct classifier *cls, const struct flow *flow,
291                   int include)
292 {
293     struct cls_table *table;
294     struct cls_rule *best;
295
296     best = NULL;
297     HMAP_FOR_EACH (table, hmap_node, &cls->tables) {
298         if (should_include(table, include)) {
299             struct cls_rule *rule = find_match(table, flow);
300             if (rule && (!best || rule->priority > best->priority)) {
301                 best = rule;
302             }
303         }
304     }
305     return best;
306 }
307
308 /* Finds and returns a rule in 'cls' with exactly the same priority and
309  * matching criteria as 'target'.  Returns a null pointer if 'cls' doesn't
310  * contain an exact match.
311  *
312  * Priority is ignored for exact-match rules (because OpenFlow 1.0 always
313  * treats exact-match rules as highest priority). */
314 struct cls_rule *
315 classifier_find_rule_exactly(const struct classifier *cls,
316                              const struct cls_rule *target)
317 {
318     struct cls_rule *head, *rule;
319     struct cls_table *table;
320
321     table = find_table(cls, &target->wc);
322     if (!table) {
323         return NULL;
324     }
325
326     head = find_equal(table, &target->flow, flow_hash(&target->flow, 0));
327     if (!target->wc.wildcards) {
328         return head;
329     }
330     FOR_EACH_RULE_IN_LIST (rule, head) {
331         if (target->priority >= rule->priority) {
332             return target->priority == rule->priority ? rule : NULL;
333         }
334     }
335     return NULL;
336 }
337
338 /* Checks if 'target' would overlap any other rule in 'cls'.  Two rules are
339  * considered to overlap if both rules have the same priority and a packet
340  * could match both. */
341 bool
342 classifier_rule_overlaps(const struct classifier *cls,
343                          const struct cls_rule *target)
344 {
345     struct cls_table *table;
346
347     HMAP_FOR_EACH (table, hmap_node, &cls->tables) {
348         struct flow_wildcards wc;
349         struct cls_rule *head;
350
351         flow_wildcards_combine(&wc, &target->wc, &table->wc);
352         HMAP_FOR_EACH (head, hmap_node, &table->rules) {
353             struct cls_rule *rule;
354
355             FOR_EACH_RULE_IN_LIST (rule, head) {
356                 if (rule->priority == target->priority
357                     && flow_equal_except(&target->flow, &rule->flow, &wc)) {
358                     return true;
359                 }
360             }
361         }
362     }
363
364     return false;
365 }
366
367 /* Searches 'cls' for rules that exactly match 'target' or are more specific
368  * than 'target'.  That is, a given 'rule' matches 'target' if, for every
369  * field:
370  *
371  *   - 'target' and 'rule' specify the same (non-wildcarded) value for the
372  *     field, or
373  *
374  *   - 'target' wildcards the field,
375  *
376  * but not if:
377  *
378  *   - 'target' and 'rule' specify different values for the field, or
379  *
380  *   - 'target' specifies a value for the field but 'rule' wildcards it.
381  *
382  * Equivalently, the truth table for whether a field matches is:
383  *
384  *                                     rule
385  *
386  *                             wildcard    exact
387  *                            +---------+---------+
388  *                   t   wild |   yes   |   yes   |
389  *                   a   card |         |         |
390  *                   r        +---------+---------+
391  *                   g  exact |    no   |if values|
392  *                   e        |         |are equal|
393  *                   t        +---------+---------+
394  *
395  * This is the matching rule used by OpenFlow 1.0 non-strict OFPT_FLOW_MOD
396  * commands and by OpenFlow 1.0 aggregate and flow stats.
397  *
398  * Ignores target->priority.
399  *
400  * 'callback' is allowed to delete the rule that is passed as its argument, but
401  * it must not delete (or move) any other rules in 'cls' that have the same
402  * wildcards as the argument rule. */
403 void
404 classifier_for_each_match(const struct classifier *cls_,
405                           const struct cls_rule *target,
406                           int include, cls_cb_func *callback, void *aux)
407 {
408     struct classifier *cls = (struct classifier *) cls_;
409     struct cls_table *table, *next_table;
410
411     for (table = classifier_first_table(cls); table; table = next_table) {
412         if (should_include(table, include)
413             && !flow_wildcards_has_extra(&table->wc, &target->wc)) {
414             /* We have eliminated the "no" case in the truth table above.  Two
415              * of the three remaining cases are trivial.  We only need to check
416              * the fourth case, where both 'rule' and 'target' require an exact
417              * match. */
418             struct cls_rule *head, *next_head;
419
420             table->n_refs++;
421             HMAP_FOR_EACH_SAFE (head, next_head, hmap_node, &table->rules) {
422                 if (flow_equal_except(&head->flow, &target->flow,
423                                       &target->wc)) {
424                     struct cls_rule *rule, *next_rule;
425
426                     FOR_EACH_RULE_IN_LIST_SAFE (rule, next_rule, head) {
427                         callback(rule, aux);
428                     }
429                 }
430             }
431             next_table = classifier_next_table(cls, table);
432             if (!--table->n_refs && !table->n_table_rules) {
433                 destroy_table(cls, table);
434             }
435         } else {
436             next_table = classifier_next_table(cls, table);
437         }
438     }
439 }
440
441 /* 'callback' is allowed to delete the rule that is passed as its argument, but
442  * it must not delete (or move) any other rules in 'cls' that have the same
443  * wildcards as the argument rule.
444  *
445  * If 'include' is CLS_INC_EXACT then CLASSIFIER_FOR_EACH_EXACT_RULE is
446  * probably easier to use. */
447 void
448 classifier_for_each(const struct classifier *cls_, int include,
449                     cls_cb_func *callback, void *aux)
450 {
451     struct classifier *cls = (struct classifier *) cls_;
452     struct cls_table *table, *next_table;
453
454     for (table = classifier_first_table(cls); table; table = next_table) {
455         if (should_include(table, include)) {
456             struct cls_rule *head, *next_head;
457
458             table->n_refs++;
459             HMAP_FOR_EACH_SAFE (head, next_head, hmap_node, &table->rules) {
460                 struct cls_rule *rule, *next_rule;
461
462                 FOR_EACH_RULE_IN_LIST_SAFE (rule, next_rule, head) {
463                     callback(rule, aux);
464                 }
465             }
466             next_table = classifier_next_table(cls, table);
467             if (!--table->n_refs && !table->n_table_rules) {
468                 destroy_table(cls, table);
469             }
470         } else {
471             next_table = classifier_next_table(cls, table);
472         }
473     }
474 }
475 \f
476 static struct cls_table *
477 find_table(const struct classifier *cls, const struct flow_wildcards *wc)
478 {
479     struct cls_table *table;
480
481     HMAP_FOR_EACH_IN_BUCKET (table, hmap_node, flow_wildcards_hash(wc),
482                              &cls->tables) {
483         if (flow_wildcards_equal(wc, &table->wc)) {
484             return table;
485         }
486     }
487     return NULL;
488 }
489
490 static struct cls_table *
491 insert_table(struct classifier *cls, const struct flow_wildcards *wc)
492 {
493     struct cls_table *table;
494
495     table = xzalloc(sizeof *table);
496     hmap_init(&table->rules);
497     table->wc = *wc;
498     hmap_insert(&cls->tables, &table->hmap_node, flow_wildcards_hash(wc));
499
500     return table;
501 }
502
503 static struct cls_table *
504 classifier_first_table(const struct classifier *cls)
505 {
506     return cls_table_from_hmap_node(hmap_first(&cls->tables));
507 }
508
509 static struct cls_table *
510 classifier_next_table(const struct classifier *cls,
511                       const struct cls_table *table)
512 {
513     return cls_table_from_hmap_node(hmap_next(&cls->tables,
514                                               &table->hmap_node));
515 }
516
517 static void
518 destroy_table(struct classifier *cls, struct cls_table *table)
519 {
520     hmap_remove(&cls->tables, &table->hmap_node);
521     hmap_destroy(&table->rules);
522     free(table);
523 }
524
525 /* Returns true if 'table' should be included by an operation with the
526  * specified 'include' (a combination of CLS_INC_*). */
527 static bool
528 should_include(const struct cls_table *table, int include)
529 {
530     return include & (table->wc.wildcards ? CLS_INC_WILD : CLS_INC_EXACT);
531 }
532
533 static struct cls_rule *
534 find_match(const struct cls_table *table, const struct flow *flow)
535 {
536     struct cls_rule *rule;
537     struct flow f;
538
539     f = *flow;
540     zero_wildcards(&f, &table->wc);
541     HMAP_FOR_EACH_WITH_HASH (rule, hmap_node, flow_hash(&f, 0),
542                              &table->rules) {
543         if (flow_equal(&f, &rule->flow)) {
544             return rule;
545         }
546     }
547     return NULL;
548 }
549
550 static struct cls_rule *
551 find_equal(struct cls_table *table, const struct flow *flow, uint32_t hash)
552 {
553     struct cls_rule *head;
554
555     HMAP_FOR_EACH_WITH_HASH (head, hmap_node, hash, &table->rules) {
556         if (flow_equal(&head->flow, flow)) {
557             return head;
558         }
559     }
560     return NULL;
561 }
562
563 static struct cls_rule *
564 insert_rule(struct cls_table *table, struct cls_rule *new)
565 {
566     struct cls_rule *head;
567
568     new->hmap_node.hash = flow_hash(&new->flow, 0);
569
570     head = find_equal(table, &new->flow, new->hmap_node.hash);
571     if (!head) {
572         hmap_insert(&table->rules, &new->hmap_node, new->hmap_node.hash);
573         list_init(&new->list);
574         return NULL;
575     } else {
576         /* Scan the list for the insertion point that will keep the list in
577          * order of decreasing priority. */
578         struct cls_rule *rule;
579         FOR_EACH_RULE_IN_LIST (rule, head) {
580             if (new->priority >= rule->priority) {
581                 if (rule == head) {
582                     /* 'new' is the new highest-priority flow in the list. */
583                     hmap_replace(&table->rules,
584                                  &rule->hmap_node, &new->hmap_node);
585                 }
586
587                 if (new->priority == rule->priority) {
588                     list_replace(&new->list, &rule->list);
589                     return rule;
590                 } else {
591                     list_insert(&rule->list, &new->list);
592                     return NULL;
593                 }
594             }
595         }
596
597         /* Insert 'new' at the end of the list. */
598         list_push_back(&head->list, &new->list);
599         return NULL;
600     }
601 }
602
603 static struct cls_rule *
604 next_rule_in_list(struct cls_rule *rule)
605 {
606     struct cls_rule *next = OBJECT_CONTAINING(rule->list.next, next, list);
607     return next->priority < rule->priority ? next : NULL;
608 }
609
610 static bool
611 flow_equal_except(const struct flow *a, const struct flow *b,
612                   const struct flow_wildcards *wildcards)
613 {
614     const uint32_t wc = wildcards->wildcards;
615
616     BUILD_ASSERT_DECL(FLOW_SIG_SIZE == 37);
617
618     return ((wc & NXFW_TUN_ID || a->tun_id == b->tun_id)
619             && !((a->nw_src ^ b->nw_src) & wildcards->nw_src_mask)
620             && !((a->nw_dst ^ b->nw_dst) & wildcards->nw_dst_mask)
621             && (wc & OFPFW_IN_PORT || a->in_port == b->in_port)
622             && (wc & OFPFW_DL_VLAN || a->dl_vlan == b->dl_vlan)
623             && (wc & OFPFW_DL_TYPE || a->dl_type == b->dl_type)
624             && (wc & OFPFW_TP_SRC || a->tp_src == b->tp_src)
625             && (wc & OFPFW_TP_DST || a->tp_dst == b->tp_dst)
626             && (wc & OFPFW_DL_SRC || eth_addr_equals(a->dl_src, b->dl_src))
627             && (wc & OFPFW_DL_DST || eth_addr_equals(a->dl_dst, b->dl_dst))
628             && (wc & OFPFW_NW_PROTO || a->nw_proto == b->nw_proto)
629             && (wc & OFPFW_DL_VLAN_PCP || a->dl_vlan_pcp == b->dl_vlan_pcp)
630             && (wc & OFPFW_NW_TOS || a->nw_tos == b->nw_tos));
631 }
632
633 static void
634 zero_wildcards(struct flow *flow, const struct flow_wildcards *wildcards)
635 {
636     const uint32_t wc = wildcards->wildcards;
637
638     BUILD_ASSERT_DECL(FLOW_SIG_SIZE == 37);
639
640     if (wc & NXFW_TUN_ID) {
641         flow->tun_id = 0;
642     }
643     flow->nw_src &= wildcards->nw_src_mask;
644     flow->nw_dst &= wildcards->nw_dst_mask;
645     if (wc & OFPFW_IN_PORT) {
646         flow->in_port = 0;
647     }
648     if (wc & OFPFW_DL_VLAN) {
649         flow->dl_vlan = 0;
650     }
651     if (wc & OFPFW_DL_TYPE) {
652         flow->dl_type = 0;
653     }
654     if (wc & OFPFW_TP_SRC) {
655         flow->tp_src = 0;
656     }
657     if (wc & OFPFW_TP_DST) {
658         flow->tp_dst = 0;
659     }
660     if (wc & OFPFW_DL_SRC) {
661         memset(flow->dl_src, 0, sizeof flow->dl_src);
662     }
663     if (wc & OFPFW_DL_DST) {
664         memset(flow->dl_dst, 0, sizeof flow->dl_dst);
665     }
666     if (wc & OFPFW_NW_PROTO) {
667         flow->nw_proto = 0;
668     }
669     if (wc & OFPFW_DL_VLAN_PCP) {
670         flow->dl_vlan_pcp = 0;
671     }
672     if (wc & OFPFW_NW_TOS) {
673         flow->nw_tos = 0;
674     }
675 }