Add logic to detect whether datapath support clone. Enhance the xlate logic to make use of it. Added logic to turn on/off clone support for testing.
Signed-off-by: Andy Zhou <az...@ovn.org> Acked-by: Jarno Rajahalme <ja...@ovn.org> --- ofproto/ofproto-dpif-xlate.c | 38 ++++++++++++++++++++++++++++++++++++-- ofproto/ofproto-dpif-xlate.h | 2 ++ ofproto/ofproto-dpif.c | 23 +++++++++++++++++++++++ tests/ofproto-dpif.at | 11 +++++++++++ 4 files changed, 72 insertions(+), 2 deletions(-) diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 9a15ec3..0513394 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -4520,9 +4520,23 @@ xlate_sample_action(struct xlate_ctx *ctx, tunnel_out_port, false); } +/* Only called if the datapath supports 'OVS_ACTION_ATTR_CLONE'. + * + * Translates 'oc' within OVS_ACTION_ATTR_CLONE. */ static void compose_clone_action(struct xlate_ctx *ctx, const struct ofpact_nest *oc) { + size_t clone_offset = nl_msg_start_nested(ctx->odp_actions, + OVS_ACTION_ATTR_CLONE); + + do_xlate_actions(oc->actions, ofpact_nest_get_action_len(oc), ctx); + + nl_msg_end_non_empty_nested(ctx->odp_actions, clone_offset); +} + +static void +xlate_clone(struct xlate_ctx *ctx, const struct ofpact_nest *oc) +{ bool old_was_mpls = ctx->was_mpls; bool old_conntracked = ctx->conntracked; struct flow old_flow = ctx->xin->flow; @@ -4537,7 +4551,16 @@ compose_clone_action(struct xlate_ctx *ctx, const struct ofpact_nest *oc) ofpbuf_use_stub(&ctx->action_set, actset_stub, sizeof actset_stub); ofpbuf_put(&ctx->action_set, old_action_set.data, old_action_set.size); - do_xlate_actions(oc->actions, ofpact_nest_get_action_len(oc), ctx); + if (ctx->xbridge->support.clone) { + /* Datapath clone action will make sure the pre clone packets + * are used for actions after clone. Save and restore + * ctx->base_flow to reflect this for the openflow pipeline. */ + struct flow old_base_flow = ctx->base_flow; + compose_clone_action(ctx, oc); + ctx->base_flow = old_base_flow; + } else { + do_xlate_actions(oc->actions, ofpact_nest_get_action_len(oc), ctx); + } ofpbuf_uninit(&ctx->action_set); ctx->action_set = old_action_set; @@ -5383,7 +5406,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, break; case OFPACT_CLONE: - compose_clone_action(ctx, ofpact_get_CLONE(a)); + xlate_clone(ctx, ofpact_get_CLONE(a)); break; case OFPACT_CT: @@ -6169,3 +6192,14 @@ xlate_mac_learning_update(const struct ofproto_dpif *ofproto, update_learning_table__(xbridge, xbundle, dl_src, vlan, is_grat_arp); } + +void +xlate_disable_dp_clone(const struct ofproto_dpif *ofproto) +{ + struct xlate_cfg *xcfg = ovsrcu_get(struct xlate_cfg *, &xcfgp); + struct xbridge *xbridge = xbridge_lookup(xcfg, ofproto); + + if (xbridge) { + xbridge->support.clone = false; + } +} diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h index 5d00d6d..3986f26 100644 --- a/ofproto/ofproto-dpif-xlate.h +++ b/ofproto/ofproto-dpif-xlate.h @@ -206,6 +206,8 @@ void xlate_mac_learning_update(const struct ofproto_dpif *ofproto, ofp_port_t in_port, struct eth_addr dl_src, int vlan, bool is_grat_arp); +void xlate_disable_dp_clone(const struct ofproto_dpif *); + void xlate_txn_start(void); void xlate_txn_commit(void); diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index df291f3..e1112eb 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -5025,6 +5025,26 @@ disable_datapath_truncate(struct unixctl_conn *conn OVS_UNUSED, } static void +disable_datapath_clone(struct unixctl_conn *conn OVS_UNUSED, + int argc, const char *argv[], + void *aux OVS_UNUSED) +{ + struct ds ds = DS_EMPTY_INITIALIZER; + const char *br = argv[argc -1]; + struct ofproto_dpif *ofproto; + + ofproto = ofproto_dpif_lookup(br); + if (!ofproto) { + unixctl_command_reply_error(conn, "no such bridge"); + return; + } + xlate_disable_dp_clone(ofproto); + udpif_flush(ofproto->backer->udpif); + ds_put_format(&ds, "Datapath clone action disabled for bridge %s", br); + unixctl_command_reply(conn, ds_cstr(&ds)); +} + +static void ofproto_unixctl_init(void) { static bool registered; @@ -5053,6 +5073,9 @@ ofproto_unixctl_init(void) unixctl_command_register("dpif/disable-truncate", "", 0, 0, disable_datapath_truncate, NULL); + + unixctl_command_register("dpif/disable-dp-clone", "bridge", 1, 1, + disable_datapath_clone, NULL); } static odp_port_t diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at index a4bf5a3..e861d9f 100644 --- a/tests/ofproto-dpif.at +++ b/tests/ofproto-dpif.at @@ -6446,6 +6446,17 @@ AT_CHECK([ovs-ofctl add-flows br0 flows.txt], [0], [ignore]) AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout]) AT_CHECK([tail -1 stdout], [0], [dnl +Datapath actions: clone(set(ipv4(src=10.10.10.2,dst=192.168.4.4)),2),clone(set(eth(src=80:81:81:81:81:81)),set(ipv4(src=10.10.10.2,dst=192.168.5.5)),3),4 +]) + +dnl Test flow xlate openflow clone action without using datapath clone action. +AT_CHECK([ovs-appctl dpif/disable-dp-clone br0], [0], +[Datapath clone action disabled for bridge br0 +]) + +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:09,dst=50:54:00:00:00:0a),eth_type(0x0800),ipv4(src=10.10.10.2,dst=10.10.10.1,proto=1,tos=1,ttl=128,frag=no),icmp(type=8,code=0)'], [0], [stdout]) + +AT_CHECK([tail -1 stdout], [0], [dnl Datapath actions: set(ipv4(src=10.10.10.2,dst=192.168.4.4)),2,set(eth(src=80:81:81:81:81:81)),set(ipv4(src=10.10.10.2,dst=192.168.5.5)),3,set(eth(src=50:54:00:00:00:09)),set(ipv4(src=10.10.10.2,dst=10.10.10.1)),4 ]) -- 1.9.1 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev