This OpenFlow action triggers the 'back_to_kernel' datapath action
to ask the datapath to return packets to the kernel.

Signed-off-by: Chris Luke <[email protected]>
---
 include/openflow/nicira-ext.h |    1 +
 lib/odp-execute.c             |    5 ++++-
 lib/ofp-actions.c             |   30 ++++++++++++++++++++++++++++++
 lib/ofp-actions.h             |    8 ++++++++
 lib/ofp-parse.c               |    4 ++++
 lib/ofp-util.def              |    1 +
 ofproto/ofproto-dpif-xlate.c  |   27 +++++++++++++++++++++++++++
 tests/ofproto-dpif.at         |   15 +++++++++++++++
 tests/ovs-ofctl.at            |    2 ++
 utilities/ovs-ofctl.8.in      |    7 +++++++
 10 files changed, 99 insertions(+), 1 deletion(-)

diff --git a/include/openflow/nicira-ext.h b/include/openflow/nicira-ext.h
index 22939f4..aadab31 100644
--- a/include/openflow/nicira-ext.h
+++ b/include/openflow/nicira-ext.h
@@ -314,6 +314,7 @@ enum nx_action_subtype {
     NXAST_SAMPLE,               /* struct nx_action_sample */
     NXAST_SET_MPLS_LABEL,       /* struct nx_action_ttl */
     NXAST_SET_MPLS_TC,          /* struct nx_action_ttl */
+    NXAST_BACK_TO_KERNEL,       /* struct nx_action_header */
 };
 
 /* Header for Nicira-defined actions. */
diff --git a/lib/odp-execute.c b/lib/odp-execute.c
index c98cfb4..0a855ab 100644
--- a/lib/odp-execute.c
+++ b/lib/odp-execute.c
@@ -195,7 +195,6 @@ odp_execute_actions__(void *dp, struct ofpbuf *packet, 
struct pkt_metadata *md,
             /* These only make sense in the context of a datapath. */
         case OVS_ACTION_ATTR_OUTPUT:
         case OVS_ACTION_ATTR_USERSPACE:
-        case OVS_ACTION_ATTR_BACK_TO_KERNEL:
             if (dp_execute_action) {
                 /* Allow 'dp_execute_action' to steal the packet data if we do
                  * not need it any more. */
@@ -233,6 +232,10 @@ odp_execute_actions__(void *dp, struct ofpbuf *packet, 
struct pkt_metadata *md,
                                more_actions || left > NLA_ALIGN(a->nla_len));
             break;
 
+        case OVS_ACTION_ATTR_BACK_TO_KERNEL:
+            /* This is a no-op in the userspace datapath */
+            break;
+
         case OVS_ACTION_ATTR_UNSPEC:
         case __OVS_ACTION_ATTR_MAX:
             OVS_NOT_REACHED();
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index df7aebd..20d082b 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -503,6 +503,10 @@ ofpact_from_nxast(const union ofp_action *a, enum 
ofputil_action_code code,
     case OFPUTIL_NXAST_SAMPLE:
         error = sample_from_openflow(&a->sample, out);
         break;
+
+    case OFPUTIL_NXAST_BACK_TO_KERNEL:
+        ofpact_put_BACK_TO_KERNEL(out);
+        break;
     }
 
     return error;
@@ -1335,6 +1339,7 @@ ofpact_is_set_action(const struct ofpact *a)
     case OFPACT_STRIP_VLAN:
     case OFPACT_WRITE_ACTIONS:
     case OFPACT_WRITE_METADATA:
+    case OFPACT_BACK_TO_KERNEL:
         return false;
     default:
         OVS_NOT_REACHED();
@@ -1394,6 +1399,7 @@ ofpact_is_allowed_in_actions_set(const struct ofpact *a)
     case OFPACT_SAMPLE:
     case OFPACT_STACK_POP:
     case OFPACT_STACK_PUSH:
+    case OFPACT_BACK_TO_KERNEL:
 
     /* The action set may only include actions and thus
      * may not include any instructions */
@@ -1632,6 +1638,7 @@ ovs_instruction_type_from_ofpact_type(enum ofpact_type 
type)
     case OFPACT_NOTE:
     case OFPACT_EXIT:
     case OFPACT_SAMPLE:
+    case OFPACT_BACK_TO_KERNEL:
     default:
         return OVSINST_OFPIT11_APPLY_ACTIONS;
     }
@@ -2118,6 +2125,9 @@ ofpact_check__(enum ofputil_protocol *usable_protocols, 
struct ofpact *a,
     case OFPACT_GROUP:
         return 0;
 
+    case OFPACT_BACK_TO_KERNEL:
+        return 0;
+
     default:
         OVS_NOT_REACHED();
     }
@@ -2351,6 +2361,14 @@ ofpact_sample_to_nxast(const struct ofpact_sample *os,
 }
 
 static void
+ofpact_back_to_kernel_to_nxast(
+                           const struct ofpact_back_to_kernel *oc OVS_UNUSED,
+                           struct ofpbuf *out)
+{
+    ofputil_put_NXAST_BACK_TO_KERNEL(out);
+}
+
+static void
 ofpact_to_nxast(const struct ofpact *a, struct ofpbuf *out)
 {
     switch (a->type) {
@@ -2460,6 +2478,10 @@ ofpact_to_nxast(const struct ofpact *a, struct ofpbuf 
*out)
         ofpact_sample_to_nxast(ofpact_get_SAMPLE(a), out);
         break;
 
+    case OFPACT_BACK_TO_KERNEL:
+        ofpact_back_to_kernel_to_nxast(ofpact_get_BACK_TO_KERNEL(a), out);
+        break;
+
     case OFPACT_GROUP:
     case OFPACT_OUTPUT:
     case OFPACT_ENQUEUE:
@@ -2616,6 +2638,7 @@ ofpact_to_openflow10(const struct ofpact *a, struct 
ofpbuf *out)
     case OFPACT_PUSH_MPLS:
     case OFPACT_POP_MPLS:
     case OFPACT_SAMPLE:
+    case OFPACT_BACK_TO_KERNEL:
         ofpact_to_nxast(a, out);
         break;
     }
@@ -2809,6 +2832,7 @@ ofpact_to_openflow11(const struct ofpact *a, struct 
ofpbuf *out)
     case OFPACT_NOTE:
     case OFPACT_EXIT:
     case OFPACT_SAMPLE:
+    case OFPACT_BACK_TO_KERNEL:
         ofpact_to_nxast(a, out);
         break;
     }
@@ -3137,6 +3161,7 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, 
ofp_port_t port)
     case OFPACT_GOTO_TABLE:
     case OFPACT_METER:
     case OFPACT_GROUP:
+    case OFPACT_BACK_TO_KERNEL:
     default:
         return false;
     }
@@ -3561,6 +3586,11 @@ ofpact_format(const struct ofpact *a, struct ds *s)
         ds_put_format(s, "group:%"PRIu32,
                       ofpact_get_GROUP(a)->group_id);
         break;
+
+    case OFPACT_BACK_TO_KERNEL:
+        ds_put_cstr(s, "back_to_kernel");
+        break;
+
     }
 }
 
diff --git a/lib/ofp-actions.h b/lib/ofp-actions.h
index 00cba6a..801959a 100644
--- a/lib/ofp-actions.h
+++ b/lib/ofp-actions.h
@@ -57,6 +57,7 @@
     DEFINE_OFPACT(ENQUEUE,         ofpact_enqueue,       ofpact)    \
     DEFINE_OFPACT(OUTPUT_REG,      ofpact_output_reg,    ofpact)    \
     DEFINE_OFPACT(BUNDLE,          ofpact_bundle,        slaves)    \
+    DEFINE_OFPACT(BACK_TO_KERNEL,  ofpact_back_to_kernel, ofpact)   \
                                                                     \
     /* Header changes. */                                           \
     DEFINE_OFPACT(SET_FIELD,       ofpact_set_field,     ofpact)    \
@@ -258,6 +259,13 @@ struct ofpact_bundle {
     ofp_port_t slaves[];
 };
 
+/* OFPACT_BACK_TO_KERNEL
+ *
+ * Used for NXAST_BACK_TO_KERNEL. */
+struct ofpact_back_to_kernel {
+    struct ofpact ofpact;
+};
+
 /* OFPACT_SET_VLAN_VID.
  *
  * We keep track if vlan was present at action validation time to avoid a
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index 251adfa..d4bcd2c 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -905,6 +905,10 @@ parse_named_action(enum ofputil_action_code code,
     case OFPUTIL_NXAST_SAMPLE:
         error = parse_sample(ofpacts, arg);
         break;
+
+    case OFPUTIL_NXAST_BACK_TO_KERNEL:
+        ofpact_put_BACK_TO_KERNEL(ofpacts);
+        break;
     }
 
     if (error) {
diff --git a/lib/ofp-util.def b/lib/ofp-util.def
index fae2bf2..951875f 100644
--- a/lib/ofp-util.def
+++ b/lib/ofp-util.def
@@ -77,6 +77,7 @@ NXAST_ACTION(NXAST_DEC_MPLS_TTL,    nx_action_header,       
0, "dec_mpls_ttl")
 NXAST_ACTION(NXAST_PUSH_MPLS,       nx_action_push_mpls,    0, "push_mpls")
 NXAST_ACTION(NXAST_POP_MPLS,        nx_action_pop_mpls,     0, "pop_mpls")
 NXAST_ACTION(NXAST_SAMPLE,          nx_action_sample,       0, "sample")
+NXAST_ACTION(NXAST_BACK_TO_KERNEL,  nx_action_header,       0, 
"back_to_kernel")
 
 #undef OFPAT10_ACTION
 #undef OFPAT11_ACTION
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index e73b7eb..bc14510 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -1680,6 +1680,23 @@ process_special(struct xlate_ctx *ctx, const struct flow 
*flow,
 }
 
 static void
+compose_back_to_kernel_action(struct xlate_ctx *ctx)
+{
+    ctx->xout->slow |= commit_odp_actions(&ctx->xin->flow,
+                                          &ctx->base_flow,
+                                          &ctx->xout->odp_actions,
+                                          &ctx->xout->wc,
+                                          &ctx->mpls_depth_delta);
+
+    nl_msg_put_flag(&ctx->xout->odp_actions,
+                    OVS_ACTION_ATTR_BACK_TO_KERNEL);
+
+    ctx->sflow_odp_port = ODPP_LOCAL;
+    ctx->sflow_n_outputs++;
+    ctx->xout->nf_output_iface = OFPP_LOCAL;
+}
+
+static void
 compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
                         bool check_stp)
 {
@@ -2585,6 +2602,12 @@ xlate_action_set(struct xlate_ctx *ctx)
 }
 
 static void
+xlate_back_to_kernel_action(struct xlate_ctx *ctx)
+{
+    compose_back_to_kernel_action(ctx);
+}
+
+static void
 do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
                  struct xlate_ctx *ctx)
 {
@@ -2877,6 +2900,10 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t 
ofpacts_len,
         case OFPACT_SAMPLE:
             xlate_sample_action(ctx, ofpact_get_SAMPLE(a));
             break;
+
+        case OFPACT_BACK_TO_KERNEL:
+            xlate_back_to_kernel_action(ctx);
+            break;
         }
     }
 }
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 730bb91..da057c6 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -3166,3 +3166,18 @@ AT_CHECK([grep -c 'resubmits yielded over 64 kB of 
stack' ovs-vswitchd.log], [0]
 ])
 OVS_VSWITCHD_STOP(["/resubmits yielded over 64 kB of stack/d"])
 AT_CLEANUP
+
+AT_SETUP([ofproto-dpif - back_to_kernel])
+OVS_VSWITCHD_START
+ADD_OF_PORTS([br0], [1])
+AT_DATA([flows.txt], [dnl
+icmp action=back_to_kernel
+])
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+AT_CHECK([ovs-appctl ofproto/trace br0 
'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,dl_type=0x0800,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=1,nw_tos=0,nw_ttl=128,icmp_type=8,icmp_code=0'],
 [0], [stdout])
+AT_CHECK([tail -1 stdout], [0],
+  [Datapath actions: back_to_kernel
+])
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index bda8666..0b07398 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -345,6 +345,7 @@ check_overlap,actions=output:1,exit,output:2
 tcp,actions=fin_timeout(idle_timeout=5,hard_timeout=15)
 actions=controller(max_len=123,reason=invalid_ttl,id=555)
 
actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+actions=back_to_kernel
 ]])
 
 AT_CHECK([ovs-ofctl parse-flows flows.txt
@@ -381,6 +382,7 @@ NXT_FLOW_MOD: ADD table:255 check_overlap 
actions=output:1,exit,output:2
 NXT_FLOW_MOD: ADD table:255 tcp 
actions=fin_timeout(idle_timeout=5,hard_timeout=15)
 NXT_FLOW_MOD: ADD table:255 
actions=controller(reason=invalid_ttl,max_len=123,id=555)
 NXT_FLOW_MOD: ADD table:255 
actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
+NXT_FLOW_MOD: ADD table:255 actions=back_to_kernel
 ]])
 AT_CLEANUP
 
diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
index 9a8fd33..af56015 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -1671,6 +1671,13 @@ configuring sample collector sets.
 .IP
 This action was added in Open vSwitch 1.10.90.
 .
+.IP "\fBback_to_kernel\fR"
+Causes packets that match to be returned to the system kernel as though 
+Open vSwitch never saw them. If this is not supported by the running
+kernel this is effectively a non-operation.
+.IP
+This action was added in Open vSwitch 2.1.x.
+.
 .IP "\fBexit\fR"
 This action causes Open vSwitch to immediately halt execution of
 further actions.  Those actions which have already been executed are
-- 
1.7.9.5

_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

Reply via email to