Signed-off-by: Daniele Di Proietto <[email protected]>
---
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
[email protected]
http://openvswitch.org/mailman/listinfo/dev