]> git.proxmox.com Git - mirror_ovs.git/blame - ovn/lib/actions.c
OVN: add icmp6{} action support
[mirror_ovs.git] / ovn / lib / actions.c
CommitLineData
3b7cb7e1 1/*
80b6743d 2 * Copyright (c) 2015, 2016, 2017 Nicira, Inc.
3b7cb7e1
BP
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>
3b7cb7e1
BP
18#include <stdarg.h>
19#include <stdbool.h>
467085fd 20#include "bitmap.h"
f4248336 21#include "byte-order.h"
3b7cb7e1 22#include "compiler.h"
16936e4d 23#include "ovn-l7.h"
467085fd 24#include "hash.h"
52ed5fcc 25#include "lib/packets.h"
667e2b0b 26#include "logical-fields.h"
42814145 27#include "nx-match.h"
b598f214 28#include "openvswitch/dynamic-string.h"
d5a76da4
BP
29#include "openvswitch/hmap.h"
30#include "openvswitch/json.h"
b598f214 31#include "openvswitch/ofp-actions.h"
64c96779 32#include "openvswitch/ofpbuf.h"
d5a76da4 33#include "openvswitch/vlog.h"
8b2ed684
AR
34#include "ovn/actions.h"
35#include "ovn/expr.h"
36#include "ovn/lex.h"
d383eed5 37#include "ovn/lib/acl-log.h"
ad35c0c5 38#include "ovn/lib/extend-table.h"
42814145 39#include "packets.h"
ee89ea7b 40#include "openvswitch/shash.h"
78aab811 41#include "simap.h"
3b7cb7e1 42
d5a76da4
BP
43VLOG_DEFINE_THIS_MODULE(actions);
44\f
45/* Prototypes for functions to be defined by each action. */
46#define OVNACT(ENUM, STRUCT) \
47 static void format_##ENUM(const struct STRUCT *, struct ds *); \
48 static void encode_##ENUM(const struct STRUCT *, \
49 const struct ovnact_encode_params *, \
50 struct ofpbuf *ofpacts); \
80b6743d 51 static void STRUCT##_free(struct STRUCT *a);
d5a76da4
BP
52OVNACTS
53#undef OVNACT
54\f
55/* Helpers. */
56
57/* Implementation of ovnact_put_<ENUM>(). */
58void *
59ovnact_put(struct ofpbuf *ovnacts, enum ovnact_type type, size_t len)
60{
8a41ad8e 61 ovs_assert(len == OVNACT_ALIGN(len));
d5a76da4
BP
62
63 ovnacts->header = ofpbuf_put_uninit(ovnacts, len);
8a41ad8e 64 struct ovnact *ovnact = ovnacts->header;
d5a76da4
BP
65 ovnact_init(ovnact, type, len);
66 return ovnact;
67}
68
69/* Implementation of ovnact_init_<ENUM>(). */
70void
71ovnact_init(struct ovnact *ovnact, enum ovnact_type type, size_t len)
72{
8a41ad8e 73 ovs_assert(len == OVNACT_ALIGN(len));
d5a76da4
BP
74 memset(ovnact, 0, len);
75 ovnact->type = type;
76 ovnact->len = len;
77}
78
79static size_t
80encode_start_controller_op(enum action_opcode opcode, bool pause,
81 struct ofpbuf *ofpacts)
82{
83 size_t ofs = ofpacts->size;
84
85 struct ofpact_controller *oc = ofpact_put_CONTROLLER(ofpacts);
86 oc->max_len = UINT16_MAX;
87 oc->reason = OFPR_ACTION;
88 oc->pause = pause;
89
90 struct action_header ah = { .opcode = htonl(opcode) };
91 ofpbuf_put(ofpacts, &ah, sizeof ah);
92
93 return ofs;
94}
95
96static void
97encode_finish_controller_op(size_t ofs, struct ofpbuf *ofpacts)
98{
99 struct ofpact_controller *oc = ofpbuf_at_assert(ofpacts, ofs, sizeof *oc);
100 ofpacts->header = oc;
101 oc->userdata_len = ofpacts->size - (ofs + sizeof *oc);
102 ofpact_finish_CONTROLLER(ofpacts, &oc);
103}
104
105static void
106encode_controller_op(enum action_opcode opcode, struct ofpbuf *ofpacts)
107{
108 size_t ofs = encode_start_controller_op(opcode, false, ofpacts);
109 encode_finish_controller_op(ofs, ofpacts);
110}
111
112static void
113init_stack(struct ofpact_stack *stack, enum mf_field_id field)
114{
115 stack->subfield.field = mf_from_id(field);
116 stack->subfield.ofs = 0;
117 stack->subfield.n_bits = stack->subfield.field->n_bits;
118}
119
120struct arg {
121 const struct mf_subfield src;
122 enum mf_field_id dst;
123};
124
125static void
126encode_setup_args(const struct arg args[], size_t n_args,
127 struct ofpbuf *ofpacts)
128{
129 /* 1. Save all of the destinations that will be modified. */
130 for (const struct arg *a = args; a < &args[n_args]; a++) {
131 ovs_assert(a->src.n_bits == mf_from_id(a->dst)->n_bits);
132 if (a->src.field->id != a->dst) {
133 init_stack(ofpact_put_STACK_PUSH(ofpacts), a->dst);
134 }
135 }
136
137 /* 2. Push the sources, in reverse order. */
138 for (size_t i = n_args - 1; i < n_args; i--) {
139 const struct arg *a = &args[i];
140 if (a->src.field->id != a->dst) {
141 ofpact_put_STACK_PUSH(ofpacts)->subfield = a->src;
142 }
143 }
144
145 /* 3. Pop the sources into the destinations. */
146 for (const struct arg *a = args; a < &args[n_args]; a++) {
147 if (a->src.field->id != a->dst) {
148 init_stack(ofpact_put_STACK_POP(ofpacts), a->dst);
149 }
150 }
151}
152
153static void
154encode_restore_args(const struct arg args[], size_t n_args,
155 struct ofpbuf *ofpacts)
156{
157 for (size_t i = n_args - 1; i < n_args; i--) {
158 const struct arg *a = &args[i];
159 if (a->src.field->id != a->dst) {
160 init_stack(ofpact_put_STACK_POP(ofpacts), a->dst);
161 }
162 }
163}
164
165static void
166put_load(uint64_t value, enum mf_field_id dst, int ofs, int n_bits,
167 struct ofpbuf *ofpacts)
168{
128684a6
JR
169 struct ofpact_set_field *sf = ofpact_put_set_field(ofpacts,
170 mf_from_id(dst), NULL,
171 NULL);
d5a76da4 172 ovs_be64 n_value = htonll(value);
128684a6
JR
173 bitwise_copy(&n_value, 8, 0, sf->value, sf->field->n_bytes, ofs, n_bits);
174 bitwise_one(ofpact_set_field_mask(sf), sf->field->n_bytes, ofs, n_bits);
d5a76da4 175}
4c99cb18
BP
176
177static uint8_t
178first_ptable(const struct ovnact_encode_params *ep,
179 enum ovnact_pipeline pipeline)
180{
181 return (pipeline == OVNACT_P_INGRESS
182 ? ep->ingress_ptable
183 : ep->egress_ptable);
184}
d5a76da4
BP
185\f
186/* Context maintained during ovnacts_parse(). */
3b7cb7e1 187struct action_context {
d5a76da4 188 const struct ovnact_parse_params *pp; /* Parameters. */
3b7cb7e1 189 struct lexer *lexer; /* Lexer for pulling more tokens. */
d5a76da4 190 struct ofpbuf *ovnacts; /* Actions. */
3b7cb7e1
BP
191 struct expr *prereqs; /* Prerequisites to apply to match. */
192};
193
bac29564 194static void parse_actions(struct action_context *, enum lex_type sentinel);
d8681a83 195
3b7cb7e1 196static bool
9aef3c1b
BP
197action_parse_field(struct action_context *ctx,
198 int n_bits, bool rw, struct expr_field *f)
3b7cb7e1 199{
9aef3c1b 200 if (!expr_field_parse(ctx->lexer, ctx->pp->symtab, f, &ctx->prereqs)) {
3b7cb7e1
BP
201 return false;
202 }
d5a76da4 203
9aef3c1b
BP
204 char *error = expr_type_check(f, n_bits, rw);
205 if (error) {
206 lexer_error(ctx->lexer, "%s", error);
207 free(error);
d5a76da4 208 return false;
3b7cb7e1 209 }
3b7cb7e1 210
9aef3c1b 211 return true;
558ec83d
BP
212}
213
d5a76da4
BP
214static bool
215action_parse_port(struct action_context *ctx, uint16_t *port)
216{
217 if (lexer_is_int(ctx->lexer)) {
218 int value = ntohll(ctx->lexer->token.value.integer);
219 if (value <= UINT16_MAX) {
220 *port = value;
221 lexer_get(ctx->lexer);
222 return true;
223 }
224 }
9aef3c1b 225 lexer_syntax_error(ctx->lexer, "expecting port number");
d5a76da4
BP
226 return false;
227}
228
229/* Parses 'prerequisite' as an expression in the context of 'ctx', then adds it
230 * as a conjunction with the existing 'ctx->prereqs'. */
231static void
232add_prerequisite(struct action_context *ctx, const char *prerequisite)
233{
234 struct expr *expr;
235 char *error;
236
237 expr = expr_parse_string(prerequisite, ctx->pp->symtab, NULL, &error);
238 ovs_assert(!error);
239 ctx->prereqs = expr_combine(EXPR_T_AND, ctx->prereqs, expr);
240}
80b6743d
BP
241
242static void
243ovnact_null_free(struct ovnact_null *a OVS_UNUSED)
244{
245}
d5a76da4
BP
246\f
247static void
248format_OUTPUT(const struct ovnact_null *a OVS_UNUSED, struct ds *s)
249{
250 ds_put_cstr(s, "output;");
251}
252
253static void
254emit_resubmit(struct ofpbuf *ofpacts, uint8_t ptable)
255{
256 struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(ofpacts);
257 resubmit->in_port = OFPP_IN_PORT;
258 resubmit->table_id = ptable;
259}
260
261static void
262encode_OUTPUT(const struct ovnact_null *a OVS_UNUSED,
263 const struct ovnact_encode_params *ep,
264 struct ofpbuf *ofpacts)
265{
266 emit_resubmit(ofpacts, ep->output_ptable);
267}
d5a76da4 268\f
558ec83d 269static void
d5a76da4 270parse_NEXT(struct action_context *ctx)
558ec83d 271{
d5a76da4 272 if (!ctx->pp->n_tables) {
9aef3c1b 273 lexer_error(ctx->lexer, "\"next\" action not allowed here.");
8f5de083
BP
274 return;
275 }
558ec83d 276
4c99cb18 277 int pipeline = ctx->pp->pipeline;
8f5de083 278 int table = ctx->pp->cur_ltable + 1;
4c99cb18
BP
279 if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {
280 if (lexer_is_int(ctx->lexer)) {
281 lexer_get_int(ctx->lexer, &table);
282 } else {
283 do {
284 if (lexer_match_id(ctx->lexer, "pipeline")) {
285 if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) {
286 return;
287 }
288 if (lexer_match_id(ctx->lexer, "ingress")) {
289 pipeline = OVNACT_P_INGRESS;
290 } else if (lexer_match_id(ctx->lexer, "egress")) {
291 pipeline = OVNACT_P_EGRESS;
292 } else {
293 lexer_syntax_error(
294 ctx->lexer, "expecting \"ingress\" or \"egress\"");
295 return;
296 }
297 } else if (lexer_match_id(ctx->lexer, "table")) {
298 if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS) ||
299 !lexer_force_int(ctx->lexer, &table)) {
300 return;
301 }
302 } else {
303 lexer_syntax_error(ctx->lexer,
304 "expecting \"pipeline\" or \"table\"");
305 return;
306 }
307 } while (lexer_match(ctx->lexer, LEX_T_COMMA));
308 }
309 if (!lexer_force_match(ctx->lexer, LEX_T_RPAREN)) {
310 return;
311 }
8f5de083 312 }
558ec83d 313
4c99cb18
BP
314 if (pipeline == OVNACT_P_EGRESS && ctx->pp->pipeline == OVNACT_P_INGRESS) {
315 lexer_error(ctx->lexer,
316 "\"next\" action cannot advance from ingress to egress "
317 "pipeline (use \"output\" action instead)");
318 } else if (table >= ctx->pp->n_tables) {
8f5de083
BP
319 lexer_error(ctx->lexer,
320 "\"next\" action cannot advance beyond table %d.",
321 ctx->pp->n_tables - 1);
322 return;
558ec83d 323 }
8f5de083
BP
324
325 struct ovnact_next *next = ovnact_put_NEXT(ctx->ovnacts);
4c99cb18 326 next->pipeline = pipeline;
8f5de083 327 next->ltable = table;
4c99cb18 328 next->src_pipeline = ctx->pp->pipeline;
8f5de083 329 next->src_ltable = ctx->pp->cur_ltable;
558ec83d
BP
330}
331
5b84185b 332static void
d5a76da4 333format_NEXT(const struct ovnact_next *next, struct ds *s)
5b84185b 334{
4c99cb18
BP
335 if (next->pipeline != next->src_pipeline) {
336 ds_put_format(s, "next(pipeline=%s, table=%d);",
337 (next->pipeline == OVNACT_P_INGRESS
338 ? "ingress" : "egress"),
339 next->ltable);
340 } else if (next->ltable != next->src_ltable + 1) {
8f5de083
BP
341 ds_put_format(s, "next(%d);", next->ltable);
342 } else {
343 ds_put_cstr(s, "next;");
344 }
d5a76da4 345}
5b84185b 346
d5a76da4
BP
347static void
348encode_NEXT(const struct ovnact_next *next,
349 const struct ovnact_encode_params *ep,
350 struct ofpbuf *ofpacts)
351{
4c99cb18 352 emit_resubmit(ofpacts, first_ptable(ep, next->pipeline) + next->ltable);
5b84185b
BP
353}
354
d5a76da4 355static void
80b6743d 356ovnact_next_free(struct ovnact_next *a OVS_UNUSED)
0bac7164 357{
d5a76da4
BP
358}
359\f
360static void
361parse_LOAD(struct action_context *ctx, const struct expr_field *lhs)
362{
363 size_t ofs = ctx->ovnacts->size;
364 struct ovnact_load *load = ovnact_put_LOAD(ctx->ovnacts);
365 load->dst = *lhs;
9aef3c1b 366
d5a76da4 367 char *error = expr_type_check(lhs, lhs->n_bits, true);
d5a76da4
BP
368 if (error) {
369 ctx->ovnacts->size = ofs;
9aef3c1b 370 lexer_error(ctx->lexer, "%s", error);
d5a76da4 371 free(error);
9aef3c1b
BP
372 return;
373 }
374 if (!expr_constant_parse(ctx->lexer, lhs, &load->imm)) {
375 ctx->ovnacts->size = ofs;
376 return;
d5a76da4
BP
377 }
378}
0bac7164 379
d5a76da4
BP
380static enum expr_constant_type
381load_type(const struct ovnact_load *load)
382{
383 return load->dst.symbol->width > 0 ? EXPR_C_INTEGER : EXPR_C_STRING;
384}
0bac7164 385
d5a76da4
BP
386static void
387format_LOAD(const struct ovnact_load *load, struct ds *s)
388{
389 expr_field_format(&load->dst, s);
390 ds_put_cstr(s, " = ");
391 expr_constant_format(&load->imm, load_type(load), s);
392 ds_put_char(s, ';');
393}
0bac7164 394
128684a6
JR
395static void
396encode_LOAD(const struct ovnact_load *load,
397 const struct ovnact_encode_params *ep,
398 struct ofpbuf *ofpacts)
d5a76da4
BP
399{
400 const union expr_constant *c = &load->imm;
401 struct mf_subfield dst = expr_resolve_field(&load->dst);
128684a6
JR
402 struct ofpact_set_field *sf = ofpact_put_set_field(ofpacts, dst.field,
403 NULL, NULL);
d5a76da4
BP
404
405 if (load->dst.symbol->width) {
406 bitwise_copy(&c->value, sizeof c->value, 0,
128684a6 407 sf->value, dst.field->n_bytes, dst.ofs,
d5a76da4
BP
408 dst.n_bits);
409 if (c->masked) {
410 bitwise_copy(&c->mask, sizeof c->mask, 0,
128684a6
JR
411 ofpact_set_field_mask(sf), dst.field->n_bytes,
412 dst.ofs, dst.n_bits);
d5a76da4 413 } else {
128684a6 414 bitwise_one(ofpact_set_field_mask(sf), dst.field->n_bytes,
d5a76da4
BP
415 dst.ofs, dst.n_bits);
416 }
417 } else {
418 uint32_t port;
128684a6 419 if (!ep->lookup_port(ep->aux, load->imm.string, &port)) {
d5a76da4
BP
420 port = 0;
421 }
128684a6 422 bitwise_put(port, sf->value,
d5a76da4 423 sf->field->n_bytes, 0, sf->field->n_bits);
128684a6
JR
424 bitwise_one(ofpact_set_field_mask(sf), sf->field->n_bytes, 0,
425 sf->field->n_bits);
d5a76da4 426 }
0bac7164
BP
427}
428
429static void
80b6743d 430ovnact_load_free(struct ovnact_load *load)
0bac7164 431{
d5a76da4
BP
432 expr_constant_destroy(&load->imm, load_type(load));
433}
434\f
435static void
436format_assignment(const struct ovnact_move *move, const char *operator,
437 struct ds *s)
438{
439 expr_field_format(&move->lhs, s);
440 ds_put_format(s, " %s ", operator);
441 expr_field_format(&move->rhs, s);
442 ds_put_char(s, ';');
0bac7164
BP
443}
444
445static void
d5a76da4 446format_MOVE(const struct ovnact_move *move, struct ds *s)
0bac7164 447{
d5a76da4 448 format_assignment(move, "=", s);
0bac7164
BP
449}
450
6335d074 451static void
d5a76da4
BP
452format_EXCHANGE(const struct ovnact_move *move, struct ds *s)
453{
454 format_assignment(move, "<->", s);
455}
456
457static void
458parse_assignment_action(struct action_context *ctx, bool exchange,
459 const struct expr_field *lhs)
6335d074 460{
d5a76da4 461 struct expr_field rhs;
9aef3c1b 462 if (!expr_field_parse(ctx->lexer, ctx->pp->symtab, &rhs, &ctx->prereqs)) {
6335d074
BP
463 return;
464 }
465
d5a76da4
BP
466 const struct expr_symbol *ls = lhs->symbol;
467 const struct expr_symbol *rs = rhs.symbol;
468 if ((ls->width != 0) != (rs->width != 0)) {
469 if (exchange) {
9aef3c1b
BP
470 lexer_error(ctx->lexer,
471 "Can't exchange %s field (%s) with %s field (%s).",
472 ls->width ? "integer" : "string",
473 ls->name,
474 rs->width ? "integer" : "string",
475 rs->name);
d5a76da4 476 } else {
9aef3c1b
BP
477 lexer_error(ctx->lexer,
478 "Can't assign %s field (%s) to %s field (%s).",
479 rs->width ? "integer" : "string",
480 rs->name,
481 ls->width ? "integer" : "string",
482 ls->name);
d5a76da4
BP
483 }
484 return;
485 }
6335d074 486
d5a76da4
BP
487 if (lhs->n_bits != rhs.n_bits) {
488 if (exchange) {
9aef3c1b
BP
489 lexer_error(ctx->lexer,
490 "Can't exchange %d-bit field with %d-bit field.",
491 lhs->n_bits, rhs.n_bits);
d5a76da4 492 } else {
9aef3c1b
BP
493 lexer_error(ctx->lexer,
494 "Can't assign %d-bit value to %d-bit destination.",
495 rhs.n_bits, lhs->n_bits);
6335d074 496 }
d5a76da4
BP
497 return;
498 } else if (!lhs->n_bits &&
499 ls->field->n_bits != rs->field->n_bits) {
9aef3c1b
BP
500 lexer_error(ctx->lexer, "String fields %s and %s are incompatible for "
501 "%s.", ls->name, rs->name,
502 exchange ? "exchange" : "assignment");
d5a76da4 503 return;
6335d074
BP
504 }
505
9aef3c1b 506 char *error = expr_type_check(lhs, lhs->n_bits, true);
d5a76da4
BP
507 if (!error) {
508 error = expr_type_check(&rhs, rhs.n_bits, true);
509 }
510 if (error) {
9aef3c1b 511 lexer_error(ctx->lexer, "%s", error);
d5a76da4
BP
512 free(error);
513 return;
514 }
6335d074 515
d5a76da4
BP
516 struct ovnact_move *move;
517 move = (exchange
518 ? ovnact_put_EXCHANGE(ctx->ovnacts)
519 : ovnact_put_MOVE(ctx->ovnacts));
520 move->lhs = *lhs;
521 move->rhs = rhs;
522}
6335d074 523
d5a76da4
BP
524static void
525encode_MOVE(const struct ovnact_move *move,
526 const struct ovnact_encode_params *ep OVS_UNUSED,
527 struct ofpbuf *ofpacts)
528{
529 struct ofpact_reg_move *orm = ofpact_put_REG_MOVE(ofpacts);
530 orm->src = expr_resolve_field(&move->rhs);
531 orm->dst = expr_resolve_field(&move->lhs);
6335d074
BP
532}
533
d5a76da4
BP
534static void
535encode_EXCHANGE(const struct ovnact_move *xchg,
536 const struct ovnact_encode_params *ep OVS_UNUSED,
537 struct ofpbuf *ofpacts)
0bac7164 538{
d5a76da4
BP
539 ofpact_put_STACK_PUSH(ofpacts)->subfield = expr_resolve_field(&xchg->rhs);
540 ofpact_put_STACK_PUSH(ofpacts)->subfield = expr_resolve_field(&xchg->lhs);
541 ofpact_put_STACK_POP(ofpacts)->subfield = expr_resolve_field(&xchg->rhs);
542 ofpact_put_STACK_POP(ofpacts)->subfield = expr_resolve_field(&xchg->lhs);
543}
0bac7164 544
d5a76da4 545static void
80b6743d 546ovnact_move_free(struct ovnact_move *move OVS_UNUSED)
d5a76da4
BP
547{
548}
549\f
550static void
551parse_DEC_TTL(struct action_context *ctx)
552{
9aef3c1b 553 lexer_force_match(ctx->lexer, LEX_T_DECREMENT);
d5a76da4
BP
554 ovnact_put_DEC_TTL(ctx->ovnacts);
555 add_prerequisite(ctx, "ip");
556}
0bac7164 557
d5a76da4
BP
558static void
559format_DEC_TTL(const struct ovnact_null *null OVS_UNUSED, struct ds *s)
560{
561 ds_put_cstr(s, "ip.ttl--;");
0bac7164
BP
562}
563
d5a76da4
BP
564static void
565encode_DEC_TTL(const struct ovnact_null *null OVS_UNUSED,
566 const struct ovnact_encode_params *ep OVS_UNUSED,
567 struct ofpbuf *ofpacts)
0bac7164 568{
d5a76da4
BP
569 ofpact_put_DEC_TTL(ofpacts);
570}
d5a76da4
BP
571\f
572static void
573parse_CT_NEXT(struct action_context *ctx)
574{
575 if (ctx->pp->cur_ltable >= ctx->pp->n_tables) {
9aef3c1b
BP
576 lexer_error(ctx->lexer,
577 "\"ct_next\" action not allowed in last table.");
d5a76da4 578 return;
0bac7164
BP
579 }
580
d5a76da4
BP
581 add_prerequisite(ctx, "ip");
582 ovnact_put_CT_NEXT(ctx->ovnacts)->ltable = ctx->pp->cur_ltable + 1;
0bac7164
BP
583}
584
585static void
ebb467ff 586format_CT_NEXT(const struct ovnact_ct_next *ct_next OVS_UNUSED, struct ds *s)
0bac7164 587{
d5a76da4 588 ds_put_cstr(s, "ct_next;");
0bac7164
BP
589}
590
d5a76da4 591static void
ebb467ff 592encode_CT_NEXT(const struct ovnact_ct_next *ct_next,
d5a76da4
BP
593 const struct ovnact_encode_params *ep,
594 struct ofpbuf *ofpacts)
595{
596 struct ofpact_conntrack *ct = ofpact_put_CT(ofpacts);
4c99cb18 597 ct->recirc_table = first_ptable(ep, ep->pipeline) + ct_next->ltable;
d7039b9a
GS
598 ct->zone_src.field = ep->is_switch ? mf_from_id(MFF_LOG_CT_ZONE)
599 : mf_from_id(MFF_LOG_DNAT_ZONE);
d5a76da4
BP
600 ct->zone_src.ofs = 0;
601 ct->zone_src.n_bits = 16;
602 ofpact_finish(ofpacts, &ct->ofpact);
603}
ebb467ff
BP
604
605static void
606ovnact_ct_next_free(struct ovnact_ct_next *a OVS_UNUSED)
607{
608}
d5a76da4
BP
609\f
610static void
611parse_ct_commit_arg(struct action_context *ctx,
612 struct ovnact_ct_commit *cc)
613{
614 if (lexer_match_id(ctx->lexer, "ct_mark")) {
9aef3c1b 615 if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) {
d5a76da4 616 return;
0bac7164 617 }
d5a76da4
BP
618 if (ctx->lexer->token.type == LEX_T_INTEGER) {
619 cc->ct_mark = ntohll(ctx->lexer->token.value.integer);
620 cc->ct_mark_mask = UINT32_MAX;
621 } else if (ctx->lexer->token.type == LEX_T_MASKED_INTEGER) {
622 cc->ct_mark = ntohll(ctx->lexer->token.value.integer);
623 cc->ct_mark_mask = ntohll(ctx->lexer->token.mask.integer);
624 } else {
9aef3c1b 625 lexer_syntax_error(ctx->lexer, "expecting integer");
d5a76da4 626 return;
0bac7164 627 }
d5a76da4
BP
628 lexer_get(ctx->lexer);
629 } else if (lexer_match_id(ctx->lexer, "ct_label")) {
9aef3c1b 630 if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) {
d5a76da4 631 return;
0bac7164 632 }
d5a76da4
BP
633 if (ctx->lexer->token.type == LEX_T_INTEGER) {
634 cc->ct_label = ctx->lexer->token.value.be128_int;
635 cc->ct_label_mask = OVS_BE128_MAX;
636 } else if (ctx->lexer->token.type == LEX_T_MASKED_INTEGER) {
637 cc->ct_label = ctx->lexer->token.value.be128_int;
638 cc->ct_label_mask = ctx->lexer->token.mask.be128_int;
639 } else {
9aef3c1b 640 lexer_syntax_error(ctx->lexer, "expecting integer");
d5a76da4
BP
641 return;
642 }
643 lexer_get(ctx->lexer);
644 } else {
9aef3c1b 645 lexer_syntax_error(ctx->lexer, NULL);
0bac7164
BP
646 }
647}
648
649static void
d5a76da4 650parse_CT_COMMIT(struct action_context *ctx)
0bac7164 651{
d5a76da4
BP
652 add_prerequisite(ctx, "ip");
653
654 struct ovnact_ct_commit *ct_commit = ovnact_put_CT_COMMIT(ctx->ovnacts);
655 if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {
656 while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
657 parse_ct_commit_arg(ctx, ct_commit);
9aef3c1b 658 if (ctx->lexer->error) {
d5a76da4
BP
659 return;
660 }
661 lexer_match(ctx->lexer, LEX_T_COMMA);
0bac7164
BP
662 }
663 }
664}
665
666static void
d5a76da4 667format_CT_COMMIT(const struct ovnact_ct_commit *cc, struct ds *s)
0bac7164 668{
d5a76da4
BP
669 ds_put_cstr(s, "ct_commit(");
670 if (cc->ct_mark_mask) {
671 ds_put_format(s, "ct_mark=%#"PRIx32, cc->ct_mark);
672 if (cc->ct_mark_mask != UINT32_MAX) {
673 ds_put_format(s, "/%#"PRIx32, cc->ct_mark_mask);
674 }
675 }
676 if (!ovs_be128_is_zero(cc->ct_label_mask)) {
677 if (ds_last(s) != '(') {
678 ds_put_cstr(s, ", ");
679 }
0bac7164 680
d5a76da4
BP
681 ds_put_format(s, "ct_label=");
682 ds_put_hex(s, &cc->ct_label, sizeof cc->ct_label);
683 if (!ovs_be128_equals(cc->ct_label_mask, OVS_BE128_MAX)) {
684 ds_put_char(s, '/');
685 ds_put_hex(s, &cc->ct_label_mask, sizeof cc->ct_label_mask);
686 }
687 }
688 if (!ds_chomp(s, '(')) {
689 ds_put_char(s, ')');
690 }
691 ds_put_char(s, ';');
0bac7164
BP
692}
693
694static void
d5a76da4
BP
695encode_CT_COMMIT(const struct ovnact_ct_commit *cc,
696 const struct ovnact_encode_params *ep OVS_UNUSED,
697 struct ofpbuf *ofpacts)
0bac7164 698{
d5a76da4
BP
699 struct ofpact_conntrack *ct = ofpact_put_CT(ofpacts);
700 ct->flags = NX_CT_F_COMMIT;
701 ct->recirc_table = NX_CT_RECIRC_NONE;
702 ct->zone_src.field = mf_from_id(MFF_LOG_CT_ZONE);
703 ct->zone_src.ofs = 0;
704 ct->zone_src.n_bits = 16;
0bac7164 705
d5a76da4
BP
706 size_t set_field_offset = ofpacts->size;
707 ofpbuf_pull(ofpacts, set_field_offset);
0bac7164 708
d5a76da4 709 if (cc->ct_mark_mask) {
128684a6
JR
710 const ovs_be32 value = htonl(cc->ct_mark);
711 const ovs_be32 mask = htonl(cc->ct_mark_mask);
712 ofpact_put_set_field(ofpacts, mf_from_id(MFF_CT_MARK), &value, &mask);
d5a76da4 713 }
0bac7164 714
d5a76da4 715 if (!ovs_be128_is_zero(cc->ct_label_mask)) {
128684a6
JR
716 ofpact_put_set_field(ofpacts, mf_from_id(MFF_CT_LABEL), &cc->ct_label,
717 &cc->ct_label_mask);
d5a76da4 718 }
0bac7164 719
d5a76da4
BP
720 ofpacts->header = ofpbuf_push_uninit(ofpacts, set_field_offset);
721 ct = ofpacts->header;
722 ofpact_finish(ofpacts, &ct->ofpact);
0bac7164
BP
723}
724
725static void
80b6743d 726ovnact_ct_commit_free(struct ovnact_ct_commit *cc OVS_UNUSED)
0bac7164 727{
0bac7164 728}
d5a76da4 729\f
42814145 730static void
d5a76da4
BP
731parse_ct_nat(struct action_context *ctx, const char *name,
732 struct ovnact_ct_nat *cn)
42814145 733{
d5a76da4 734 add_prerequisite(ctx, "ip");
42814145 735
d5a76da4 736 if (ctx->pp->cur_ltable >= ctx->pp->n_tables) {
9aef3c1b
BP
737 lexer_error(ctx->lexer,
738 "\"%s\" action not allowed in last table.", name);
42814145
NS
739 return;
740 }
d5a76da4 741 cn->ltable = ctx->pp->cur_ltable + 1;
42814145 742
d5a76da4
BP
743 if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {
744 if (ctx->lexer->token.type != LEX_T_INTEGER
745 || ctx->lexer->token.format != LEX_F_IPV4) {
9aef3c1b 746 lexer_syntax_error(ctx->lexer, "expecting IPv4 address");
42814145
NS
747 return;
748 }
d5a76da4
BP
749 cn->ip = ctx->lexer->token.value.ipv4;
750 lexer_get(ctx->lexer);
751
9aef3c1b 752 if (!lexer_force_match(ctx->lexer, LEX_T_RPAREN)) {
42814145
NS
753 return;
754 }
755 }
d5a76da4 756}
42814145 757
d5a76da4
BP
758static void
759parse_CT_DNAT(struct action_context *ctx)
760{
761 parse_ct_nat(ctx, "ct_dnat", ovnact_put_CT_DNAT(ctx->ovnacts));
762}
42814145 763
d5a76da4
BP
764static void
765parse_CT_SNAT(struct action_context *ctx)
766{
767 parse_ct_nat(ctx, "ct_snat", ovnact_put_CT_SNAT(ctx->ovnacts));
768}
42814145 769
d5a76da4
BP
770static void
771format_ct_nat(const struct ovnact_ct_nat *cn, const char *name, struct ds *s)
772{
773 ds_put_cstr(s, name);
774 if (cn->ip) {
775 ds_put_format(s, "("IP_FMT")", IP_ARGS(cn->ip));
42814145 776 }
d5a76da4
BP
777 ds_put_char(s, ';');
778}
42814145 779
d5a76da4
BP
780static void
781format_CT_DNAT(const struct ovnact_ct_nat *cn, struct ds *s)
782{
783 format_ct_nat(cn, "ct_dnat", s);
784}
42814145 785
d5a76da4
BP
786static void
787format_CT_SNAT(const struct ovnact_ct_nat *cn, struct ds *s)
788{
789 format_ct_nat(cn, "ct_snat", s);
790}
42814145 791
d5a76da4
BP
792static void
793encode_ct_nat(const struct ovnact_ct_nat *cn,
794 const struct ovnact_encode_params *ep,
795 bool snat, struct ofpbuf *ofpacts)
796{
797 const size_t ct_offset = ofpacts->size;
798 ofpbuf_pull(ofpacts, ct_offset);
42814145 799
d5a76da4 800 struct ofpact_conntrack *ct = ofpact_put_CT(ofpacts);
4c99cb18 801 ct->recirc_table = cn->ltable + first_ptable(ep, ep->pipeline);
d5a76da4
BP
802 if (snat) {
803 ct->zone_src.field = mf_from_id(MFF_LOG_SNAT_ZONE);
804 } else {
805 ct->zone_src.field = mf_from_id(MFF_LOG_DNAT_ZONE);
806 }
807 ct->zone_src.ofs = 0;
808 ct->zone_src.n_bits = 16;
809 ct->flags = 0;
810 ct->alg = 0;
42814145 811
d5a76da4
BP
812 struct ofpact_nat *nat;
813 size_t nat_offset;
814 nat_offset = ofpacts->size;
815 ofpbuf_pull(ofpacts, nat_offset);
816
817 nat = ofpact_put_NAT(ofpacts);
818 nat->flags = 0;
819 nat->range_af = AF_UNSPEC;
820
821 if (cn->ip) {
822 nat->range_af = AF_INET;
823 nat->range.addr.ipv4.min = cn->ip;
824 if (snat) {
825 nat->flags |= NX_NAT_F_SRC;
826 } else {
827 nat->flags |= NX_NAT_F_DST;
42814145 828 }
42814145
NS
829 }
830
d5a76da4
BP
831 ofpacts->header = ofpbuf_push_uninit(ofpacts, nat_offset);
832 ct = ofpacts->header;
833 if (cn->ip) {
834 ct->flags |= NX_CT_F_COMMIT;
1b441300
MS
835 } else if (snat && ep->is_gateway_router) {
836 /* For performance reasons, we try to prevent additional
837 * recirculations. ct_snat which is used in a gateway router
838 * does not need a recirculation. ct_snat(IP) does need a
839 * recirculation. ct_snat in a distributed router needs
840 * recirculation regardless of whether an IP address is
841 * specified.
842 * XXX Should we consider a method to let the actions specify
843 * whether an action needs recirculation if there are more use
d5a76da4
BP
844 * cases?. */
845 ct->recirc_table = NX_CT_RECIRC_NONE;
846 }
847 ofpact_finish(ofpacts, &ct->ofpact);
848 ofpbuf_push_uninit(ofpacts, ct_offset);
42814145
NS
849}
850
42814145 851static void
d5a76da4
BP
852encode_CT_DNAT(const struct ovnact_ct_nat *cn,
853 const struct ovnact_encode_params *ep,
854 struct ofpbuf *ofpacts)
42814145 855{
d5a76da4 856 encode_ct_nat(cn, ep, false, ofpacts);
42814145
NS
857}
858
01cfdb2f 859static void
d5a76da4
BP
860encode_CT_SNAT(const struct ovnact_ct_nat *cn,
861 const struct ovnact_encode_params *ep,
862 struct ofpbuf *ofpacts)
01cfdb2f 863{
d5a76da4
BP
864 encode_ct_nat(cn, ep, true, ofpacts);
865}
01cfdb2f 866
d5a76da4 867static void
80b6743d 868ovnact_ct_nat_free(struct ovnact_ct_nat *ct_nat OVS_UNUSED)
d5a76da4
BP
869{
870}
871\f
872static void
873parse_ct_lb_action(struct action_context *ctx)
874{
875 if (ctx->pp->cur_ltable >= ctx->pp->n_tables) {
9aef3c1b 876 lexer_error(ctx->lexer, "\"ct_lb\" action not allowed in last table.");
01cfdb2f
NS
877 return;
878 }
879
d5a76da4 880 add_prerequisite(ctx, "ip");
01cfdb2f 881
d5a76da4
BP
882 struct ovnact_ct_lb_dst *dsts = NULL;
883 size_t allocated_dsts = 0;
884 size_t n_dsts = 0;
01cfdb2f 885
d5a76da4
BP
886 if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {
887 while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
9d236afa
MM
888 struct ovnact_ct_lb_dst dst;
889 if (lexer_match(ctx->lexer, LEX_T_LSQUARE)) {
890 /* IPv6 address and port */
891 if (ctx->lexer->token.type != LEX_T_INTEGER
892 || ctx->lexer->token.format != LEX_F_IPV6) {
893 free(dsts);
894 lexer_syntax_error(ctx->lexer, "expecting IPv6 address");
895 return;
896 }
897 dst.family = AF_INET6;
898 dst.ipv6 = ctx->lexer->token.value.ipv6;
899
900 lexer_get(ctx->lexer);
901 if (!lexer_match(ctx->lexer, LEX_T_RSQUARE)) {
902 free(dsts);
903 lexer_syntax_error(ctx->lexer, "no closing square "
904 "bracket");
905 return;
906 }
907 dst.port = 0;
908 if (lexer_match(ctx->lexer, LEX_T_COLON)
909 && !action_parse_port(ctx, &dst.port)) {
910 free(dsts);
911 return;
912 }
913 } else {
914 if (ctx->lexer->token.type != LEX_T_INTEGER
915 || (ctx->lexer->token.format != LEX_F_IPV4
916 && ctx->lexer->token.format != LEX_F_IPV6)) {
917 free(dsts);
918 lexer_syntax_error(ctx->lexer, "expecting IP address");
919 return;
920 }
01cfdb2f 921
9d236afa
MM
922 /* Parse IP. */
923 if (ctx->lexer->token.format == LEX_F_IPV4) {
924 dst.family = AF_INET;
925 dst.ipv4 = ctx->lexer->token.value.ipv4;
926 } else {
927 dst.family = AF_INET6;
928 dst.ipv6 = ctx->lexer->token.value.ipv6;
929 }
01cfdb2f 930
9d236afa
MM
931 lexer_get(ctx->lexer);
932 dst.port = 0;
933 if (lexer_match(ctx->lexer, LEX_T_COLON)) {
934 if (dst.family == AF_INET6) {
935 free(dsts);
936 lexer_syntax_error(ctx->lexer, "IPv6 address needs "
937 "square brackets if port is included");
938 return;
939 } else if (!action_parse_port(ctx, &dst.port)) {
940 free(dsts);
941 return;
942 }
943 }
d5a76da4
BP
944 }
945 lexer_match(ctx->lexer, LEX_T_COMMA);
01cfdb2f 946
d5a76da4
BP
947 /* Append to dsts. */
948 if (n_dsts >= allocated_dsts) {
949 dsts = x2nrealloc(dsts, &allocated_dsts, sizeof *dsts);
950 }
9d236afa 951 dsts[n_dsts++] = dst;
01cfdb2f 952 }
01cfdb2f
NS
953 }
954
d5a76da4
BP
955 struct ovnact_ct_lb *cl = ovnact_put_CT_LB(ctx->ovnacts);
956 cl->ltable = ctx->pp->cur_ltable + 1;
957 cl->dsts = dsts;
958 cl->n_dsts = n_dsts;
01cfdb2f
NS
959}
960
01cfdb2f 961static void
d5a76da4 962format_CT_LB(const struct ovnact_ct_lb *cl, struct ds *s)
01cfdb2f 963{
d5a76da4
BP
964 ds_put_cstr(s, "ct_lb");
965 if (cl->n_dsts) {
966 ds_put_char(s, '(');
967 for (size_t i = 0; i < cl->n_dsts; i++) {
968 if (i) {
969 ds_put_cstr(s, ", ");
970 }
01cfdb2f 971
d5a76da4 972 const struct ovnact_ct_lb_dst *dst = &cl->dsts[i];
9d236afa
MM
973 if (dst->family == AF_INET) {
974 ds_put_format(s, IP_FMT, IP_ARGS(dst->ipv4));
975 if (dst->port) {
976 ds_put_format(s, ":%"PRIu16, dst->port);
977 }
978 } else {
979 if (dst->port) {
980 ds_put_char(s, '[');
981 }
982 ipv6_format_addr(&dst->ipv6, s);
983 if (dst->port) {
984 ds_put_format(s, "]:%"PRIu16, dst->port);
985 }
d5a76da4 986 }
467085fd 987 }
d5a76da4 988 ds_put_char(s, ')');
467085fd 989 }
d5a76da4 990 ds_put_char(s, ';');
467085fd
GS
991}
992
993static void
d5a76da4
BP
994encode_CT_LB(const struct ovnact_ct_lb *cl,
995 const struct ovnact_encode_params *ep,
996 struct ofpbuf *ofpacts)
467085fd 997{
4c99cb18 998 uint8_t recirc_table = cl->ltable + first_ptable(ep, ep->pipeline);
d5a76da4
BP
999 if (!cl->n_dsts) {
1000 /* ct_lb without any destinations means that this is an established
467085fd 1001 * connection and we just need to do a NAT. */
d5a76da4
BP
1002 const size_t ct_offset = ofpacts->size;
1003 ofpbuf_pull(ofpacts, ct_offset);
467085fd 1004
d5a76da4 1005 struct ofpact_conntrack *ct = ofpact_put_CT(ofpacts);
467085fd
GS
1006 struct ofpact_nat *nat;
1007 size_t nat_offset;
c2e954a1
GS
1008 ct->zone_src.field = ep->is_switch ? mf_from_id(MFF_LOG_CT_ZONE)
1009 : mf_from_id(MFF_LOG_DNAT_ZONE);
467085fd
GS
1010 ct->zone_src.ofs = 0;
1011 ct->zone_src.n_bits = 16;
1012 ct->flags = 0;
1013 ct->recirc_table = recirc_table;
1014 ct->alg = 0;
1015
d5a76da4
BP
1016 nat_offset = ofpacts->size;
1017 ofpbuf_pull(ofpacts, nat_offset);
467085fd 1018
d5a76da4 1019 nat = ofpact_put_NAT(ofpacts);
467085fd
GS
1020 nat->flags = 0;
1021 nat->range_af = AF_UNSPEC;
1022
d5a76da4
BP
1023 ofpacts->header = ofpbuf_push_uninit(ofpacts, nat_offset);
1024 ct = ofpacts->header;
1025 ofpact_finish(ofpacts, &ct->ofpact);
1026 ofpbuf_push_uninit(ofpacts, ct_offset);
467085fd
GS
1027 return;
1028 }
1029
ad35c0c5 1030 uint32_t table_id = 0;
467085fd 1031 struct ofpact_group *og;
c2e954a1
GS
1032 uint32_t zone_reg = ep->is_switch ? MFF_LOG_CT_ZONE - MFF_REG0
1033 : MFF_LOG_DNAT_ZONE - MFF_REG0;
467085fd
GS
1034
1035 struct ds ds = DS_EMPTY_INITIALIZER;
eacd48ec 1036 ds_put_format(&ds, "type=select,selection_method=dp_hash");
467085fd
GS
1037
1038 BUILD_ASSERT(MFF_LOG_CT_ZONE >= MFF_REG0);
1039 BUILD_ASSERT(MFF_LOG_CT_ZONE < MFF_REG0 + FLOW_N_REGS);
c2e954a1
GS
1040 BUILD_ASSERT(MFF_LOG_DNAT_ZONE >= MFF_REG0);
1041 BUILD_ASSERT(MFF_LOG_DNAT_ZONE < MFF_REG0 + FLOW_N_REGS);
d5a76da4
BP
1042 for (size_t bucket_id = 0; bucket_id < cl->n_dsts; bucket_id++) {
1043 const struct ovnact_ct_lb_dst *dst = &cl->dsts[bucket_id];
9d236afa
MM
1044 char ip_addr[INET6_ADDRSTRLEN];
1045 if (dst->family == AF_INET) {
1046 inet_ntop(AF_INET, &dst->ipv4, ip_addr, sizeof ip_addr);
1047 } else {
1048 inet_ntop(AF_INET6, &dst->ipv6, ip_addr, sizeof ip_addr);
1049 }
d5a76da4 1050 ds_put_format(&ds, ",bucket=bucket_id=%"PRIuSIZE",weight:100,actions="
9d236afa
MM
1051 "ct(nat(dst=%s%s%s", bucket_id,
1052 dst->family == AF_INET6 && dst->port ? "[" : "",
1053 ip_addr,
1054 dst->family == AF_INET6 && dst->port ? "]" : "");
d5a76da4
BP
1055 if (dst->port) {
1056 ds_put_format(&ds, ":%"PRIu16, dst->port);
467085fd
GS
1057 }
1058 ds_put_format(&ds, "),commit,table=%d,zone=NXM_NX_REG%d[0..15])",
c2e954a1 1059 recirc_table, zone_reg);
d5a76da4 1060 }
467085fd 1061
ad35c0c5
GL
1062 table_id = ovn_extend_table_assign_id(ep->group_table, &ds);
1063 ds_destroy(&ds);
1064 if (table_id == EXT_TABLE_ID_INVALID) {
1065 return;
467085fd
GS
1066 }
1067
d5a76da4
BP
1068 /* Create an action to set the group. */
1069 og = ofpact_put_GROUP(ofpacts);
ad35c0c5 1070 og->group_id = table_id;
d5a76da4
BP
1071}
1072
1073static void
80b6743d 1074ovnact_ct_lb_free(struct ovnact_ct_lb *ct_lb)
d5a76da4
BP
1075{
1076 free(ct_lb->dsts);
1077}
1078\f
db0e819b
BP
1079static void
1080format_CT_CLEAR(const struct ovnact_null *null OVS_UNUSED, struct ds *s)
1081{
1082 ds_put_cstr(s, "ct_clear;");
1083}
1084
1085static void
1086encode_CT_CLEAR(const struct ovnact_null *null OVS_UNUSED,
1087 const struct ovnact_encode_params *ep OVS_UNUSED,
1088 struct ofpbuf *ofpacts)
1089{
1090 ofpact_put_CT_CLEAR(ofpacts);
1091}
1092\f
b3bd2c33
BP
1093/* Implements the "arp", "nd_na", and "clone" actions, which execute nested
1094 * actions on a packet derived from the one being processed. */
d5a76da4
BP
1095static void
1096parse_nested_action(struct action_context *ctx, enum ovnact_type type,
1097 const char *prereq)
1098{
9aef3c1b 1099 if (!lexer_force_match(ctx->lexer, LEX_T_LCURLY)) {
d5a76da4
BP
1100 return;
1101 }
1102
1103 uint64_t stub[1024 / 8];
1104 struct ofpbuf nested = OFPBUF_STUB_INITIALIZER(stub);
1105
1106 struct action_context inner_ctx = {
1107 .pp = ctx->pp,
1108 .lexer = ctx->lexer,
d5a76da4 1109 .ovnacts = &nested,
b3bd2c33 1110 .prereqs = NULL,
d5a76da4 1111 };
bac29564 1112 parse_actions(&inner_ctx, LEX_T_RCURLY);
d5a76da4 1113
b3bd2c33
BP
1114 if (prereq) {
1115 /* XXX Not really sure what we should do with prerequisites for "arp"
1116 * and "nd_na" actions. */
1117 expr_destroy(inner_ctx.prereqs);
1118 add_prerequisite(ctx, prereq);
1119 } else {
1120 /* For "clone", the inner prerequisites should just add to the outer
1121 * ones. */
1122 ctx->prereqs = expr_combine(EXPR_T_AND,
1123 inner_ctx.prereqs, ctx->prereqs);
1124 }
d5a76da4 1125
9aef3c1b 1126 if (inner_ctx.lexer->error) {
d5a76da4
BP
1127 ovnacts_free(nested.data, nested.size);
1128 ofpbuf_uninit(&nested);
1129 return;
1130 }
1131
8a41ad8e
BP
1132 struct ovnact_nest *on = ovnact_put(ctx->ovnacts, type,
1133 OVNACT_ALIGN(sizeof *on));
d5a76da4
BP
1134 on->nested_len = nested.size;
1135 on->nested = ofpbuf_steal_data(&nested);
1136}
1137
1138static void
1139parse_ARP(struct action_context *ctx)
1140{
1141 parse_nested_action(ctx, OVNACT_ARP, "ip4");
1142}
1143
bc3d6a63
LB
1144static void
1145parse_ICMP4(struct action_context *ctx)
1146{
1147 parse_nested_action(ctx, OVNACT_ICMP4, "ip4");
1148}
1149
3e7fa1e3
LB
1150static void
1151parse_ICMP6(struct action_context *ctx)
1152{
1153 parse_nested_action(ctx, OVNACT_ICMP6, "ip6");
1154}
1155
22b65e4d
LB
1156static void
1157parse_TCP_RESET(struct action_context *ctx)
1158{
1159 parse_nested_action(ctx, OVNACT_TCP_RESET, "tcp");
1160}
1161
d5a76da4
BP
1162static void
1163parse_ND_NA(struct action_context *ctx)
1164{
1165 parse_nested_action(ctx, OVNACT_ND_NA, "nd_ns");
1166}
1167
b1a3a6a4
NS
1168static void
1169parse_ND_NS(struct action_context *ctx)
1170{
1171 parse_nested_action(ctx, OVNACT_ND_NS, "ip6");
1172}
1173
b3bd2c33
BP
1174static void
1175parse_CLONE(struct action_context *ctx)
1176{
1177 parse_nested_action(ctx, OVNACT_CLONE, NULL);
1178}
1179
d5a76da4
BP
1180static void
1181format_nested_action(const struct ovnact_nest *on, const char *name,
1182 struct ds *s)
1183{
1184 ds_put_format(s, "%s { ", name);
1185 ovnacts_format(on->nested, on->nested_len, s);
1186 ds_put_format(s, " };");
1187}
1188
1189static void
1190format_ARP(const struct ovnact_nest *nest, struct ds *s)
1191{
1192 format_nested_action(nest, "arp", s);
1193}
1194
bc3d6a63
LB
1195static void
1196format_ICMP4(const struct ovnact_nest *nest, struct ds *s)
1197{
1198 format_nested_action(nest, "icmp4", s);
1199}
1200
3e7fa1e3
LB
1201static void
1202format_ICMP6(const struct ovnact_nest *nest, struct ds *s)
1203{
1204 format_nested_action(nest, "icmp6", s);
1205}
1206
22b65e4d
LB
1207static void
1208format_TCP_RESET(const struct ovnact_nest *nest, struct ds *s)
1209{
1210 format_nested_action(nest, "tcp_reset", s);
1211}
1212
d5a76da4
BP
1213static void
1214format_ND_NA(const struct ovnact_nest *nest, struct ds *s)
1215{
1216 format_nested_action(nest, "nd_na", s);
1217}
1218
b1a3a6a4
NS
1219static void
1220format_ND_NS(const struct ovnact_nest *nest, struct ds *s)
1221{
1222 format_nested_action(nest, "nd_ns", s);
1223}
1224
d5a76da4 1225static void
b3bd2c33
BP
1226format_CLONE(const struct ovnact_nest *nest, struct ds *s)
1227{
1228 format_nested_action(nest, "clone", s);
1229}
1230
1231static void
358fa138
LB
1232encode_nested_actions(const struct ovnact_nest *on,
1233 const struct ovnact_encode_params *ep,
1234 enum action_opcode opcode,
1235 struct ofpbuf *ofpacts)
d5a76da4
BP
1236{
1237 /* Convert nested actions into ofpacts. */
1238 uint64_t inner_ofpacts_stub[1024 / 8];
1239 struct ofpbuf inner_ofpacts = OFPBUF_STUB_INITIALIZER(inner_ofpacts_stub);
1240 ovnacts_encode(on->nested, on->nested_len, ep, &inner_ofpacts);
1241
1242 /* Add a "controller" action with the actions nested inside "{...}",
1243 * converted to OpenFlow, as its userdata. ovn-controller will convert the
1244 * packet to ARP or NA and then send the packet and actions back to the
1245 * switch inside an OFPT_PACKET_OUT message. */
1246 size_t oc_offset = encode_start_controller_op(opcode, false, ofpacts);
1247 ofpacts_put_openflow_actions(inner_ofpacts.data, inner_ofpacts.size,
1248 ofpacts, OFP13_VERSION);
1249 encode_finish_controller_op(oc_offset, ofpacts);
1250
1251 /* Free memory. */
1252 ofpbuf_uninit(&inner_ofpacts);
1253}
1254
1255static void
1256encode_ARP(const struct ovnact_nest *on,
1257 const struct ovnact_encode_params *ep,
1258 struct ofpbuf *ofpacts)
1259{
358fa138 1260 encode_nested_actions(on, ep, ACTION_OPCODE_ARP, ofpacts);
d5a76da4
BP
1261}
1262
bc3d6a63
LB
1263static void
1264encode_ICMP4(const struct ovnact_nest *on,
1265 const struct ovnact_encode_params *ep,
1266 struct ofpbuf *ofpacts)
1267{
3e7fa1e3
LB
1268 encode_nested_actions(on, ep, ACTION_OPCODE_ICMP, ofpacts);
1269}
1270
1271static void
1272encode_ICMP6(const struct ovnact_nest *on,
1273 const struct ovnact_encode_params *ep,
1274 struct ofpbuf *ofpacts)
1275{
1276 encode_nested_actions(on, ep, ACTION_OPCODE_ICMP, ofpacts);
bc3d6a63
LB
1277}
1278
22b65e4d
LB
1279static void
1280encode_TCP_RESET(const struct ovnact_nest *on,
1281 const struct ovnact_encode_params *ep,
1282 struct ofpbuf *ofpacts)
1283{
1284 encode_nested_actions(on, ep, ACTION_OPCODE_TCP_RESET, ofpacts);
1285}
1286
d5a76da4
BP
1287static void
1288encode_ND_NA(const struct ovnact_nest *on,
1289 const struct ovnact_encode_params *ep,
1290 struct ofpbuf *ofpacts)
1291{
358fa138 1292 encode_nested_actions(on, ep, ACTION_OPCODE_ND_NA, ofpacts);
d5a76da4
BP
1293}
1294
b1a3a6a4
NS
1295static void
1296encode_ND_NS(const struct ovnact_nest *on,
1297 const struct ovnact_encode_params *ep,
1298 struct ofpbuf *ofpacts)
1299{
358fa138 1300 encode_nested_actions(on, ep, ACTION_OPCODE_ND_NS, ofpacts);
b1a3a6a4
NS
1301}
1302
b3bd2c33
BP
1303static void
1304encode_CLONE(const struct ovnact_nest *on,
1305 const struct ovnact_encode_params *ep,
1306 struct ofpbuf *ofpacts)
1307{
1308 size_t ofs = ofpacts->size;
1309 ofpact_put_CLONE(ofpacts);
1310 ovnacts_encode(on->nested, on->nested_len, ep, ofpacts);
1311
1312 struct ofpact_nest *clone = ofpbuf_at_assert(ofpacts, ofs, sizeof *clone);
1313 ofpacts->header = clone;
1314 ofpact_finish_CLONE(ofpacts, &clone);
1315}
80b6743d 1316
d5a76da4 1317static void
80b6743d 1318ovnact_nest_free(struct ovnact_nest *on)
d5a76da4
BP
1319{
1320 ovnacts_free(on->nested, on->nested_len);
1321 free(on->nested);
1322}
d5a76da4
BP
1323\f
1324static void
1325parse_get_mac_bind(struct action_context *ctx, int width,
1326 struct ovnact_get_mac_bind *get_mac)
1327{
9aef3c1b 1328 lexer_force_match(ctx->lexer, LEX_T_LPAREN);
d5a76da4 1329 action_parse_field(ctx, 0, false, &get_mac->port);
9aef3c1b 1330 lexer_force_match(ctx->lexer, LEX_T_COMMA);
d5a76da4 1331 action_parse_field(ctx, width, false, &get_mac->ip);
9aef3c1b 1332 lexer_force_match(ctx->lexer, LEX_T_RPAREN);
d5a76da4
BP
1333}
1334
1335static void
1336format_get_mac_bind(const struct ovnact_get_mac_bind *get_mac,
1337 const char *name, struct ds *s)
1338{
1339 ds_put_format(s, "%s(", name);
1340 expr_field_format(&get_mac->port, s);
1341 ds_put_cstr(s, ", ");
1342 expr_field_format(&get_mac->ip, s);
1343 ds_put_cstr(s, ");");
1344}
1345
1346static void
1347format_GET_ARP(const struct ovnact_get_mac_bind *get_mac, struct ds *s)
1348{
1349 format_get_mac_bind(get_mac, "get_arp", s);
1350}
1351
1352static void
1353format_GET_ND(const struct ovnact_get_mac_bind *get_mac, struct ds *s)
1354{
1355 format_get_mac_bind(get_mac, "get_nd", s);
1356}
1357
1358static void
1359encode_get_mac(const struct ovnact_get_mac_bind *get_mac,
1360 enum mf_field_id ip_field,
1361 const struct ovnact_encode_params *ep,
1362 struct ofpbuf *ofpacts)
1363{
1364 const struct arg args[] = {
1365 { expr_resolve_field(&get_mac->port), MFF_LOG_OUTPORT },
1366 { expr_resolve_field(&get_mac->ip), ip_field },
1367 };
1368 encode_setup_args(args, ARRAY_SIZE(args), ofpacts);
1369
1370 put_load(0, MFF_ETH_DST, 0, 48, ofpacts);
1371 emit_resubmit(ofpacts, ep->mac_bind_ptable);
1372
1373 encode_restore_args(args, ARRAY_SIZE(args), ofpacts);
1374}
1375
1376static void
1377encode_GET_ARP(const struct ovnact_get_mac_bind *get_mac,
1378 const struct ovnact_encode_params *ep,
1379 struct ofpbuf *ofpacts)
1380{
1381 encode_get_mac(get_mac, MFF_REG0, ep, ofpacts);
1382}
1383
1384static void
1385encode_GET_ND(const struct ovnact_get_mac_bind *get_mac,
1386 const struct ovnact_encode_params *ep,
1387 struct ofpbuf *ofpacts)
1388{
1389 encode_get_mac(get_mac, MFF_XXREG0, ep, ofpacts);
1390}
1391
1392static void
80b6743d 1393ovnact_get_mac_bind_free(struct ovnact_get_mac_bind *get_mac OVS_UNUSED)
d5a76da4
BP
1394{
1395}
1396\f
1397static void
1398parse_put_mac_bind(struct action_context *ctx, int width,
1399 struct ovnact_put_mac_bind *put_mac)
1400{
9aef3c1b 1401 lexer_force_match(ctx->lexer, LEX_T_LPAREN);
d5a76da4 1402 action_parse_field(ctx, 0, false, &put_mac->port);
9aef3c1b 1403 lexer_force_match(ctx->lexer, LEX_T_COMMA);
d5a76da4 1404 action_parse_field(ctx, width, false, &put_mac->ip);
9aef3c1b 1405 lexer_force_match(ctx->lexer, LEX_T_COMMA);
d5a76da4 1406 action_parse_field(ctx, 48, false, &put_mac->mac);
9aef3c1b 1407 lexer_force_match(ctx->lexer, LEX_T_RPAREN);
d5a76da4
BP
1408}
1409
1410static void
1411format_put_mac_bind(const struct ovnact_put_mac_bind *put_mac,
1412 const char *name, struct ds *s)
1413{
1414 ds_put_format(s, "%s(", name);
1415 expr_field_format(&put_mac->port, s);
1416 ds_put_cstr(s, ", ");
1417 expr_field_format(&put_mac->ip, s);
1418 ds_put_cstr(s, ", ");
1419 expr_field_format(&put_mac->mac, s);
1420 ds_put_cstr(s, ");");
1421}
1422
1423static void
1424format_PUT_ARP(const struct ovnact_put_mac_bind *put_mac, struct ds *s)
1425{
1426 format_put_mac_bind(put_mac, "put_arp", s);
1427}
1428
1429static void
1430format_PUT_ND(const struct ovnact_put_mac_bind *put_mac, struct ds *s)
1431{
1432 format_put_mac_bind(put_mac, "put_nd", s);
1433}
1434
1435static void
1436encode_put_mac(const struct ovnact_put_mac_bind *put_mac,
1437 enum mf_field_id ip_field, enum action_opcode opcode,
1438 struct ofpbuf *ofpacts)
1439{
1440 const struct arg args[] = {
1441 { expr_resolve_field(&put_mac->port), MFF_LOG_INPORT },
1442 { expr_resolve_field(&put_mac->ip), ip_field },
1443 { expr_resolve_field(&put_mac->mac), MFF_ETH_SRC }
1444 };
1445 encode_setup_args(args, ARRAY_SIZE(args), ofpacts);
1446 encode_controller_op(opcode, ofpacts);
1447 encode_restore_args(args, ARRAY_SIZE(args), ofpacts);
1448}
1449
1450static void
1451encode_PUT_ARP(const struct ovnact_put_mac_bind *put_mac,
1452 const struct ovnact_encode_params *ep OVS_UNUSED,
1453 struct ofpbuf *ofpacts)
1454{
1455 encode_put_mac(put_mac, MFF_REG0, ACTION_OPCODE_PUT_ARP, ofpacts);
1456}
1457
1458static void
1459encode_PUT_ND(const struct ovnact_put_mac_bind *put_mac,
1460 const struct ovnact_encode_params *ep OVS_UNUSED,
1461 struct ofpbuf *ofpacts)
1462{
1463 encode_put_mac(put_mac, MFF_XXREG0, ACTION_OPCODE_PUT_ND, ofpacts);
467085fd
GS
1464}
1465
c34a87b6 1466static void
80b6743d 1467ovnact_put_mac_bind_free(struct ovnact_put_mac_bind *put_mac OVS_UNUSED)
d5a76da4
BP
1468{
1469}
1470\f
1471static void
16936e4d
NS
1472parse_gen_opt(struct action_context *ctx, struct ovnact_gen_option *o,
1473 const struct hmap *gen_opts, const char *opts_type)
d5a76da4
BP
1474{
1475 if (ctx->lexer->token.type != LEX_T_ID) {
9aef3c1b 1476 lexer_syntax_error(ctx->lexer, NULL);
c34a87b6
JP
1477 return;
1478 }
1479
16936e4d 1480 o->option = gen_opts ? gen_opts_find(gen_opts, ctx->lexer->token.s) : NULL;
d5a76da4 1481 if (!o->option) {
16936e4d 1482 lexer_syntax_error(ctx->lexer, "expecting %s option name", opts_type);
d5a76da4
BP
1483 return;
1484 }
1485 lexer_get(ctx->lexer);
1486
9aef3c1b 1487 if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) {
d5a76da4
BP
1488 return;
1489 }
1490
9aef3c1b 1491 if (!expr_constant_set_parse(ctx->lexer, &o->value)) {
d5a76da4 1492 memset(&o->value, 0, sizeof o->value);
d5a76da4
BP
1493 return;
1494 }
c34a87b6 1495
d5a76da4
BP
1496 if (!strcmp(o->option->type, "str")) {
1497 if (o->value.type != EXPR_C_STRING) {
9aef3c1b 1498 lexer_error(ctx->lexer, "%s option %s requires string value.",
16936e4d 1499 opts_type, o->option->name);
d5a76da4
BP
1500 return;
1501 }
1502 } else {
1503 if (o->value.type != EXPR_C_INTEGER) {
9aef3c1b 1504 lexer_error(ctx->lexer, "%s option %s requires numeric value.",
16936e4d 1505 opts_type, o->option->name);
d5a76da4
BP
1506 return;
1507 }
1508 }
1509}
c34a87b6 1510
16936e4d
NS
1511static const struct ovnact_gen_option *
1512find_offerip(const struct ovnact_gen_option *options, size_t n)
d5a76da4 1513{
16936e4d 1514 for (const struct ovnact_gen_option *o = options; o < &options[n]; o++) {
d5a76da4
BP
1515 if (o->option->code == 0) {
1516 return o;
1517 }
1518 }
1519 return NULL;
c34a87b6
JP
1520}
1521
1522static void
16936e4d 1523free_gen_options(struct ovnact_gen_option *options, size_t n)
c34a87b6 1524{
16936e4d 1525 for (struct ovnact_gen_option *o = options; o < &options[n]; o++) {
d5a76da4 1526 expr_constant_set_destroy(&o->value);
c34a87b6 1527 }
d5a76da4 1528 free(options);
c34a87b6
JP
1529}
1530
78aab811 1531static void
16936e4d
NS
1532parse_put_opts(struct action_context *ctx, const struct expr_field *dst,
1533 struct ovnact_put_opts *po, const struct hmap *gen_opts,
1534 const char *opts_type)
78aab811 1535{
52ed5fcc 1536 lexer_get(ctx->lexer); /* Skip put_dhcp[v6]_opts / put_nd_ra_opts. */
d5a76da4 1537 lexer_get(ctx->lexer); /* Skip '('. */
78aab811 1538
d5a76da4
BP
1539 /* Validate that the destination is a 1-bit, modifiable field. */
1540 char *error = expr_type_check(dst, 1, true);
1541 if (error) {
9aef3c1b 1542 lexer_error(ctx->lexer, "%s", error);
d5a76da4
BP
1543 free(error);
1544 return;
78aab811 1545 }
16936e4d 1546 po->dst = *dst;
78aab811 1547
d5a76da4
BP
1548 size_t allocated_options = 0;
1549 while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
16936e4d
NS
1550 if (po->n_options >= allocated_options) {
1551 po->options = x2nrealloc(po->options, &allocated_options,
1552 sizeof *po->options);
d5a76da4 1553 }
78aab811 1554
16936e4d 1555 struct ovnact_gen_option *o = &po->options[po->n_options++];
d5a76da4 1556 memset(o, 0, sizeof *o);
16936e4d 1557 parse_gen_opt(ctx, o, gen_opts, opts_type);
9aef3c1b 1558 if (ctx->lexer->error) {
d5a76da4
BP
1559 return;
1560 }
a9e1b66f 1561
d5a76da4
BP
1562 lexer_match(ctx->lexer, LEX_T_COMMA);
1563 }
16936e4d
NS
1564}
1565
1566/* Parses the "put_dhcp_opts" and "put_dhcpv6_opts" actions.
1567 *
1568 * The caller has already consumed "<dst> =", so this just parses the rest. */
1569static void
1570parse_put_dhcp_opts(struct action_context *ctx,
1571 const struct expr_field *dst,
1572 struct ovnact_put_opts *po)
1573{
1574 const struct hmap *dhcp_opts =
1575 (po->ovnact.type == OVNACT_PUT_DHCPV6_OPTS) ?
1576 ctx->pp->dhcpv6_opts : ctx->pp->dhcp_opts;
1577 const char *opts_type =
1578 (po->ovnact.type == OVNACT_PUT_DHCPV6_OPTS) ? "DHCPv6" : "DHCPv4";
1579
1580 parse_put_opts(ctx, dst, po, dhcp_opts, opts_type);
a9e1b66f 1581
16936e4d
NS
1582 if (!ctx->lexer->error && po->ovnact.type == OVNACT_PUT_DHCPV4_OPTS
1583 && !find_offerip(po->options, po->n_options)) {
9aef3c1b
BP
1584 lexer_error(ctx->lexer,
1585 "put_dhcp_opts requires offerip to be specified.");
d5a76da4 1586 return;
a9e1b66f 1587 }
d5a76da4 1588}
a9e1b66f 1589
d5a76da4 1590static void
16936e4d
NS
1591format_put_opts(const char *name, const struct ovnact_put_opts *pdo,
1592 struct ds *s)
d5a76da4
BP
1593{
1594 expr_field_format(&pdo->dst, s);
1595 ds_put_format(s, " = %s(", name);
16936e4d 1596 for (const struct ovnact_gen_option *o = pdo->options;
d5a76da4
BP
1597 o < &pdo->options[pdo->n_options]; o++) {
1598 if (o != pdo->options) {
1599 ds_put_cstr(s, ", ");
1600 }
1601 ds_put_format(s, "%s = ", o->option->name);
1602 expr_constant_set_format(&o->value, s);
a9e1b66f 1603 }
d5a76da4
BP
1604 ds_put_cstr(s, ");");
1605}
a9e1b66f 1606
d5a76da4 1607static void
16936e4d 1608format_PUT_DHCPV4_OPTS(const struct ovnact_put_opts *pdo, struct ds *s)
d5a76da4 1609{
16936e4d 1610 format_put_opts("put_dhcp_opts", pdo, s);
a9e1b66f
RB
1611}
1612
d5a76da4 1613static void
16936e4d 1614format_PUT_DHCPV6_OPTS(const struct ovnact_put_opts *pdo, struct ds *s)
a9e1b66f 1615{
16936e4d 1616 format_put_opts("put_dhcpv6_opts", pdo, s);
d5a76da4
BP
1617}
1618
1619static void
16936e4d 1620encode_put_dhcpv4_option(const struct ovnact_gen_option *o,
d5a76da4
BP
1621 struct ofpbuf *ofpacts)
1622{
1623 uint8_t *opt_header = ofpbuf_put_zeros(ofpacts, 2);
1624 opt_header[0] = o->option->code;
1625
1626 const union expr_constant *c = o->value.values;
1627 size_t n_values = o->value.n_values;
1628 if (!strcmp(o->option->type, "bool") ||
1629 !strcmp(o->option->type, "uint8")) {
1630 opt_header[1] = 1;
1631 ofpbuf_put(ofpacts, &c->value.u8_val, 1);
1632 } else if (!strcmp(o->option->type, "uint16")) {
1633 opt_header[1] = 2;
1634 ofpbuf_put(ofpacts, &c->value.be16_int, 2);
1635 } else if (!strcmp(o->option->type, "uint32")) {
1636 opt_header[1] = 4;
1637 ofpbuf_put(ofpacts, &c->value.be32_int, 4);
1638 } else if (!strcmp(o->option->type, "ipv4")) {
1639 opt_header[1] = n_values * sizeof(ovs_be32);
1640 for (size_t i = 0; i < n_values; i++) {
1641 ofpbuf_put(ofpacts, &c[i].value.ipv4, sizeof(ovs_be32));
a9e1b66f 1642 }
d5a76da4
BP
1643 } else if (!strcmp(o->option->type, "static_routes")) {
1644 size_t no_of_routes = n_values;
1645 if (no_of_routes % 2) {
1646 no_of_routes -= 1;
a9e1b66f 1647 }
d5a76da4 1648 opt_header[1] = 0;
354b8f27 1649
d5a76da4
BP
1650 /* Calculating the length of this option first because when
1651 * we call ofpbuf_put, it might reallocate the buffer if the
1652 * tail room is short making "opt_header" pointer invalid.
1653 * So running the for loop twice.
1654 */
1655 for (size_t i = 0; i < no_of_routes; i += 2) {
1656 uint8_t plen = 32;
1657 if (c[i].masked) {
1658 plen = (uint8_t) ip_count_cidr_bits(c[i].mask.ipv4);
1659 }
1660 opt_header[1] += (1 + (plen / 8) + sizeof(ovs_be32)) ;
a9e1b66f 1661 }
a9e1b66f 1662
d5a76da4
BP
1663 /* Copied from RFC 3442. Please refer to this RFC for the format of
1664 * the classless static route option.
1665 *
1666 * The following table contains some examples of how various subnet
1667 * number/mask combinations can be encoded:
1668 *
1669 * Subnet number Subnet mask Destination descriptor
1670 * 0 0 0
1671 * 10.0.0.0 255.0.0.0 8.10
1672 * 10.0.0.0 255.255.255.0 24.10.0.0
1673 * 10.17.0.0 255.255.0.0 16.10.17
1674 * 10.27.129.0 255.255.255.0 24.10.27.129
1675 * 10.229.0.128 255.255.255.128 25.10.229.0.128
1676 * 10.198.122.47 255.255.255.255 32.10.198.122.47
1677 */
1678
1679 for (size_t i = 0; i < no_of_routes; i += 2) {
1680 uint8_t plen = 32;
1681 if (c[i].masked) {
1682 plen = ip_count_cidr_bits(c[i].mask.ipv4);
1683 }
1684 ofpbuf_put(ofpacts, &plen, 1);
1685 ofpbuf_put(ofpacts, &c[i].value.ipv4, plen / 8);
1686 ofpbuf_put(ofpacts, &c[i + 1].value.ipv4,
1687 sizeof(ovs_be32));
a9e1b66f 1688 }
d5a76da4
BP
1689 } else if (!strcmp(o->option->type, "str")) {
1690 opt_header[1] = strlen(c->string);
1691 ofpbuf_put(ofpacts, c->string, opt_header[1]);
a9e1b66f 1692 }
a9e1b66f
RB
1693}
1694
1695static void
16936e4d 1696encode_put_dhcpv6_option(const struct ovnact_gen_option *o,
d5a76da4 1697 struct ofpbuf *ofpacts)
a9e1b66f 1698{
d5a76da4 1699 struct dhcp_opt6_header *opt = ofpbuf_put_uninit(ofpacts, sizeof *opt);
d5a76da4
BP
1700 const union expr_constant *c = o->value.values;
1701 size_t n_values = o->value.n_values;
a55dacac
DDP
1702 size_t size;
1703
1704 opt->opt_code = htons(o->option->code);
1705
d5a76da4 1706 if (!strcmp(o->option->type, "ipv6")) {
a55dacac
DDP
1707 size = n_values * sizeof(struct in6_addr);
1708 opt->size = htons(size);
d5a76da4
BP
1709 for (size_t i = 0; i < n_values; i++) {
1710 ofpbuf_put(ofpacts, &c[i].value.ipv6, sizeof(struct in6_addr));
1711 }
1712 } else if (!strcmp(o->option->type, "mac")) {
a55dacac
DDP
1713 size = sizeof(struct eth_addr);
1714 opt->size = htons(size);
1715 ofpbuf_put(ofpacts, &c->value.mac, size);
d5a76da4 1716 } else if (!strcmp(o->option->type, "str")) {
a55dacac
DDP
1717 size = strlen(c->string);
1718 opt->size = htons(size);
1719 ofpbuf_put(ofpacts, c->string, size);
a9e1b66f 1720 }
d5a76da4 1721}
a9e1b66f 1722
d5a76da4 1723static void
16936e4d 1724encode_PUT_DHCPV4_OPTS(const struct ovnact_put_opts *pdo,
d5a76da4
BP
1725 const struct ovnact_encode_params *ep OVS_UNUSED,
1726 struct ofpbuf *ofpacts)
1727{
1728 struct mf_subfield dst = expr_resolve_field(&pdo->dst);
1729
1730 size_t oc_offset = encode_start_controller_op(ACTION_OPCODE_PUT_DHCP_OPTS,
1731 true, ofpacts);
1732 nx_put_header(ofpacts, dst.field->id, OFP13_VERSION, false);
1733 ovs_be32 ofs = htonl(dst.ofs);
1734 ofpbuf_put(ofpacts, &ofs, sizeof ofs);
1735
1736 /* Encode the offerip option first, because it's a special case and needs
1737 * to be first in the actual DHCP response, and then encode the rest
1738 * (skipping offerip the second time around). */
16936e4d 1739 const struct ovnact_gen_option *offerip_opt = find_offerip(
d5a76da4
BP
1740 pdo->options, pdo->n_options);
1741 ovs_be32 offerip = offerip_opt->value.values[0].value.ipv4;
1742 ofpbuf_put(ofpacts, &offerip, sizeof offerip);
1743
16936e4d 1744 for (const struct ovnact_gen_option *o = pdo->options;
d5a76da4
BP
1745 o < &pdo->options[pdo->n_options]; o++) {
1746 if (o != offerip_opt) {
1747 encode_put_dhcpv4_option(o, ofpacts);
a9e1b66f
RB
1748 }
1749 }
1750
d5a76da4 1751 encode_finish_controller_op(oc_offset, ofpacts);
78aab811
JP
1752}
1753
de297547 1754static void
16936e4d 1755encode_PUT_DHCPV6_OPTS(const struct ovnact_put_opts *pdo,
d5a76da4
BP
1756 const struct ovnact_encode_params *ep OVS_UNUSED,
1757 struct ofpbuf *ofpacts)
de297547 1758{
d5a76da4 1759 struct mf_subfield dst = expr_resolve_field(&pdo->dst);
de297547 1760
d5a76da4
BP
1761 size_t oc_offset = encode_start_controller_op(
1762 ACTION_OPCODE_PUT_DHCPV6_OPTS, true, ofpacts);
1763 nx_put_header(ofpacts, dst.field->id, OFP13_VERSION, false);
1764 ovs_be32 ofs = htonl(dst.ofs);
1765 ofpbuf_put(ofpacts, &ofs, sizeof ofs);
de297547 1766
16936e4d 1767 for (const struct ovnact_gen_option *o = pdo->options;
d5a76da4
BP
1768 o < &pdo->options[pdo->n_options]; o++) {
1769 encode_put_dhcpv6_option(o, ofpacts);
de297547 1770 }
de297547 1771
d5a76da4
BP
1772 encode_finish_controller_op(oc_offset, ofpacts);
1773}
de297547 1774
d5a76da4 1775static void
16936e4d 1776ovnact_put_opts_free(struct ovnact_put_opts *pdo)
d5a76da4 1777{
16936e4d 1778 free_gen_options(pdo->options, pdo->n_options);
d5a76da4 1779}
de297547 1780
a6095f81
BS
1781static void
1782parse_SET_QUEUE(struct action_context *ctx)
1783{
1784 int queue_id;
1785
1786 if (!lexer_force_match(ctx->lexer, LEX_T_LPAREN)
1787 || !lexer_get_int(ctx->lexer, &queue_id)
1788 || !lexer_force_match(ctx->lexer, LEX_T_RPAREN)) {
1789 return;
1790 }
1791
1792 if (queue_id < QDISC_MIN_QUEUE_ID || queue_id > QDISC_MAX_QUEUE_ID) {
1793 lexer_error(ctx->lexer, "Queue ID %d for set_queue is "
1794 "not in valid range %d to %d.",
1795 queue_id, QDISC_MIN_QUEUE_ID, QDISC_MAX_QUEUE_ID);
1796 return;
1797 }
1798
1799 ovnact_put_SET_QUEUE(ctx->ovnacts)->queue_id = queue_id;
1800}
1801
1802static void
1803format_SET_QUEUE(const struct ovnact_set_queue *set_queue, struct ds *s)
1804{
1805 ds_put_format(s, "set_queue(%d);", set_queue->queue_id);
1806}
1807
1808static void
1809encode_SET_QUEUE(const struct ovnact_set_queue *set_queue,
1810 const struct ovnact_encode_params *ep OVS_UNUSED,
1811 struct ofpbuf *ofpacts)
1812{
1813 ofpact_put_SET_QUEUE(ofpacts)->queue_id = set_queue->queue_id;
1814}
1815
1816static void
80b6743d 1817ovnact_set_queue_free(struct ovnact_set_queue *a OVS_UNUSED)
a6095f81
BS
1818{
1819}
ea991ad2
NS
1820
1821static void
1822parse_dns_lookup(struct action_context *ctx, const struct expr_field *dst,
1823 struct ovnact_dns_lookup *dl)
1824{
1825 lexer_get(ctx->lexer); /* Skip dns_lookup. */
1826 lexer_get(ctx->lexer); /* Skip '('. */
1827 if (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
1828 lexer_error(ctx->lexer, "dns_lookup doesn't take any parameters");
1829 return;
1830 }
1831 /* Validate that the destination is a 1-bit, modifiable field. */
1832 char *error = expr_type_check(dst, 1, true);
1833 if (error) {
1834 lexer_error(ctx->lexer, "%s", error);
1835 free(error);
1836 return;
1837 }
1838 dl->dst = *dst;
1839 add_prerequisite(ctx, "udp");
1840}
1841
1842static void
1843format_DNS_LOOKUP(const struct ovnact_dns_lookup *dl, struct ds *s)
1844{
1845 expr_field_format(&dl->dst, s);
1846 ds_put_cstr(s, " = dns_lookup();");
1847}
1848
1849static void
1850encode_DNS_LOOKUP(const struct ovnact_dns_lookup *dl,
1851 const struct ovnact_encode_params *ep OVS_UNUSED,
1852 struct ofpbuf *ofpacts)
1853{
1854 struct mf_subfield dst = expr_resolve_field(&dl->dst);
1855
1856 size_t oc_offset = encode_start_controller_op(ACTION_OPCODE_DNS_LOOKUP,
1857 true, ofpacts);
1858 nx_put_header(ofpacts, dst.field->id, OFP13_VERSION, false);
1859 ovs_be32 ofs = htonl(dst.ofs);
1860 ofpbuf_put(ofpacts, &ofs, sizeof ofs);
1861 encode_finish_controller_op(oc_offset, ofpacts);
1862}
1863
1864
1865static void
1866ovnact_dns_lookup_free(struct ovnact_dns_lookup *dl OVS_UNUSED)
1867{
1868}
52ed5fcc
NS
1869
1870/* Parses the "put_nd_ra_opts" action.
1871 * The caller has already consumed "<dst> =", so this just parses the rest. */
1872static void
1873parse_put_nd_ra_opts(struct action_context *ctx, const struct expr_field *dst,
1874 struct ovnact_put_opts *po)
1875{
1876 parse_put_opts(ctx, dst, po, ctx->pp->nd_ra_opts, "IPv6 ND RA");
1877
1878 if (ctx->lexer->error) {
1879 return;
1880 }
1881
1882 bool addr_mode_stateful = false;
1883 bool prefix_set = false;
1884 bool slla_present = false;
1885 /* Let's validate the options. */
1886 for (struct ovnact_gen_option *o = po->options;
1887 o < &po->options[po->n_options]; o++) {
1888 const union expr_constant *c = o->value.values;
1889 if (o->value.n_values > 1) {
1890 lexer_error(ctx->lexer, "Invalid value for \"%s\" option",
1891 o->option->name);
1892 return;
1893 }
1894
1895 bool ok = true;
1896 switch (o->option->code) {
1897 case ND_RA_FLAG_ADDR_MODE:
1898 ok = (c->string && (!strcmp(c->string, "slaac") ||
1899 !strcmp(c->string, "dhcpv6_stateful") ||
1900 !strcmp(c->string, "dhcpv6_stateless")));
1901 if (ok && !strcmp(c->string, "dhcpv6_stateful")) {
1902 addr_mode_stateful = true;
1903 }
1904 break;
1905
1906 case ND_OPT_SOURCE_LINKADDR:
1907 ok = c->format == LEX_F_ETHERNET;
1908 slla_present = true;
1909 break;
1910
1911 case ND_OPT_PREFIX_INFORMATION:
1912 ok = c->format == LEX_F_IPV6 && c->masked;
1913 prefix_set = true;
1914 break;
1915
1916 case ND_OPT_MTU:
1917 ok = c->format == LEX_F_DECIMAL;
1918 break;
1919 }
1920
1921 if (!ok) {
1922 lexer_error(ctx->lexer, "Invalid value for \"%s\" option",
1923 o->option->name);
1924 return;
1925 }
1926 }
1927
1928 if (!slla_present) {
1929 lexer_error(ctx->lexer, "slla option not present");
1930 return;
1931 }
1932
1933 if (addr_mode_stateful && prefix_set) {
1934 lexer_error(ctx->lexer, "prefix option can't be"
1935 " set when address mode is dhcpv6_stateful.");
1936 return;
1937 }
1938
1939 if (!addr_mode_stateful && !prefix_set) {
1940 lexer_error(ctx->lexer, "prefix option needs "
1941 "to be set when address mode is slaac/dhcpv6_stateless.");
1942 return;
1943 }
1944
1945 add_prerequisite(ctx, "ip6");
1946}
1947
1948static void
1949format_PUT_ND_RA_OPTS(const struct ovnact_put_opts *po,
1950 struct ds *s)
1951{
1952 format_put_opts("put_nd_ra_opts", po, s);
1953}
1954
1955static void
1956encode_put_nd_ra_option(const struct ovnact_gen_option *o,
1957 struct ofpbuf *ofpacts, struct ovs_ra_msg *ra)
1958{
1959 const union expr_constant *c = o->value.values;
1960
1961 switch (o->option->code) {
1962 case ND_RA_FLAG_ADDR_MODE:
1963 if (!strcmp(c->string, "dhcpv6_stateful")) {
1964 ra->mo_flags = IPV6_ND_RA_FLAG_MANAGED_ADDR_CONFIG;
1965 } else if (!strcmp(c->string, "dhcpv6_stateless")) {
1966 ra->mo_flags = IPV6_ND_RA_FLAG_OTHER_ADDR_CONFIG;
1967 }
1968 break;
1969
1970 case ND_OPT_SOURCE_LINKADDR:
1971 {
1972 struct ovs_nd_lla_opt *lla_opt =
1973 ofpbuf_put_uninit(ofpacts, sizeof *lla_opt);
1974 lla_opt->type = ND_OPT_SOURCE_LINKADDR;
1975 lla_opt->len = 1;
1976 lla_opt->mac = c->value.mac;
1977 break;
1978 }
1979
1980 case ND_OPT_MTU:
1981 {
1982 struct ovs_nd_mtu_opt *mtu_opt =
1983 ofpbuf_put_uninit(ofpacts, sizeof *mtu_opt);
1984 mtu_opt->type = ND_OPT_MTU;
1985 mtu_opt->len = 1;
1986 mtu_opt->reserved = 0;
1987 put_16aligned_be32(&mtu_opt->mtu, c->value.be32_int);
1988 break;
1989 }
1990
1991 case ND_OPT_PREFIX_INFORMATION:
1992 {
1993 struct ovs_nd_prefix_opt *prefix_opt =
1994 ofpbuf_put_uninit(ofpacts, sizeof *prefix_opt);
1995 uint8_t prefix_len = ipv6_count_cidr_bits(&c->mask.ipv6);
1996 prefix_opt->type = ND_OPT_PREFIX_INFORMATION;
1997 prefix_opt->len = 4;
1998 prefix_opt->prefix_len = prefix_len;
1999 prefix_opt->la_flags = IPV6_ND_RA_OPT_PREFIX_FLAGS;
2000 put_16aligned_be32(&prefix_opt->valid_lifetime,
2001 htonl(IPV6_ND_RA_OPT_PREFIX_VALID_LIFETIME));
2002 put_16aligned_be32(&prefix_opt->preferred_lifetime,
2003 htonl(IPV6_ND_RA_OPT_PREFIX_PREFERRED_LIFETIME));
2004 put_16aligned_be32(&prefix_opt->reserved, 0);
2005 memcpy(prefix_opt->prefix.be32, &c->value.be128[7].be32,
2006 sizeof(ovs_be32[4]));
2007 break;
2008 }
2009 }
2010}
2011
2012static void
2013encode_PUT_ND_RA_OPTS(const struct ovnact_put_opts *po,
2014 const struct ovnact_encode_params *ep OVS_UNUSED,
2015 struct ofpbuf *ofpacts)
2016{
2017 struct mf_subfield dst = expr_resolve_field(&po->dst);
2018
2019 size_t oc_offset = encode_start_controller_op(
2020 ACTION_OPCODE_PUT_ND_RA_OPTS, true, ofpacts);
2021 nx_put_header(ofpacts, dst.field->id, OFP13_VERSION, false);
2022 ovs_be32 ofs = htonl(dst.ofs);
2023 ofpbuf_put(ofpacts, &ofs, sizeof ofs);
2024
2025 /* Frame the complete ICMPv6 Router Advertisement data encoding
2026 * the ND RA options in it, in the userdata field, so that when
2027 * pinctrl module receives the ICMPv6 Router Solicitation packet
2028 * it can copy the userdata field AS IS and resume the packet.
2029 */
2030 struct ovs_ra_msg *ra = ofpbuf_put_zeros(ofpacts, sizeof *ra);
2031 ra->icmph.icmp6_type = ND_ROUTER_ADVERT;
2032 ra->cur_hop_limit = IPV6_ND_RA_CUR_HOP_LIMIT;
2033 ra->mo_flags = 0;
2034 ra->router_lifetime = htons(IPV6_ND_RA_LIFETIME);
2035
2036 for (const struct ovnact_gen_option *o = po->options;
2037 o < &po->options[po->n_options]; o++) {
2038 encode_put_nd_ra_option(o, ofpacts, ra);
2039 }
2040
2041 encode_finish_controller_op(oc_offset, ofpacts);
2042}
2043
d5a76da4 2044\f
d383eed5
JP
2045static void
2046parse_log_arg(struct action_context *ctx, struct ovnact_log *log)
2047{
2048 if (lexer_match_id(ctx->lexer, "verdict")) {
2049 if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) {
2050 return;
2051 }
2052 if (lexer_match_id(ctx->lexer, "drop")) {
2053 log->verdict = LOG_VERDICT_DROP;
2054 } else if (lexer_match_id(ctx->lexer, "reject")) {
2055 log->verdict = LOG_VERDICT_REJECT;
2056 } else if (lexer_match_id(ctx->lexer, "allow")) {
2057 log->verdict = LOG_VERDICT_ALLOW;
2058 } else {
2059 lexer_syntax_error(ctx->lexer, "unknown acl verdict");
2060 }
2061 } else if (lexer_match_id(ctx->lexer, "name")) {
2062 if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) {
2063 return;
2064 }
2065 /* If multiple names are given, use the most recent. */
2066 if (ctx->lexer->token.type == LEX_T_STRING) {
2067 /* Arbitrarily limit the name length to 64 bytes, since
2068 * these will be encoded in datapath actions. */
2069 if (strlen(ctx->lexer->token.s) >= 64) {
2070 lexer_syntax_error(ctx->lexer, "name must be shorter "
2071 "than 64 characters");
2072 return;
2073 }
2074 free(log->name);
2075 log->name = xstrdup(ctx->lexer->token.s);
2076 } else {
2077 lexer_syntax_error(ctx->lexer, "expecting string");
2078 return;
2079 }
2080 lexer_get(ctx->lexer);
2081 } else if (lexer_match_id(ctx->lexer, "severity")) {
2082 if (!lexer_force_match(ctx->lexer, LEX_T_EQUALS)) {
2083 return;
2084 }
2085 if (ctx->lexer->token.type == LEX_T_ID) {
2086 uint8_t severity = log_severity_from_string(ctx->lexer->token.s);
2087 if (severity != UINT8_MAX) {
2088 log->severity = severity;
2089 lexer_get(ctx->lexer);
2090 return;
2091 }
2092 }
2093 lexer_syntax_error(ctx->lexer, "expecting severity");
2094 } else {
2095 lexer_syntax_error(ctx->lexer, NULL);
2096 }
2097}
2098
2099static void
2100parse_LOG(struct action_context *ctx)
2101{
2102 struct ovnact_log *log = ovnact_put_LOG(ctx->ovnacts);
2103
2104 /* Provide default values. */
2105 log->severity = LOG_SEVERITY_INFO;
2106 log->verdict = LOG_VERDICT_UNKNOWN;
2107
2108 if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {
2109 while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
2110 parse_log_arg(ctx, log);
2111 if (ctx->lexer->error) {
2112 return;
2113 }
2114 lexer_match(ctx->lexer, LEX_T_COMMA);
2115 }
2116 }
2117}
2118
2119static void
2120format_LOG(const struct ovnact_log *log, struct ds *s)
2121{
2122 ds_put_cstr(s, "log(");
2123
2124 if (log->name) {
2125 ds_put_format(s, "name=\"%s\", ", log->name);
2126 }
2127
2128 ds_put_format(s, "verdict=%s, ", log_verdict_to_string(log->verdict));
2129 ds_put_format(s, "severity=%s);", log_severity_to_string(log->severity));
2130}
2131
2132static void
2133encode_LOG(const struct ovnact_log *log,
2134 const struct ovnact_encode_params *ep OVS_UNUSED,
2135 struct ofpbuf *ofpacts)
2136{
2137 size_t oc_offset = encode_start_controller_op(ACTION_OPCODE_LOG, false,
2138 ofpacts);
2139
2140 struct log_pin_header *lph = ofpbuf_put_uninit(ofpacts, sizeof *lph);
2141 lph->verdict = log->verdict;
2142 lph->severity = log->severity;
2143
2144 if (log->name) {
2145 int name_len = strlen(log->name);
2146 ofpbuf_put(ofpacts, log->name, name_len);
2147 }
2148
2149 encode_finish_controller_op(oc_offset, ofpacts);
2150}
2151
2152static void
2153ovnact_log_free(struct ovnact_log *log)
2154{
2155 free(log->name);
2156}
2157
66d89287
GL
2158static void
2159parse_set_meter_action(struct action_context *ctx)
2160{
2161 uint64_t rate = 0;
2162 uint64_t burst = 0;
2163
2164 lexer_force_match(ctx->lexer, LEX_T_LPAREN); /* Skip '('. */
2165 if (ctx->lexer->token.type == LEX_T_INTEGER
2166 && ctx->lexer->token.format == LEX_F_DECIMAL) {
2167 rate = ntohll(ctx->lexer->token.value.integer);
2168 }
2169 lexer_get(ctx->lexer);
2170 if (lexer_match(ctx->lexer, LEX_T_COMMA)) { /* Skip ','. */
2171 if (ctx->lexer->token.type == LEX_T_INTEGER
2172 && ctx->lexer->token.format == LEX_F_DECIMAL) {
2173 burst = ntohll(ctx->lexer->token.value.integer);
2174 }
2175 lexer_get(ctx->lexer);
2176 }
2177 lexer_force_match(ctx->lexer, LEX_T_RPAREN); /* Skip ')'. */
2178
2179 if (!rate) {
2180 lexer_error(ctx->lexer,
2181 "Rate %"PRId64" for set_meter is not in valid.",
2182 rate);
2183 return;
2184 }
2185
2186 struct ovnact_set_meter *cl = ovnact_put_SET_METER(ctx->ovnacts);
2187 cl->rate = rate;
2188 cl->burst = burst;
2189}
2190
2191static void
2192format_SET_METER(const struct ovnact_set_meter *cl, struct ds *s)
2193{
2194 if (cl->burst) {
2195 ds_put_format(s, "set_meter(%"PRId64", %"PRId64");",
2196 cl->rate, cl->burst);
2197 } else {
2198 ds_put_format(s, "set_meter(%"PRId64");", cl->rate);
2199 }
2200}
2201
2202static void
2203encode_SET_METER(const struct ovnact_set_meter *cl,
2204 const struct ovnact_encode_params *ep,
2205 struct ofpbuf *ofpacts)
2206{
2207 uint32_t table_id;
2208 struct ofpact_meter *om;
2209
2210 struct ds ds = DS_EMPTY_INITIALIZER;
2211 if (cl->burst) {
2212 ds_put_format(&ds,
2213 "kbps burst stats bands=type=drop rate=%"PRId64" "
2214 "burst_size=%"PRId64"",
2215 cl->rate, cl->burst);
2216 } else {
2217 ds_put_format(&ds, "kbps stats bands=type=drop rate=%"PRId64"",
2218 cl->rate);
2219 }
2220
2221 table_id = ovn_extend_table_assign_id(ep->meter_table, &ds);
2222 if (table_id == EXT_TABLE_ID_INVALID) {
2223 ds_destroy(&ds);
2224 return;
2225 }
2226
2227 ds_destroy(&ds);
2228
2229 /* Create an action to set the meter. */
2230 om = ofpact_put_METER(ofpacts);
2231 om->meter_id = table_id;
2232}
2233
2234static void
2235ovnact_set_meter_free(struct ovnact_set_meter *ct OVS_UNUSED)
2236{
2237}
2238
d5a76da4
BP
2239/* Parses an assignment or exchange or put_dhcp_opts action. */
2240static void
2241parse_set_action(struct action_context *ctx)
2242{
d5a76da4 2243 struct expr_field lhs;
9aef3c1b
BP
2244 if (!expr_field_parse(ctx->lexer, ctx->pp->symtab, &lhs, &ctx->prereqs)) {
2245 return;
2246 }
de297547 2247
9aef3c1b
BP
2248 if (lexer_match(ctx->lexer, LEX_T_EXCHANGE)) {
2249 parse_assignment_action(ctx, true, &lhs);
2250 } else if (lexer_match(ctx->lexer, LEX_T_EQUALS)) {
2251 if (ctx->lexer->token.type != LEX_T_ID) {
2252 parse_LOAD(ctx, &lhs);
2253 } else if (!strcmp(ctx->lexer->token.s, "put_dhcp_opts")
2254 && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) {
2255 parse_put_dhcp_opts(ctx, &lhs, ovnact_put_PUT_DHCPV4_OPTS(
2256 ctx->ovnacts));
2257 } else if (!strcmp(ctx->lexer->token.s, "put_dhcpv6_opts")
2258 && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) {
2259 parse_put_dhcp_opts(ctx, &lhs, ovnact_put_PUT_DHCPV6_OPTS(
2260 ctx->ovnacts));
ea991ad2
NS
2261 } else if (!strcmp(ctx->lexer->token.s, "dns_lookup")
2262 && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) {
2263 parse_dns_lookup(ctx, &lhs, ovnact_put_DNS_LOOKUP(ctx->ovnacts));
52ed5fcc
NS
2264 } else if (!strcmp(ctx->lexer->token.s, "put_nd_ra_opts")
2265 && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) {
2266 parse_put_nd_ra_opts(ctx, &lhs,
2267 ovnact_put_PUT_ND_RA_OPTS(ctx->ovnacts));
de297547 2268 } else {
9aef3c1b 2269 parse_assignment_action(ctx, false, &lhs);
de297547 2270 }
9aef3c1b
BP
2271 } else {
2272 lexer_syntax_error(ctx->lexer, "expecting `=' or `<->'");
de297547 2273 }
de297547
GS
2274}
2275
d8681a83
BP
2276static bool
2277parse_action(struct action_context *ctx)
2278{
2279 if (ctx->lexer->token.type != LEX_T_ID) {
9aef3c1b 2280 lexer_syntax_error(ctx->lexer, NULL);
d8681a83
BP
2281 return false;
2282 }
2283
2284 enum lex_type lookahead = lexer_lookahead(ctx->lexer);
2285 if (lookahead == LEX_T_EQUALS || lookahead == LEX_T_EXCHANGE
2286 || lookahead == LEX_T_LSQUARE) {
2287 parse_set_action(ctx);
2288 } else if (lexer_match_id(ctx->lexer, "next")) {
d5a76da4 2289 parse_NEXT(ctx);
d8681a83 2290 } else if (lexer_match_id(ctx->lexer, "output")) {
d5a76da4 2291 ovnact_put_OUTPUT(ctx->ovnacts);
d8681a83 2292 } else if (lexer_match_id(ctx->lexer, "ip.ttl")) {
d5a76da4 2293 parse_DEC_TTL(ctx);
d8681a83 2294 } else if (lexer_match_id(ctx->lexer, "ct_next")) {
d5a76da4 2295 parse_CT_NEXT(ctx);
d8681a83 2296 } else if (lexer_match_id(ctx->lexer, "ct_commit")) {
d5a76da4 2297 parse_CT_COMMIT(ctx);
de297547 2298 } else if (lexer_match_id(ctx->lexer, "ct_dnat")) {
d5a76da4 2299 parse_CT_DNAT(ctx);
de297547 2300 } else if (lexer_match_id(ctx->lexer, "ct_snat")) {
d5a76da4 2301 parse_CT_SNAT(ctx);
467085fd
GS
2302 } else if (lexer_match_id(ctx->lexer, "ct_lb")) {
2303 parse_ct_lb_action(ctx);
db0e819b
BP
2304 } else if (lexer_match_id(ctx->lexer, "ct_clear")) {
2305 ovnact_put_CT_CLEAR(ctx->ovnacts);
b3bd2c33
BP
2306 } else if (lexer_match_id(ctx->lexer, "clone")) {
2307 parse_CLONE(ctx);
6335d074 2308 } else if (lexer_match_id(ctx->lexer, "arp")) {
d5a76da4 2309 parse_ARP(ctx);
bc3d6a63
LB
2310 } else if (lexer_match_id(ctx->lexer, "icmp4")) {
2311 parse_ICMP4(ctx);
3e7fa1e3
LB
2312 } else if (lexer_match_id(ctx->lexer, "icmp6")) {
2313 parse_ICMP6(ctx);
22b65e4d
LB
2314 } else if (lexer_match_id(ctx->lexer, "tcp_reset")) {
2315 parse_TCP_RESET(ctx);
d5a76da4
BP
2316 } else if (lexer_match_id(ctx->lexer, "nd_na")) {
2317 parse_ND_NA(ctx);
b1a3a6a4
NS
2318 } else if (lexer_match_id(ctx->lexer, "nd_ns")) {
2319 parse_ND_NS(ctx);
0bac7164 2320 } else if (lexer_match_id(ctx->lexer, "get_arp")) {
d5a76da4 2321 parse_get_mac_bind(ctx, 32, ovnact_put_GET_ARP(ctx->ovnacts));
0bac7164 2322 } else if (lexer_match_id(ctx->lexer, "put_arp")) {
d5a76da4 2323 parse_put_mac_bind(ctx, 32, ovnact_put_PUT_ARP(ctx->ovnacts));
c34a87b6 2324 } else if (lexer_match_id(ctx->lexer, "get_nd")) {
d5a76da4 2325 parse_get_mac_bind(ctx, 128, ovnact_put_GET_ND(ctx->ovnacts));
c34a87b6 2326 } else if (lexer_match_id(ctx->lexer, "put_nd")) {
d5a76da4 2327 parse_put_mac_bind(ctx, 128, ovnact_put_PUT_ND(ctx->ovnacts));
a6095f81
BS
2328 } else if (lexer_match_id(ctx->lexer, "set_queue")) {
2329 parse_SET_QUEUE(ctx);
d383eed5
JP
2330 } else if (lexer_match_id(ctx->lexer, "log")) {
2331 parse_LOG(ctx);
66d89287
GL
2332 } else if (lexer_match_id(ctx->lexer, "set_meter")) {
2333 parse_set_meter_action(ctx);
d8681a83 2334 } else {
9aef3c1b 2335 lexer_syntax_error(ctx->lexer, "expecting action");
d8681a83 2336 }
9aef3c1b
BP
2337 lexer_force_match(ctx->lexer, LEX_T_SEMICOLON);
2338 return !ctx->lexer->error;
d8681a83
BP
2339}
2340
3b7cb7e1 2341static void
bac29564 2342parse_actions(struct action_context *ctx, enum lex_type sentinel)
3b7cb7e1
BP
2343{
2344 /* "drop;" by itself is a valid (empty) set of actions, but it can't be
2345 * combined with other actions because that doesn't make sense. */
2346 if (ctx->lexer->token.type == LEX_T_ID
2347 && !strcmp(ctx->lexer->token.s, "drop")
2348 && lexer_lookahead(ctx->lexer) == LEX_T_SEMICOLON) {
2349 lexer_get(ctx->lexer); /* Skip "drop". */
2350 lexer_get(ctx->lexer); /* Skip ";". */
bac29564 2351 lexer_force_match(ctx->lexer, sentinel);
3b7cb7e1
BP
2352 return;
2353 }
2354
bac29564 2355 while (!lexer_match(ctx->lexer, sentinel)) {
d8681a83 2356 if (!parse_action(ctx)) {
3b7cb7e1
BP
2357 return;
2358 }
2359 }
2360}
2361
2362/* Parses OVN actions, in the format described for the "actions" column in the
48605550 2363 * Logical_Flow table in ovn-sb(5), and appends the parsed versions of the
d5a76da4
BP
2364 * actions to 'ovnacts' as "struct ovnact"s. The caller must eventually free
2365 * the parsed ovnacts with ovnacts_free().
3b7cb7e1 2366 *
d5a76da4 2367 * 'pp' provides most of the parameters for translation.
3646e396 2368 *
3b7cb7e1
BP
2369 * Some actions add extra requirements (prerequisites) to the flow's match. If
2370 * so, this function sets '*prereqsp' to the actions' prerequisites; otherwise,
2371 * it sets '*prereqsp' to NULL. The caller owns '*prereqsp' and must
2372 * eventually free it.
2373 *
9aef3c1b
BP
2374 * Returns true if successful, false if an error occurred. Upon return,
2375 * returns true if and only if lexer->error is NULL.
d5a76da4 2376 */
9aef3c1b 2377bool
d5a76da4
BP
2378ovnacts_parse(struct lexer *lexer, const struct ovnact_parse_params *pp,
2379 struct ofpbuf *ovnacts, struct expr **prereqsp)
3b7cb7e1 2380{
d5a76da4 2381 size_t ovnacts_start = ovnacts->size;
3b7cb7e1 2382
1d7b2ece 2383 struct action_context ctx = {
d5a76da4 2384 .pp = pp,
1d7b2ece 2385 .lexer = lexer,
d5a76da4 2386 .ovnacts = ovnacts,
1d7b2ece
BP
2387 .prereqs = NULL,
2388 };
9aef3c1b 2389 if (!lexer->error) {
bac29564 2390 parse_actions(&ctx, LEX_T_END);
9aef3c1b 2391 }
3b7cb7e1 2392
9aef3c1b 2393 if (!lexer->error) {
3b7cb7e1 2394 *prereqsp = ctx.prereqs;
9aef3c1b 2395 return true;
3b7cb7e1 2396 } else {
d5a76da4
BP
2397 ofpbuf_pull(ovnacts, ovnacts_start);
2398 ovnacts_free(ovnacts->data, ovnacts->size);
2399 ofpbuf_push_uninit(ovnacts, ovnacts_start);
2400
2401 ovnacts->size = ovnacts_start;
3b7cb7e1
BP
2402 expr_destroy(ctx.prereqs);
2403 *prereqsp = NULL;
9aef3c1b 2404 return false;
3b7cb7e1
BP
2405 }
2406}
2407
d5a76da4 2408/* Like ovnacts_parse(), but the actions are taken from 's'. */
3b7cb7e1 2409char * OVS_WARN_UNUSED_RESULT
d5a76da4 2410ovnacts_parse_string(const char *s, const struct ovnact_parse_params *pp,
1d7b2ece 2411 struct ofpbuf *ofpacts, struct expr **prereqsp)
3b7cb7e1
BP
2412{
2413 struct lexer lexer;
3b7cb7e1
BP
2414
2415 lexer_init(&lexer, s);
2416 lexer_get(&lexer);
9aef3c1b
BP
2417 ovnacts_parse(&lexer, pp, ofpacts, prereqsp);
2418 char *error = lexer_steal_error(&lexer);
3b7cb7e1
BP
2419 lexer_destroy(&lexer);
2420
2421 return error;
2422}
d5a76da4
BP
2423\f
2424/* Formatting ovnacts. */
2425
2426static void
2427ovnact_format(const struct ovnact *a, struct ds *s)
2428{
2429 switch (a->type) {
2430#define OVNACT(ENUM, STRUCT) \
2431 case OVNACT_##ENUM: \
2432 format_##ENUM(ALIGNED_CAST(const struct STRUCT *, a), s); \
2433 break;
2434 OVNACTS
2435#undef OVNACT
2436 default:
2437 OVS_NOT_REACHED();
2438 }
2439}
2440
2441/* Appends a string representing the 'ovnacts_len' bytes of ovnacts in
2442 * 'ovnacts' to 'string'. */
2443void
2444ovnacts_format(const struct ovnact *ovnacts, size_t ovnacts_len,
2445 struct ds *string)
2446{
2447 if (!ovnacts_len) {
2448 ds_put_cstr(string, "drop;");
2449 } else {
2450 const struct ovnact *a;
2451
2452 OVNACT_FOR_EACH (a, ovnacts, ovnacts_len) {
2453 if (a != ovnacts) {
2454 ds_put_char(string, ' ');
2455 }
2456 ovnact_format(a, string);
2457 }
2458 }
2459}
2460\f
2461/* Encoding ovnacts to OpenFlow. */
2462
2463static void
2464ovnact_encode(const struct ovnact *a, const struct ovnact_encode_params *ep,
2465 struct ofpbuf *ofpacts)
2466{
2467 switch (a->type) {
2468#define OVNACT(ENUM, STRUCT) \
2469 case OVNACT_##ENUM: \
2470 encode_##ENUM(ALIGNED_CAST(const struct STRUCT *, a), \
2471 ep, ofpacts); \
2472 break;
2473 OVNACTS
2474#undef OVNACT
2475 default:
2476 OVS_NOT_REACHED();
2477 }
2478}
2479
2480/* Appends ofpacts to 'ofpacts' that represent the actions in the 'ovnacts_len'
2481 * bytes of actions starting at 'ovnacts'. */
2482void
2483ovnacts_encode(const struct ovnact *ovnacts, size_t ovnacts_len,
2484 const struct ovnact_encode_params *ep,
2485 struct ofpbuf *ofpacts)
2486{
2487 if (ovnacts) {
2488 const struct ovnact *a;
2489
2490 OVNACT_FOR_EACH (a, ovnacts, ovnacts_len) {
2491 ovnact_encode(a, ep, ofpacts);
2492 }
2493 }
2494}
2495\f
2496/* Freeing ovnacts. */
2497
2498static void
2499ovnact_free(struct ovnact *a)
2500{
2501 switch (a->type) {
2502#define OVNACT(ENUM, STRUCT) \
2503 case OVNACT_##ENUM: \
80b6743d 2504 STRUCT##_free(ALIGNED_CAST(struct STRUCT *, a)); \
d5a76da4
BP
2505 break;
2506 OVNACTS
2507#undef OVNACT
2508 default:
2509 OVS_NOT_REACHED();
2510 }
2511}
2512
2513/* Frees each of the actions in the 'ovnacts_len' bytes of actions starting at
2514 * 'ovnacts'.
2515 *
2516 * Does not call free(ovnacts); the caller must do so if desirable. */
2517void
2518ovnacts_free(struct ovnact *ovnacts, size_t ovnacts_len)
2519{
2520 if (ovnacts) {
2521 struct ovnact *a;
2522
2523 OVNACT_FOR_EACH (a, ovnacts, ovnacts_len) {
2524 ovnact_free(a);
2525 }
2526 }
2527}