The exit action causes the switch to immediately halt processing of
further actions. It's intended to be used in conjunction with
multi table support. It allows a table to force tables which call
it to discontinue processing a flow.
---
include/openflow/nicira-ext.h | 15 ++++++++++++++-
lib/ofp-parse.c | 3 +++
lib/ofp-print.c | 4 ++++
lib/ofp-util.c | 1 +
lib/ofp-util.def | 1 +
ofproto/ofproto-dpif.c | 10 ++++++++++
tests/ofproto-dpif.at | 23 +++++++++++++++++++++++
tests/ovs-ofctl.at | 2 ++
utilities/ovs-ofctl.8.in | 6 ++++++
9 files changed, 64 insertions(+), 1 deletions(-)
diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
index 7621bca..db8134c 100644
--- a/include/openflow/nicira-ext.h
+++ b/include/openflow/nicira-ext.h
@@ -282,7 +282,8 @@ enum nx_action_subtype {
NXAST_BUNDLE_LOAD, /* struct nx_action_bundle */
NXAST_RESUBMIT_TABLE, /* struct nx_action_resubmit */
NXAST_OUTPUT_REG, /* struct nx_action_output_reg */
- NXAST_LEARN /* struct nx_action_learn */
+ NXAST_LEARN, /* struct nx_action_learn */
+ NXAST_EXIT /* struct nx_action_header */
};
/* Header for Nicira-defined actions. */
@@ -1034,6 +1035,18 @@ struct nx_action_output_reg {
};
OFP_ASSERT(sizeof(struct nx_action_output_reg) == 24);
+/* NXAST_EXIT
+ *
+ * Discontinues action processing.
+ *
+ * The NXAST_EXIT action causes the switch to immediately halt processing
+ * actions for the flow. Any actions which have already been processed are
+ * executed by the switch. However, any further actions, including those which
+ * may be in different tables, or different levels of the NXAST_RESUBMIT
+ * hierarchy, will be ignored.
+ *
+ * Uses the nx_action_header structure. */
+
/* Flexible flow specifications (aka NXM = Nicira Extended Match).
*
* OpenFlow 1.0 has "struct ofp_match" for specifying flow matches. This
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index 67224eb..0146a33 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -360,6 +360,9 @@ parse_named_action(enum ofputil_action_code code, const
struct flow *flow,
case OFPUTIL_NXAST_LEARN:
learn_parse(b, arg, flow);
break;
+ case OFPUTIL_NXAST_EXIT:
+ ofputil_put_NXAST_EXIT(b);
+ break;
}
}
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index a6e41eb..6278395 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -338,6 +338,10 @@ ofp_print_action(struct ds *s, const union ofp_action *a,
learn_format((const struct nx_action_learn *) a, s);
break;
+ case OFPUTIL_NXAST_EXIT:
+ ds_put_cstr(s, "exit");
+ break;
+
default:
break;
}
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 328d0df..bf03a82 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -2185,6 +2185,7 @@ validate_actions(const union ofp_action *actions, size_t
n_actions,
case OFPUTIL_NXAST_POP_QUEUE:
case OFPUTIL_NXAST_NOTE:
case OFPUTIL_NXAST_SET_TUNNEL64:
+ case OFPUTIL_NXAST_EXIT:
break;
}
diff --git a/lib/ofp-util.def b/lib/ofp-util.def
index 7868faa..2958eb6 100644
--- a/lib/ofp-util.def
+++ b/lib/ofp-util.def
@@ -35,4 +35,5 @@ NXAST_ACTION(NXAST_BUNDLE_LOAD, nx_action_bundle, 1,
"bundle_load")
NXAST_ACTION(NXAST_RESUBMIT_TABLE, nx_action_resubmit, 0, NULL)
NXAST_ACTION(NXAST_OUTPUT_REG, nx_action_output_reg, 0, NULL)
NXAST_ACTION(NXAST_LEARN, nx_action_learn, 1, "learn")
+NXAST_ACTION(NXAST_EXIT, nx_action_header, 0, "exit")
#undef NXAST_ACTION
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index aba8e3c..d0a5e00 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -212,6 +212,7 @@ struct action_xlate_ctx {
uint32_t sflow_n_outputs; /* Number of output ports. */
uint16_t sflow_odp_port; /* Output port for composing sFlow action. */
uint16_t user_cookie_offset;/* Used for user_action_cookie fixup. */
+ bool exit; /* No further actions should be processed. */
};
static void action_xlate_ctx_init(struct action_xlate_ctx *,
@@ -4123,6 +4124,10 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
enum ofputil_action_code code;
ovs_be64 tun_id;
+ if (ctx->exit) {
+ break;
+ }
+
code = ofputil_decode_action_unsafe(ia);
switch (code) {
case OFPUTIL_OFPAT_OUTPUT:
@@ -4258,6 +4263,10 @@ do_xlate_actions(const union ofp_action *in, size_t n_in,
xlate_learn_action(ctx, (const struct nx_action_learn *) ia);
}
break;
+
+ case OFPUTIL_NXAST_EXIT:
+ ctx->exit = true;
+ break;
}
}
@@ -4300,6 +4309,7 @@ xlate_actions(struct action_xlate_ctx *ctx,
ctx->base_flow = ctx->flow;
ctx->base_flow.tun_id = 0;
ctx->table_id = 0;
+ ctx->exit = false;
if (ctx->flow.tos_frag & FLOW_FRAG_ANY) {
switch (ctx->ofproto->up.frag_handling) {
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index ec5c238..d08097b 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -266,3 +266,26 @@ do
done
OVS_VSWITCHD_STOP
AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - exit])
+OVS_VSWITCHD_START
+AT_DATA([flows.txt], [dnl
+in_port=1 actions=output:10,exit,output:11
+in_port=2 actions=output:12,resubmit:1,output:12
+in_port=3 actions=output:13,resubmit:2,output:14
+])
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+AT_CHECK([ovs-appctl ofproto/trace br0
'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,frag=no),icmp(type=8,code=0)'],
[0], [stdout])
+AT_CHECK([tail -1 stdout], [0],
+ [Datapath actions: 10
+])
+AT_CHECK([ovs-appctl ofproto/trace br0
'in_port(2),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,frag=no),icmp(type=8,code=0)'],
[0], [stdout])
+AT_CHECK([tail -1 stdout], [0],
+ [Datapath actions: 12,10
+])
+AT_CHECK([ovs-appctl ofproto/trace br0
'in_port(3),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,frag=no),icmp(type=8,code=0)'],
[0], [stdout])
+AT_CHECK([tail -1 stdout], [0],
+ [Datapath actions: 13,12,10
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index b5c119f..d2bf7f7 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -26,6 +26,7 @@
actions=bundle_load(symmetric_l4,60,hrw,ofport,NXM_NX_REG0[0..30],slaves:)
actions=output:1,bundle_load(eth_src,0,hrw,ofport,NXM_NX_REG0[16..31],slaves:1),output:2
actions=resubmit:1,resubmit(2),resubmit(,3),resubmit(2,3)
actions=output:1,output:NXM_NX_REG0[],output:2,output:NXM_NX_REG1[16..31],output:3
+actions=output:1,exit,output:2
]])
AT_CHECK([ovs-ofctl parse-flows flows.txt
@@ -56,6 +57,7 @@ NXT_FLOW_MOD: ADD table:255
actions=bundle_load(symmetric_l4,60,hrw,ofport,NXM_N
NXT_FLOW_MOD: ADD table:255
actions=output:1,bundle_load(eth_src,0,hrw,ofport,NXM_NX_REG0[16..31],slaves:1),output:2
NXT_FLOW_MOD: ADD table:255
actions=resubmit:1,resubmit:2,resubmit(,3),resubmit(2,3)
NXT_FLOW_MOD: ADD table:255
actions=output:1,output:NXM_NX_REG0[],output:2,output:NXM_NX_REG1[16..31],output:3
+NXT_FLOW_MOD: ADD table:255 actions=output:1,exit,output:2
]])
AT_CLEANUP
diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
index 215f8f9..007b54a 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -898,6 +898,12 @@ with no match criteria. (This is why the default
\fBtable\fR is 1, to
keep the learned flows separate from the primary flow table 0.)
.RE
.
+.IP "\fBexit\fR"
+This action causes Open vSwitch to immediately halt execution of further
+actions. Those actions which have already been executed are unaffected. Any
+further actions, including those which may be in other tables, or different
+levels of the \fBresubmit\fR call stack, are ignored.
+.
.PP
The \fBadd\-flow\fR, \fBadd\-flows\fR, and \fBmod\-flows\fR commands
support an additional optional field:
--
1.7.7.1
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev