ovn: Add stateful ACL support.
[cascardo/ovs.git] / ovn / controller / lflow.c
1 /* Copyright (c) 2015 Nicira, Inc.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <config.h>
17 #include "lflow.h"
18 #include "dynamic-string.h"
19 #include "ofctrl.h"
20 #include "ofp-actions.h"
21 #include "ofpbuf.h"
22 #include "openvswitch/vlog.h"
23 #include "ovn/controller/ovn-controller.h"
24 #include "ovn/lib/actions.h"
25 #include "ovn/lib/expr.h"
26 #include "ovn/lib/ovn-sb-idl.h"
27 #include "simap.h"
28
29 VLOG_DEFINE_THIS_MODULE(lflow);
30 \f
31 /* Symbol table. */
32
33 /* Contains "struct expr_symbol"s for fields supported by OVN lflows. */
34 static struct shash symtab;
35
36 static void
37 add_logical_register(struct shash *symtab, enum mf_field_id id)
38 {
39     char name[8];
40
41     snprintf(name, sizeof name, "reg%d", id - MFF_REG0);
42     expr_symtab_add_field(symtab, name, id, NULL, false);
43 }
44
45 static void
46 symtab_init(void)
47 {
48     shash_init(&symtab);
49
50     /* Reserve a pair of registers for the logical inport and outport.  A full
51      * 32-bit register each is bigger than we need, but the expression code
52      * doesn't yet support string fields that occupy less than a full OXM. */
53     expr_symtab_add_string(&symtab, "inport", MFF_LOG_INPORT, NULL);
54     expr_symtab_add_string(&symtab, "outport", MFF_LOG_OUTPORT, NULL);
55
56     /* Logical registers. */
57 #define MFF_LOG_REG(ID) add_logical_register(&symtab, ID);
58     MFF_LOG_REGS;
59 #undef MFF_LOG_REG
60
61     /* Connection tracking state. */
62     expr_symtab_add_field(&symtab, "ct_state", MFF_CT_STATE, NULL, false);
63     expr_symtab_add_predicate(&symtab, "ct.trk", "ct_state[7]");
64     expr_symtab_add_subfield(&symtab, "ct.new", "ct.trk", "ct_state[0]");
65     expr_symtab_add_subfield(&symtab, "ct.est", "ct.trk", "ct_state[1]");
66     expr_symtab_add_subfield(&symtab, "ct.rel", "ct.trk", "ct_state[2]");
67     expr_symtab_add_subfield(&symtab, "ct.inv", "ct.trk", "ct_state[5]");
68     expr_symtab_add_subfield(&symtab, "ct.rpl", "ct.trk", "ct_state[6]");
69
70     /* Data fields. */
71     expr_symtab_add_field(&symtab, "eth.src", MFF_ETH_SRC, NULL, false);
72     expr_symtab_add_field(&symtab, "eth.dst", MFF_ETH_DST, NULL, false);
73     expr_symtab_add_field(&symtab, "eth.type", MFF_ETH_TYPE, NULL, true);
74
75     expr_symtab_add_field(&symtab, "vlan.tci", MFF_VLAN_TCI, NULL, false);
76     expr_symtab_add_predicate(&symtab, "vlan.present", "vlan.tci[12]");
77     expr_symtab_add_subfield(&symtab, "vlan.pcp", "vlan.present",
78                              "vlan.tci[13..15]");
79     expr_symtab_add_subfield(&symtab, "vlan.vid", "vlan.present",
80                              "vlan.tci[0..11]");
81
82     expr_symtab_add_predicate(&symtab, "ip4", "eth.type == 0x800");
83     expr_symtab_add_predicate(&symtab, "ip6", "eth.type == 0x86dd");
84     expr_symtab_add_predicate(&symtab, "ip", "ip4 || ip6");
85     expr_symtab_add_field(&symtab, "ip.proto", MFF_IP_PROTO, "ip", true);
86     expr_symtab_add_field(&symtab, "ip.dscp", MFF_IP_DSCP, "ip", false);
87     expr_symtab_add_field(&symtab, "ip.ecn", MFF_IP_ECN, "ip", false);
88     expr_symtab_add_field(&symtab, "ip.ttl", MFF_IP_TTL, "ip", false);
89
90     expr_symtab_add_field(&symtab, "ip4.src", MFF_IPV4_SRC, "ip4", false);
91     expr_symtab_add_field(&symtab, "ip4.dst", MFF_IPV4_DST, "ip4", false);
92
93     expr_symtab_add_predicate(&symtab, "icmp4", "ip4 && ip.proto == 1");
94     expr_symtab_add_field(&symtab, "icmp4.type", MFF_ICMPV4_TYPE, "icmp4",
95               false);
96     expr_symtab_add_field(&symtab, "icmp4.code", MFF_ICMPV4_CODE, "icmp4",
97               false);
98
99     expr_symtab_add_field(&symtab, "ip6.src", MFF_IPV6_SRC, "ip6", false);
100     expr_symtab_add_field(&symtab, "ip6.dst", MFF_IPV6_DST, "ip6", false);
101     expr_symtab_add_field(&symtab, "ip6.label", MFF_IPV6_LABEL, "ip6", false);
102
103     expr_symtab_add_predicate(&symtab, "icmp6", "ip6 && ip.proto == 58");
104     expr_symtab_add_field(&symtab, "icmp6.type", MFF_ICMPV6_TYPE, "icmp6",
105                           true);
106     expr_symtab_add_field(&symtab, "icmp6.code", MFF_ICMPV6_CODE, "icmp6",
107                           true);
108
109     expr_symtab_add_predicate(&symtab, "icmp", "icmp4 || icmp6");
110
111     expr_symtab_add_field(&symtab, "ip.frag", MFF_IP_FRAG, "ip", false);
112     expr_symtab_add_predicate(&symtab, "ip.is_frag", "ip.frag[0]");
113     expr_symtab_add_predicate(&symtab, "ip.later_frag", "ip.frag[1]");
114     expr_symtab_add_predicate(&symtab, "ip.first_frag",
115                               "ip.is_frag && !ip.later_frag");
116
117     expr_symtab_add_predicate(&symtab, "arp", "eth.type == 0x806");
118     expr_symtab_add_field(&symtab, "arp.op", MFF_ARP_OP, "arp", false);
119     expr_symtab_add_field(&symtab, "arp.spa", MFF_ARP_SPA, "arp", false);
120     expr_symtab_add_field(&symtab, "arp.sha", MFF_ARP_SHA, "arp", false);
121     expr_symtab_add_field(&symtab, "arp.tpa", MFF_ARP_TPA, "arp", false);
122     expr_symtab_add_field(&symtab, "arp.tha", MFF_ARP_THA, "arp", false);
123
124     expr_symtab_add_predicate(&symtab, "nd",
125                               "icmp6.type == {135, 136} && icmp6.code == 0");
126     expr_symtab_add_field(&symtab, "nd.target", MFF_ND_TARGET, "nd", false);
127     expr_symtab_add_field(&symtab, "nd.sll", MFF_ND_SLL,
128               "nd && icmp6.type == 135", false);
129     expr_symtab_add_field(&symtab, "nd.tll", MFF_ND_TLL,
130               "nd && icmp6.type == 136", false);
131
132     expr_symtab_add_predicate(&symtab, "tcp", "ip.proto == 6");
133     expr_symtab_add_field(&symtab, "tcp.src", MFF_TCP_SRC, "tcp", false);
134     expr_symtab_add_field(&symtab, "tcp.dst", MFF_TCP_DST, "tcp", false);
135     expr_symtab_add_field(&symtab, "tcp.flags", MFF_TCP_FLAGS, "tcp", false);
136
137     expr_symtab_add_predicate(&symtab, "udp", "ip.proto == 17");
138     expr_symtab_add_field(&symtab, "udp.src", MFF_UDP_SRC, "udp", false);
139     expr_symtab_add_field(&symtab, "udp.dst", MFF_UDP_DST, "udp", false);
140
141     expr_symtab_add_predicate(&symtab, "sctp", "ip.proto == 132");
142     expr_symtab_add_field(&symtab, "sctp.src", MFF_SCTP_SRC, "sctp", false);
143     expr_symtab_add_field(&symtab, "sctp.dst", MFF_SCTP_DST, "sctp", false);
144 }
145 \f
146 /* Logical datapaths and logical port numbers. */
147
148 /* A logical datapath.
149  *
150  * 'ports' maps 'logical_port' names to 'tunnel_key' values in the OVN_SB
151  * Port_Binding table within the logical datapath. */
152 struct logical_datapath {
153     struct hmap_node hmap_node; /* Indexed on 'uuid'. */
154     struct uuid uuid;           /* UUID from Datapath_Binding row. */
155     uint32_t tunnel_key;        /* 'tunnel_key' from Datapath_Binding row. */
156     struct simap ports;         /* Logical port name to port number. */
157 };
158
159 /* Contains "struct logical_datapath"s. */
160 static struct hmap logical_datapaths = HMAP_INITIALIZER(&logical_datapaths);
161
162 /* Finds and returns the logical_datapath for 'binding', or NULL if no such
163  * logical_datapath exists. */
164 static struct logical_datapath *
165 ldp_lookup(const struct sbrec_datapath_binding *binding)
166 {
167     struct logical_datapath *ldp;
168     HMAP_FOR_EACH_IN_BUCKET (ldp, hmap_node, uuid_hash(&binding->header_.uuid),
169                              &logical_datapaths) {
170         if (uuid_equals(&ldp->uuid, &binding->header_.uuid)) {
171             return ldp;
172         }
173     }
174     return NULL;
175 }
176
177 /* Creates a new logical_datapath for the given 'binding'. */
178 static struct logical_datapath *
179 ldp_create(const struct sbrec_datapath_binding *binding)
180 {
181     struct logical_datapath *ldp;
182
183     ldp = xmalloc(sizeof *ldp);
184     hmap_insert(&logical_datapaths, &ldp->hmap_node,
185                 uuid_hash(&binding->header_.uuid));
186     ldp->uuid = binding->header_.uuid;
187     ldp->tunnel_key = binding->tunnel_key;
188     simap_init(&ldp->ports);
189     return ldp;
190 }
191
192 static struct logical_datapath *
193 ldp_lookup_or_create(const struct sbrec_datapath_binding *binding)
194 {
195     struct logical_datapath *ldp = ldp_lookup(binding);
196     return ldp ? ldp : ldp_create(binding);
197 }
198
199 static void
200 ldp_free(struct logical_datapath *ldp)
201 {
202     simap_destroy(&ldp->ports);
203     hmap_remove(&logical_datapaths, &ldp->hmap_node);
204     free(ldp);
205 }
206
207 /* Iterates through all of the records in the Port_Binding table, updating the
208  * table of logical_datapaths to match the values found in active
209  * Port_Bindings. */
210 static void
211 ldp_run(struct controller_ctx *ctx)
212 {
213     struct logical_datapath *ldp;
214     HMAP_FOR_EACH (ldp, hmap_node, &logical_datapaths) {
215         simap_clear(&ldp->ports);
216     }
217
218     const struct sbrec_port_binding *binding;
219     SBREC_PORT_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) {
220         struct logical_datapath *ldp = ldp_lookup_or_create(binding->datapath);
221
222         simap_put(&ldp->ports, binding->logical_port, binding->tunnel_key);
223     }
224
225     const struct sbrec_multicast_group *mc;
226     SBREC_MULTICAST_GROUP_FOR_EACH (mc, ctx->ovnsb_idl) {
227         struct logical_datapath *ldp = ldp_lookup_or_create(mc->datapath);
228         simap_put(&ldp->ports, mc->name, mc->tunnel_key);
229     }
230
231     struct logical_datapath *next_ldp;
232     HMAP_FOR_EACH_SAFE (ldp, next_ldp, hmap_node, &logical_datapaths) {
233         if (simap_is_empty(&ldp->ports)) {
234             ldp_free(ldp);
235         }
236     }
237 }
238
239 static void
240 ldp_destroy(void)
241 {
242     struct logical_datapath *ldp, *next_ldp;
243     HMAP_FOR_EACH_SAFE (ldp, next_ldp, hmap_node, &logical_datapaths) {
244         ldp_free(ldp);
245     }
246 }
247 \f
248 void
249 lflow_init(void)
250 {
251     symtab_init();
252 }
253
254 /* Translates logical flows in the Logical_Flow table in the OVN_SB database
255  * into OpenFlow flows.  See ovn-architecture(7) for more information. */
256 void
257 lflow_run(struct controller_ctx *ctx, struct hmap *flow_table,
258           const struct simap *ct_zones)
259 {
260     struct hmap flows = HMAP_INITIALIZER(&flows);
261     uint32_t conj_id_ofs = 1;
262
263     ldp_run(ctx);
264
265     const struct sbrec_logical_flow *lflow;
266     SBREC_LOGICAL_FLOW_FOR_EACH (lflow, ctx->ovnsb_idl) {
267         /* Find the "struct logical_datapath" asssociated with this
268          * Logical_Flow row.  If there's no such struct, that must be because
269          * no logical ports are bound to that logical datapath, so there's no
270          * point in maintaining any flows for it anyway, so skip it. */
271         const struct logical_datapath *ldp;
272         ldp = ldp_lookup(lflow->logical_datapath);
273         if (!ldp) {
274             continue;
275         }
276
277         /* Determine translation of logical table IDs to physical table IDs. */
278         bool ingress = !strcmp(lflow->pipeline, "ingress");
279         uint8_t first_ptable = (ingress
280                                 ? OFTABLE_LOG_INGRESS_PIPELINE
281                                 : OFTABLE_LOG_EGRESS_PIPELINE);
282         uint8_t ptable = first_ptable + lflow->table_id;
283         uint8_t output_ptable = (ingress
284                                  ? OFTABLE_REMOTE_OUTPUT
285                                  : OFTABLE_LOG_TO_PHY);
286
287         /* Translate OVN actions into OpenFlow actions.
288          *
289          * XXX Deny changes to 'outport' in egress pipeline. */
290         uint64_t ofpacts_stub[64 / 8];
291         struct ofpbuf ofpacts;
292         struct expr *prereqs;
293         char *error;
294
295         ofpbuf_use_stub(&ofpacts, ofpacts_stub, sizeof ofpacts_stub);
296         error = actions_parse_string(lflow->actions, &symtab, &ldp->ports,
297                                      ct_zones, first_ptable, LOG_PIPELINE_LEN,
298                                      lflow->table_id, output_ptable,
299                                      &ofpacts, &prereqs);
300         if (error) {
301             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
302             VLOG_WARN_RL(&rl, "error parsing actions \"%s\": %s",
303                          lflow->actions, error);
304             free(error);
305             continue;
306         }
307
308         /* Translate OVN match into table of OpenFlow matches. */
309         struct hmap matches;
310         struct expr *expr;
311
312         expr = expr_parse_string(lflow->match, &symtab, &error);
313         if (!error) {
314             if (prereqs) {
315                 expr = expr_combine(EXPR_T_AND, expr, prereqs);
316                 prereqs = NULL;
317             }
318             expr = expr_annotate(expr, &symtab, &error);
319         }
320         if (error) {
321             static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
322             VLOG_WARN_RL(&rl, "error parsing match \"%s\": %s",
323                          lflow->match, error);
324             expr_destroy(prereqs);
325             ofpbuf_uninit(&ofpacts);
326             free(error);
327             continue;
328         }
329
330         expr = expr_simplify(expr);
331         expr = expr_normalize(expr);
332         uint32_t n_conjs = expr_to_matches(expr, &ldp->ports, &matches);
333         expr_destroy(expr);
334
335         /* Prepare the OpenFlow matches for adding to the flow table. */
336         struct expr_match *m;
337         HMAP_FOR_EACH (m, hmap_node, &matches) {
338             match_set_metadata(&m->match, htonll(ldp->tunnel_key));
339             if (m->match.wc.masks.conj_id) {
340                 m->match.flow.conj_id += conj_id_ofs;
341             }
342             if (!m->n) {
343                 ofctrl_add_flow(flow_table, ptable, lflow->priority,
344                                 &m->match, &ofpacts);
345             } else {
346                 uint64_t conj_stubs[64 / 8];
347                 struct ofpbuf conj;
348
349                 ofpbuf_use_stub(&conj, conj_stubs, sizeof conj_stubs);
350                 for (int i = 0; i < m->n; i++) {
351                     const struct cls_conjunction *src = &m->conjunctions[i];
352                     struct ofpact_conjunction *dst;
353
354                     dst = ofpact_put_CONJUNCTION(&conj);
355                     dst->id = src->id + conj_id_ofs;
356                     dst->clause = src->clause;
357                     dst->n_clauses = src->n_clauses;
358                 }
359                 ofctrl_add_flow(flow_table, ptable, lflow->priority,
360                                 &m->match, &conj);
361                 ofpbuf_uninit(&conj);
362             }
363         }
364
365         /* Clean up. */
366         expr_matches_destroy(&matches);
367         ofpbuf_uninit(&ofpacts);
368         conj_id_ofs += n_conjs;
369     }
370 }
371
372 void
373 lflow_destroy(void)
374 {
375     expr_symtab_destroy(&symtab);
376     ldp_destroy();
377 }