[ovs-dev] [userspace clone v3 4/4] xlate: Generate of datapath clone action when supported

Andy Zhou azhou at ovn.org
Sat Jan 21 02:05:55 UTC 2017


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 <azhou at ovn.org>
Acked-by: Jarno Rajahalme <jarno at 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



More information about the dev mailing list