ovsdb: Factor out code to fsync a file's containing directory.
[openvswitch] / lib / classifier.h
1 /*
2  * Copyright (c) 2009 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 #ifndef CLASSIFIER_H
18 #define CLASSIFIER_H 1
19
20 /* Flow classifier.
21  *
22  * This flow classifier assumes that we can arrange the fields in a flow in an
23  * order such that the set of wildcarded fields in a rule tend to fall toward
24  * the end of the ordering.  That is, if field F is wildcarded, then all the
25  * fields after F tend to be wildcarded as well.  If this assumption is
26  * violated, then the classifier will still classify flows correctly, but its
27  * performance will suffer.
28  *
29  * The classifier uses a collection of CLS_N_FIELDS hash tables for wildcarded
30  * flows.  Each of these tables contains the flows that wildcard a given field
31  * and do not wildcard any of the fields that precede F in the ordering.  The
32  * key for each hash table is the value of the fields preceding F that are not
33  * wildcarded.  All the flows that fall within a table and have the same key
34  * are kept as a linked list ordered from highest to lowest priority.
35  *
36  * The classifier also maintains a separate hash table of exact-match flows.
37  *
38  * To search the classifier we first search the table of exact-match flows,
39  * since exact-match flows always have highest priority.  If there is a match,
40  * we're done.  Otherwise, we search each of the CLS_N_FIELDS hash tables in
41  * turn, looking for the highest-priority match, and return it (if any).
42  */
43
44 #include "flow.h"
45 #include "hmap.h"
46 #include "list.h"
47 #include "openflow/openflow.h"
48
49 /* Number of bytes of fields in a rule. */
50 #define CLS_N_BYTES 31
51
52 /* Fields in a rule.
53  *
54  * This definition sets the ordering of fields, which is important for
55  * performance (see above).  To adjust the ordering, change the order of the
56  * lines. */
57 #define CLS_FIELDS                                          \
58     /*                           flow_t       all-caps */   \
59     /*        wildcard bit(s)    member name  name     */   \
60     /*        -----------------  -----------  -------- */   \
61     CLS_FIELD(OFPFW_IN_PORT,     in_port,     IN_PORT)      \
62     CLS_FIELD(OFPFW_DL_VLAN,     dl_vlan,     DL_VLAN)      \
63     CLS_FIELD(OFPFW_DL_SRC,      dl_src,      DL_SRC)       \
64     CLS_FIELD(OFPFW_DL_DST,      dl_dst,      DL_DST)       \
65     CLS_FIELD(OFPFW_DL_TYPE,     dl_type,     DL_TYPE)      \
66     CLS_FIELD(OFPFW_NW_SRC_MASK, nw_src,      NW_SRC)       \
67     CLS_FIELD(OFPFW_NW_DST_MASK, nw_dst,      NW_DST)       \
68     CLS_FIELD(OFPFW_NW_PROTO,    nw_proto,    NW_PROTO)     \
69     CLS_FIELD(OFPFW_TP_SRC,      tp_src,      TP_SRC)       \
70     CLS_FIELD(OFPFW_TP_DST,      tp_dst,      TP_DST)
71
72 /* Field indexes.
73  *
74  * (These are also indexed into struct classifier's 'tables' array.) */
75 enum {
76 #define CLS_FIELD(WILDCARDS, MEMBER, NAME) CLS_F_IDX_##NAME,
77     CLS_FIELDS
78 #undef CLS_FIELD
79     CLS_F_IDX_EXACT,            /* Exact-match table. */
80     CLS_N_FIELDS = CLS_F_IDX_EXACT
81 };
82
83 /* Field information. */
84 struct cls_field {
85     int ofs;                    /* Offset in flow_t. */
86     int len;                    /* Length in bytes. */
87     uint32_t wildcards;         /* OFPFW_* bit or bits for this field. */
88     const char *name;           /* Name (for debugging). */
89 };
90 extern const struct cls_field cls_fields[CLS_N_FIELDS + 1];
91
92 /* A flow classifier. */
93 struct classifier {
94     int n_rules;                /* Sum of hmap_count() over tables[]. */
95     struct hmap tables[CLS_N_FIELDS]; /* Contain cls_bucket elements. */
96     struct hmap exact_table;          /* Contain cls_rule elements. */
97 };
98
99 /* A group of rules with the same fixed values for initial fields. */
100 struct cls_bucket {
101     struct hmap_node hmap_node; /* Within struct classifier 'tables'. */
102     struct list rules;          /* In order from highest to lowest priority. */
103     flow_t fixed;               /* Values for fixed fields. */
104 };
105
106 /* A flow classification rule.
107  *
108  * Use cls_rule_from_flow() or cls_rule_from_match() to initialize a cls_rule
109  * or you will almost certainly not initialize 'table_idx' correctly, with
110  * disastrous results! */
111 struct cls_rule {
112     union {
113         struct list list;       /* Within struct cls_bucket 'rules'. */
114         struct hmap_node hmap;  /* Within struct classifier 'exact_table'. */
115     } node;
116     flow_t flow;                /* All field values. */
117     struct flow_wildcards wc;   /* Wildcards for fields. */
118     unsigned int priority;      /* Larger numbers are higher priorities. */
119     unsigned int table_idx;     /* Index into struct classifier 'tables'. */
120 };
121
122 void cls_rule_from_flow(struct cls_rule *, const flow_t *, uint32_t wildcards,
123                         unsigned int priority);
124 void cls_rule_from_match(struct cls_rule *, const struct ofp_match *,
125                          unsigned int priority);
126 void cls_rule_print(const struct cls_rule *);
127 void cls_rule_moved(struct classifier *,
128                     struct cls_rule *old, struct cls_rule *new);
129 void cls_rule_replace(struct classifier *, const struct cls_rule *old,
130                       struct cls_rule *new);
131
132 void classifier_init(struct classifier *);
133 void classifier_destroy(struct classifier *);
134 bool classifier_is_empty(const struct classifier *);
135 int classifier_count(const struct classifier *);
136 int classifier_count_exact(const struct classifier *);
137 struct cls_rule *classifier_insert(struct classifier *, struct cls_rule *);
138 void classifier_insert_exact(struct classifier *, struct cls_rule *);
139 void classifier_remove(struct classifier *, struct cls_rule *);
140 struct cls_rule *classifier_lookup(const struct classifier *, const flow_t *);
141 struct cls_rule *classifier_lookup_wild(const struct classifier *,
142                                         const flow_t *);
143 struct cls_rule *classifier_lookup_exact(const struct classifier *,
144                                          const flow_t *);
145
146 typedef void cls_cb_func(struct cls_rule *, void *aux);
147
148 enum {
149     CLS_INC_EXACT = 1 << 0,     /* Include exact-match flows? */
150     CLS_INC_WILD = 1 << 1,      /* Include flows with wildcards? */
151     CLS_INC_ALL = CLS_INC_EXACT | CLS_INC_WILD
152 };
153 void classifier_for_each(const struct classifier *, int include,
154                          cls_cb_func *, void *aux);
155 void classifier_for_each_match(const struct classifier *,
156                                const struct cls_rule *,
157                                int include, cls_cb_func *, void *aux);
158 struct cls_rule *classifier_find_rule_exactly(const struct classifier *,
159                                               const flow_t *target,
160                                               uint32_t wildcards,
161                                               unsigned int priority);
162
163 #endif /* classifier.h */