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
