netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Stephen Hemminger <stephen@networkplumber.org>
To: Stephen Hemminger <stephen@networkplumber.org>
Cc: Helmut Grohne <h.grohne@cygnusnetworks.de>,
	David Miller <davem@davemloft.net>,
	netdev@vger.kernel.org
Subject: [PATCH net-next 3/3] tuntap: allow overriding link statistics
Date: Wed, 24 Jul 2013 16:15:19 -0700	[thread overview]
Message-ID: <20130724161519.2bdbe528@nehalam.linuxnetplumber.net> (raw)
In-Reply-To: <20130724161156.4a8cf02b@nehalam.linuxnetplumber.net>

This patch adds new ioctl to allow overriding the link statistics
returned by the TUN device. This is useful when using tun device as a surrogate
for hardware or other software emulation. To use this application periodically
makes ioctl(TUNSETSTATS) to update statistics.

If TUNSETSTATS is not used the original software based statistics
are used.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>

---
v2 - don't use exchange, use regular RCU

--- a/drivers/net/tun.c	2013-07-24 12:47:37.344206628 -0700
+++ b/drivers/net/tun.c	2013-07-24 16:14:00.964658040 -0700
@@ -152,6 +152,11 @@ struct tun_flow_entry {
 	unsigned long updated;
 };
 
+struct tun_link_stats {
+	struct rtnl_link_stats64 link_stats;
+	struct rcu_head rcu;
+};
+
 #define TUN_NUM_FLOW_ENTRIES 1024
 
 /* Since the socket were moved to tun_file, to preserve the behavior of persist
@@ -190,6 +195,7 @@ struct tun_struct {
 	u32 speed;
 	u8 duplex;
 	struct tun_info info;
+	struct tun_link_stats __rcu *stats;
 };
 
 static inline u32 tun_hashfn(u32 rxhash)
@@ -803,6 +809,32 @@ static netdev_features_t tun_net_fix_fea
 
 	return (features & tun->set_features) | (features & ~TUN_USER_FEATURES);
 }
+
+static struct rtnl_link_stats64 *
+tun_net_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *storage)
+{
+	struct tun_struct *tun = netdev_priv(dev);
+	struct tun_link_stats *stats;
+
+	rcu_read_lock();
+	stats = rcu_dereference(tun->stats);
+	if (stats) {
+		/* Stats received from device */
+		*storage = stats->link_stats;
+		rcu_read_unlock();
+
+		/* Add tunnel detected errors to mix */
+		storage->tx_dropped += dev->stats.tx_dropped;
+		storage->rx_dropped += dev->stats.rx_dropped;
+		storage->rx_frame_errors += dev->stats.rx_frame_errors;
+		return storage;
+	}
+	rcu_read_unlock();
+
+	netdev_stats_to_stats64(storage, &dev->stats);
+	return storage;
+}
+
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void tun_poll_controller(struct net_device *dev)
 {
@@ -825,6 +857,7 @@ static const struct net_device_ops tun_n
 	.ndo_open		= tun_net_open,
 	.ndo_stop		= tun_net_close,
 	.ndo_start_xmit		= tun_net_xmit,
+	.ndo_get_stats64	= tun_net_get_stats64,
 	.ndo_change_mtu		= tun_net_change_mtu,
 	.ndo_fix_features	= tun_net_fix_features,
 	.ndo_select_queue	= tun_select_queue,
@@ -838,6 +871,7 @@ static const struct net_device_ops tap_n
 	.ndo_open		= tun_net_open,
 	.ndo_stop		= tun_net_close,
 	.ndo_start_xmit		= tun_net_xmit,
+	.ndo_get_stats64	= tun_net_get_stats64,
 	.ndo_change_mtu		= tun_net_change_mtu,
 	.ndo_fix_features	= tun_net_fix_features,
 	.ndo_set_rx_mode	= tun_net_mclist,
@@ -1422,9 +1456,13 @@ out:
 static void tun_free_netdev(struct net_device *dev)
 {
 	struct tun_struct *tun = netdev_priv(dev);
+	struct tun_link_stats *stats;
 
 	BUG_ON(!(list_empty(&tun->disabled)));
 	tun_flow_uninit(tun);
+	stats = rtnl_dereference(tun->stats);
+	if (stats)
+		kfree_rcu(stats, rcu);
 	security_tun_dev_free_security(tun->security);
 	free_netdev(dev);
 }
@@ -1886,6 +1924,28 @@ unlock:
 	return ret;
 }
 
+static int tun_set_stats(struct tun_struct *tun, void __user *argp)
+{
+	struct tun_link_stats *stats, *old;
+
+	stats = kmalloc(sizeof(struct tun_link_stats), GFP_KERNEL);
+	if (!stats)
+		return -ENOMEM;
+
+	if (copy_from_user(&stats->link_stats, argp,
+			   sizeof(struct rtnl_link_stats64))) {
+		kfree(stats);
+		return -EFAULT;
+	}
+
+	old = rtnl_dereference(tun->stats);
+	rcu_assign_pointer(tun->stats, stats);
+	if (old)
+		kfree_rcu(old, rcu);
+
+	return 0;
+}
+
 static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 			    unsigned long arg, int ifreq_len)
 {
@@ -2108,6 +2168,11 @@ static long __tun_chr_ioctl(struct file
 		tun->info = info;
 		break;
 	}
+
+	case TUNSETSTATS:
+		ret = tun_set_stats(tun, argp);
+		break;
+
 	default:
 		ret = -EINVAL;
 		break;
@@ -2137,6 +2202,7 @@ static long tun_chr_compat_ioctl(struct
 	case TUNGETSNDBUF:
 	case TUNSETSNDBUF:
 	case TUNSETINFO:
+	case TUNSETSTATS:
 	case SIOCGIFHWADDR:
 	case SIOCSIFHWADDR:
 		arg = (unsigned long)compat_ptr(arg);
--- a/include/uapi/linux/if_tun.h	2013-07-24 12:47:37.344206628 -0700
+++ b/include/uapi/linux/if_tun.h	2013-07-24 12:47:37.352206531 -0700
@@ -57,6 +57,7 @@
 #define TUNSETVNETHDRSZ _IOW('T', 216, int)
 #define TUNSETQUEUE  _IOW('T', 217, int)
 #define TUNSETINFO     _IOW('T', 219, struct tun_info)
+#define TUNSETSTATS    _IOW('T', 220, struct rtnl_link_stats64)
 
 /* TUNSETIFF ifr flags */
 #define IFF_TUN		0x0001

  parent reply	other threads:[~2013-07-24 23:15 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-24 23:11 [PATCH net-next 1/3] tuntap: allow changing ethtool speed (v2) Stephen Hemminger
2013-07-24 23:13 ` [PATCH net-next 2/3] tuntap: allow overriding ethtool driver info Stephen Hemminger
2013-07-24 23:48   ` Ben Hutchings
2013-07-25  0:16     ` Stephen Hemminger
2013-07-25 21:19       ` Ben Hutchings
2013-07-25 21:32         ` Stephen Hemminger
2013-07-25 21:36           ` Ben Hutchings
2013-07-25 21:56             ` Stephen Hemminger
2013-07-24 23:15 ` Stephen Hemminger [this message]
2013-07-24 23:40 ` [PATCH net-next 1/3] tuntap: allow changing ethtool speed (v2) Ben Hutchings
2013-07-25  0:17   ` Stephen Hemminger
2013-07-25  0:29     ` David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20130724161519.2bdbe528@nehalam.linuxnetplumber.net \
    --to=stephen@networkplumber.org \
    --cc=davem@davemloft.net \
    --cc=h.grohne@cygnusnetworks.de \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).