summaryrefslogtreecommitdiff
path: root/ovn
diff options
context:
space:
mode:
authorBen Pfaff <blp@ovn.org>2017-01-20 13:41:23 -0800
committerBen Pfaff <blp@ovn.org>2017-01-21 12:25:13 -0800
commitb3bd2c33e83e2039d75e830368a64d596f820aaa (patch)
tree2398a4fbb280395c5e4cc20d4577edee0c5479ca /ovn
parent80b6743d0ab3a39884fe873dd616cb49b6f55fab (diff)
downloadopenvswitch-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.c61
-rw-r--r--ovn/ovn-sb.xml10
-rw-r--r--ovn/utilities/ovn-trace.c19
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);