b515bf5b998515e5b950ab5fd5a546cd72046c22
[sliver-openvswitch.git] / lib / classifier.h
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 #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/nicira-ext.h"
48 #include "openflow/openflow.h"
49
50 #ifdef  __cplusplus
51 extern "C" {
52 #endif
53
54 /* Number of bytes of fields in a rule. */
55 #define CLS_N_BYTES 37
56
57 /* Fields in a rule.
58  *
59  * This definition sets the ordering of fields, which is important for
60  * performance (see above).  To adjust the ordering, change the order of the
61  * lines. */
62 #define CLS_FIELDS                                          \
63     /*                           flow_t       all-caps */   \
64     /*        wildcard bit(s)    member name  name     */   \
65     /*        -----------------  -----------  -------- */   \
66     CLS_FIELD(OFPFW_IN_PORT,     in_port,     IN_PORT)      \
67     CLS_FIELD(NXFW_TUN_ID,       tun_id,      TUN_ID)       \
68     CLS_FIELD(OFPFW_DL_VLAN,     dl_vlan,     DL_VLAN)      \
69     CLS_FIELD(OFPFW_DL_VLAN_PCP, dl_vlan_pcp, DL_VLAN_PCP)  \
70     CLS_FIELD(OFPFW_DL_SRC,      dl_src,      DL_SRC)       \
71     CLS_FIELD(OFPFW_DL_DST,      dl_dst,      DL_DST)       \
72     CLS_FIELD(OFPFW_DL_TYPE,     dl_type,     DL_TYPE)      \
73     CLS_FIELD(OFPFW_NW_SRC_MASK, nw_src,      NW_SRC)       \
74     CLS_FIELD(OFPFW_NW_DST_MASK, nw_dst,      NW_DST)       \
75     CLS_FIELD(OFPFW_NW_PROTO,    nw_proto,    NW_PROTO)     \
76     CLS_FIELD(OFPFW_NW_TOS,      nw_tos,      NW_TOS)       \
77     CLS_FIELD(OFPFW_TP_SRC,      tp_src,      TP_SRC)       \
78     CLS_FIELD(OFPFW_TP_DST,      tp_dst,      TP_DST)
79
80 /* Field indexes.
81  *
82  * (These are also indexed into struct classifier's 'tables' array.) */
83 enum {
84 #define CLS_FIELD(WILDCARDS, MEMBER, NAME) CLS_F_IDX_##NAME,
85     CLS_FIELDS
86 #undef CLS_FIELD
87     CLS_F_IDX_EXACT,            /* Exact-match table. */
88     CLS_N_FIELDS = CLS_F_IDX_EXACT
89 };
90
91 /* Field information. */
92 struct cls_field {
93     int ofs;                    /* Offset in flow_t. */
94     int len;                    /* Length in bytes. */
95     uint32_t wildcards;         /* OFPFW_* bit or bits for this field. */
96     const char *name;           /* Name (for debugging). */
97 };
98 extern const struct cls_field cls_fields[CLS_N_FIELDS + 1];
99
100 /* A flow classifier. */
101 struct classifier {
102     int n_rules;                /* Sum of hmap_count() over tables[]. */
103     struct hmap tables[CLS_N_FIELDS]; /* Contain cls_bucket elements. */
104     struct hmap exact_table;          /* Contain cls_rule elements. */
105 };
106
107 /* A group of rules with the same fixed values for initial fields. */
108 struct cls_bucket {
109     struct hmap_node hmap_node; /* Within struct classifier 'tables'. */
110     struct list rules;          /* In order from highest to lowest priority. */
111     flow_t fixed;               /* Values for fixed fields. */
112 };
113
114 /* A flow classification rule.
115  *
116  * Use cls_rule_from_flow() or cls_rule_from_match() to initialize a cls_rule
117  * or you will almost certainly not initialize 'table_idx' correctly, with
118  * disastrous results! */
119 struct cls_rule {
120     union {
121         struct list list;       /* Within struct cls_bucket 'rules'. */
122         struct hmap_node hmap;  /* Within struct classifier 'exact_table'. */
123     } node;
124     flow_t flow;                /* All field values. */
125     struct flow_wildcards wc;   /* Wildcards for fields. */
126     unsigned int table_idx;     /* Index into struct classifier 'tables'. */
127 };
128
129 void cls_rule_from_flow(const flow_t *, struct cls_rule *);
130 void cls_rule_from_match(const struct ofp_match *, unsigned int priority,
131                          bool tun_id_from_cookie, uint64_t cookie,
132                          struct cls_rule *);
133 char *cls_rule_to_string(const struct cls_rule *);
134 void cls_rule_print(const struct cls_rule *);
135 void cls_rule_moved(struct classifier *,
136                     struct cls_rule *old_rule, struct cls_rule *new_rule);
137 void cls_rule_replace(struct classifier *, const struct cls_rule *old_rule,
138                       struct cls_rule *new_rule);
139
140 void classifier_init(struct classifier *);
141 void classifier_destroy(struct classifier *);
142 bool classifier_is_empty(const struct classifier *);
143 int classifier_count(const struct classifier *);
144 int classifier_count_exact(const struct classifier *);
145 int classifier_count_wild(const struct classifier *);
146 struct cls_rule *classifier_insert(struct classifier *, struct cls_rule *);
147 void classifier_insert_exact(struct classifier *, struct cls_rule *);
148 void classifier_remove(struct classifier *, struct cls_rule *);
149 struct cls_rule *classifier_lookup(const struct classifier *, const flow_t *);
150 struct cls_rule *classifier_lookup_wild(const struct classifier *,
151                                         const flow_t *);
152 struct cls_rule *classifier_lookup_exact(const struct classifier *,
153                                          const flow_t *);
154 bool classifier_rule_overlaps(const struct classifier *, const flow_t *);
155
156 typedef void cls_cb_func(struct cls_rule *, void *aux);
157
158 enum {
159     CLS_INC_EXACT = 1 << 0,     /* Include exact-match flows? */
160     CLS_INC_WILD = 1 << 1,      /* Include flows with wildcards? */
161     CLS_INC_ALL = CLS_INC_EXACT | CLS_INC_WILD
162 };
163 void classifier_for_each(const struct classifier *, int include,
164                          cls_cb_func *, void *aux);
165 void classifier_for_each_match(const struct classifier *, const flow_t *,
166                                int include, cls_cb_func *, void *aux);
167 struct cls_rule *classifier_find_rule_exactly(const struct classifier *,
168                                               const flow_t *target);
169
170 #ifdef  __cplusplus
171 }
172 #endif
173
174 #endif /* classifier.h */