Move lib/ofpbuf.h to include/openvswitch directory
[cascardo/ovs.git] / ovn / lib / actions.c
1 /*
2  * Copyright (c) 2015, 2016 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 #include <config.h>
18 #include "actions.h"
19 #include <stdarg.h>
20 #include <stdbool.h>
21 #include "compiler.h"
22 #include "openvswitch/dynamic-string.h"
23 #include "expr.h"
24 #include "lex.h"
25 #include "logical-fields.h"
26 #include "ofp-actions.h"
27 #include "openvswitch/ofpbuf.h"
28 #include "simap.h"
29
30 /* Context maintained during actions_parse(). */
31 struct action_context {
32     const struct action_params *ap; /* Parameters. */
33     struct lexer *lexer;        /* Lexer for pulling more tokens. */
34     char *error;                /* Error, if any, otherwise NULL. */
35     struct ofpbuf *ofpacts;     /* Actions. */
36     struct expr *prereqs;       /* Prerequisites to apply to match. */
37 };
38
39 static bool parse_action(struct action_context *);
40
41 static bool
42 action_error_handle_common(struct action_context *ctx)
43 {
44     if (ctx->error) {
45         /* Already have an error, suppress this one since the cascade seems
46          * unlikely to be useful. */
47         return true;
48     } else if (ctx->lexer->token.type == LEX_T_ERROR) {
49         /* The lexer signaled an error.  Nothing at the action level
50          * accepts an error token, so we'll inevitably end up here with some
51          * meaningless parse error.  Report the lexical error instead. */
52         ctx->error = xstrdup(ctx->lexer->token.s);
53         return true;
54     } else {
55         return false;
56     }
57 }
58
59 static void OVS_PRINTF_FORMAT(2, 3)
60 action_error(struct action_context *ctx, const char *message, ...)
61 {
62     if (action_error_handle_common(ctx)) {
63         return;
64     }
65
66     va_list args;
67     va_start(args, message);
68     ctx->error = xvasprintf(message, args);
69     va_end(args);
70 }
71
72 static void OVS_PRINTF_FORMAT(2, 3)
73 action_syntax_error(struct action_context *ctx, const char *message, ...)
74 {
75     if (action_error_handle_common(ctx)) {
76         return;
77     }
78
79     struct ds s;
80
81     ds_init(&s);
82     ds_put_cstr(&s, "Syntax error");
83     if (ctx->lexer->token.type == LEX_T_END) {
84         ds_put_cstr(&s, " at end of input");
85     } else if (ctx->lexer->start) {
86         ds_put_format(&s, " at `%.*s'",
87                       (int) (ctx->lexer->input - ctx->lexer->start),
88                       ctx->lexer->start);
89     }
90
91     if (message) {
92         ds_put_char(&s, ' ');
93
94         va_list args;
95         va_start(args, message);
96         ds_put_format_valist(&s, message, args);
97         va_end(args);
98     }
99     ds_put_char(&s, '.');
100
101     ctx->error = ds_steal_cstr(&s);
102 }
103
104 /* Parses an assignment or exchange action. */
105 static void
106 parse_set_action(struct action_context *ctx)
107 {
108     struct expr *prereqs;
109     char *error;
110
111     error = expr_parse_assignment(ctx->lexer, ctx->ap->symtab,
112                                   ctx->ap->lookup_port, ctx->ap->aux,
113                                   ctx->ofpacts, &prereqs);
114     if (error) {
115         action_error(ctx, "%s", error);
116         free(error);
117         return;
118     }
119
120     ctx->prereqs = expr_combine(EXPR_T_AND, ctx->prereqs, prereqs);
121 }
122
123 static void
124 emit_resubmit(struct action_context *ctx, uint8_t table_id)
125 {
126     struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(ctx->ofpacts);
127     resubmit->in_port = OFPP_IN_PORT;
128     resubmit->table_id = table_id;
129 }
130
131 static bool
132 action_get_int(struct action_context *ctx, int *value)
133 {
134     bool ok = lexer_get_int(ctx->lexer, value);
135     if (!ok) {
136         action_syntax_error(ctx, "expecting small integer");
137     }
138     return ok;
139 }
140
141 static void
142 parse_next_action(struct action_context *ctx)
143 {
144     if (!ctx->ap->n_tables) {
145         action_error(ctx, "\"next\" action not allowed here.");
146     } else if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {
147         int ltable;
148
149         if (!action_get_int(ctx, &ltable)) {
150             return;
151         }
152         if (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
153             action_syntax_error(ctx, "expecting `)'");
154             return;
155         }
156
157         if (ltable >= ctx->ap->n_tables) {
158             action_error(ctx, "\"next\" argument must be in range 0 to %d.",
159                          ctx->ap->n_tables - 1);
160             return;
161         }
162
163         emit_resubmit(ctx, ctx->ap->first_ptable + ltable);
164     } else {
165         if (ctx->ap->cur_ltable < ctx->ap->n_tables) {
166             emit_resubmit(ctx,
167                           ctx->ap->first_ptable + ctx->ap->cur_ltable + 1);
168         } else {
169             action_error(ctx, "\"next\" action not allowed in last table.");
170         }
171     }
172 }
173
174 /* Parses 'prerequisite' as an expression in the context of 'ctx', then adds it
175  * as a conjunction with the existing 'ctx->prereqs'. */
176 static void
177 add_prerequisite(struct action_context *ctx, const char *prerequisite)
178 {
179     struct expr *expr;
180     char *error;
181
182     expr = expr_parse_string(prerequisite, ctx->ap->symtab, &error);
183     ovs_assert(!error);
184     ctx->prereqs = expr_combine(EXPR_T_AND, ctx->prereqs, expr);
185 }
186
187 static size_t
188 start_controller_op(struct ofpbuf *ofpacts, enum action_opcode opcode)
189 {
190     size_t ofs = ofpacts->size;
191
192     struct ofpact_controller *oc = ofpact_put_CONTROLLER(ofpacts);
193     oc->max_len = UINT16_MAX;
194     oc->reason = OFPR_ACTION;
195
196     struct action_header ah = { .opcode = htonl(opcode) };
197     ofpbuf_put(ofpacts, &ah, sizeof ah);
198
199     return ofs;
200 }
201
202 static void
203 finish_controller_op(struct ofpbuf *ofpacts, size_t ofs)
204 {
205     struct ofpact_controller *oc = ofpbuf_at_assert(ofpacts, ofs, sizeof *oc);
206     ofpacts->header = oc;
207     oc->userdata_len = ofpacts->size - (ofs + sizeof *oc);
208     ofpact_finish(ofpacts, &oc->ofpact);
209 }
210
211 static void
212 put_controller_op(struct ofpbuf *ofpacts, enum action_opcode opcode)
213 {
214     size_t ofs = start_controller_op(ofpacts, opcode);
215     finish_controller_op(ofpacts, ofs);
216 }
217
218 static void
219 parse_arp_action(struct action_context *ctx)
220 {
221     if (!lexer_match(ctx->lexer, LEX_T_LCURLY)) {
222         action_syntax_error(ctx, "expecting `{'");
223         return;
224     }
225
226     struct ofpbuf *outer_ofpacts = ctx->ofpacts;
227     uint64_t inner_ofpacts_stub[1024 / 8];
228     struct ofpbuf inner_ofpacts = OFPBUF_STUB_INITIALIZER(inner_ofpacts_stub);
229     ctx->ofpacts = &inner_ofpacts;
230
231     /* Save prerequisites.  (XXX What is the right treatment for prereqs?) */
232     struct expr *outer_prereqs = ctx->prereqs;
233     ctx->prereqs = NULL;
234
235     /* Parse inner actions. */
236     while (!lexer_match(ctx->lexer, LEX_T_RCURLY)) {
237         if (!parse_action(ctx)) {
238             break;
239         }
240     }
241
242     ctx->ofpacts = outer_ofpacts;
243
244     /* Add a "controller" action with the actions nested inside "arp {...}",
245      * converted to OpenFlow, as its userdata.  ovn-controller will convert the
246      * packet to an ARP and then send the packet and actions back to the switch
247      * inside an OFPT_PACKET_OUT message. */
248     size_t oc_offset = start_controller_op(ctx->ofpacts, ACTION_OPCODE_ARP);
249     ofpacts_put_openflow_actions(inner_ofpacts.data, inner_ofpacts.size,
250                                  ctx->ofpacts, OFP13_VERSION);
251     finish_controller_op(ctx->ofpacts, oc_offset);
252
253     /* Restore prerequisites. */
254     expr_destroy(ctx->prereqs);
255     ctx->prereqs = outer_prereqs;
256     add_prerequisite(ctx, "ip4");
257
258     /* Free memory. */
259     ofpbuf_uninit(&inner_ofpacts);
260 }
261
262 static bool
263 action_force_match(struct action_context *ctx, enum lex_type t)
264 {
265     if (lexer_match(ctx->lexer, t)) {
266         return true;
267     } else {
268         struct lex_token token = { .type = t };
269         struct ds s = DS_EMPTY_INITIALIZER;
270         lex_token_format(&token, &s);
271
272         action_syntax_error(ctx, "expecting `%s'", ds_cstr(&s));
273
274         ds_destroy(&s);
275
276         return false;
277     }
278 }
279
280 static bool
281 action_parse_field(struct action_context *ctx,
282                    int n_bits, struct mf_subfield *sf)
283 {
284     struct expr *prereqs;
285     char *error;
286
287     error = expr_parse_field(ctx->lexer, n_bits, false, ctx->ap->symtab, sf,
288                              &prereqs);
289     if (error) {
290         action_error(ctx, "%s", error);
291         return false;
292     }
293
294     ctx->prereqs = expr_combine(EXPR_T_AND, ctx->prereqs, prereqs);
295     return true;
296 }
297
298 static void
299 init_stack(struct ofpact_stack *stack, enum mf_field_id field)
300 {
301     stack->subfield.field = mf_from_id(field);
302     stack->subfield.ofs = 0;
303     stack->subfield.n_bits = stack->subfield.field->n_bits;
304 }
305
306 struct arg {
307     const struct mf_subfield *src;
308     enum mf_field_id dst;
309 };
310
311 static void
312 setup_args(struct action_context *ctx,
313            const struct arg args[], size_t n_args)
314 {
315     /* 1. Save all of the destinations that will be modified. */
316     for (const struct arg *a = args; a < &args[n_args]; a++) {
317         ovs_assert(a->src->n_bits == mf_from_id(a->dst)->n_bits);
318         if (a->src->field->id != a->dst) {
319             init_stack(ofpact_put_STACK_PUSH(ctx->ofpacts), a->dst);
320         }
321     }
322
323     /* 2. Push the sources, in reverse order. */
324     for (size_t i = n_args - 1; i < n_args; i--) {
325         const struct arg *a = &args[i];
326         if (a->src->field->id != a->dst) {
327             ofpact_put_STACK_PUSH(ctx->ofpacts)->subfield = *a->src;
328         }
329     }
330
331     /* 3. Pop the sources into the destinations. */
332     for (const struct arg *a = args; a < &args[n_args]; a++) {
333         if (a->src->field->id != a->dst) {
334             init_stack(ofpact_put_STACK_POP(ctx->ofpacts), a->dst);
335         }
336     }
337 }
338
339 static void
340 restore_args(struct action_context *ctx,
341              const struct arg args[], size_t n_args)
342 {
343     for (size_t i = n_args - 1; i < n_args; i--) {
344         const struct arg *a = &args[i];
345         if (a->src->field->id != a->dst) {
346             init_stack(ofpact_put_STACK_POP(ctx->ofpacts), a->dst);
347         }
348     }
349 }
350
351 static void
352 put_load(uint64_t value, enum mf_field_id dst, int ofs, int n_bits,
353          struct ofpbuf *ofpacts)
354 {
355     struct ofpact_set_field *sf = ofpact_put_SET_FIELD(ofpacts);
356     sf->field = mf_from_id(dst);
357     sf->flow_has_vlan = false;
358
359     ovs_be64 n_value = htonll(value);
360     bitwise_copy(&n_value, 8, 0, &sf->value, sf->field->n_bytes, ofs, n_bits);
361     bitwise_one(&sf->mask, sf->field->n_bytes, ofs, n_bits);
362 }
363
364 static void
365 parse_get_arp_action(struct action_context *ctx)
366 {
367     struct mf_subfield port, ip;
368
369     if (!action_force_match(ctx, LEX_T_LPAREN)
370         || !action_parse_field(ctx, 0, &port)
371         || !action_force_match(ctx, LEX_T_COMMA)
372         || !action_parse_field(ctx, 32, &ip)
373         || !action_force_match(ctx, LEX_T_RPAREN)) {
374         return;
375     }
376
377     const struct arg args[] = {
378         { &port, MFF_LOG_OUTPORT },
379         { &ip, MFF_REG0 },
380     };
381     setup_args(ctx, args, ARRAY_SIZE(args));
382
383     put_load(0, MFF_ETH_DST, 0, 48, ctx->ofpacts);
384     emit_resubmit(ctx, ctx->ap->arp_ptable);
385
386     restore_args(ctx, args, ARRAY_SIZE(args));
387 }
388
389 static void
390 parse_put_arp_action(struct action_context *ctx)
391 {
392     struct mf_subfield port, ip, mac;
393
394     if (!action_force_match(ctx, LEX_T_LPAREN)
395         || !action_parse_field(ctx, 0, &port)
396         || !action_force_match(ctx, LEX_T_COMMA)
397         || !action_parse_field(ctx, 32, &ip)
398         || !action_force_match(ctx, LEX_T_COMMA)
399         || !action_parse_field(ctx, 48, &mac)
400         || !action_force_match(ctx, LEX_T_RPAREN)) {
401         return;
402     }
403
404     const struct arg args[] = {
405         { &port, MFF_LOG_INPORT },
406         { &ip, MFF_REG0 },
407         { &mac, MFF_ETH_SRC }
408     };
409     setup_args(ctx, args, ARRAY_SIZE(args));
410     put_controller_op(ctx->ofpacts, ACTION_OPCODE_PUT_ARP);
411     restore_args(ctx, args, ARRAY_SIZE(args));
412 }
413
414 static void
415 emit_ct(struct action_context *ctx, bool recirc_next, bool commit)
416 {
417     struct ofpact_conntrack *ct = ofpact_put_CT(ctx->ofpacts);
418     ct->flags |= commit ? NX_CT_F_COMMIT : 0;
419
420     /* If "recirc" is set, we automatically go to the next table. */
421     if (recirc_next) {
422         if (ctx->ap->cur_ltable < ctx->ap->n_tables) {
423             ct->recirc_table = ctx->ap->first_ptable + ctx->ap->cur_ltable + 1;
424         } else {
425             action_error(ctx, "\"ct_next\" action not allowed in last table.");
426             return;
427         }
428     } else {
429         ct->recirc_table = NX_CT_RECIRC_NONE;
430     }
431
432     ct->zone_src.field = mf_from_id(MFF_LOG_CT_ZONE);
433     ct->zone_src.ofs = 0;
434     ct->zone_src.n_bits = 16;
435
436     /* We do not support ALGs yet. */
437     ct->alg = 0;
438
439     /* CT only works with IP, so set up a prerequisite. */
440     add_prerequisite(ctx, "ip");
441 }
442
443 static bool
444 parse_action(struct action_context *ctx)
445 {
446     if (ctx->lexer->token.type != LEX_T_ID) {
447         action_syntax_error(ctx, NULL);
448         return false;
449     }
450
451     enum lex_type lookahead = lexer_lookahead(ctx->lexer);
452     if (lookahead == LEX_T_EQUALS || lookahead == LEX_T_EXCHANGE
453         || lookahead == LEX_T_LSQUARE) {
454         parse_set_action(ctx);
455     } else if (lexer_match_id(ctx->lexer, "next")) {
456         parse_next_action(ctx);
457     } else if (lexer_match_id(ctx->lexer, "output")) {
458         emit_resubmit(ctx, ctx->ap->output_ptable);
459     } else if (lexer_match_id(ctx->lexer, "ip.ttl")) {
460         if (lexer_match(ctx->lexer, LEX_T_DECREMENT)) {
461             add_prerequisite(ctx, "ip");
462             ofpact_put_DEC_TTL(ctx->ofpacts);
463         } else {
464             action_syntax_error(ctx, "expecting `--'");
465         }
466     } else if (lexer_match_id(ctx->lexer, "ct_next")) {
467         emit_ct(ctx, true, false);
468     } else if (lexer_match_id(ctx->lexer, "ct_commit")) {
469         emit_ct(ctx, false, true);
470     } else if (lexer_match_id(ctx->lexer, "arp")) {
471         parse_arp_action(ctx);
472     } else if (lexer_match_id(ctx->lexer, "get_arp")) {
473         parse_get_arp_action(ctx);
474     } else if (lexer_match_id(ctx->lexer, "put_arp")) {
475         parse_put_arp_action(ctx);
476     } else {
477         action_syntax_error(ctx, "expecting action");
478     }
479     if (!lexer_match(ctx->lexer, LEX_T_SEMICOLON)) {
480         action_syntax_error(ctx, "expecting ';'");
481     }
482     return !ctx->error;
483 }
484
485 static void
486 parse_actions(struct action_context *ctx)
487 {
488     /* "drop;" by itself is a valid (empty) set of actions, but it can't be
489      * combined with other actions because that doesn't make sense. */
490     if (ctx->lexer->token.type == LEX_T_ID
491         && !strcmp(ctx->lexer->token.s, "drop")
492         && lexer_lookahead(ctx->lexer) == LEX_T_SEMICOLON) {
493         lexer_get(ctx->lexer);  /* Skip "drop". */
494         lexer_get(ctx->lexer);  /* Skip ";". */
495         if (ctx->lexer->token.type != LEX_T_END) {
496             action_syntax_error(ctx, "expecting end of input");
497         }
498         return;
499     }
500
501     while (ctx->lexer->token.type != LEX_T_END) {
502         if (!parse_action(ctx)) {
503             return;
504         }
505     }
506 }
507
508 /* Parses OVN actions, in the format described for the "actions" column in the
509  * Logical_Flow table in ovn-sb(5), and appends the parsed versions of the
510  * actions to 'ofpacts' as "struct ofpact"s.
511  *
512  * 'ap' provides most of the parameters for translation.
513  *
514  * Some actions add extra requirements (prerequisites) to the flow's match.  If
515  * so, this function sets '*prereqsp' to the actions' prerequisites; otherwise,
516  * it sets '*prereqsp' to NULL.  The caller owns '*prereqsp' and must
517  * eventually free it.
518  *
519  * Returns NULL on success, otherwise a malloc()'d error message that the
520  * caller must free.  On failure, 'ofpacts' has the same contents and
521  * '*prereqsp' is set to NULL, but some tokens may have been consumed from
522  * 'lexer'.
523   */
524 char * OVS_WARN_UNUSED_RESULT
525 actions_parse(struct lexer *lexer, const struct action_params *ap,
526               struct ofpbuf *ofpacts, struct expr **prereqsp)
527 {
528     size_t ofpacts_start = ofpacts->size;
529
530     struct action_context ctx = {
531         .ap = ap,
532         .lexer = lexer,
533         .error = NULL,
534         .ofpacts = ofpacts,
535         .prereqs = NULL,
536     };
537     parse_actions(&ctx);
538
539     if (!ctx.error) {
540         *prereqsp = ctx.prereqs;
541         return NULL;
542     } else {
543         ofpacts->size = ofpacts_start;
544         expr_destroy(ctx.prereqs);
545         *prereqsp = NULL;
546         return ctx.error;
547     }
548 }
549
550 /* Like actions_parse(), but the actions are taken from 's'. */
551 char * OVS_WARN_UNUSED_RESULT
552 actions_parse_string(const char *s, const struct action_params *ap,
553                      struct ofpbuf *ofpacts, struct expr **prereqsp)
554 {
555     struct lexer lexer;
556     char *error;
557
558     lexer_init(&lexer, s);
559     lexer_get(&lexer);
560     error = actions_parse(&lexer, ap, ofpacts, prereqsp);
561     lexer_destroy(&lexer);
562
563     return error;
564 }