By avoiding Tx recirculation and embracing tnl_push action within clone,
the tunnel metadata is not propagated. Unless clone action is handled in
the dpif_sflow_read_actions() function as well. This commit resolves
this issue.
In addition, some sflow data needs to be stored and restored in
ofproto-dpif-xlate when native_tunnel_output() is invoked. Otherwise the
output action of underlay bridge is getting counted as well if sFlow is
set on the overlay bridge.

Signed-off-by: Zoltan Balogh <zoltan.bal...@ericsson.com>
---
 ofproto/ofproto-dpif-sflow.c  | 31 ++++++++++++++++++++-----------
 ofproto/ofproto-dpif-sflow.h  |  4 ++--
 ofproto/ofproto-dpif-upcall.c |  2 +-
 ofproto/ofproto-dpif-xlate.c  |  7 +++++++
 tests/ofproto-dpif.at         |  2 +-
 5 files changed, 31 insertions(+), 15 deletions(-)

diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
index ccf89645b..0948551d3 100644
--- a/ofproto/ofproto-dpif-sflow.c
+++ b/ofproto/ofproto-dpif-sflow.c
@@ -961,7 +961,7 @@ sflow_read_set_action(const struct nlattr *attr,
         } else {
             dpif_sflow_read_actions(NULL,
                                     nl_attr_get(attr), nl_attr_get_size(attr),
-                                    sflow_actions);
+                                    sflow_actions, true);
         }
         break;
     case OVS_KEY_ATTR_PRIORITY:
@@ -1088,8 +1088,9 @@ dpif_sflow_capture_input_mpls(const struct flow *flow,
 
 void
 dpif_sflow_read_actions(const struct flow *flow,
-                       const struct nlattr *actions, size_t actions_len,
-                       struct dpif_sflow_actions *sflow_actions)
+                        const struct nlattr *actions, size_t actions_len,
+                        struct dpif_sflow_actions *sflow_actions,
+                        bool capture_mpls)
 {
     const struct nlattr *a;
     unsigned int left;
@@ -1099,7 +1100,7 @@ dpif_sflow_read_actions(const struct flow *flow,
        return;
     }
 
-    if (flow != NULL) {
+    if (flow != NULL && capture_mpls == true) {
        /* Make sure the MPLS output stack
         * is seeded with the input stack.
         */
@@ -1197,8 +1198,13 @@ dpif_sflow_read_actions(const struct flow *flow,
             * structure to report this.
             */
            break;
+    case OVS_ACTION_ATTR_CLONE:
+        if (flow != NULL) {
+            dpif_sflow_read_actions(flow, nl_attr_get(a), nl_attr_get_size(a),
+                                    sflow_actions, false);
+        }
+        break;
        case OVS_ACTION_ATTR_SAMPLE:
-       case OVS_ACTION_ATTR_CLONE:
         case OVS_ACTION_ATTR_ENCAP_NSH:
         case OVS_ACTION_ATTR_DECAP_NSH:
        case OVS_ACTION_ATTR_UNSPEC:
@@ -1266,6 +1272,7 @@ dpif_sflow_received(struct dpif_sflow *ds, const struct 
dp_packet *packet,
     struct dpif_sflow_port *in_dsp;
     struct dpif_sflow_port *out_dsp;
     ovs_be16 vlan_tci;
+    uint32_t num_outputs;
 
     ovs_mutex_lock(&mutex);
     sampler = ds->sflow_agent->samplers;
@@ -1333,11 +1340,13 @@ dpif_sflow_received(struct dpif_sflow *ds, const struct 
dp_packet *packet,
        }
     }
 
+    num_outputs = dpif_sflow_cookie_num_outputs(cookie);
     /* Output tunnel. */
     if (sflow_actions
-       && sflow_actions->encap_depth == 1
-       && !sflow_actions->tunnel_err
-       && dpif_sflow_cookie_num_outputs(cookie) == 1) {
+        && sflow_actions->encap_depth == 1
+        && !sflow_actions->tunnel_err
+        && (num_outputs == 1        /* push_tnl or      */
+            || num_outputs == 2)) { /* clone + push_tnl */
        tnlOutProto = sflow_actions->tunnel_ipproto;
        if (tnlOutProto == 0) {
            /* Try to infer the ip-protocol from the output port. */
@@ -1365,9 +1374,9 @@ dpif_sflow_received(struct dpif_sflow *ds, const struct 
dp_packet *packet,
 
     /* MPLS output label stack. */
     if (sflow_actions
-       && sflow_actions->mpls_stack_depth > 0
-       && !sflow_actions->mpls_err
-       && dpif_sflow_cookie_num_outputs(cookie) == 1) {
+        && sflow_actions->mpls_stack_depth > 0
+        && !sflow_actions->mpls_err
+        && num_outputs == 1) {
        memset(&mplsElem, 0, sizeof(mplsElem));
        mplsElem.tag = SFLFLOW_EX_MPLS;
        dpif_sflow_encode_mpls_stack(&mplsElem.flowType.mpls.out_stack,
diff --git a/ofproto/ofproto-dpif-sflow.h b/ofproto/ofproto-dpif-sflow.h
index 014e6cce3..87ed93c6e 100644
--- a/ofproto/ofproto-dpif-sflow.h
+++ b/ofproto/ofproto-dpif-sflow.h
@@ -70,8 +70,8 @@ void dpif_sflow_run(struct dpif_sflow *);
 void dpif_sflow_wait(struct dpif_sflow *);
 
 void dpif_sflow_read_actions(const struct flow *,
-                            const struct nlattr *actions, size_t actions_len,
-                            struct dpif_sflow_actions *);
+                             const struct nlattr *actions, size_t actions_len,
+                             struct dpif_sflow_actions *, bool capture_mpls);
 
 void dpif_sflow_received(struct dpif_sflow *, const struct dp_packet *,
                          const struct flow *, odp_port_t odp_port,
diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
index 02cf5415b..dc496344f 100644
--- a/ofproto/ofproto-dpif-upcall.c
+++ b/ofproto/ofproto-dpif-upcall.c
@@ -1317,7 +1317,7 @@ dpif_read_actions(struct udpif *udpif, struct upcall 
*upcall,
 
     switch (type) {
     case SFLOW_UPCALL:
-        dpif_sflow_read_actions(flow, actions, actions_len, upcall_data);
+        dpif_sflow_read_actions(flow, actions, actions_len, upcall_data, true);
         break;
     case FLOW_SAMPLE_UPCALL:
     case IPFIX_UPCALL:
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 9b3a2f28a..9be0bbd84 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -3259,6 +3259,9 @@ native_tunnel_output(struct xlate_ctx *ctx, const struct 
xport *xport,
     char buf_sip6[INET6_ADDRSTRLEN];
     char buf_dip6[INET6_ADDRSTRLEN];
 
+    /* Store sFlow data. */
+    uint32_t sflow_n_outputs = ctx->sflow_n_outputs;
+
     /* Structures to backup Ethernet and IP of base_flow. */
     struct flow old_base_flow;
     struct flow old_flow;
@@ -3410,6 +3413,10 @@ native_tunnel_output(struct xlate_ctx *ctx, const struct 
xport *xport,
     /* Restore the flows after the translation. */
     memcpy(&ctx->xin->flow, &old_flow, sizeof ctx->xin->flow);
     memcpy(&ctx->base_flow, &old_base_flow, sizeof ctx->base_flow);
+
+    /* Restore sFlow data. */
+    ctx->sflow_n_outputs = sflow_n_outputs;
+
     return 0;
 }
 
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 9a51a1364..cdf48f4de 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -6286,7 +6286,7 @@ AT_CHECK([ovs-appctl ovs/route/add 1.1.2.92/24 br0], [0], 
[OK
 AT_CHECK([ovs-ofctl add-flow br0 action=normal])
 
 dnl Prime ARP Cache for 1.1.2.92
-AT_CHECK([ovs-appctl netdev-dummy/receive br0 
'recirc_id(0),in_port(100),eth(src=f8:bc:12:44:34:b6,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=00:00:00:00:00:00)'])
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 
'recirc_id(0),in_port(1),eth(src=f8:bc:12:44:34:b6,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=00:00:00:00:00:00)'])
 
 dnl configure sflow on int-br only
 ovs-vsctl \
-- 
2.14.1

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to