lkml.org 
[lkml]   [2012]   [Jun]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 5/6] tuntap: per queue 64 bit stats
Date
As we've added multiqueue support for tun/tap, this patch convert the statistics
to use per-queue 64 bit statistics.

Signed-off-by: Jason Wang <jasowang@redhat.com>
---
drivers/net/tun.c | 105 ++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 83 insertions(+), 22 deletions(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 5c26757..37e62d3 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -64,6 +64,7 @@
#include <linux/nsproxy.h>
#include <linux/virtio_net.h>
#include <linux/rcupdate.h>
+#include <linux/u64_stats_sync.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
#include <net/rtnetlink.h>
@@ -109,6 +110,19 @@ struct tap_filter {

#define MAX_TAP_QUEUES (NR_CPUS < 16 ? NR_CPUS : 16)

+struct tun_queue_stats {
+ u64 rx_packets;
+ u64 rx_bytes;
+ u64 tx_packets;
+ u64 tx_bytes;
+ struct u64_stats_sync rx_syncp;
+ struct u64_stats_sync tx_syncp;
+ u32 rx_dropped;
+ u32 tx_dropped;
+ u32 rx_frame_errors;
+ u32 tx_fifo_errors;
+};
+
struct tun_file {
struct sock sk;
struct socket socket;
@@ -119,6 +133,7 @@ struct tun_file {
struct tun_struct __rcu *tun;
struct net *net;
struct fasync_struct *fasync;
+ struct tun_queue_stats stats;
unsigned int flags;
u16 queue_index;
};
@@ -134,6 +149,7 @@ struct tun_struct {

struct net_device *dev;
netdev_features_t set_features;
+ struct tun_queue_stats stats;
#define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \
NETIF_F_TSO6|NETIF_F_UFO)

@@ -463,7 +479,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)

/* We won't see all dropped packets individually, so overrun
* error is more appropriate. */
- dev->stats.tx_fifo_errors++;
+ tfile->stats.tx_fifo_errors++;
} else {
/* Single queue mode or multi queue mode.
* Driver handles dropping of all packets itself. */
@@ -488,7 +504,8 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)

drop:
rcu_read_unlock();
- dev->stats.tx_dropped++;
+ if (tfile)
+ tfile->stats.tx_dropped++;
kfree_skb(skb);
return NETDEV_TX_OK;
}
@@ -538,6 +555,56 @@ static void tun_poll_controller(struct net_device *dev)
return;
}
#endif
+
+static struct rtnl_link_stats64 *tun_net_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct tun_struct *tun = netdev_priv(dev);
+ struct tun_file *tfile;
+ struct tun_queue_stats *qstats;
+ u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
+ u32 rx_dropped = 0, tx_dropped = 0,
+ rx_frame_errors = 0, tx_fifo_errors = 0;
+ unsigned int start;
+ int i;
+
+ rcu_read_lock();
+ for (i = 0; i < tun->numqueues; i++) {
+ tfile = rcu_dereference(tun->tfiles[i]);
+ qstats = &tfile->stats;
+
+ do {
+ start = u64_stats_fetch_begin_bh(&qstats->rx_syncp);
+ rx_packets = qstats->rx_packets;
+ rx_bytes = qstats->rx_bytes;
+ } while (u64_stats_fetch_retry_bh(&qstats->rx_syncp, start));
+
+ do {
+ start = u64_stats_fetch_begin_bh(&qstats->tx_syncp);
+ tx_packets = qstats->tx_packets;
+ tx_bytes = qstats->tx_bytes;
+ } while (u64_stats_fetch_retry_bh(&qstats->tx_syncp, start));
+
+ stats->rx_packets += rx_packets;
+ stats->rx_bytes += rx_bytes;
+ stats->tx_packets += tx_packets;
+ stats->tx_bytes += tx_bytes;
+ /* following fileds are u32, no need syncp */
+ rx_dropped += qstats->rx_dropped;
+ tx_dropped += qstats->tx_dropped;
+ rx_frame_errors += qstats->rx_frame_errors;
+ tx_fifo_errors += qstats->tx_fifo_errors;
+ }
+ rcu_read_unlock();
+
+ stats->rx_dropped = rx_dropped;
+ stats->tx_dropped = tx_dropped;
+ stats->rx_frame_errors = rx_frame_errors;
+ stats->tx_fifo_errors = tx_fifo_errors;
+
+ return stats;
+}
+
static const struct net_device_ops tun_netdev_ops = {
.ndo_uninit = tun_net_uninit,
.ndo_open = tun_net_open,
@@ -545,6 +612,7 @@ static const struct net_device_ops tun_netdev_ops = {
.ndo_start_xmit = tun_net_xmit,
.ndo_change_mtu = tun_net_change_mtu,
.ndo_fix_features = tun_net_fix_features,
+ .ndo_get_stats64 = tun_net_stats,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = tun_poll_controller,
#endif
@@ -560,6 +628,7 @@ static const struct net_device_ops tap_netdev_ops = {
.ndo_set_rx_mode = tun_net_mclist,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_get_stats64 = tun_net_stats,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = tun_poll_controller,
#endif
@@ -808,30 +877,25 @@ static ssize_t tun_get_user(struct tun_file *tfile,
skb->protocol = eth_type_trans(skb, tun->dev);
break;
}
- tun->dev->stats.rx_packets++;
- tun->dev->stats.rx_bytes += len;
rcu_read_unlock();

netif_rx_ni(skb);

+ u64_stats_update_begin(&tfile->stats.rx_syncp);
+ tfile->stats.rx_packets++;
+ tfile->stats.rx_bytes += len;
+ u64_stats_update_end(&tfile->stats.rx_syncp);
+
return count;

err_free:
count = -EINVAL;
kfree_skb(skb);
err:
- rcu_read_lock();
- tun = rcu_dereference(tfile->tun);
- if (!tun) {
- rcu_read_unlock();
- return -EBADFD;
- }
-
if (drop)
- tun->dev->stats.rx_dropped++;
+ tfile->stats.rx_dropped++;
if (error)
- tun->dev->stats.rx_frame_errors++;
- rcu_read_unlock();
+ tfile->stats.rx_frame_errors++;
return count;
}

@@ -853,7 +917,6 @@ static ssize_t tun_put_user(struct tun_file *tfile,
struct sk_buff *skb,
const struct iovec *iv, int len)
{
- struct tun_struct *tun = NULL;
struct tun_pi pi = { 0, skb->protocol };
ssize_t total = 0;

@@ -925,13 +988,10 @@ static ssize_t tun_put_user(struct tun_file *tfile,
skb_copy_datagram_const_iovec(skb, 0, iv, total, len);
total += skb->len;

- rcu_read_lock();
- tun = rcu_dereference(tfile->tun);
- if (tun) {
- tun->dev->stats.tx_packets++;
- tun->dev->stats.tx_bytes += len;
- }
- rcu_read_unlock();
+ u64_stats_update_begin(&tfile->stats.tx_syncp);
+ tfile->stats.tx_packets++;
+ tfile->stats.tx_bytes += total;
+ u64_stats_update_end(&tfile->stats.tx_syncp);

return total;
}
@@ -1650,6 +1710,7 @@ static int tun_chr_open(struct inode *inode, struct file * file)
tfile->socket.file = file;
tfile->socket.ops = &tun_socket_ops;
sock_init_data(&tfile->socket, &tfile->sk);
+ memset(&tfile->stats, 0, sizeof(struct tun_queue_stats));

tfile->sk.sk_write_space = tun_sock_write_space;
tfile->sk.sk_destruct = tun_sock_destruct;
--
1.7.1


\
 
 \ /
  Last update: 2012-06-25 15:01    [W:0.080 / U:0.540 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site