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