[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <c02e519b-8b7d-414c-b602-5575c9382101@lunn.ch>
Date: Tue, 6 May 2025 18:07:31 +0200
From: Andrew Lunn <andrew@...n.ch>
To: Alexander Shalimov <alex-shalimov@...dex-team.ru>
Cc: netdev@...r.kernel.org, linux-kernel@...r.kernel.org,
willemdebruijn.kernel@...il.com, jasowang@...hat.com,
davem@...emloft.net, edumazet@...gle.com, kuba@...nel.org,
pabeni@...hat.com
Subject: Re: [PATCH] net/tun: expose queue utilization stats via ethtool
On Tue, May 06, 2025 at 06:41:17PM +0300, Alexander Shalimov wrote:
> TUN/TAP devices are heavily used in network virtualization scenarios
> such as QEMU/KVM with "-netdev tap" and are commonly paired with virtio-net
> or vhost-net backends. Under high network load, queues of the tuntap device
> may become saturated, resulting in TX drops.
>
> Existing aggregated drop counters alone are often insufficient during
> complex debugging and performance tuning, especially in high-throughput
> environments. Visibility of real-time queue utilization is critical for
> understanding why guest VMs might be unable to dequeue packets in time.
>
> This patch exposes per-queue utilization statistics via ethtool -S,
> allowing on-demand inspection of queue fill levels. Utilization metrics are
> captured at the time of the ethtool invocation, providing a snapshot useful
> for correlation with guest and host behavior.
This does not fit the usual statistics pattern, which are simple
incremental counters. Are there any other drivers doing anything like
this?
Maybe devlink resources would be a better API? That would also allow
you to report the size of the ring.
> +static void tun_get_ethtool_stats(struct net_device *dev,
> + struct ethtool_stats *stats, u64 *data)
> +{
> + struct tun_struct *tun = netdev_priv(dev);
> + struct tun_file *tfile;
> + int i;
> + int producer, consumer, size, usage;
> +
> + rcu_read_lock();
> + for (i = 0; i < dev->real_num_tx_queues; i++) {
> + tfile = rcu_dereference(tun->tfiles[i]);
> +
> + producer = READ_ONCE(tfile->tx_ring.producer);
> + consumer = READ_ONCE(tfile->tx_ring.consumer_head);
> + size = READ_ONCE(tfile->tx_ring.size);
> +
> + if (producer >= consumer)
> + usage = producer - consumer;
> + else
> + usage = size - (consumer - producer);
It seems like this belongs in ptr_ring.h along with all the other
methods which deal with insides of the ring.
Andrew
Powered by blists - more mailing lists