> On 30 Mar 2015, at 22:41, Ethan Jackson <et...@nicira.com> wrote: > > You're not going to like my review of this patch =) >
Anything to try to make the code better :-) > So the code is very high quality, though I haven't read it super > closely yet. My main question, is if this is really the right > approach to handle stats in the DPDK fast path in general. > > So here's my question: why not just use atomic variables for the > members of dp_netdev_flow_stats and dp_netdev_pmd_stats? If you use > relaxed reads and writes (no increments), then there's zero > performance penalty on x86. Also it has the added side benefits of > not requiring additional error-prone multiplatform compat code, saves > us having to expose the seqlock, and makes it impossible to access the > variables without locking properly. All said, we get the exact same > performance profile of this proposed series, with significantly > simpler and less error-prone code. > > What do you think? > You’re right, it makes maintenance easier. Thanks for the suggestion! I’m sending another version of the patch with atomic statistics. Minor issue: the compilers I’ve tried (GCC 4.9, 4.8 clang 3.5 and sparse 0.4.5) do not report a warning if I try to access atomic variables without atomic function. Maybe someone can confirm this? > Ethan > > > On Fri, Mar 27, 2015 at 9:29 AM, Daniele Di Proietto > <diproiet...@vmware.com> wrote: >> While the values are written only by a single thread, reading them >> concurrently might produce incorrect results, given the lack of 64-bit >> atomic loads on 32-bit systems. >> >> This fix prevent unconsistent reads of 64-bit values on 32-bit systems. >> >> Signed-off-by: Daniele Di Proietto <diproiet...@vmware.com> >> --- >> lib/dpif-netdev.c | 48 +++++++++++++++++++++++++++++++++++++++++------- >> 1 file changed, 41 insertions(+), 7 deletions(-) >> >> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c >> index 2637e8d..ba677eb 100644 >> --- a/lib/dpif-netdev.c >> +++ b/lib/dpif-netdev.c >> @@ -64,6 +64,7 @@ >> #include "sset.h" >> #include "timeval.h" >> #include "tnl-arp-cache.h" >> +#include "u64-stats-sync.h" >> #include "unixctl.h" >> #include "util.h" >> #include "openvswitch/vlog.h" >> @@ -301,6 +302,9 @@ struct dp_netdev_flow { >> >> /* Statistics. */ >> struct dp_netdev_flow_stats stats; >> + /* Used to protect 'stats'. Only guarantees consistency of single stats >> + * members, not of the structure as a whole */ >> + struct u64_stats_sync stats_lock; >> >> /* Actions. */ >> OVSRCU_TYPE(struct dp_netdev_actions *) actions; >> @@ -382,6 +386,9 @@ struct dp_netdev_pmd_thread { >> >> /* Statistics. */ >> struct dp_netdev_pmd_stats stats; >> + /* Used to protect 'stats'. Only guarantees consistency of single stats >> + * members, not of the structure as a whole */ >> + struct u64_stats_sync stats_lock; >> >> struct latch exit_latch; /* For terminating the pmd thread. */ >> atomic_uint change_seq; /* For reloading pmd ports. */ >> @@ -754,10 +761,19 @@ dpif_netdev_get_stats(const struct dpif *dpif, struct >> dpif_dp_stats *stats) >> >> stats->n_flows = stats->n_hit = stats->n_missed = stats->n_lost = 0; >> CMAP_FOR_EACH (pmd, node, &dp->poll_threads) { >> + struct dp_netdev_pmd_stats s; >> + uint32_t c; >> + >> + do { >> + c = u64_stats_read_begin(&pmd->stats_lock); >> + s = pmd->stats; >> + } while (!u64_stats_read_correct(&pmd->stats_lock, c)); >> + >> stats->n_flows += cmap_count(&pmd->flow_table); >> - stats->n_hit += pmd->stats.n[DP_STAT_HIT]; >> - stats->n_missed += pmd->stats.n[DP_STAT_MISS]; >> - stats->n_lost += pmd->stats.n[DP_STAT_LOST]; >> + >> + stats->n_hit += s.n[DP_STAT_HIT]; >> + stats->n_missed += s.n[DP_STAT_MISS]; >> + stats->n_lost += s.n[DP_STAT_LOST]; >> } >> stats->n_masks = UINT32_MAX; >> stats->n_mask_hit = UINT64_MAX; >> @@ -1548,10 +1564,15 @@ static void >> get_dpif_flow_stats(const struct dp_netdev_flow *netdev_flow, >> struct dpif_flow_stats *stats) >> { >> - stats->n_packets = netdev_flow->stats.packet_count; >> - stats->n_bytes = netdev_flow->stats.byte_count; >> - stats->used = netdev_flow->stats.used; >> - stats->tcp_flags = netdev_flow->stats.tcp_flags; >> + uint32_t c; >> + do { >> + c = u64_stats_read_begin(&netdev_flow->stats_lock); >> + >> + stats->n_packets = netdev_flow->stats.packet_count; >> + stats->n_bytes = netdev_flow->stats.byte_count; >> + stats->used = netdev_flow->stats.used; >> + stats->tcp_flags = netdev_flow->stats.tcp_flags; >> + } while (!u64_stats_read_correct(&netdev_flow->stats_lock, c)); >> } >> >> /* Converts to the dpif_flow format, using 'key_buf' and 'mask_buf' for >> @@ -1735,6 +1756,7 @@ dp_netdev_flow_add(struct dp_netdev_pmd_thread *pmd, >> /* Do not allocate extra space. */ >> flow = xmalloc(sizeof *flow - sizeof flow->cr.flow.mf + mask.len); >> memset(&flow->stats, 0, sizeof flow->stats); >> + memset(&flow->stats_lock, 0, sizeof flow->stats_lock); >> flow->dead = false; >> *CONST_CAST(int *, &flow->pmd_id) = pmd->core_id; >> *CONST_CAST(struct flow *, &flow->flow) = match->flow; >> @@ -2670,18 +2692,30 @@ dp_netdev_flow_used(struct dp_netdev_flow >> *netdev_flow, int cnt, int size, >> uint16_t tcp_flags) >> { >> long long int now = time_msec(); >> + uint32_t c; >> + >> + c = u64_stats_write_begin(&netdev_flow->stats_lock); >> >> netdev_flow->stats.used = MAX(now, netdev_flow->stats.used); >> netdev_flow->stats.packet_count += cnt; >> netdev_flow->stats.byte_count += size; >> netdev_flow->stats.tcp_flags |= tcp_flags; >> + >> + u64_stats_write_end(&netdev_flow->stats_lock, c); >> } >> >> static void >> dp_netdev_count_packet(struct dp_netdev_pmd_thread *pmd, >> enum dp_stat_type type, int cnt) >> { >> + uint32_t c; >> + >> + if (!cnt) >> + return; >> + >> + c = u64_stats_write_begin(&pmd->stats_lock); >> pmd->stats.n[type] += cnt; >> + u64_stats_write_end(&pmd->stats_lock, c); >> } >> >> static int >> -- >> 2.1.4 >> >> _______________________________________________ >> dev mailing list >> dev@openvswitch.org >> https://urldefense.proofpoint.com/v2/url?u=http-3A__openvswitch.org_mailman_listinfo_dev&d=AwIBaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=SmB5nZacmXNq0gKCC1s_Cw5yUNjxgD4v5kJqZ2uWLlE&m=F7XZgy4UdNNeJnxr1xwBXFMFZNDwd3ftwiI8xVoyWgg&s=8EWnbDvB_nGnZnRIozFlOhBRkhlDf2WKZo1ovTx1CH8&e= >> _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev