2 * Copyright (c) 2015, 2016 Nicira, Inc.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include "openvswitch/dynamic-string.h"
25 #include "logical-fields.h"
26 #include "ofp-actions.h"
27 #include "openvswitch/ofpbuf.h"
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. */
39 static bool parse_action(struct action_context *);
42 action_error_handle_common(struct action_context *ctx)
45 /* Already have an error, suppress this one since the cascade seems
46 * unlikely to be useful. */
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);
59 static void OVS_PRINTF_FORMAT(2, 3)
60 action_error(struct action_context *ctx, const char *message, ...)
62 if (action_error_handle_common(ctx)) {
67 va_start(args, message);
68 ctx->error = xvasprintf(message, args);
72 static void OVS_PRINTF_FORMAT(2, 3)
73 action_syntax_error(struct action_context *ctx, const char *message, ...)
75 if (action_error_handle_common(ctx)) {
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),
95 va_start(args, message);
96 ds_put_format_valist(&s, message, args);
101 ctx->error = ds_steal_cstr(&s);
104 /* Parses an assignment or exchange action. */
106 parse_set_action(struct action_context *ctx)
108 struct expr *prereqs;
111 error = expr_parse_assignment(ctx->lexer, ctx->ap->symtab,
112 ctx->ap->lookup_port, ctx->ap->aux,
113 ctx->ofpacts, &prereqs);
115 action_error(ctx, "%s", error);
120 ctx->prereqs = expr_combine(EXPR_T_AND, ctx->prereqs, prereqs);
124 emit_resubmit(struct action_context *ctx, uint8_t table_id)
126 struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(ctx->ofpacts);
127 resubmit->in_port = OFPP_IN_PORT;
128 resubmit->table_id = table_id;
132 action_get_int(struct action_context *ctx, int *value)
134 bool ok = lexer_get_int(ctx->lexer, value);
136 action_syntax_error(ctx, "expecting small integer");
142 parse_next_action(struct action_context *ctx)
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)) {
149 if (!action_get_int(ctx, <able)) {
152 if (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
153 action_syntax_error(ctx, "expecting `)'");
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);
163 emit_resubmit(ctx, ctx->ap->first_ptable + ltable);
165 if (ctx->ap->cur_ltable < ctx->ap->n_tables) {
167 ctx->ap->first_ptable + ctx->ap->cur_ltable + 1);
169 action_error(ctx, "\"next\" action not allowed in last table.");
174 /* Parses 'prerequisite' as an expression in the context of 'ctx', then adds it
175 * as a conjunction with the existing 'ctx->prereqs'. */
177 add_prerequisite(struct action_context *ctx, const char *prerequisite)
182 expr = expr_parse_string(prerequisite, ctx->ap->symtab, &error);
184 ctx->prereqs = expr_combine(EXPR_T_AND, ctx->prereqs, expr);
188 start_controller_op(struct ofpbuf *ofpacts, enum action_opcode opcode)
190 size_t ofs = ofpacts->size;
192 struct ofpact_controller *oc = ofpact_put_CONTROLLER(ofpacts);
193 oc->max_len = UINT16_MAX;
194 oc->reason = OFPR_ACTION;
196 struct action_header ah = { .opcode = htonl(opcode) };
197 ofpbuf_put(ofpacts, &ah, sizeof ah);
203 finish_controller_op(struct ofpbuf *ofpacts, size_t ofs)
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);
212 put_controller_op(struct ofpbuf *ofpacts, enum action_opcode opcode)
214 size_t ofs = start_controller_op(ofpacts, opcode);
215 finish_controller_op(ofpacts, ofs);
219 parse_arp_action(struct action_context *ctx)
221 if (!lexer_match(ctx->lexer, LEX_T_LCURLY)) {
222 action_syntax_error(ctx, "expecting `{'");
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;
231 /* Save prerequisites. (XXX What is the right treatment for prereqs?) */
232 struct expr *outer_prereqs = ctx->prereqs;
235 /* Parse inner actions. */
236 while (!lexer_match(ctx->lexer, LEX_T_RCURLY)) {
237 if (!parse_action(ctx)) {
242 ctx->ofpacts = outer_ofpacts;
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);
253 /* Restore prerequisites. */
254 expr_destroy(ctx->prereqs);
255 ctx->prereqs = outer_prereqs;
256 add_prerequisite(ctx, "ip4");
259 ofpbuf_uninit(&inner_ofpacts);
263 action_force_match(struct action_context *ctx, enum lex_type t)
265 if (lexer_match(ctx->lexer, t)) {
268 struct lex_token token = { .type = t };
269 struct ds s = DS_EMPTY_INITIALIZER;
270 lex_token_format(&token, &s);
272 action_syntax_error(ctx, "expecting `%s'", ds_cstr(&s));
281 action_parse_field(struct action_context *ctx,
282 int n_bits, struct mf_subfield *sf)
284 struct expr *prereqs;
287 error = expr_parse_field(ctx->lexer, n_bits, false, ctx->ap->symtab, sf,
290 action_error(ctx, "%s", error);
294 ctx->prereqs = expr_combine(EXPR_T_AND, ctx->prereqs, prereqs);
299 init_stack(struct ofpact_stack *stack, enum mf_field_id field)
301 stack->subfield.field = mf_from_id(field);
302 stack->subfield.ofs = 0;
303 stack->subfield.n_bits = stack->subfield.field->n_bits;
307 const struct mf_subfield *src;
308 enum mf_field_id dst;
312 setup_args(struct action_context *ctx,
313 const struct arg args[], size_t n_args)
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);
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;
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);
340 restore_args(struct action_context *ctx,
341 const struct arg args[], size_t n_args)
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);
352 put_load(uint64_t value, enum mf_field_id dst, int ofs, int n_bits,
353 struct ofpbuf *ofpacts)
355 struct ofpact_set_field *sf = ofpact_put_SET_FIELD(ofpacts);
356 sf->field = mf_from_id(dst);
357 sf->flow_has_vlan = false;
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);
365 parse_get_arp_action(struct action_context *ctx)
367 struct mf_subfield port, ip;
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)) {
377 const struct arg args[] = {
378 { &port, MFF_LOG_OUTPORT },
381 setup_args(ctx, args, ARRAY_SIZE(args));
383 put_load(0, MFF_ETH_DST, 0, 48, ctx->ofpacts);
384 emit_resubmit(ctx, ctx->ap->arp_ptable);
386 restore_args(ctx, args, ARRAY_SIZE(args));
390 parse_put_arp_action(struct action_context *ctx)
392 struct mf_subfield port, ip, mac;
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)) {
404 const struct arg args[] = {
405 { &port, MFF_LOG_INPORT },
407 { &mac, MFF_ETH_SRC }
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));
415 emit_ct(struct action_context *ctx, bool recirc_next, bool commit)
417 struct ofpact_conntrack *ct = ofpact_put_CT(ctx->ofpacts);
418 ct->flags |= commit ? NX_CT_F_COMMIT : 0;
420 /* If "recirc" is set, we automatically go to the next table. */
422 if (ctx->ap->cur_ltable < ctx->ap->n_tables) {
423 ct->recirc_table = ctx->ap->first_ptable + ctx->ap->cur_ltable + 1;
425 action_error(ctx, "\"ct_next\" action not allowed in last table.");
429 ct->recirc_table = NX_CT_RECIRC_NONE;
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;
436 /* We do not support ALGs yet. */
439 /* CT only works with IP, so set up a prerequisite. */
440 add_prerequisite(ctx, "ip");
444 parse_action(struct action_context *ctx)
446 if (ctx->lexer->token.type != LEX_T_ID) {
447 action_syntax_error(ctx, NULL);
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);
464 action_syntax_error(ctx, "expecting `--'");
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);
477 action_syntax_error(ctx, "expecting action");
479 if (!lexer_match(ctx->lexer, LEX_T_SEMICOLON)) {
480 action_syntax_error(ctx, "expecting ';'");
486 parse_actions(struct action_context *ctx)
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");
501 while (ctx->lexer->token.type != LEX_T_END) {
502 if (!parse_action(ctx)) {
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.
512 * 'ap' provides most of the parameters for translation.
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.
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
524 char * OVS_WARN_UNUSED_RESULT
525 actions_parse(struct lexer *lexer, const struct action_params *ap,
526 struct ofpbuf *ofpacts, struct expr **prereqsp)
528 size_t ofpacts_start = ofpacts->size;
530 struct action_context ctx = {
540 *prereqsp = ctx.prereqs;
543 ofpacts->size = ofpacts_start;
544 expr_destroy(ctx.prereqs);
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)
558 lexer_init(&lexer, s);
560 error = actions_parse(&lexer, ap, ofpacts, prereqsp);
561 lexer_destroy(&lexer);