Signed-off-by: Daniele Di Proietto <ddiproie...@vmware.com>
---
 ofproto/ofproto-dpif.c | 103 +++++++++++++++++++++++++++++++++++--------------
 1 file changed, 75 insertions(+), 28 deletions(-)

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index d965d38..915b8c2 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -25,10 +25,10 @@
 #include "bond.h"
 #include "bundle.h"
 #include "byte-order.h"
+#include "cfm.h"
 #include "connectivity.h"
 #include "connmgr.h"
 #include "coverage.h"
-#include "cfm.h"
 #include "dpif.h"
 #include "dynamic-string.h"
 #include "fail-open.h"
@@ -44,13 +44,13 @@
 #include "netdev.h"
 #include "netlink.h"
 #include "nx-match.h"
-#include "odp-util.h"
 #include "odp-execute.h"
-#include "ofp-util.h"
-#include "ofpbuf.h"
+#include "odp-util.h"
 #include "ofp-actions.h"
 #include "ofp-parse.h"
 #include "ofp-print.h"
+#include "ofp-util.h"
+#include "ofpbuf.h"
 #include "ofproto-dpif-ipfix.h"
 #include "ofproto-dpif-mirror.h"
 #include "ofproto-dpif-monitor.h"
@@ -58,6 +58,7 @@
 #include "ofproto-dpif-sflow.h"
 #include "ofproto-dpif-upcall.h"
 #include "ofproto-dpif-xlate.h"
+#include "ovs-thread-stats.h"
 #include "poll-loop.h"
 #include "seq.h"
 #include "simap.h"
@@ -83,8 +84,7 @@ struct rule_dpif {
      *
      *   - Do include packets and bytes from datapath flows which have not
      *   recently been processed by a revalidator. */
-    struct ovs_mutex stats_mutex;
-    struct dpif_flow_stats stats OVS_GUARDED;
+    int stats; /* Contains 'struct dpif_flow_stats'. */
 
     /* If non-zero then the recirculation id that has
      * been allocated for use with this rule.
@@ -369,6 +369,19 @@ static void ofproto_trace(struct ofproto_dpif *, struct 
flow *,
                           const struct ofpact[], size_t ofpacts_len,
                           struct ds *);
 
+static void
+dpif_flow_stats_aggregate(void *aux, struct ovsthread_stats_bucket *b)
+{
+    struct dpif_flow_stats *dst = (struct dpif_flow_stats *)aux;
+    struct dpif_flow_stats *src
+        = OVSTHREAD_STATS_BUCKET_CAST(struct dpif_flow_stats *, b);
+
+    dst->n_packets += src->n_packets;
+    dst->n_bytes += src->n_bytes;
+    dst->used = MAX(src->used, dst->used);
+    dst->tcp_flags |= src->tcp_flags;
+}
+
 /* Global variables. */
 static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
 
@@ -3432,10 +3445,12 @@ rule_expire(struct rule_dpif *rule)
 
     if (reason < 0 && idle_timeout) {
         long long int used;
+        struct dpif_flow_stats stats;
 
-        ovs_mutex_lock(&rule->stats_mutex);
-        used = rule->stats.used;
-        ovs_mutex_unlock(&rule->stats_mutex);
+        memset(&stats, 0, sizeof(stats));
+        ovsthread_stats_aggregate(rule->stats, &stats,
+                                  dpif_flow_stats_aggregate);
+        used = stats.used;
 
         if (now > used + idle_timeout * 1000) {
             reason = OFPRR_IDLE_TIMEOUT;
@@ -3504,11 +3519,18 @@ void
 rule_dpif_credit_stats(struct rule_dpif *rule,
                        const struct dpif_flow_stats *stats)
 {
-    ovs_mutex_lock(&rule->stats_mutex);
-    rule->stats.n_packets += stats->n_packets;
-    rule->stats.n_bytes += stats->n_bytes;
-    rule->stats.used = MAX(rule->stats.used, stats->used);
-    ovs_mutex_unlock(&rule->stats_mutex);
+    struct ovsthread_stats_bucket *bucket;
+    struct dpif_flow_stats *dst;
+    uint32_t seq;
+
+    bucket = ovsthread_stats_get_bucket(rule->stats, &seq);
+    dst = OVSTHREAD_STATS_BUCKET_CAST(struct dpif_flow_stats *, bucket);
+
+    dst->n_packets += stats->n_packets;
+    dst->n_bytes += stats->n_bytes;
+    dst->used = MAX(dst->used, stats->used);
+
+    ovsthread_stats_bucket_done(bucket, seq);
 }
 
 ovs_be64
@@ -3825,12 +3847,19 @@ rule_construct(struct rule *rule_)
     OVS_NO_THREAD_SAFETY_ANALYSIS
 {
     struct rule_dpif *rule = rule_dpif_cast(rule_);
-    ovs_mutex_init_adaptive(&rule->stats_mutex);
-    rule->stats.n_packets = 0;
-    rule->stats.n_bytes = 0;
-    rule->stats.used = rule->up.modified;
+    struct ovsthread_stats_bucket *bucket;
+    struct dpif_flow_stats *stats;
+    uint32_t seq;
+
     rule->recirc_id = 0;
 
+    rule->stats = ovsthread_stats_create_bucket();
+
+    bucket = ovsthread_stats_get_bucket(rule->stats, &seq);
+    stats = OVSTHREAD_STATS_BUCKET_CAST(struct dpif_flow_stats *, bucket);
+    stats->used = rule->up.modified;
+    ovsthread_stats_bucket_done(bucket, seq);
+
     return 0;
 }
 
@@ -3856,7 +3885,7 @@ rule_destruct(struct rule *rule_)
 {
     struct rule_dpif *rule = rule_dpif_cast(rule_);
 
-    ovs_mutex_destroy(&rule->stats_mutex);
+    ovsthread_stats_destroy_bucket(rule->stats);
     if (rule->recirc_id) {
         struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
 
@@ -3869,12 +3898,15 @@ rule_get_stats(struct rule *rule_, uint64_t *packets, 
uint64_t *bytes,
                long long int *used)
 {
     struct rule_dpif *rule = rule_dpif_cast(rule_);
+    struct dpif_flow_stats stats;
 
-    ovs_mutex_lock(&rule->stats_mutex);
-    *packets = rule->stats.n_packets;
-    *bytes = rule->stats.n_bytes;
-    *used = rule->stats.used;
-    ovs_mutex_unlock(&rule->stats_mutex);
+    memset(&stats, 0, sizeof(stats));
+
+    ovsthread_stats_aggregate(rule->stats, &stats, dpif_flow_stats_aggregate);
+
+    *packets = stats.n_packets;
+    *bytes = stats.n_bytes;
+    *used = stats.used;
 }
 
 static void
@@ -3902,10 +3934,25 @@ rule_modify_actions(struct rule *rule_, bool 
reset_counters)
     struct rule_dpif *rule = rule_dpif_cast(rule_);
 
     if (reset_counters) {
-        ovs_mutex_lock(&rule->stats_mutex);
-        rule->stats.n_packets = 0;
-        rule->stats.n_bytes = 0;
-        ovs_mutex_unlock(&rule->stats_mutex);
+        /* We should reset only 'n_packets' and 'n_bytes', but ovsthread_stats
+         * provides only APIs to clear the whole structure.  Therefore, we read
+         * the old stats, clear everything and restore 'used' and 'tcp_flags'.
+         */
+        struct dpif_flow_stats oldstats, *newstats;
+        struct ovsthread_stats_bucket *b;
+        uint32_t seq;
+
+        memset(&oldstats, 0, sizeof(oldstats));
+        ovsthread_stats_aggregate(rule->stats, &oldstats,
+                dpif_flow_stats_aggregate);
+
+        ovsthread_stats_clear(rule->stats);
+
+        b = ovsthread_stats_get_bucket(rule->stats, &seq);
+        newstats = OVSTHREAD_STATS_BUCKET_CAST(struct dpif_flow_stats *, b);
+        newstats->used = oldstats.used;
+        newstats->tcp_flags = oldstats.tcp_flags;
+        ovsthread_stats_bucket_done(b, seq);
     }
 
     complete_operation(rule);
-- 
2.1.0.rc1

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to