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