On Wed, 13 Jun 2018 12:36:08 -0700
Yidong Ren <yid...@linuxonhyperv.com> wrote:

> From: Yidong Ren <yid...@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 <yid...@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.
_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to