Thread (17 messages) flat view 17 messages, 6 authors, 2012-06-08

Re: [V2 RFC net-next PATCH 2/2] virtio_net: export more statistics through ethtool

From: Jason Wang <hidden>
Date: 2012-06-08 03:33:51
Also in: lkml, virtualization

On 06/08/2012 06:19 AM, Michael S. Tsirkin wrote:
On Wed, Jun 06, 2012 at 03:52:17PM +0800, Jason Wang wrote:
quoted
quoted
 Satistics counters is useful for debugging and performance optimization, so this
 patch lets virtio_net driver collect following and export them to userspace
 through "ethtool -S":
 
 - number of packets sent/received
 - number of bytes sent/received
 - number of callbacks for tx/rx
 - number of kick for tx/rx
 - number of bytes/packets queued for tx
 
 As virtnet_stats were per-cpu, so both per-cpu and gloabl satistics were
 collected like:
 
 NIC statistics:
       tx_bytes[0]: 1731209929
       tx_packets[0]: 60685
       tx_kicks[0]: 63
       tx_callbacks[0]: 73
       tx_queued_bytes[0]: 1935749360
       tx_queued_packets[0]: 80652
       rx_bytes[0]: 2695648
       rx_packets[0]: 40767
       rx_kicks[0]: 1
       rx_callbacks[0]: 2077
       tx_bytes[1]: 9105588697
       tx_packets[1]: 344150
       tx_kicks[1]: 162
       tx_callbacks[1]: 905
       tx_queued_bytes[1]: 8901049412
       tx_queued_packets[1]: 324184
       rx_bytes[1]: 23679828
       rx_packets[1]: 358770
       rx_kicks[1]: 6
       rx_callbacks[1]: 17717
       tx_bytes: 10836798626
       tx_packets: 404835
       tx_kicks: 225
       tx_callbacks: 978
       tx_queued_bytes: 10836798772
       tx_queued_packets: 404836
       rx_bytes: 26375476
       rx_packets: 399537
       rx_kicks: 7
       rx_callbacks: 19794
 
 TODO:
 
 - more statistics
 - calculate the pending bytes/pkts
 
 Signed-off-by: Jason Wang[off-list ref]
 
 ---
 Changes from v1:
 
 - style&  typo fixs
 - convert the statistics fields to array
 - use unlikely()
 ---
   drivers/net/virtio_net.c |  115 +++++++++++++++++++++++++++++++++++++++++++++-
   1 files changed, 113 insertions(+), 2 deletions(-)
 
 diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
 index 6e4aa6f..909a0a7 100644
 --- a/drivers/net/virtio_net.c
 +++ b/drivers/net/virtio_net.c
 @@ -44,8 +44,14 @@ module_param(gso, bool, 0444);
   enum virtnet_stats_type {
   	VIRTNET_TX_BYTES,
   	VIRTNET_TX_PACKETS,
 +	VIRTNET_TX_KICKS,
 +	VIRTNET_TX_CBS,
 +	VIRTNET_TX_Q_BYTES,
 +	VIRTNET_TX_Q_PACKETS,
   	VIRTNET_RX_BYTES,
   	VIRTNET_RX_PACKETS,
 +	VIRTNET_RX_KICKS,
 +	VIRTNET_RX_CBS,
   	VIRTNET_NUM_STATS,
   };
 
 @@ -54,6 +60,21 @@ struct virtnet_stats {
   	u64 data[VIRTNET_NUM_STATS];
   };
 
 +static struct {
 +	char string[ETH_GSTRING_LEN];
 +} virtnet_stats_str_attr[] = {
 +	{ "tx_bytes" },
 +	{ "tx_packets" },
 +	{ "tx_kicks" },
 +	{ "tx_callbacks" },
 +	{ "tx_queued_bytes" },
 +	{ "tx_queued_packets" },
 +	{ "rx_bytes" },
 +	{ "rx_packets" },
 +	{ "rx_kicks" },
 +	{ "rx_callbacks" },
 +};
 +
   struct virtnet_info {
   	struct virtio_device *vdev;
   	struct virtqueue *rvq, *svq, *cvq;
 @@ -146,6 +167,11 @@ static struct page *get_a_page(struct virtnet_info *vi, gfp_t gfp_mask)
   static void skb_xmit_done(struct virtqueue *svq)
   {
   	struct virtnet_info *vi = svq->vdev->priv;
 +	struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
 +
 +	u64_stats_update_begin(&stats->syncp);
 +	stats->data[VIRTNET_TX_CBS]++;
 +	u64_stats_update_end(&stats->syncp);
 
   	/* Suppress further interrupts. */
   	virtqueue_disable_cb(svq);
 @@ -465,6 +491,7 @@ static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
   {
   	int err;
   	bool oom;
 +	struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
 
   	do {
   		if (vi->mergeable_rx_bufs)
 @@ -481,13 +508,24 @@ static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
   	} while (err>  0);
   	if (unlikely(vi->num>  vi->max))
   		vi->max = vi->num;
 -	virtqueue_kick(vi->rvq);
 +	if (virtqueue_kick_prepare(vi->rvq)) {
 +		virtqueue_notify(vi->rvq);
 +		u64_stats_update_begin(&stats->syncp);
 +		stats->data[VIRTNET_RX_KICKS]++;
 +		u64_stats_update_end(&stats->syncp);
 +	}
   	return !oom;
   }
 
   static void skb_recv_done(struct virtqueue *rvq)
   {
   	struct virtnet_info *vi = rvq->vdev->priv;
 +	struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
 +
 +	u64_stats_update_begin(&stats->syncp);
 +	stats->data[VIRTNET_RX_CBS]++;
 +	u64_stats_update_end(&stats->syncp);
 +
   	/* Schedule NAPI, Suppress further interrupts if successful. */
   	if (napi_schedule_prep(&vi->napi)) {
   		virtqueue_disable_cb(rvq);
 @@ -630,7 +668,9 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
   static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
   {
   	struct virtnet_info *vi = netdev_priv(dev);
 +	struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
   	int capacity;
 +	bool kick;
 
   	/* Free up any pending old buffers before queueing new ones. */
   	free_old_xmit_skbs(vi);
 @@ -655,7 +695,17 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
   		kfree_skb(skb);
   		return NETDEV_TX_OK;
   	}
 -	virtqueue_kick(vi->svq);
 +
 +	kick = virtqueue_kick_prepare(vi->svq);
 +	if (unlikely(kick))
 +		virtqueue_notify(vi->svq);
 +
 +	u64_stats_update_begin(&stats->syncp);
 +	if (unlikely(kick))
 +		stats->data[VIRTNET_TX_KICKS]++;
 +	stats->data[VIRTNET_TX_Q_BYTES] += skb->len;
 +	stats->data[VIRTNET_TX_Q_PACKETS]++;
is this statistic interesting?
how about decrementing when we free?
this way we see how many are pending..
Currently we didn't have per-vq statistics but per-cpu, so the skb could 
be sent by one vcpu and freed by another.
Pehaps another reason to use per-queue satistics.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help