Skip to content

Commit

Permalink
actions: Add new OVN action "clone".
Browse files Browse the repository at this point in the history
Signed-off-by: Ben Pfaff <[email protected]>
Acked-by: Mickey Spiegel <[email protected]>
  • Loading branch information
blp committed Jan 21, 2017
1 parent 80b6743 commit b3bd2c3
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 16 deletions.
5 changes: 3 additions & 2 deletions include/ovn/actions.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2016 Nicira, Inc.
* Copyright (c) 2015, 2016, 2017 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -60,6 +60,7 @@ struct simap;
OVNACT(CT_DNAT, ovnact_ct_nat) \
OVNACT(CT_SNAT, ovnact_ct_nat) \
OVNACT(CT_LB, ovnact_ct_lb) \
OVNACT(CLONE, ovnact_nest) \
OVNACT(ARP, ovnact_nest) \
OVNACT(ND_NA, ovnact_nest) \
OVNACT(GET_ARP, ovnact_get_mac_bind) \
Expand Down Expand Up @@ -186,7 +187,7 @@ struct ovnact_ct_lb {
uint8_t ltable; /* Logical table ID of next table. */
};

/* OVNACT_ARP, OVNACT_ND_NA. */
/* OVNACT_ARP, OVNACT_ND_NA, OVNACT_CLONE. */
struct ovnact_nest {
struct ovnact ovnact;
struct ovnact *nested;
Expand Down
61 changes: 47 additions & 14 deletions ovn/lib/actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -1018,22 +1018,28 @@ 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);
ofpbuf_uninit(&nested);
return;
}

add_prerequisite(ctx, prereq);

struct ovnact_nest *on = ovnact_put(ctx->ovnacts, type,
OVNACT_ALIGN(sizeof *on));
on->nested_len = nested.size;
Expand All @@ -1052,6 +1058,12 @@ parse_ND_NA(struct action_context *ctx)
parse_nested_action(ctx, OVNACT_ND_NA, "nd_ns");
}

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)
Expand All @@ -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];
Expand All @@ -1102,17 +1120,30 @@ 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
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)
Expand Down Expand Up @@ -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")) {
Expand Down
10 changes: 10 additions & 0 deletions ovn/ovn-sb.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
19 changes: 19 additions & 0 deletions ovn/utilities/ovn-trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -1227,6 +1227,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,
Expand Down Expand Up @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions tests/ovn.at
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,11 @@ ct_snat(foo, bar);
ct_snat();
Syntax error at `)' expecting IPv4 address.

# clone
clone { ip4.dst = 255.255.255.255; output; }; next(11);
encodes as clone(set_field:255.255.255.255->ip_dst,resubmit(,64)),resubmit(,27)
has prereqs eth.type == 0x800

# arp
arp { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
encodes as controller(userdata=00.00.00.00.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
Expand Down

0 comments on commit b3bd2c3

Please sign in to comment.