diff options
author | Ben Pfaff <blp@ovn.org> | 2017-01-20 13:41:23 -0800 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2017-01-21 12:25:13 -0800 |
commit | b3bd2c33e83e2039d75e830368a64d596f820aaa (patch) | |
tree | 2398a4fbb280395c5e4cc20d4577edee0c5479ca /ovn | |
parent | 80b6743d0ab3a39884fe873dd616cb49b6f55fab (diff) | |
download | openvswitch-b3bd2c33e83e2039d75e830368a64d596f820aaa.tar.gz |
actions: Add new OVN action "clone".
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mickey Spiegel <mickeys.dev@gmail.com>
Diffstat (limited to 'ovn')
-rw-r--r-- | ovn/lib/actions.c | 61 | ||||
-rw-r--r-- | ovn/ovn-sb.xml | 10 | ||||
-rw-r--r-- | ovn/utilities/ovn-trace.c | 19 |
3 files changed, 76 insertions, 14 deletions
diff --git a/ovn/lib/actions.c b/ovn/lib/actions.c index 7c5a292f8..213e22e6e 100644 --- a/ovn/lib/actions.c +++ b/ovn/lib/actions.c @@ -1001,8 +1001,8 @@ ovnact_ct_lb_free(struct ovnact_ct_lb *ct_lb) free(ct_lb->dsts); } -/* Implements the "arp" and "nd_na" actions, which execute nested actions on a - * packet derived from the one being processed. */ +/* Implements the "arp", "nd_na", and "clone" actions, which execute nested + * actions on a packet derived from the one being processed. */ static void parse_nested_action(struct action_context *ctx, enum ovnact_type type, const char *prereq) @@ -1018,13 +1018,21 @@ parse_nested_action(struct action_context *ctx, enum ovnact_type type, .pp = ctx->pp, .lexer = ctx->lexer, .ovnacts = &nested, - .prereqs = NULL + .prereqs = NULL, }; parse_actions(&inner_ctx, LEX_T_RCURLY); - /* XXX Not really sure what we should do with prerequisites for nested - * actions. */ - expr_destroy(inner_ctx.prereqs); + if (prereq) { + /* XXX Not really sure what we should do with prerequisites for "arp" + * and "nd_na" actions. */ + expr_destroy(inner_ctx.prereqs); + add_prerequisite(ctx, prereq); + } else { + /* For "clone", the inner prerequisites should just add to the outer + * ones. */ + ctx->prereqs = expr_combine(EXPR_T_AND, + inner_ctx.prereqs, ctx->prereqs); + } if (inner_ctx.lexer->error) { ovnacts_free(nested.data, nested.size); @@ -1032,8 +1040,6 @@ parse_nested_action(struct action_context *ctx, enum ovnact_type type, return; } - add_prerequisite(ctx, prereq); - struct ovnact_nest *on = ovnact_put(ctx->ovnacts, type, OVNACT_ALIGN(sizeof *on)); on->nested_len = nested.size; @@ -1053,6 +1059,12 @@ parse_ND_NA(struct action_context *ctx) } static void +parse_CLONE(struct action_context *ctx) +{ + parse_nested_action(ctx, OVNACT_CLONE, NULL); +} + +static void format_nested_action(const struct ovnact_nest *on, const char *name, struct ds *s) { @@ -1074,10 +1086,16 @@ format_ND_NA(const struct ovnact_nest *nest, struct ds *s) } static void -encode_nested_actions(const struct ovnact_nest *on, - const struct ovnact_encode_params *ep, - enum action_opcode opcode, - struct ofpbuf *ofpacts) +format_CLONE(const struct ovnact_nest *nest, struct ds *s) +{ + format_nested_action(nest, "clone", s); +} + +static void +encode_nested_neighbor_actions(const struct ovnact_nest *on, + const struct ovnact_encode_params *ep, + enum action_opcode opcode, + struct ofpbuf *ofpacts) { /* Convert nested actions into ofpacts. */ uint64_t inner_ofpacts_stub[1024 / 8]; @@ -1102,7 +1120,7 @@ encode_ARP(const struct ovnact_nest *on, const struct ovnact_encode_params *ep, struct ofpbuf *ofpacts) { - encode_nested_actions(on, ep, ACTION_OPCODE_ARP, ofpacts); + encode_nested_neighbor_actions(on, ep, ACTION_OPCODE_ARP, ofpacts); } static void @@ -1110,9 +1128,22 @@ encode_ND_NA(const struct ovnact_nest *on, const struct ovnact_encode_params *ep, struct ofpbuf *ofpacts) { - encode_nested_actions(on, ep, ACTION_OPCODE_ND_NA, ofpacts); + encode_nested_neighbor_actions(on, ep, ACTION_OPCODE_ND_NA, ofpacts); } +static void +encode_CLONE(const struct ovnact_nest *on, + const struct ovnact_encode_params *ep, + struct ofpbuf *ofpacts) +{ + size_t ofs = ofpacts->size; + ofpact_put_CLONE(ofpacts); + ovnacts_encode(on->nested, on->nested_len, ep, ofpacts); + + struct ofpact_nest *clone = ofpbuf_at_assert(ofpacts, ofs, sizeof *clone); + ofpacts->header = clone; + ofpact_finish_CLONE(ofpacts, &clone); +} static void ovnact_nest_free(struct ovnact_nest *on) @@ -1664,6 +1695,8 @@ parse_action(struct action_context *ctx) parse_CT_SNAT(ctx); } else if (lexer_match_id(ctx->lexer, "ct_lb")) { parse_ct_lb_action(ctx); + } else if (lexer_match_id(ctx->lexer, "clone")) { + parse_CLONE(ctx); } else if (lexer_match_id(ctx->lexer, "arp")) { parse_ARP(ctx); } else if (lexer_match_id(ctx->lexer, "nd_na")) { diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml index 5704f4147..a724ae699 100644 --- a/ovn/ovn-sb.xml +++ b/ovn/ovn-sb.xml @@ -1137,6 +1137,16 @@ </p> </dd> + + <dt><code>clone { <var>action</var>; </code>...<code> };</code></dt> + <dd> + Makes a copy of the packet being processed and executes each + <code>action</code> on the copy. Actions following the + <var>clone</var> action, if any, apply to the original, unmodified + packet. This can be used as a way to ``save and restore'' the packet + around a set of actions that may modify it and should not persist. + </dd> + <dt><code>arp { <var>action</var>; </code>...<code> };</code></dt> <dd> <p> diff --git a/ovn/utilities/ovn-trace.c b/ovn/utilities/ovn-trace.c index c15ea0b65..6386b68de 100644 --- a/ovn/utilities/ovn-trace.c +++ b/ovn/utilities/ovn-trace.c @@ -1228,6 +1228,20 @@ execute_output(const struct ovntrace_datapath *dp, struct flow *uflow, } static void +execute_clone(const struct ovnact_nest *on, const struct ovntrace_datapath *dp, + const struct flow *uflow, uint8_t table_id, + enum ovntrace_pipeline pipeline, struct ovs_list *super) +{ + struct flow cloned_flow = *uflow; + + struct ovntrace_node *node = ovntrace_node_append( + super, OVNTRACE_NODE_TRANSFORMATION, "clone"); + + trace_actions(on->nested, on->nested_len, dp, &cloned_flow, + table_id, pipeline, &node->subs); +} + +static void execute_arp(const struct ovnact_nest *on, const struct ovntrace_datapath *dp, const struct flow *uflow, uint8_t table_id, enum ovntrace_pipeline pipeline, struct ovs_list *super) @@ -1416,6 +1430,11 @@ trace_actions(const struct ovnact *ovnacts, size_t ovnacts_len, "*** ct_* actions not implemented"); break; + case OVNACT_CLONE: + execute_clone(ovnact_get_CLONE(a), dp, uflow, table_id, pipeline, + super); + break; + case OVNACT_ARP: execute_arp(ovnact_get_ARP(a), dp, uflow, table_id, pipeline, super); |