nicira-ext: New action "exit".
authorEthan Jackson <ethan@nicira.com>
Fri, 28 Oct 2011 21:46:42 +0000 (14:46 -0700)
committerEthan Jackson <ethan@nicira.com>
Sat, 29 Oct 2011 01:16:40 +0000 (18:16 -0700)
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
lib/ofp-parse.c
lib/ofp-print.c
lib/ofp-util.c
lib/ofp-util.def
ofproto/ofproto-dpif.c
tests/ofproto-dpif.at
tests/ovs-ofctl.at
utilities/ovs-ofctl.8.in

index 7621bca..db8134c 100644 (file)
@@ -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);
 \f
+/* 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. */
+\f
 /* Flexible flow specifications (aka NXM = Nicira Extended Match).
  *
  * OpenFlow 1.0 has "struct ofp_match" for specifying flow matches.  This
index 67224eb..0146a33 100644 (file)
@@ -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;
     }
 }
 
index a6e41eb..6278395 100644 (file)
@@ -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;
     }
index 328d0df..bf03a82 100644 (file)
@@ -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;
         }
 
index 7868faa..2958eb6 100644 (file)
@@ -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
index aba8e3c..d0a5e00 100644 (file)
@@ -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) {
index ec5c238..d08097b 100644 (file)
@@ -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
index b5c119f..d2bf7f7 100644 (file)
@@ -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
 
index 215f8f9..007b54a 100644 (file)
@@ -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: