2 * Copyright (c) 2015, 2016 Nicira, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #include "byte-order.h"
25 #include "openvswitch/hmap.h"
26 #include "logical-fields.h"
28 #include "openvswitch/dynamic-string.h"
29 #include "openvswitch/ofp-actions.h"
30 #include "openvswitch/ofpbuf.h"
31 #include "ovn/actions.h"
35 #include "openvswitch/shash.h"
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. */
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
);
52 action_error_handle_common(struct action_context
*ctx
)
55 /* Already have an error, suppress this one since the cascade seems
56 * unlikely to be useful. */
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
);
69 static void OVS_PRINTF_FORMAT(2, 3)
70 action_error(struct action_context
*ctx
, const char *message
, ...)
72 if (action_error_handle_common(ctx
)) {
77 va_start(args
, message
);
78 ctx
->error
= xvasprintf(message
, args
);
82 static void OVS_PRINTF_FORMAT(2, 3)
83 action_syntax_error(struct action_context
*ctx
, const char *message
, ...)
85 if (action_error_handle_common(ctx
)) {
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
),
102 ds_put_char(&s
, ' ');
105 va_start(args
, message
);
106 ds_put_format_valist(&s
, message
, args
);
109 ds_put_char(&s
, '.');
111 ctx
->error
= ds_steal_cstr(&s
);
114 /* Parses an assignment or exchange or put_dhcp_opts action. */
116 parse_set_action(struct action_context
*ctx
)
118 struct expr
*prereqs
= NULL
;
119 struct expr_field dst
;
122 error
= expr_parse_field(ctx
->lexer
, ctx
->ap
->symtab
, &dst
);
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
);
136 error
= expr_parse_assignment(
137 ctx
->lexer
, &dst
, ctx
->ap
->symtab
, ctx
->ap
->lookup_port
,
138 ctx
->ap
->aux
, ctx
->ofpacts
, &prereqs
);
141 action_syntax_error(ctx
, "expecting `=' or `<->'");
144 ctx
->prereqs
= expr_combine(EXPR_T_AND
, ctx
->prereqs
, prereqs
);
149 expr_destroy(prereqs
);
150 action_error(ctx
, "%s", error
);
156 emit_resubmit(struct action_context
*ctx
, uint8_t table_id
)
158 struct ofpact_resubmit
*resubmit
= ofpact_put_RESUBMIT(ctx
->ofpacts
);
159 resubmit
->in_port
= OFPP_IN_PORT
;
160 resubmit
->table_id
= table_id
;
164 action_get_int(struct action_context
*ctx
, int *value
)
166 bool ok
= lexer_get_int(ctx
->lexer
, value
);
168 action_syntax_error(ctx
, "expecting small integer");
174 parse_next_action(struct action_context
*ctx
)
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
)) {
181 if (!action_get_int(ctx
, <able
)) {
184 if (!lexer_match(ctx
->lexer
, LEX_T_RPAREN
)) {
185 action_syntax_error(ctx
, "expecting `)'");
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);
195 emit_resubmit(ctx
, ctx
->ap
->first_ptable
+ ltable
);
197 if (ctx
->ap
->cur_ltable
< ctx
->ap
->n_tables
) {
199 ctx
->ap
->first_ptable
+ ctx
->ap
->cur_ltable
+ 1);
201 action_error(ctx
, "\"next\" action not allowed in last table.");
206 /* Parses 'prerequisite' as an expression in the context of 'ctx', then adds it
207 * as a conjunction with the existing 'ctx->prereqs'. */
209 add_prerequisite(struct action_context
*ctx
, const char *prerequisite
)
214 expr
= expr_parse_string(prerequisite
, ctx
->ap
->symtab
, NULL
, &error
);
216 ctx
->prereqs
= expr_combine(EXPR_T_AND
, ctx
->prereqs
, expr
);
220 start_controller_op(struct ofpbuf
*ofpacts
, enum action_opcode opcode
,
223 size_t ofs
= ofpacts
->size
;
225 struct ofpact_controller
*oc
= ofpact_put_CONTROLLER(ofpacts
);
226 oc
->max_len
= UINT16_MAX
;
227 oc
->reason
= OFPR_ACTION
;
230 struct action_header ah
= { .opcode
= htonl(opcode
) };
231 ofpbuf_put(ofpacts
, &ah
, sizeof ah
);
237 finish_controller_op(struct ofpbuf
*ofpacts
, size_t ofs
)
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
);
246 put_controller_op(struct ofpbuf
*ofpacts
, enum action_opcode opcode
)
248 size_t ofs
= start_controller_op(ofpacts
, opcode
, false);
249 finish_controller_op(ofpacts
, ofs
);
252 /* Implements the "arp" and "nd_na" actions, which execute nested
253 * actions on a packet derived fro: the one being processed. */
255 parse_nested_action(struct action_context
*ctx
, enum action_opcode opcode
,
258 if (!lexer_match(ctx
->lexer
, LEX_T_LCURLY
)) {
259 action_syntax_error(ctx
, "expecting `{'");
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
;
268 /* Save prerequisites. (XXX What is the right treatment for prereqs?) */
269 struct expr
*outer_prereqs
= ctx
->prereqs
;
272 /* Parse inner actions. */
273 while (!lexer_match(ctx
->lexer
, LEX_T_RCURLY
)) {
274 if (!parse_action(ctx
)) {
279 ctx
->ofpacts
= outer_ofpacts
;
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
);
291 /* Restore prerequisites. */
292 expr_destroy(ctx
->prereqs
);
293 ctx
->prereqs
= outer_prereqs
;
294 add_prerequisite(ctx
, prereq
);
297 ofpbuf_uninit(&inner_ofpacts
);
301 action_force_match(struct action_context
*ctx
, enum lex_type t
)
303 if (lexer_match(ctx
->lexer
, t
)) {
306 struct lex_token token
= { .type
= t
};
307 struct ds s
= DS_EMPTY_INITIALIZER
;
308 lex_token_format(&token
, &s
);
310 action_syntax_error(ctx
, "expecting `%s'", ds_cstr(&s
));
319 action_parse_field(struct action_context
*ctx
,
320 int n_bits
, struct mf_subfield
*sf
)
322 struct expr_field field
;
325 error
= expr_parse_field(ctx
->lexer
, ctx
->ap
->symtab
, &field
);
327 struct expr
*prereqs
;
328 error
= expr_expand_field(ctx
->lexer
, ctx
->ap
->symtab
,
329 &field
, n_bits
, false, sf
, &prereqs
);
331 ctx
->prereqs
= expr_combine(EXPR_T_AND
, ctx
->prereqs
, prereqs
);
336 action_error(ctx
, "%s", error
);
342 init_stack(struct ofpact_stack
*stack
, enum mf_field_id field
)
344 stack
->subfield
.field
= mf_from_id(field
);
345 stack
->subfield
.ofs
= 0;
346 stack
->subfield
.n_bits
= stack
->subfield
.field
->n_bits
;
350 const struct mf_subfield
*src
;
351 enum mf_field_id dst
;
355 setup_args(struct action_context
*ctx
,
356 const struct arg args
[], size_t n_args
)
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
);
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
;
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
);
383 restore_args(struct action_context
*ctx
,
384 const struct arg args
[], size_t n_args
)
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
);
395 put_load(uint64_t value
, enum mf_field_id dst
, int ofs
, int n_bits
,
396 struct ofpbuf
*ofpacts
)
398 struct ofpact_set_field
*sf
= ofpact_put_SET_FIELD(ofpacts
);
399 sf
->field
= mf_from_id(dst
);
400 sf
->flow_has_vlan
= false;
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
);
408 parse_get_arp_action(struct action_context
*ctx
)
410 struct mf_subfield port
, ip
;
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
)) {
420 const struct arg args
[] = {
421 { &port
, MFF_LOG_OUTPORT
},
424 setup_args(ctx
, args
, ARRAY_SIZE(args
));
426 put_load(0, MFF_ETH_DST
, 0, 48, ctx
->ofpacts
);
427 emit_resubmit(ctx
, ctx
->ap
->mac_bind_ptable
);
429 restore_args(ctx
, args
, ARRAY_SIZE(args
));
433 parse_put_arp_action(struct action_context
*ctx
)
435 struct mf_subfield port
, ip
, mac
;
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
)) {
447 const struct arg args
[] = {
448 { &port
, MFF_LOG_INPORT
},
450 { &mac
, MFF_ETH_SRC
}
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
));
458 parse_dhcp_opt(struct action_context
*ctx
, struct ofpbuf
*ofpacts
)
460 if (ctx
->lexer
->token
.type
!= LEX_T_ID
) {
461 action_syntax_error(ctx
, NULL
);
464 const struct dhcp_opts_map
*dhcp_opt
= dhcp_opts_find(
465 ctx
->ap
->dhcp_opts
, ctx
->lexer
->token
.s
);
467 action_syntax_error(ctx
, "expecting DHCP option name");
470 lexer_get(ctx
->lexer
);
472 if (!action_force_match(ctx
, LEX_T_EQUALS
)) {
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
);
480 action_error(ctx
, "%s", error
);
485 if (!strcmp(dhcp_opt
->type
, "str")) {
486 if (cs
.type
!= EXPR_C_STRING
) {
487 action_error(ctx
, "DHCP option %s requires string value.",
492 if (cs
.type
!= EXPR_C_INTEGER
) {
493 action_error(ctx
, "DHCP option %s requires numeric value.",
499 if (!lexer_match(ctx
->lexer
, LEX_T_COMMA
) && (
500 ctx
->lexer
->token
.type
!= LEX_T_RPAREN
)) {
501 action_syntax_error(ctx
, NULL
);
506 if (dhcp_opt
->code
== 0) {
508 ofpbuf_put(ofpacts
, &cs
.values
[0].value
.ipv4
, sizeof(ovs_be32
));
512 uint8_t *opt_header
= ofpbuf_put_uninit(ofpacts
, 2);
513 opt_header
[0] = dhcp_opt
->code
;
515 if (!strcmp(dhcp_opt
->type
, "bool") || !strcmp(dhcp_opt
->type
, "uint8")) {
517 ofpbuf_put(ofpacts
, &cs
.values
[0].value
.u8_val
, 1);
518 } else if (!strcmp(dhcp_opt
->type
, "uint16")) {
520 ofpbuf_put(ofpacts
, &cs
.values
[0].value
.be16_int
, 2);
521 } else if (!strcmp(dhcp_opt
->type
, "uint32")) {
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
));
529 } else if (!strcmp(dhcp_opt
->type
, "static_routes")) {
530 size_t no_of_routes
= cs
.n_values
;
531 if (no_of_routes
% 2) {
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.
541 for (size_t i
= 0; i
< no_of_routes
; i
+= 2) {
543 if (cs
.values
[i
].masked
) {
544 plen
= (uint8_t) ip_count_cidr_bits(cs
.values
[i
].mask
.ipv4
);
546 opt_header
[1] += (1 + (plen
/ 8) + sizeof(ovs_be32
)) ;
549 /* Copied from RFC 3442. Please refer to this RFC for the format of
550 * the classless static route option.
552 * The following table contains some examples of how various subnet
553 * number/mask combinations can be encoded:
555 * Subnet number Subnet mask Destination descriptor
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
565 for (size_t i
= 0; i
< no_of_routes
; i
+= 2) {
567 if (cs
.values
[i
].masked
) {
568 plen
= ip_count_cidr_bits(cs
.values
[i
].mask
.ipv4
);
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
,
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]);
581 expr_constant_set_destroy(&cs
);
584 /* Parses the "put_dhcp_opts" action. The result should be stored into 'dst'.
586 * The caller has already consumed "put_dhcp_opts(", so this just parses the
589 parse_put_dhcp_opts_action(struct action_context
*ctx
,
590 const struct expr_field
*dst
)
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
);
598 action_error(ctx
, "%s", error
);
602 ctx
->prereqs
= expr_combine(EXPR_T_AND
, ctx
->prereqs
, prereqs
);
604 /* Make sure the first option is "offer_ip" */
605 if (ctx
->lexer
->token
.type
!= LEX_T_ID
) {
606 action_syntax_error(ctx
, NULL
);
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");
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
);
628 finish_controller_op(ctx
->ofpacts
, oc_offset
);
632 action_parse_port(struct action_context
*ctx
, uint16_t *port
)
634 if (lexer_is_int(ctx
->lexer
)) {
635 int value
= ntohll(ctx
->lexer
->token
.value
.integer
);
636 if (value
<= UINT16_MAX
) {
638 lexer_get(ctx
->lexer
);
642 action_syntax_error(ctx
, "expecting port number");
647 parse_ct_lb_action(struct action_context
*ctx
)
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;
653 action_error(ctx
, "\"ct_lb\" action not allowed in last table.");
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
);
663 struct ofpact_conntrack
*ct
= ofpact_put_CT(ctx
->ofpacts
);
664 struct ofpact_nat
*nat
;
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;
670 ct
->recirc_table
= recirc_table
;
673 add_prerequisite(ctx
, "ip");
675 nat_offset
= ctx
->ofpacts
->size
;
676 ofpbuf_pull(ctx
->ofpacts
, nat_offset
);
678 nat
= ofpact_put_NAT(ctx
->ofpacts
);
680 nat
->range_af
= AF_UNSPEC
;
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
);
689 uint32_t group_id
= 0, bucket_id
= 0, hash
;
690 struct group_info
*group_info
;
691 struct ofpact_group
*og
;
693 struct ds ds
= DS_EMPTY_INITIALIZER
;
694 ds_put_format(&ds
, "type=select");
696 BUILD_ASSERT(MFF_LOG_CT_ZONE
>= MFF_REG0
);
697 BUILD_ASSERT(MFF_LOG_CT_ZONE
< MFF_REG0
+ FLOW_N_REGS
);
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");
705 ovs_be32 ip
= ctx
->lexer
->token
.value
.ipv4
;
706 lexer_get(ctx
->lexer
);
709 if (lexer_match(ctx
->lexer
, LEX_T_COLON
)
710 && !action_parse_port(ctx
, &port
)) {
716 ds_put_format(&ds
, ",bucket=bucket_id=%u,weight:100,actions="
717 "ct(nat(dst="IP_FMT
, bucket_id
, IP_ARGS(ip
));
719 ds_put_format(&ds
, ":%"PRIu16
, port
);
721 ds_put_format(&ds
, "),commit,table=%d,zone=NXM_NX_REG%d[0..15])",
722 recirc_table
, MFF_LOG_CT_ZONE
- MFF_REG0
);
724 lexer_match(ctx
->lexer
, LEX_T_COMMA
);
725 } while (!lexer_match(ctx
->lexer
, LEX_T_RPAREN
));
726 add_prerequisite(ctx
, "ip");
728 hash
= hash_string(ds_cstr(&ds
), 0);
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
;
740 /* Check whether we already have an installed entry for this
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
;
750 /* Reserve a new group_id. */
751 group_id
= bitmap_scan(ctx
->ap
->group_table
->group_ids
, 0, 1,
755 if (group_id
== MAX_OVN_GROUPS
+ 1) {
757 action_error(ctx
, "out of group ids.");
760 bitmap_set1(ctx
->ap
->group_table
->group_ids
, group_id
);
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
;
768 hmap_insert(&ctx
->ap
->group_table
->desired_groups
,
769 &group_info
->hmap_node
, group_info
->hmap_node
.hash
);
774 /* Create an action to set the group. */
775 og
= ofpact_put_GROUP(ctx
->ofpacts
);
776 og
->group_id
= group_id
;
780 parse_get_nd_action(struct action_context
*ctx
)
782 struct mf_subfield port
, ip6
;
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
)) {
792 const struct arg args
[] = {
793 { &port
, MFF_LOG_OUTPORT
},
794 { &ip6
, MFF_XXREG0
},
796 setup_args(ctx
, args
, ARRAY_SIZE(args
));
798 put_load(0, MFF_ETH_DST
, 0, 48, ctx
->ofpacts
);
799 emit_resubmit(ctx
, ctx
->ap
->mac_bind_ptable
);
801 restore_args(ctx
, args
, ARRAY_SIZE(args
));
805 parse_put_nd_action(struct action_context
*ctx
)
807 struct mf_subfield port
, ip6
, mac
;
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
)) {
819 const struct arg args
[] = {
820 { &port
, MFF_LOG_INPORT
},
821 { &ip6
, MFF_XXREG0
},
822 { &mac
, MFF_ETH_SRC
}
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
));
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
)
834 struct ofpact_conntrack
*ct
= ofpact_put_CT(ctx
->ofpacts
);
835 ct
->flags
|= commit
? NX_CT_F_COMMIT
: 0;
837 /* If "recirc" is set, we automatically go to the next table. */
839 if (ctx
->ap
->cur_ltable
< ctx
->ap
->n_tables
) {
840 ct
->recirc_table
= ctx
->ap
->first_ptable
+ ctx
->ap
->cur_ltable
+ 1;
842 action_error(ctx
, "\"ct_next\" action not allowed in last table.");
846 ct
->recirc_table
= NX_CT_RECIRC_NONE
;
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;
853 /* We do not support ALGs yet. */
856 /* CT only works with IP, so set up a prerequisite. */
857 add_prerequisite(ctx
, "ip");
859 size_t set_field_offset
= ctx
->ofpacts
->size
;
860 ofpbuf_pull(ctx
->ofpacts
, set_field_offset
);
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
;
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
;
876 ctx
->ofpacts
->header
= ofpbuf_push_uninit(ctx
->ofpacts
, set_field_offset
);
877 ct
= ctx
->ofpacts
->header
;
878 ofpact_finish(ctx
->ofpacts
, &ct
->ofpact
);
881 /* Parse an argument to the ct_commit(); action. Supported arguments include:
883 * ct_mark=<value>[/<mask>]
884 * ct_label=<value>[/<mask>]
886 * If a comma separates the current argument from the next argument, this
887 * function will consume it.
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
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
906 * Return true after successfully parsing an argument. false on failure. */
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
)
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");
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
);
924 action_error(ctx
, "Expected integer after 'ct_mark='");
927 lexer_get(ctx
->lexer
);
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");
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
;
947 action_error(ctx
, "Expected integer after 'ct_label='");
950 lexer_get(ctx
->lexer
);
953 action_error(ctx
, "Expected argument to ct_commit()");
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 "
971 parse_ct_commit_action(struct action_context
*ctx
)
973 if (!lexer_match(ctx
->lexer
, LEX_T_LPAREN
)) {
975 emit_ct(ctx
, false, true, NULL
, NULL
, NULL
, NULL
);
980 * ct_commit(ct_mark=0);
981 * ct_commit(ct_label=0);
982 * ct_commit(ct_mark=0, ct_label=0); */
984 bool set_mark
= false;
985 bool set_label
= false;
988 ovs_be128 label_value
= { .be32
= { 0, }, };
989 ovs_be128 label_mask
= OVS_BE128_MAX
;
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
)) {
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
);
1006 parse_ct_nat(struct action_context
*ctx
, bool snat
)
1008 const size_t ct_offset
= ctx
->ofpacts
->size
;
1009 ofpbuf_pull(ctx
->ofpacts
, ct_offset
);
1011 struct ofpact_conntrack
*ct
= ofpact_put_CT(ctx
->ofpacts
);
1013 if (ctx
->ap
->cur_ltable
< ctx
->ap
->n_tables
) {
1014 ct
->recirc_table
= ctx
->ap
->first_ptable
+ ctx
->ap
->cur_ltable
+ 1;
1017 "\"ct_[sd]nat\" action not allowed in last table.");
1022 ct
->zone_src
.field
= mf_from_id(MFF_LOG_SNAT_ZONE
);
1024 ct
->zone_src
.field
= mf_from_id(MFF_LOG_DNAT_ZONE
);
1026 ct
->zone_src
.ofs
= 0;
1027 ct
->zone_src
.n_bits
= 16;
1031 add_prerequisite(ctx
, "ip");
1033 struct ofpact_nat
*nat
;
1035 nat_offset
= ctx
->ofpacts
->size
;
1036 ofpbuf_pull(ctx
->ofpacts
, nat_offset
);
1038 nat
= ofpact_put_NAT(ctx
->ofpacts
);
1040 nat
->range_af
= AF_UNSPEC
;
1043 if (lexer_match(ctx
->lexer
, LEX_T_LPAREN
)) {
1045 if (ctx
->lexer
->token
.type
== LEX_T_INTEGER
1046 && ctx
->lexer
->token
.format
== LEX_F_IPV4
) {
1047 ip
= ctx
->lexer
->token
.value
.ipv4
;
1049 action_syntax_error(ctx
, "invalid ip");
1053 nat
->range_af
= AF_INET
;
1054 nat
->range
.addr
.ipv4
.min
= ip
;
1056 nat
->flags
|= NX_NAT_F_SRC
;
1058 nat
->flags
|= NX_NAT_F_DST
;
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 `)'");
1068 ctx
->ofpacts
->header
= ofpbuf_push_uninit(ctx
->ofpacts
, nat_offset
);
1069 ct
= ctx
->ofpacts
->header
;
1070 ct
->flags
|= commit
;
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
;
1080 ofpact_finish(ctx
->ofpacts
, &ct
->ofpact
);
1081 ofpbuf_push_uninit(ctx
->ofpacts
, ct_offset
);
1085 parse_action(struct action_context
*ctx
)
1087 if (ctx
->lexer
->token
.type
!= LEX_T_ID
) {
1088 action_syntax_error(ctx
, NULL
);
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
);
1105 action_syntax_error(ctx
, "expecting `--'");
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
);
1130 action_syntax_error(ctx
, "expecting action");
1132 if (!lexer_match(ctx
->lexer
, LEX_T_SEMICOLON
)) {
1133 action_syntax_error(ctx
, "expecting ';'");
1139 parse_actions(struct action_context
*ctx
)
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");
1154 while (ctx
->lexer
->token
.type
!= LEX_T_END
) {
1155 if (!parse_action(ctx
)) {
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.
1165 * 'ap' provides most of the parameters for translation.
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.
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
1177 char * OVS_WARN_UNUSED_RESULT
1178 actions_parse(struct lexer
*lexer
, const struct action_params
*ap
,
1179 struct ofpbuf
*ofpacts
, struct expr
**prereqsp
)
1181 size_t ofpacts_start
= ofpacts
->size
;
1183 struct action_context ctx
= {
1190 parse_actions(&ctx
);
1193 *prereqsp
= ctx
.prereqs
;
1196 ofpacts
->size
= ofpacts_start
;
1197 expr_destroy(ctx
.prereqs
);
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
)
1211 lexer_init(&lexer
, s
);
1213 error
= actions_parse(&lexer
, ap
, ofpacts
, prereqsp
);
1214 lexer_destroy(&lexer
);