From: Anthony Liguori <[EMAIL PROTECTED]>

ifconfig down or remove the module to get the statistics dump.
---
 drivers/net/virtio_net.c |  120 +++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 103 insertions(+), 17 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index c4f970e..538cc37 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -49,6 +49,32 @@ struct virtnet_info
        /* Receive & send queues. */
        struct sk_buff_head recv;
        struct sk_buff_head send;
+
+       struct {
+               unsigned int free_old_xmit_skbs_manual;
+               unsigned int free_old_xmit_skbs_tasklet;
+               unsigned int hrtimer_starts;
+               unsigned int hrtimer_fires;
+               unsigned int hrtimer_cancels;
+               unsigned int sendq_kicks;
+               unsigned int sendq_packets;
+               unsigned int sendq_partial_csum;
+               unsigned int sendq_gso;
+               unsigned int sendq_sglen;
+               unsigned int sendq_full;
+               unsigned int sendq_restarted;
+               unsigned int sendq_restart_failed;
+               unsigned int sendq_cancelled;
+               unsigned int recvq_packets;
+               unsigned int recvq_refills;
+               unsigned int recvq_restarted;
+               unsigned int recvq_restart_failed;
+               unsigned int recvq_reschedule_failed;
+               unsigned int recvq_partial_csum;
+               unsigned int recvq_gso;
+               unsigned int recvq_kicks;
+               unsigned int poll;
+       } stats;
 };
 
 static inline struct virtio_net_hdr *skb_vnet_hdr(struct sk_buff *skb)
@@ -84,6 +110,7 @@ static void xmit_free(unsigned long data)
        netif_tx_lock(vi->dev);
        free_old_xmit_skbs(vi);
        netif_tx_unlock(vi->dev);
+       vi->stats.free_old_xmit_skbs_tasklet++;
 
        /* In case we were waiting for output buffers. */
        netif_wake_queue(vi->dev);
@@ -97,28 +124,31 @@ static bool skb_xmit_done(struct virtqueue *rvq)
        return false;
 }
 
-static void receive_skb(struct net_device *dev, struct sk_buff *skb,
+static void receive_skb(struct virtnet_info *vi, struct sk_buff *skb,
                        unsigned len)
 {
        struct virtio_net_hdr *hdr = skb_vnet_hdr(skb);
 
+       vi->stats.recvq_packets++;
+
        if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) {
-               pr_debug("%s: short packet %i\n", dev->name, len);
-               dev->stats.rx_length_errors++;
+               pr_debug("%s: short packet %i\n", vi->dev->name, len);
+               vi->dev->stats.rx_length_errors++;
                goto drop;
        }
        len -= sizeof(struct virtio_net_hdr);
        BUG_ON(len > MAX_PACKET_LEN);
 
        skb_trim(skb, len);
-       skb->protocol = eth_type_trans(skb, dev);
+       skb->protocol = eth_type_trans(skb, vi->dev);
        pr_debug("Receiving skb proto 0x%04x len %i type %i\n",
                 ntohs(skb->protocol), skb->len, skb->pkt_type);
-       dev->stats.rx_bytes += skb->len;
-       dev->stats.rx_packets++;
+       vi->dev->stats.rx_bytes += skb->len;
+       vi->dev->stats.rx_packets++;
 
        if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
                pr_debug("Needs csum!\n");
+               vi->stats.recvq_partial_csum++;
                skb->ip_summed = CHECKSUM_PARTIAL;
                skb->csum_start = hdr->csum_start;
                skb->csum_offset = hdr->csum_offset;
@@ -126,7 +156,7 @@ static void receive_skb(struct net_device *dev, struct 
sk_buff *skb,
                    || skb->csum_offset > skb->len - 2) {
                        if (net_ratelimit())
                                printk(KERN_WARNING "%s: csum=%u/%u len=%u\n",
-                                      dev->name, skb->csum_start,
+                                      vi->dev->name, skb->csum_start,
                                       skb->csum_offset, skb->len);
                        goto frame_err;
                }
@@ -134,6 +164,7 @@ static void receive_skb(struct net_device *dev, struct 
sk_buff *skb,
 
        if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
                pr_debug("GSO!\n");
+               vi->stats.recvq_gso++;
                switch (hdr->gso_type) {
                case VIRTIO_NET_HDR_GSO_TCPV4:
                        skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
@@ -150,7 +181,7 @@ static void receive_skb(struct net_device *dev, struct 
sk_buff *skb,
                default:
                        if (net_ratelimit())
                                printk(KERN_WARNING "%s: bad gso type %u.\n",
-                                      dev->name, hdr->gso_type);
+                                      vi->dev->name, hdr->gso_type);
                        goto frame_err;
                }
 
@@ -158,7 +189,7 @@ static void receive_skb(struct net_device *dev, struct 
sk_buff *skb,
                if (skb_shinfo(skb)->gso_size == 0) {
                        if (net_ratelimit())
                                printk(KERN_WARNING "%s: zero gso size.\n",
-                                      dev->name);
+                                      vi->dev->name);
                        goto frame_err;
                }
 
@@ -171,7 +202,7 @@ static void receive_skb(struct net_device *dev, struct 
sk_buff *skb,
        return;
 
 frame_err:
-       dev->stats.rx_frame_errors++;
+       vi->dev->stats.rx_frame_errors++;
 drop:
        dev_kfree_skb(skb);
 }
@@ -203,6 +234,7 @@ static void try_fill_recv(struct virtnet_info *vi)
        }
        if (unlikely(vi->num > vi->max))
                vi->max = vi->num;
+       vi->stats.recvq_kicks++;
        vi->rvq->vq_ops->kick(vi->rvq);
 }
 
@@ -220,26 +252,33 @@ static int virtnet_poll(struct napi_struct *napi, int 
budget)
        struct sk_buff *skb = NULL;
        unsigned int len, received = 0;
 
+       vi->stats.poll++;
 again:
        while (received < budget &&
               (skb = vi->rvq->vq_ops->get_buf(vi->rvq, &len)) != NULL) {
                __skb_unlink(skb, &vi->recv);
-               receive_skb(vi->dev, skb, len);
+               receive_skb(vi, skb, len);
                vi->num--;
                received++;
        }
 
        /* FIXME: If we oom and completely run out of inbufs, we need
         * to start a timer trying to fill more. */
-       if (vi->num < vi->max / 2)
+       if (vi->num < vi->max / 2) {
+               vi->stats.recvq_refills++;
                try_fill_recv(vi);
+       }
 
        /* Out of packets? */
        if (received < budget) {
                netif_rx_complete(vi->dev, napi);
-               if (unlikely(!vi->rvq->vq_ops->restart(vi->rvq))
-                   && netif_rx_reschedule(vi->dev, napi))
-                       goto again;
+               vi->stats.recvq_restarted++;
+               if (unlikely(!vi->rvq->vq_ops->restart(vi->rvq))) {
+                       vi->stats.recvq_restart_failed++;
+                       if (netif_rx_reschedule(vi->dev, napi))
+                               goto again;
+                       vi->stats.recvq_reschedule_failed++;
+               }
        }
 
        return received;
@@ -249,9 +288,11 @@ static enum hrtimer_restart kick_xmit(struct hrtimer *t)
 {
        struct virtnet_info *vi = container_of(t,struct virtnet_info,tx_timer);
 
+       vi->stats.hrtimer_fires++;
        BUG_ON(!in_softirq());
        BUG_ON(in_irq());
        netif_tx_lock(vi->dev);
+       vi->stats.sendq_kicks++;
        vi->svq->vq_ops->kick(vi->svq);
        vi->out_num = 0;
        netif_tx_unlock(vi->dev);
@@ -272,12 +313,14 @@ static int start_xmit(struct sk_buff *skb, struct 
net_device *dev)
 
        pr_debug("%s: xmit %p %s\n", dev->name, skb, print_mac(mac, dest));
 
+       vi->stats.sendq_packets++;
        /* Encode metadata header at front. */
        hdr = skb_vnet_hdr(skb);
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
                hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
                hdr->csum_start = skb->csum_start - skb_headroom(skb);
                hdr->csum_offset = skb->csum_offset;
+               vi->stats.sendq_partial_csum++;
        } else {
                hdr->flags = 0;
                hdr->csum_offset = hdr->csum_start = 0;
@@ -285,6 +328,7 @@ static int start_xmit(struct sk_buff *skb, struct 
net_device *dev)
 
        if (skb_is_gso(skb)) {
                hdr->gso_size = skb_shinfo(skb)->gso_size;
+               vi->stats.sendq_gso++;
                if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN)
                        hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4_ECN;
                else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
@@ -303,18 +347,23 @@ static int start_xmit(struct sk_buff *skb, struct 
net_device *dev)
        vnet_hdr_to_sg(sg, skb);
        num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
        __skb_queue_head(&vi->send, skb);
+       vi->stats.sendq_sglen += num;
 
 again:
        err = vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb);
        if (err) {
+               vi->stats.sendq_full++;
+
                /* Can we free any used skbs? */
+               vi->stats.free_old_xmit_skbs_manual++;
                if (free_old_xmit_skbs(vi))
                        goto again;
 
                /* Activate callback for using skbs: if this fails it
                 * means some were used in the meantime. */
+               vi->stats.sendq_restarted++;
                if (unlikely(!vi->svq->vq_ops->restart(vi->svq))) {
-                       printk("Unlikely: restart svq failed\n");
+                       vi->stats.sendq_restart_failed++;
                        goto again;
                }
 
@@ -326,20 +375,28 @@ again:
                               dev->name, vi->out_max, vi->out_num);
                vi->out_max = vi->out_num;
                vi->out_num = 0;
+               vi->stats.sendq_cancelled++;
+
                /* Kick off send immediately. */
+               vi->stats.hrtimer_cancels++;
                hrtimer_cancel(&vi->tx_timer);
+               vi->stats.sendq_kicks++;
                vi->svq->vq_ops->kick(vi->svq);
                netif_stop_queue(dev);
                return NETDEV_TX_BUSY;
        }
 
        if (++vi->out_num == vi->out_max) {
+               vi->stats.hrtimer_cancels++;
                hrtimer_cancel(&vi->tx_timer);
+               vi->stats.sendq_kicks++;
                vi->svq->vq_ops->kick(vi->svq);
                vi->out_num = 0;
-       } else
+       } else {
+               vi->stats.hrtimer_starts++;
                hrtimer_start(&vi->tx_timer, ktime_set(0,500000),
                              HRTIMER_MODE_REL);
+       }
        return 0;
 }
 
@@ -376,6 +433,35 @@ static int virtnet_close(struct net_device *dev)
                kfree_skb(skb);
 
        BUG_ON(vi->num != 0);
+
+       printk("Stats for %s\n", dev->name);
+       printk("free_old_xmit_skbs_manual = %u\n",
+              vi->stats.free_old_xmit_skbs_manual);
+       printk("free_old_xmit_skbs_tasklet = %u\n",
+              vi->stats.free_old_xmit_skbs_tasklet);
+       printk("hrtimer_starts = %u\n", vi->stats.hrtimer_starts);
+       printk("hrtimer_fires = %u\n", vi->stats.hrtimer_fires);
+       printk("hrtimer_cancels = %u\n", vi->stats.hrtimer_cancels);
+       printk("sendq_kicks = %u\n", vi->stats.sendq_kicks);
+       printk("sendq_packets = %u\n", vi->stats.sendq_packets);
+       printk("sendq_partial_csum = %u\n", vi->stats.sendq_partial_csum);
+       printk("sendq_gso = %u\n", vi->stats.sendq_gso);
+       printk("sendq_sglen = %u\n", vi->stats.sendq_sglen);
+       printk("sendq_full = %u\n", vi->stats.sendq_full);
+       printk("sendq_restarted = %u\n", vi->stats.sendq_restarted);
+       printk("sendq_restart_failed = %u\n", vi->stats.sendq_restart_failed);
+       printk("sendq_cancelled = %u\n", vi->stats.sendq_cancelled);
+       printk("recvq_packets = %u\n", vi->stats.recvq_packets);
+       printk("recvq_refills = %u\n", vi->stats.recvq_refills);
+       printk("recvq_restarted = %u\n", vi->stats.recvq_restarted);
+       printk("recvq_restart_failed = %u\n", vi->stats.recvq_restart_failed);
+       printk("recvq_reschedule_failed = %u\n",
+              vi->stats.recvq_reschedule_failed);
+       printk("recvq_partial_csum = %u\n", vi->stats.recvq_partial_csum);
+       printk("recvq_gso = %u\n", vi->stats.recvq_gso);
+       printk("recvq_kicks = %u\n", vi->stats.recvq_kicks);
+       printk("poll = %u\n", vi->stats.poll);
+
        return 0;
 }
 
-- 
1.5.3.3


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to