]> git.proxmox.com Git - ovs.git/blame - ovn/lib/actions.c
ovn: Support multiple addresses on a single logical router port.
[ovs.git] / ovn / lib / actions.c
CommitLineData
3b7cb7e1 1/*
6335d074 2 * Copyright (c) 2015, 2016 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>
b598f214 20#include "actions.h"
467085fd 21#include "bitmap.h"
f4248336 22#include "byte-order.h"
3b7cb7e1 23#include "compiler.h"
42814145 24#include "ovn-dhcp.h"
3b7cb7e1 25#include "expr.h"
467085fd
GS
26#include "hash.h"
27#include "hmap.h"
3b7cb7e1 28#include "lex.h"
667e2b0b 29#include "logical-fields.h"
42814145 30#include "nx-match.h"
b598f214
BW
31#include "openvswitch/dynamic-string.h"
32#include "openvswitch/ofp-actions.h"
64c96779 33#include "openvswitch/ofpbuf.h"
42814145
NS
34#include "packets.h"
35#include "shash.h"
78aab811 36#include "simap.h"
3b7cb7e1
BP
37
38/* Context maintained during actions_parse(). */
39struct action_context {
1d7b2ece 40 const struct action_params *ap; /* Parameters. */
3b7cb7e1 41 struct lexer *lexer; /* Lexer for pulling more tokens. */
3b7cb7e1 42 char *error; /* Error, if any, otherwise NULL. */
3b7cb7e1
BP
43 struct ofpbuf *ofpacts; /* Actions. */
44 struct expr *prereqs; /* Prerequisites to apply to match. */
45};
46
d8681a83 47static bool parse_action(struct action_context *);
42814145
NS
48static void parse_put_dhcp_opts_action(struct action_context *,
49 const struct expr_field *dst);
d8681a83 50
3b7cb7e1
BP
51static bool
52action_error_handle_common(struct action_context *ctx)
53{
54 if (ctx->error) {
55 /* Already have an error, suppress this one since the cascade seems
56 * unlikely to be useful. */
57 return true;
58 } else if (ctx->lexer->token.type == LEX_T_ERROR) {
59 /* The lexer signaled an error. Nothing at the action level
60 * accepts an error token, so we'll inevitably end up here with some
61 * meaningless parse error. Report the lexical error instead. */
62 ctx->error = xstrdup(ctx->lexer->token.s);
63 return true;
64 } else {
65 return false;
66 }
67}
68
69static void OVS_PRINTF_FORMAT(2, 3)
70action_error(struct action_context *ctx, const char *message, ...)
71{
72 if (action_error_handle_common(ctx)) {
73 return;
74 }
75
76 va_list args;
77 va_start(args, message);
78 ctx->error = xvasprintf(message, args);
79 va_end(args);
80}
81
82static void OVS_PRINTF_FORMAT(2, 3)
83action_syntax_error(struct action_context *ctx, const char *message, ...)
84{
85 if (action_error_handle_common(ctx)) {
86 return;
87 }
88
89 struct ds s;
90
91 ds_init(&s);
92 ds_put_cstr(&s, "Syntax error");
93 if (ctx->lexer->token.type == LEX_T_END) {
94 ds_put_cstr(&s, " at end of input");
95 } else if (ctx->lexer->start) {
96 ds_put_format(&s, " at `%.*s'",
97 (int) (ctx->lexer->input - ctx->lexer->start),
98 ctx->lexer->start);
99 }
100
101 if (message) {
102 ds_put_char(&s, ' ');
103
104 va_list args;
105 va_start(args, message);
106 ds_put_format_valist(&s, message, args);
107 va_end(args);
108 }
109 ds_put_char(&s, '.');
110
111 ctx->error = ds_steal_cstr(&s);
112}
113
42814145 114/* Parses an assignment or exchange or put_dhcp_opts action. */
3b7cb7e1
BP
115static void
116parse_set_action(struct action_context *ctx)
117{
8fb72d29
BP
118 struct expr *prereqs = NULL;
119 struct expr_field dst;
3b7cb7e1
BP
120 char *error;
121
8fb72d29
BP
122 error = expr_parse_field(ctx->lexer, ctx->ap->symtab, &dst);
123 if (!error) {
124 if (lexer_match(ctx->lexer, LEX_T_EXCHANGE)) {
125 error = expr_parse_exchange(ctx->lexer, &dst, ctx->ap->symtab,
126 ctx->ap->lookup_port, ctx->ap->aux,
127 ctx->ofpacts, &prereqs);
128 } else if (lexer_match(ctx->lexer, LEX_T_EQUALS)) {
42814145
NS
129 if (ctx->lexer->token.type == LEX_T_ID
130 && !strcmp(ctx->lexer->token.s, "put_dhcp_opts")
131 && lexer_lookahead(ctx->lexer) == LEX_T_LPAREN) {
132 lexer_get(ctx->lexer); /* Skip put_dhcp_opts. */
133 lexer_get(ctx->lexer); /* Skip '('. */
134 parse_put_dhcp_opts_action(ctx, &dst);
135 } else {
136 error = expr_parse_assignment(
137 ctx->lexer, &dst, ctx->ap->symtab, ctx->ap->lookup_port,
138 ctx->ap->aux, ctx->ofpacts, &prereqs);
139 }
8fb72d29
BP
140 } else {
141 action_syntax_error(ctx, "expecting `=' or `<->'");
142 }
143 if (!error) {
144 ctx->prereqs = expr_combine(EXPR_T_AND, ctx->prereqs, prereqs);
145 }
146 }
147
3b7cb7e1 148 if (error) {
8fb72d29 149 expr_destroy(prereqs);
3b7cb7e1
BP
150 action_error(ctx, "%s", error);
151 free(error);
3b7cb7e1 152 }
3b7cb7e1
BP
153}
154
155static void
156emit_resubmit(struct action_context *ctx, uint8_t table_id)
157{
158 struct ofpact_resubmit *resubmit = ofpact_put_RESUBMIT(ctx->ofpacts);
159 resubmit->in_port = OFPP_IN_PORT;
160 resubmit->table_id = table_id;
161}
162
558ec83d
BP
163static bool
164action_get_int(struct action_context *ctx, int *value)
165{
166 bool ok = lexer_get_int(ctx->lexer, value);
167 if (!ok) {
168 action_syntax_error(ctx, "expecting small integer");
169 }
170 return ok;
171}
172
173static void
174parse_next_action(struct action_context *ctx)
175{
1d7b2ece 176 if (!ctx->ap->n_tables) {
558ec83d
BP
177 action_error(ctx, "\"next\" action not allowed here.");
178 } else if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {
179 int ltable;
180
181 if (!action_get_int(ctx, &ltable)) {
182 return;
183 }
184 if (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
185 action_syntax_error(ctx, "expecting `)'");
186 return;
187 }
188
1d7b2ece 189 if (ltable >= ctx->ap->n_tables) {
558ec83d 190 action_error(ctx, "\"next\" argument must be in range 0 to %d.",
1d7b2ece 191 ctx->ap->n_tables - 1);
558ec83d
BP
192 return;
193 }
194
1d7b2ece 195 emit_resubmit(ctx, ctx->ap->first_ptable + ltable);
558ec83d 196 } else {
1d7b2ece
BP
197 if (ctx->ap->cur_ltable < ctx->ap->n_tables) {
198 emit_resubmit(ctx,
199 ctx->ap->first_ptable + ctx->ap->cur_ltable + 1);
558ec83d
BP
200 } else {
201 action_error(ctx, "\"next\" action not allowed in last table.");
202 }
203 }
204}
205
5b84185b
BP
206/* Parses 'prerequisite' as an expression in the context of 'ctx', then adds it
207 * as a conjunction with the existing 'ctx->prereqs'. */
208static void
209add_prerequisite(struct action_context *ctx, const char *prerequisite)
210{
211 struct expr *expr;
212 char *error;
213
2c5cbb15 214 expr = expr_parse_string(prerequisite, ctx->ap->symtab, NULL, &error);
5b84185b
BP
215 ovs_assert(!error);
216 ctx->prereqs = expr_combine(EXPR_T_AND, ctx->prereqs, expr);
217}
218
0bac7164 219static size_t
42814145
NS
220start_controller_op(struct ofpbuf *ofpacts, enum action_opcode opcode,
221 bool pause)
0bac7164
BP
222{
223 size_t ofs = ofpacts->size;
224
225 struct ofpact_controller *oc = ofpact_put_CONTROLLER(ofpacts);
226 oc->max_len = UINT16_MAX;
227 oc->reason = OFPR_ACTION;
42814145 228 oc->pause = pause;
0bac7164
BP
229
230 struct action_header ah = { .opcode = htonl(opcode) };
231 ofpbuf_put(ofpacts, &ah, sizeof ah);
232
233 return ofs;
234}
235
236static void
237finish_controller_op(struct ofpbuf *ofpacts, size_t ofs)
238{
239 struct ofpact_controller *oc = ofpbuf_at_assert(ofpacts, ofs, sizeof *oc);
240 ofpacts->header = oc;
241 oc->userdata_len = ofpacts->size - (ofs + sizeof *oc);
ce058104 242 ofpact_finish_CONTROLLER(ofpacts, &oc);
0bac7164
BP
243}
244
245static void
246put_controller_op(struct ofpbuf *ofpacts, enum action_opcode opcode)
247{
42814145 248 size_t ofs = start_controller_op(ofpacts, opcode, false);
0bac7164
BP
249 finish_controller_op(ofpacts, ofs);
250}
251
e75451fe
ZKL
252/* Implements the "arp" and "na" actions, which execute nested actions on a
253 * packet derived from the one being processed. */
6335d074 254static void
e75451fe
ZKL
255parse_nested_action(struct action_context *ctx, enum action_opcode opcode,
256 const char *prereq)
6335d074
BP
257{
258 if (!lexer_match(ctx->lexer, LEX_T_LCURLY)) {
259 action_syntax_error(ctx, "expecting `{'");
260 return;
261 }
262
263 struct ofpbuf *outer_ofpacts = ctx->ofpacts;
264 uint64_t inner_ofpacts_stub[1024 / 8];
265 struct ofpbuf inner_ofpacts = OFPBUF_STUB_INITIALIZER(inner_ofpacts_stub);
266 ctx->ofpacts = &inner_ofpacts;
267
268 /* Save prerequisites. (XXX What is the right treatment for prereqs?) */
269 struct expr *outer_prereqs = ctx->prereqs;
270 ctx->prereqs = NULL;
271
272 /* Parse inner actions. */
273 while (!lexer_match(ctx->lexer, LEX_T_RCURLY)) {
274 if (!parse_action(ctx)) {
275 break;
276 }
277 }
278
279 ctx->ofpacts = outer_ofpacts;
280
e75451fe 281 /* Add a "controller" action with the actions nested inside "{...}",
6335d074 282 * converted to OpenFlow, as its userdata. ovn-controller will convert the
e75451fe
ZKL
283 * packet to ARP or NA and then send the packet and actions back to the
284 * switch inside an OFPT_PACKET_OUT message. */
285 size_t oc_offset = start_controller_op(ctx->ofpacts, opcode, false);
6335d074
BP
286 ofpacts_put_openflow_actions(inner_ofpacts.data, inner_ofpacts.size,
287 ctx->ofpacts, OFP13_VERSION);
0bac7164 288 finish_controller_op(ctx->ofpacts, oc_offset);
6335d074
BP
289
290 /* Restore prerequisites. */
291 expr_destroy(ctx->prereqs);
292 ctx->prereqs = outer_prereqs;
e75451fe 293 add_prerequisite(ctx, prereq);
6335d074
BP
294
295 /* Free memory. */
296 ofpbuf_uninit(&inner_ofpacts);
297}
298
0bac7164
BP
299static bool
300action_force_match(struct action_context *ctx, enum lex_type t)
301{
302 if (lexer_match(ctx->lexer, t)) {
303 return true;
304 } else {
305 struct lex_token token = { .type = t };
306 struct ds s = DS_EMPTY_INITIALIZER;
307 lex_token_format(&token, &s);
308
309 action_syntax_error(ctx, "expecting `%s'", ds_cstr(&s));
310
311 ds_destroy(&s);
312
313 return false;
314 }
315}
316
317static bool
318action_parse_field(struct action_context *ctx,
319 int n_bits, struct mf_subfield *sf)
320{
8fb72d29 321 struct expr_field field;
0bac7164
BP
322 char *error;
323
8fb72d29
BP
324 error = expr_parse_field(ctx->lexer, ctx->ap->symtab, &field);
325 if (!error) {
326 struct expr *prereqs;
327 error = expr_expand_field(ctx->lexer, ctx->ap->symtab,
328 &field, n_bits, false, sf, &prereqs);
329 if (!error) {
330 ctx->prereqs = expr_combine(EXPR_T_AND, ctx->prereqs, prereqs);
331 return true;
332 }
0bac7164
BP
333 }
334
8fb72d29
BP
335 action_error(ctx, "%s", error);
336 free(error);
337 return false;
0bac7164
BP
338}
339
340static void
341init_stack(struct ofpact_stack *stack, enum mf_field_id field)
342{
343 stack->subfield.field = mf_from_id(field);
344 stack->subfield.ofs = 0;
345 stack->subfield.n_bits = stack->subfield.field->n_bits;
346}
347
348struct arg {
349 const struct mf_subfield *src;
350 enum mf_field_id dst;
351};
352
353static void
354setup_args(struct action_context *ctx,
355 const struct arg args[], size_t n_args)
356{
357 /* 1. Save all of the destinations that will be modified. */
358 for (const struct arg *a = args; a < &args[n_args]; a++) {
359 ovs_assert(a->src->n_bits == mf_from_id(a->dst)->n_bits);
360 if (a->src->field->id != a->dst) {
361 init_stack(ofpact_put_STACK_PUSH(ctx->ofpacts), a->dst);
362 }
363 }
364
365 /* 2. Push the sources, in reverse order. */
366 for (size_t i = n_args - 1; i < n_args; i--) {
367 const struct arg *a = &args[i];
368 if (a->src->field->id != a->dst) {
369 ofpact_put_STACK_PUSH(ctx->ofpacts)->subfield = *a->src;
370 }
371 }
372
373 /* 3. Pop the sources into the destinations. */
374 for (const struct arg *a = args; a < &args[n_args]; a++) {
375 if (a->src->field->id != a->dst) {
376 init_stack(ofpact_put_STACK_POP(ctx->ofpacts), a->dst);
377 }
378 }
379}
380
381static void
382restore_args(struct action_context *ctx,
383 const struct arg args[], size_t n_args)
384{
385 for (size_t i = n_args - 1; i < n_args; i--) {
386 const struct arg *a = &args[i];
387 if (a->src->field->id != a->dst) {
388 init_stack(ofpact_put_STACK_POP(ctx->ofpacts), a->dst);
389 }
390 }
391}
392
393static void
394put_load(uint64_t value, enum mf_field_id dst, int ofs, int n_bits,
395 struct ofpbuf *ofpacts)
396{
397 struct ofpact_set_field *sf = ofpact_put_SET_FIELD(ofpacts);
398 sf->field = mf_from_id(dst);
399 sf->flow_has_vlan = false;
400
401 ovs_be64 n_value = htonll(value);
402 bitwise_copy(&n_value, 8, 0, &sf->value, sf->field->n_bytes, ofs, n_bits);
403 bitwise_one(&sf->mask, sf->field->n_bytes, ofs, n_bits);
404}
405
406static void
407parse_get_arp_action(struct action_context *ctx)
408{
409 struct mf_subfield port, ip;
410
411 if (!action_force_match(ctx, LEX_T_LPAREN)
412 || !action_parse_field(ctx, 0, &port)
413 || !action_force_match(ctx, LEX_T_COMMA)
414 || !action_parse_field(ctx, 32, &ip)
415 || !action_force_match(ctx, LEX_T_RPAREN)) {
416 return;
417 }
418
419 const struct arg args[] = {
420 { &port, MFF_LOG_OUTPORT },
421 { &ip, MFF_REG0 },
422 };
423 setup_args(ctx, args, ARRAY_SIZE(args));
424
425 put_load(0, MFF_ETH_DST, 0, 48, ctx->ofpacts);
426 emit_resubmit(ctx, ctx->ap->arp_ptable);
427
428 restore_args(ctx, args, ARRAY_SIZE(args));
429}
430
431static void
432parse_put_arp_action(struct action_context *ctx)
433{
434 struct mf_subfield port, ip, mac;
435
436 if (!action_force_match(ctx, LEX_T_LPAREN)
437 || !action_parse_field(ctx, 0, &port)
438 || !action_force_match(ctx, LEX_T_COMMA)
439 || !action_parse_field(ctx, 32, &ip)
440 || !action_force_match(ctx, LEX_T_COMMA)
441 || !action_parse_field(ctx, 48, &mac)
442 || !action_force_match(ctx, LEX_T_RPAREN)) {
443 return;
444 }
445
446 const struct arg args[] = {
447 { &port, MFF_LOG_INPORT },
448 { &ip, MFF_REG0 },
449 { &mac, MFF_ETH_SRC }
450 };
451 setup_args(ctx, args, ARRAY_SIZE(args));
452 put_controller_op(ctx->ofpacts, ACTION_OPCODE_PUT_ARP);
453 restore_args(ctx, args, ARRAY_SIZE(args));
454}
455
42814145
NS
456static void
457parse_dhcp_opt(struct action_context *ctx, struct ofpbuf *ofpacts)
458{
459 if (ctx->lexer->token.type != LEX_T_ID) {
460 action_syntax_error(ctx, NULL);
461 return;
462 }
463 const struct dhcp_opts_map *dhcp_opt = dhcp_opts_find(
464 ctx->ap->dhcp_opts, ctx->lexer->token.s);
465 if (!dhcp_opt) {
466 action_syntax_error(ctx, "expecting DHCP option name");
467 return;
468 }
469 lexer_get(ctx->lexer);
470
471 if (!action_force_match(ctx, LEX_T_EQUALS)) {
472 return;
473 }
474
475 struct expr_constant_set cs;
476 memset(&cs, 0, sizeof(struct expr_constant_set));
477 char *error = expr_parse_constant_set(ctx->lexer, NULL, &cs);
478 if (error) {
479 action_error(ctx, "%s", error);
480 free(error);
481 return;
482 }
483
484 if (!strcmp(dhcp_opt->type, "str")) {
485 if (cs.type != EXPR_C_STRING) {
486 action_error(ctx, "DHCP option %s requires string value.",
487 dhcp_opt->name);
488 return;
489 }
490 } else {
491 if (cs.type != EXPR_C_INTEGER) {
492 action_error(ctx, "DHCP option %s requires numeric value.",
493 dhcp_opt->name);
494 return;
495 }
496 }
497
498 if (!lexer_match(ctx->lexer, LEX_T_COMMA) && (
499 ctx->lexer->token.type != LEX_T_RPAREN)) {
500 action_syntax_error(ctx, NULL);
501 return;
502 }
503
504
505 if (dhcp_opt->code == 0) {
506 /* offer-ip */
507 ofpbuf_put(ofpacts, &cs.values[0].value.ipv4, sizeof(ovs_be32));
508 goto exit;
509 }
510
511 uint8_t *opt_header = ofpbuf_put_uninit(ofpacts, 2);
512 opt_header[0] = dhcp_opt->code;
513
514 if (!strcmp(dhcp_opt->type, "bool") || !strcmp(dhcp_opt->type, "uint8")) {
515 opt_header[1] = 1;
516 ofpbuf_put(ofpacts, &cs.values[0].value.u8_val, 1);
517 } else if (!strcmp(dhcp_opt->type, "uint16")) {
518 opt_header[1] = 2;
519 ofpbuf_put(ofpacts, &cs.values[0].value.be16_int, 2);
520 } else if (!strcmp(dhcp_opt->type, "uint32")) {
521 opt_header[1] = 4;
522 ofpbuf_put(ofpacts, &cs.values[0].value.be32_int, 4);
523 } else if (!strcmp(dhcp_opt->type, "ipv4")) {
524 opt_header[1] = cs.n_values * sizeof(ovs_be32);
525 for (size_t i = 0; i < cs.n_values; i++) {
526 ofpbuf_put(ofpacts, &cs.values[i].value.ipv4, sizeof(ovs_be32));
527 }
528 } else if (!strcmp(dhcp_opt->type, "static_routes")) {
529 size_t no_of_routes = cs.n_values;
530 if (no_of_routes % 2) {
531 no_of_routes -= 1;
532 }
533 opt_header[1] = 0;
534
535 /* Calculating the length of this option first because when
536 * we call ofpbuf_put, it might reallocate the buffer if the
537 * tail room is short making "opt_header" pointer invalid.
538 * So running the for loop twice.
539 */
540 for (size_t i = 0; i < no_of_routes; i += 2) {
541 uint8_t plen = 32;
542 if (cs.values[i].masked) {
543 plen = (uint8_t) ip_count_cidr_bits(cs.values[i].mask.ipv4);
544 }
545 opt_header[1] += (1 + (plen / 8) + sizeof(ovs_be32)) ;
546 }
547
548 /* Copied from RFC 3442. Please refer to this RFC for the format of
549 * the classless static route option.
550 *
551 * The following table contains some examples of how various subnet
552 * number/mask combinations can be encoded:
553 *
554 * Subnet number Subnet mask Destination descriptor
555 * 0 0 0
556 * 10.0.0.0 255.0.0.0 8.10
557 * 10.0.0.0 255.255.255.0 24.10.0.0
558 * 10.17.0.0 255.255.0.0 16.10.17
559 * 10.27.129.0 255.255.255.0 24.10.27.129
560 * 10.229.0.128 255.255.255.128 25.10.229.0.128
561 * 10.198.122.47 255.255.255.255 32.10.198.122.47
562 */
563
564 for (size_t i = 0; i < no_of_routes; i += 2) {
565 uint8_t plen = 32;
566 if (cs.values[i].masked) {
567 plen = ip_count_cidr_bits(cs.values[i].mask.ipv4);
568 }
569 ofpbuf_put(ofpacts, &plen, 1);
570 ofpbuf_put(ofpacts, &cs.values[i].value.ipv4, plen / 8);
571 ofpbuf_put(ofpacts, &cs.values[i + 1].value.ipv4,
572 sizeof(ovs_be32));
573 }
574 } else if (!strcmp(dhcp_opt->type, "str")) {
575 opt_header[1] = strlen(cs.values[0].string);
576 ofpbuf_put(ofpacts, cs.values[0].string, opt_header[1]);
577 }
578
579exit:
580 expr_constant_set_destroy(&cs);
581}
582
583/* Parses the "put_dhcp_opts" action. The result should be stored into 'dst'.
584 *
585 * The caller has already consumed "put_dhcp_opts(", so this just parses the
586 * rest. */
587static void
588parse_put_dhcp_opts_action(struct action_context *ctx,
589 const struct expr_field *dst)
590{
591 /* Validate that the destination is a 1-bit, modifiable field. */
592 struct mf_subfield sf;
593 struct expr *prereqs;
594 char *error = expr_expand_field(ctx->lexer, ctx->ap->symtab,
595 dst, 1, true, &sf, &prereqs);
596 if (error) {
597 action_error(ctx, "%s", error);
598 free(error);
599 return;
600 }
601 ctx->prereqs = expr_combine(EXPR_T_AND, ctx->prereqs, prereqs);
602
603 /* Make sure the first option is "offer_ip" */
604 if (ctx->lexer->token.type != LEX_T_ID) {
605 action_syntax_error(ctx, NULL);
606 return;
607 }
608 const struct dhcp_opts_map *dhcp_opt = dhcp_opts_find(
609 ctx->ap->dhcp_opts, ctx->lexer->token.s);
610 if (!dhcp_opt || dhcp_opt->code != 0) {
611 action_syntax_error(ctx, "expecting offerip option");
612 return;
613 }
614
615 /* controller. */
616 size_t oc_offset = start_controller_op(ctx->ofpacts,
617 ACTION_OPCODE_PUT_DHCP_OPTS, true);
618 nx_put_header(ctx->ofpacts, sf.field->id, OFP13_VERSION, false);
619 ovs_be32 ofs = htonl(sf.ofs);
620 ofpbuf_put(ctx->ofpacts, &ofs, sizeof ofs);
621 while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
622 parse_dhcp_opt(ctx, ctx->ofpacts);
623 if (ctx->error) {
624 return;
625 }
626 }
627 finish_controller_op(ctx->ofpacts, oc_offset);
628}
629
467085fd
GS
630static bool
631action_parse_port(struct action_context *ctx, uint16_t *port)
632{
633 if (lexer_is_int(ctx->lexer)) {
634 int value = ntohll(ctx->lexer->token.value.integer);
635 if (value <= UINT16_MAX) {
636 *port = value;
637 lexer_get(ctx->lexer);
638 return true;
639 }
640 }
641 action_syntax_error(ctx, "expecting port number");
642 return false;
643}
644
645static void
646parse_ct_lb_action(struct action_context *ctx)
647{
648 uint8_t recirc_table;
649 if (ctx->ap->cur_ltable < ctx->ap->n_tables) {
650 recirc_table = ctx->ap->first_ptable + ctx->ap->cur_ltable + 1;
651 } else {
652 action_error(ctx, "\"ct_lb\" action not allowed in last table.");
653 return;
654 }
655
656 if (!lexer_match(ctx->lexer, LEX_T_LPAREN)) {
657 /* ct_lb without parentheses means that this is an established
658 * connection and we just need to do a NAT. */
659 const size_t ct_offset = ctx->ofpacts->size;
660 ofpbuf_pull(ctx->ofpacts, ct_offset);
661
662 struct ofpact_conntrack *ct = ofpact_put_CT(ctx->ofpacts);
663 struct ofpact_nat *nat;
664 size_t nat_offset;
665 ct->zone_src.field = mf_from_id(MFF_LOG_CT_ZONE);
666 ct->zone_src.ofs = 0;
667 ct->zone_src.n_bits = 16;
668 ct->flags = 0;
669 ct->recirc_table = recirc_table;
670 ct->alg = 0;
671
672 add_prerequisite(ctx, "ip");
673
674 nat_offset = ctx->ofpacts->size;
675 ofpbuf_pull(ctx->ofpacts, nat_offset);
676
677 nat = ofpact_put_NAT(ctx->ofpacts);
678 nat->flags = 0;
679 nat->range_af = AF_UNSPEC;
680
681 ctx->ofpacts->header = ofpbuf_push_uninit(ctx->ofpacts, nat_offset);
682 ct = ctx->ofpacts->header;
683 ofpact_finish(ctx->ofpacts, &ct->ofpact);
684 ofpbuf_push_uninit(ctx->ofpacts, ct_offset);
685 return;
686 }
687
688 uint32_t group_id = 0, bucket_id = 0, hash;
689 struct group_info *group_info;
690 struct ofpact_group *og;
691
692 struct ds ds = DS_EMPTY_INITIALIZER;
693 ds_put_format(&ds, "type=select");
694
695 BUILD_ASSERT(MFF_LOG_CT_ZONE >= MFF_REG0);
696 BUILD_ASSERT(MFF_LOG_CT_ZONE < MFF_REG0 + FLOW_N_REGS);
697 do {
698 if (ctx->lexer->token.type != LEX_T_INTEGER
699 || mf_subvalue_width(&ctx->lexer->token.value) > 32) {
700 action_syntax_error(ctx, "expecting IPv4 address");
701 ds_destroy(&ds);
702 return;
703 }
704 ovs_be32 ip = ctx->lexer->token.value.ipv4;
705 lexer_get(ctx->lexer);
706
707 uint16_t port = 0;
708 if (lexer_match(ctx->lexer, LEX_T_COLON)
709 && !action_parse_port(ctx, &port)) {
710 ds_destroy(&ds);
711 return;
712 }
713
714 bucket_id++;
715 ds_put_format(&ds, ",bucket=bucket_id=%u,weight:100,actions="
716 "ct(nat(dst="IP_FMT, bucket_id, IP_ARGS(ip));
717 if (port) {
718 ds_put_format(&ds, ":%"PRIu16, port);
719 }
720 ds_put_format(&ds, "),commit,table=%d,zone=NXM_NX_REG%d[0..15])",
721 recirc_table, MFF_LOG_CT_ZONE - MFF_REG0);
722
723 lexer_match(ctx->lexer, LEX_T_COMMA);
724 } while (!lexer_match(ctx->lexer, LEX_T_RPAREN));
725 add_prerequisite(ctx, "ip");
726
727 hash = hash_string(ds_cstr(&ds), 0);
728
729 /* Check whether we have non installed but allocated group_id. */
730 HMAP_FOR_EACH_WITH_HASH (group_info, hmap_node, hash,
731 &ctx->ap->group_table->desired_groups) {
732 if (!strcmp(ds_cstr(&group_info->group), ds_cstr(&ds))) {
733 group_id = group_info->group_id;
734 break;
735 }
736 }
737
738 if (!group_id) {
739 /* Check whether we already have an installed entry for this
740 * combination. */
741 HMAP_FOR_EACH_WITH_HASH (group_info, hmap_node, hash,
742 &ctx->ap->group_table->existing_groups) {
743 if (!strcmp(ds_cstr(&group_info->group), ds_cstr(&ds))) {
744 group_id = group_info->group_id;
745 }
746 }
747
748 if (!group_id) {
749 /* Reserve a new group_id. */
750 group_id = bitmap_scan(ctx->ap->group_table->group_ids, 0, 1,
751 MAX_OVN_GROUPS + 1);
752 }
753
754 if (group_id == MAX_OVN_GROUPS + 1) {
755 ds_destroy(&ds);
756 action_error(ctx, "out of group ids.");
757 return;
758 }
759 bitmap_set1(ctx->ap->group_table->group_ids, group_id);
760
761 group_info = xmalloc(sizeof *group_info);
762 group_info->group = ds;
763 group_info->group_id = group_id;
764 group_info->hmap_node.hash = hash;
765
766 hmap_insert(&ctx->ap->group_table->desired_groups,
767 &group_info->hmap_node, group_info->hmap_node.hash);
768 } else {
769 ds_destroy(&ds);
770 }
771
772 /* Create an action to set the group. */
773 og = ofpact_put_GROUP(ctx->ofpacts);
774 og->group_id = group_id;
775}
776
78aab811 777static void
a9e1b66f
RB
778emit_ct(struct action_context *ctx, bool recirc_next, bool commit,
779 int *ct_mark, int *ct_mark_mask,
780 ovs_be128 *ct_label, ovs_be128 *ct_label_mask)
78aab811
JP
781{
782 struct ofpact_conntrack *ct = ofpact_put_CT(ctx->ofpacts);
783 ct->flags |= commit ? NX_CT_F_COMMIT : 0;
784
785 /* If "recirc" is set, we automatically go to the next table. */
786 if (recirc_next) {
1d7b2ece
BP
787 if (ctx->ap->cur_ltable < ctx->ap->n_tables) {
788 ct->recirc_table = ctx->ap->first_ptable + ctx->ap->cur_ltable + 1;
78aab811
JP
789 } else {
790 action_error(ctx, "\"ct_next\" action not allowed in last table.");
791 return;
792 }
793 } else {
794 ct->recirc_table = NX_CT_RECIRC_NONE;
795 }
796
667e2b0b 797 ct->zone_src.field = mf_from_id(MFF_LOG_CT_ZONE);
78aab811
JP
798 ct->zone_src.ofs = 0;
799 ct->zone_src.n_bits = 16;
800
801 /* We do not support ALGs yet. */
802 ct->alg = 0;
803
804 /* CT only works with IP, so set up a prerequisite. */
5b84185b 805 add_prerequisite(ctx, "ip");
a9e1b66f
RB
806
807 size_t set_field_offset = ctx->ofpacts->size;
808 ofpbuf_pull(ctx->ofpacts, set_field_offset);
809
810 if (ct_mark) {
811 struct ofpact_set_field *sf = ofpact_put_SET_FIELD(ctx->ofpacts);
812 sf->field = mf_from_id(MFF_CT_MARK);
813 sf->value.be32 = htonl(*ct_mark);
814 sf->mask.be32 = ct_mark_mask ? htonl(*ct_mark_mask) : OVS_BE32_MAX;
815 }
816
817 if (ct_label) {
818 struct ofpact_set_field *sf = ofpact_put_SET_FIELD(ctx->ofpacts);
819 sf->field = mf_from_id(MFF_CT_LABEL);
820 sf->value.be128 = *ct_label;
821 sf->mask.be128 = ct_label_mask ? *ct_label_mask : OVS_BE128_MAX;
822 }
823
824 ctx->ofpacts->header = ofpbuf_push_uninit(ctx->ofpacts, set_field_offset);
825 ct = ctx->ofpacts->header;
826 ofpact_finish(ctx->ofpacts, &ct->ofpact);
827}
828
829/* Parse an argument to the ct_commit(); action. Supported arguments include:
830 *
831 * ct_mark=<value>[/<mask>]
832 * ct_label=<value>[/<mask>]
833 *
834 * If a comma separates the current argument from the next argument, this
835 * function will consume it.
836 *
837 * set_mark - This will be set to true if a value for ct_mark was successfully
838 * parsed. Otherwise, it will be unchanged.
839 * mark_value - If set_mark was set to true, this will contain the value
840 * parsed for ct_mark.
841 * mark_mask - If set_mark was set to true, this will contain the mask
842 * for ct_mark if one was found. Otherwise, it will be
843 * unchanged, so the caller should initialize this to an
844 * appropriate value.
845 * set_label - This will be set to true if a value for ct_label was successfully
846 * parsed. Otherwise, it will be unchanged.
847 * label_value - If set_label was set to true, this will contain the value
848 * parsed for ct_label.
849 * label_mask - If set_label was set to true, this will contain the mask
850 * for ct_label if one was found. Otherwise, it will be
851 * unchanged, so the caller should initialize this to an
852 * appropriate value.
853 *
854 * Return true after successfully parsing an argument. false on failure. */
855static bool
856parse_ct_commit_arg(struct action_context *ctx,
857 bool *set_mark, int *mark_value, int *mark_mask,
858 bool *set_label, ovs_be128 *label_value,
859 ovs_be128 *label_mask)
860{
861 if (lexer_match_id(ctx->lexer, "ct_mark")) {
862 if (!lexer_match(ctx->lexer, LEX_T_EQUALS)) {
863 action_error(ctx, "Expected '=' after argument to ct_commit");
864 return false;
865 }
866 if (ctx->lexer->token.type == LEX_T_INTEGER) {
867 *mark_value = ntohll(ctx->lexer->token.value.integer);
868 } else if (ctx->lexer->token.type == LEX_T_MASKED_INTEGER) {
869 *mark_value = ntohll(ctx->lexer->token.value.integer);
870 *mark_mask = ntohll(ctx->lexer->token.mask.integer);
871 } else {
872 action_error(ctx, "Expected integer after 'ct_mark='");
873 return false;
874 }
875 lexer_get(ctx->lexer);
876 *set_mark = true;
877 } else if (lexer_match_id(ctx->lexer, "ct_label")) {
878 if (!lexer_match(ctx->lexer, LEX_T_EQUALS)) {
879 action_error(ctx, "Expected '=' after argument to ct_commit");
880 return false;
881 }
882 if (ctx->lexer->token.type == LEX_T_INTEGER) {
883 label_value->be64.lo = ctx->lexer->token.value.integer;
884 } else if (ctx->lexer->token.type == LEX_T_MASKED_INTEGER) {
885 /* XXX Technically, ct_label is a 128-bit field. The lexer
886 * only supports 64-bit integers, so that's all we support
887 * here. More work is needed to use parse_int_string()
888 * to support the full 128-bits. */
889 label_value->be64.lo = ctx->lexer->token.value.integer;
890 label_mask->be64.hi = 0;
891 label_mask->be64.lo = ctx->lexer->token.mask.integer;
892 } else {
893 action_error(ctx, "Expected integer after 'ct_label='");
894 return false;
895 }
896 lexer_get(ctx->lexer);
897 *set_label = true;
898 } else {
899 action_error(ctx, "Expected argument to ct_commit()");
900 return false;
901 }
902
903 if (lexer_match(ctx->lexer, LEX_T_COMMA)) {
904 /* A comma is valid after an argument, but only if another
905 * argument is present (not a closing paren) */
906 if (lexer_lookahead(ctx->lexer) == LEX_T_RPAREN) {
907 action_error(ctx, "Another argument to ct_commit() expected "
908 "after comma.");
909 return false;
910 }
911 }
912
913 return true;
914}
915
916static void
917parse_ct_commit_action(struct action_context *ctx)
918{
919 if (!lexer_match(ctx->lexer, LEX_T_LPAREN)) {
920 /* ct_commit; */
921 emit_ct(ctx, false, true, NULL, NULL, NULL, NULL);
922 return;
923 }
924
925 /* ct_commit();
926 * ct_commit(ct_mark=0);
927 * ct_commit(ct_label=0);
928 * ct_commit(ct_mark=0, ct_label=0); */
929
930 bool set_mark = false;
931 bool set_label = false;
932 int mark_value = 0;
933 int mark_mask = ~0;
934 ovs_be128 label_value = { .be32 = { 0, }, };
935 ovs_be128 label_mask = OVS_BE128_MAX;
936
937 while (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
938 if (!parse_ct_commit_arg(ctx, &set_mark, &mark_value, &mark_mask,
939 &set_label, &label_value, &label_mask)) {
940 return;
941 }
942 }
943
944 emit_ct(ctx, false, true,
945 set_mark ? &mark_value : NULL,
946 set_mark ? &mark_mask : NULL,
947 set_label ? &label_value : NULL,
948 set_label ? &label_mask : NULL);
78aab811
JP
949}
950
de297547
GS
951static void
952parse_ct_nat(struct action_context *ctx, bool snat)
953{
954 const size_t ct_offset = ctx->ofpacts->size;
955 ofpbuf_pull(ctx->ofpacts, ct_offset);
956
957 struct ofpact_conntrack *ct = ofpact_put_CT(ctx->ofpacts);
958
959 if (ctx->ap->cur_ltable < ctx->ap->n_tables) {
960 ct->recirc_table = ctx->ap->first_ptable + ctx->ap->cur_ltable + 1;
961 } else {
962 action_error(ctx,
963 "\"ct_[sd]nat\" action not allowed in last table.");
964 return;
965 }
966
967 if (snat) {
968 ct->zone_src.field = mf_from_id(MFF_LOG_SNAT_ZONE);
969 } else {
970 ct->zone_src.field = mf_from_id(MFF_LOG_DNAT_ZONE);
971 }
972 ct->zone_src.ofs = 0;
973 ct->zone_src.n_bits = 16;
974 ct->flags = 0;
975 ct->alg = 0;
976
977 add_prerequisite(ctx, "ip");
978
979 struct ofpact_nat *nat;
980 size_t nat_offset;
981 nat_offset = ctx->ofpacts->size;
982 ofpbuf_pull(ctx->ofpacts, nat_offset);
983
984 nat = ofpact_put_NAT(ctx->ofpacts);
985 nat->flags = 0;
986 nat->range_af = AF_UNSPEC;
987
988 int commit = 0;
989 if (lexer_match(ctx->lexer, LEX_T_LPAREN)) {
990 ovs_be32 ip;
991 if (ctx->lexer->token.type == LEX_T_INTEGER
992 && ctx->lexer->token.format == LEX_F_IPV4) {
993 ip = ctx->lexer->token.value.ipv4;
994 } else {
995 action_syntax_error(ctx, "invalid ip");
996 return;
997 }
998
999 nat->range_af = AF_INET;
1000 nat->range.addr.ipv4.min = ip;
1001 if (snat) {
1002 nat->flags |= NX_NAT_F_SRC;
1003 } else {
1004 nat->flags |= NX_NAT_F_DST;
1005 }
1006 commit = NX_CT_F_COMMIT;
1007 lexer_get(ctx->lexer);
1008 if (!lexer_match(ctx->lexer, LEX_T_RPAREN)) {
1009 action_syntax_error(ctx, "expecting `)'");
1010 return;
1011 }
1012 }
1013
1014 ctx->ofpacts->header = ofpbuf_push_uninit(ctx->ofpacts, nat_offset);
1015 ct = ctx->ofpacts->header;
1016 ct->flags |= commit;
1017
1018 /* XXX: For performance reasons, we try to prevent additional
1019 * recirculations. So far, ct_snat which is used in a gateway router
1020 * does not need a recirculation. ct_snat(IP) does need a recirculation.
1021 * Should we consider a method to let the actions specify whether a action
1022 * needs recirculation if there more use cases?. */
1023 if (!commit && snat) {
1024 ct->recirc_table = NX_CT_RECIRC_NONE;
1025 }
1026 ofpact_finish(ctx->ofpacts, &ct->ofpact);
1027 ofpbuf_push_uninit(ctx->ofpacts, ct_offset);
1028}
1029
d8681a83
BP
1030static bool
1031parse_action(struct action_context *ctx)
1032{
1033 if (ctx->lexer->token.type != LEX_T_ID) {
1034 action_syntax_error(ctx, NULL);
1035 return false;
1036 }
1037
1038 enum lex_type lookahead = lexer_lookahead(ctx->lexer);
1039 if (lookahead == LEX_T_EQUALS || lookahead == LEX_T_EXCHANGE
1040 || lookahead == LEX_T_LSQUARE) {
1041 parse_set_action(ctx);
1042 } else if (lexer_match_id(ctx->lexer, "next")) {
1043 parse_next_action(ctx);
1044 } else if (lexer_match_id(ctx->lexer, "output")) {
1d7b2ece 1045 emit_resubmit(ctx, ctx->ap->output_ptable);
d8681a83
BP
1046 } else if (lexer_match_id(ctx->lexer, "ip.ttl")) {
1047 if (lexer_match(ctx->lexer, LEX_T_DECREMENT)) {
1048 add_prerequisite(ctx, "ip");
1049 ofpact_put_DEC_TTL(ctx->ofpacts);
1050 } else {
1051 action_syntax_error(ctx, "expecting `--'");
1052 }
1053 } else if (lexer_match_id(ctx->lexer, "ct_next")) {
a9e1b66f 1054 emit_ct(ctx, true, false, NULL, NULL, NULL, NULL);
d8681a83 1055 } else if (lexer_match_id(ctx->lexer, "ct_commit")) {
a9e1b66f 1056 parse_ct_commit_action(ctx);
de297547
GS
1057 } else if (lexer_match_id(ctx->lexer, "ct_dnat")) {
1058 parse_ct_nat(ctx, false);
1059 } else if (lexer_match_id(ctx->lexer, "ct_snat")) {
1060 parse_ct_nat(ctx, true);
467085fd
GS
1061 } else if (lexer_match_id(ctx->lexer, "ct_lb")) {
1062 parse_ct_lb_action(ctx);
6335d074 1063 } else if (lexer_match_id(ctx->lexer, "arp")) {
e75451fe
ZKL
1064 parse_nested_action(ctx, ACTION_OPCODE_ARP, "ip4");
1065 } else if (lexer_match_id(ctx->lexer, "na")) {
1066 parse_nested_action(ctx, ACTION_OPCODE_NA, "nd");
0bac7164
BP
1067 } else if (lexer_match_id(ctx->lexer, "get_arp")) {
1068 parse_get_arp_action(ctx);
1069 } else if (lexer_match_id(ctx->lexer, "put_arp")) {
1070 parse_put_arp_action(ctx);
d8681a83
BP
1071 } else {
1072 action_syntax_error(ctx, "expecting action");
1073 }
1074 if (!lexer_match(ctx->lexer, LEX_T_SEMICOLON)) {
1075 action_syntax_error(ctx, "expecting ';'");
1076 }
1077 return !ctx->error;
1078}
1079
3b7cb7e1
BP
1080static void
1081parse_actions(struct action_context *ctx)
1082{
1083 /* "drop;" by itself is a valid (empty) set of actions, but it can't be
1084 * combined with other actions because that doesn't make sense. */
1085 if (ctx->lexer->token.type == LEX_T_ID
1086 && !strcmp(ctx->lexer->token.s, "drop")
1087 && lexer_lookahead(ctx->lexer) == LEX_T_SEMICOLON) {
1088 lexer_get(ctx->lexer); /* Skip "drop". */
1089 lexer_get(ctx->lexer); /* Skip ";". */
1090 if (ctx->lexer->token.type != LEX_T_END) {
1091 action_syntax_error(ctx, "expecting end of input");
1092 }
1093 return;
1094 }
1095
1096 while (ctx->lexer->token.type != LEX_T_END) {
d8681a83 1097 if (!parse_action(ctx)) {
3b7cb7e1
BP
1098 return;
1099 }
1100 }
1101}
1102
1103/* Parses OVN actions, in the format described for the "actions" column in the
48605550
BP
1104 * Logical_Flow table in ovn-sb(5), and appends the parsed versions of the
1105 * actions to 'ofpacts' as "struct ofpact"s.
3b7cb7e1 1106 *
1d7b2ece 1107 * 'ap' provides most of the parameters for translation.
3646e396 1108 *
3b7cb7e1
BP
1109 * Some actions add extra requirements (prerequisites) to the flow's match. If
1110 * so, this function sets '*prereqsp' to the actions' prerequisites; otherwise,
1111 * it sets '*prereqsp' to NULL. The caller owns '*prereqsp' and must
1112 * eventually free it.
1113 *
1114 * Returns NULL on success, otherwise a malloc()'d error message that the
1115 * caller must free. On failure, 'ofpacts' has the same contents and
1116 * '*prereqsp' is set to NULL, but some tokens may have been consumed from
1117 * 'lexer'.
1118 */
1119char * OVS_WARN_UNUSED_RESULT
1d7b2ece
BP
1120actions_parse(struct lexer *lexer, const struct action_params *ap,
1121 struct ofpbuf *ofpacts, struct expr **prereqsp)
3b7cb7e1
BP
1122{
1123 size_t ofpacts_start = ofpacts->size;
1124
1d7b2ece
BP
1125 struct action_context ctx = {
1126 .ap = ap,
1127 .lexer = lexer,
1128 .error = NULL,
1129 .ofpacts = ofpacts,
1130 .prereqs = NULL,
1131 };
3b7cb7e1
BP
1132 parse_actions(&ctx);
1133
1134 if (!ctx.error) {
1135 *prereqsp = ctx.prereqs;
1136 return NULL;
1137 } else {
1138 ofpacts->size = ofpacts_start;
1139 expr_destroy(ctx.prereqs);
1140 *prereqsp = NULL;
1141 return ctx.error;
1142 }
1143}
1144
1145/* Like actions_parse(), but the actions are taken from 's'. */
1146char * OVS_WARN_UNUSED_RESULT
1d7b2ece
BP
1147actions_parse_string(const char *s, const struct action_params *ap,
1148 struct ofpbuf *ofpacts, struct expr **prereqsp)
3b7cb7e1
BP
1149{
1150 struct lexer lexer;
1151 char *error;
1152
1153 lexer_init(&lexer, s);
1154 lexer_get(&lexer);
1d7b2ece 1155 error = actions_parse(&lexer, ap, ofpacts, prereqsp);
3b7cb7e1
BP
1156 lexer_destroy(&lexer);
1157
1158 return error;
1159}