From: Ethan Jackson Date: Fri, 28 Oct 2011 21:46:42 +0000 (-0700) Subject: nicira-ext: New action "exit". X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=848e88098fec85336b89c0c652c1d91577c87b11;p=openvswitch nicira-ext: New action "exit". 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. --- diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h index 7621bca8..db8134cc 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 67224eb6..0146a333 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 a6e41eb7..6278395d 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 328d0df8..bf03a820 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 7868faa4..2958eb6e 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 aba8e3ce..d0a5e004 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 ec5c238d..d08097b6 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 b5c119f3..d2bf7f70 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 215f8f92..007b54a8 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: