lkml.org 
[lkml]   [2018]   [Jun]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [PATCH v2] hv_netvsc: Add per-cpu ethtool stats for netvsc
    On Wed, 13 Jun 2018 12:36:08 -0700
    Yidong Ren <yidren@linuxonhyperv.com> wrote:

    > From: Yidong Ren <yidren@microsoft.com>
    >
    > This patch implements following ethtool stats fields for netvsc:
    > cpu<n>_tx/rx_packets/bytes
    > cpu<n>_vf_tx/rx_packets/bytes
    >
    > Corresponding per-cpu counters exist in current code. Exposing these
    > counters will help troubleshooting performance issues.
    >
    > Signed-off-by: Yidong Ren <yidren@microsoft.com>
    > ---
    > Changes in v2:
    > - Remove cpp style comment
    > - Resubmit after freeze
    >
    > drivers/net/hyperv/hyperv_net.h | 11 +++++
    > drivers/net/hyperv/netvsc_drv.c | 104 +++++++++++++++++++++++++++++++++++++++-
    > 2 files changed, 113 insertions(+), 2 deletions(-)
    >
    > diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
    > index 23304ac..c825353 100644
    > --- a/drivers/net/hyperv/hyperv_net.h
    > +++ b/drivers/net/hyperv/hyperv_net.h
    > @@ -873,6 +873,17 @@ struct netvsc_ethtool_stats {
    > unsigned long wake_queue;
    > };
    >
    > +struct netvsc_ethtool_pcpu_stats {
    > + u64 rx_packets;
    > + u64 rx_bytes;
    > + u64 tx_packets;
    > + u64 tx_bytes;
    > + u64 vf_rx_packets;
    > + u64 vf_rx_bytes;
    > + u64 vf_tx_packets;
    > + u64 vf_tx_bytes;
    > +};
    > +
    > struct netvsc_vf_pcpu_stats {
    > u64 rx_packets;
    > u64 rx_bytes;
    > diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
    > index 7b18a8c..6803aae 100644
    > --- a/drivers/net/hyperv/netvsc_drv.c
    > +++ b/drivers/net/hyperv/netvsc_drv.c
    > @@ -1105,6 +1105,66 @@ static void netvsc_get_vf_stats(struct net_device *net,
    > }
    > }
    >
    > +static void netvsc_get_pcpu_stats(struct net_device *net,
    > + struct netvsc_ethtool_pcpu_stats
    > + __percpu *pcpu_tot)
    > +{
    > + struct net_device_context *ndev_ctx = netdev_priv(net);
    > + struct netvsc_device *nvdev = rcu_dereference_rtnl(ndev_ctx->nvdev);
    > + int i;
    > +
    > + /* fetch percpu stats of vf */
    > + for_each_possible_cpu(i) {
    > + const struct netvsc_vf_pcpu_stats *stats =
    > + per_cpu_ptr(ndev_ctx->vf_stats, i);
    > + struct netvsc_ethtool_pcpu_stats *this_tot =
    > + per_cpu_ptr(pcpu_tot, i);
    > + unsigned int start;
    > +
    > + do {
    > + start = u64_stats_fetch_begin_irq(&stats->syncp);
    > + this_tot->vf_rx_packets = stats->rx_packets;
    > + this_tot->vf_tx_packets = stats->tx_packets;
    > + this_tot->vf_rx_bytes = stats->rx_bytes;
    > + this_tot->vf_tx_bytes = stats->tx_bytes;
    > + } while (u64_stats_fetch_retry_irq(&stats->syncp, start));
    > + this_tot->rx_packets = this_tot->vf_rx_packets;
    > + this_tot->tx_packets = this_tot->vf_tx_packets;
    > + this_tot->rx_bytes = this_tot->vf_rx_bytes;
    > + this_tot->tx_bytes = this_tot->vf_tx_bytes;
    > + }
    > +
    > + /* fetch percpu stats of netvsc */
    > + for (i = 0; i < nvdev->num_chn; i++) {
    > + const struct netvsc_channel *nvchan = &nvdev->chan_table[i];
    > + const struct netvsc_stats *stats;
    > + struct netvsc_ethtool_pcpu_stats *this_tot =
    > + per_cpu_ptr(pcpu_tot, nvchan->channel->target_cpu);
    > + u64 packets, bytes;
    > + unsigned int start;
    > +
    > + stats = &nvchan->tx_stats;
    > + do {
    > + start = u64_stats_fetch_begin_irq(&stats->syncp);
    > + packets = stats->packets;
    > + bytes = stats->bytes;
    > + } while (u64_stats_fetch_retry_irq(&stats->syncp, start));
    > +
    > + this_tot->tx_bytes += bytes;
    > + this_tot->tx_packets += packets;
    > +
    > + stats = &nvchan->rx_stats;
    > + do {
    > + start = u64_stats_fetch_begin_irq(&stats->syncp);
    > + packets = stats->packets;
    > + bytes = stats->bytes;
    > + } while (u64_stats_fetch_retry_irq(&stats->syncp, start));
    > +
    > + this_tot->rx_bytes += bytes;
    > + this_tot->rx_packets += packets;
    > + }
    > +}
    > +
    > static void netvsc_get_stats64(struct net_device *net,
    > struct rtnl_link_stats64 *t)
    > {
    > @@ -1202,6 +1262,23 @@ static const struct {
    > { "rx_no_memory", offsetof(struct netvsc_ethtool_stats, rx_no_memory) },
    > { "stop_queue", offsetof(struct netvsc_ethtool_stats, stop_queue) },
    > { "wake_queue", offsetof(struct netvsc_ethtool_stats, wake_queue) },
    > +}, pcpu_stats[] = {
    > + { "cpu%u_rx_packets",
    > + offsetof(struct netvsc_ethtool_pcpu_stats, rx_packets) },
    > + { "cpu%u_rx_bytes",
    > + offsetof(struct netvsc_ethtool_pcpu_stats, rx_bytes) },
    > + { "cpu%u_tx_packets",
    > + offsetof(struct netvsc_ethtool_pcpu_stats, tx_packets) },
    > + { "cpu%u_tx_bytes",
    > + offsetof(struct netvsc_ethtool_pcpu_stats, tx_bytes) },
    > + { "cpu%u_vf_rx_packets",
    > + offsetof(struct netvsc_ethtool_pcpu_stats, vf_rx_packets) },
    > + { "cpu%u_vf_rx_bytes",
    > + offsetof(struct netvsc_ethtool_pcpu_stats, vf_rx_bytes) },
    > + { "cpu%u_vf_tx_packets",
    > + offsetof(struct netvsc_ethtool_pcpu_stats, vf_tx_packets) },
    > + { "cpu%u_vf_tx_bytes",
    > + offsetof(struct netvsc_ethtool_pcpu_stats, vf_tx_bytes) },
    > }, vf_stats[] = {
    > { "vf_rx_packets", offsetof(struct netvsc_vf_pcpu_stats, rx_packets) },
    > { "vf_rx_bytes", offsetof(struct netvsc_vf_pcpu_stats, rx_bytes) },
    > @@ -1213,6 +1290,9 @@ static const struct {
    > #define NETVSC_GLOBAL_STATS_LEN ARRAY_SIZE(netvsc_stats)
    > #define NETVSC_VF_STATS_LEN ARRAY_SIZE(vf_stats)
    >
    > +/* statistics per queue (rx/tx packets/bytes) */
    > +#define NETVSC_PCPU_STATS_LEN (num_present_cpus() * ARRAY_SIZE(pcpu_stats))

    Even though Hyper-V/Azure does not support hot plug cpu's it might be better
    to num_cpu_possible to avoid any possible future surprises.

    \
     
     \ /
      Last update: 2018-06-13 23:48    [W:2.646 / U:0.028 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site