DORMANTno replies

[PATCH] tun: Add offload related ethtool ops

From: Mark McLoughlin <hidden>
Date: 2008-10-08 19:49:31
Subsystem: networking drivers, the rest, tun/tap driver · Maintainers: Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds, Willem de Bruijn, Jason Wang

The TUNSETOFFLOAD ioctl() allows setting various offload related
device fields, however it is not currently possible to then tweak
those settings using ethtool.

Implement the ethtool ops, but don't allow enabling a feature that
hasn't already been enabled by TUNSETOFFLOAD.

Signed-off-by: Mark McLoughlin <redacted>
---
 drivers/net/tun.c |   40 +++++++++++++++++++++++++++++++++++++++-
 1 files changed, 39 insertions(+), 1 deletions(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 6daea0c..211e953 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -90,6 +90,7 @@ struct tap_filter {
 struct tun_struct {
 	struct list_head        list;
 	unsigned int 		flags;
+	unsigned long		offload;
 	int			attached;
 	uid_t			owner;
 	gid_t			group;
@@ -753,6 +754,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 		tun = netdev_priv(dev);
 		tun->dev = dev;
 		tun->flags = flags;
+		tun->offload = 0;
 		tun->txflt.count = 0;
 
 		tun_net_init(dev);
@@ -840,6 +842,7 @@ static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr)
  * privs required. */
 static int set_offload(struct net_device *dev, unsigned long arg)
 {
+	struct tun_struct *tun = netdev_priv(dev);
 	unsigned int old_features, features;
 
 	old_features = dev->features;
@@ -873,6 +876,8 @@ static int set_offload(struct net_device *dev, unsigned long arg)
 	if (old_features != dev->features)
 		netdev_features_change(dev);
 
+	tun->offload = dev->features & (NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_TSO);
+
 	return 0;
 }
 
@@ -1187,6 +1192,36 @@ static int tun_set_rx_csum(struct net_device *dev, u32 data)
 	return 0;
 }
 
+static int tun_set_tx_csum(struct net_device *dev, u32 data)
+{
+	struct tun_struct *tun = netdev_priv(dev);
+
+	if (data && !(tun->offload & NETIF_F_HW_CSUM))
+		return -EOPNOTSUPP;
+
+	return ethtool_op_set_tx_hw_csum(dev, data);
+}
+
+static int tun_set_sg(struct net_device *dev, u32 data)
+{
+	struct tun_struct *tun = netdev_priv(dev);
+
+	if (data && !(tun->offload & NETIF_F_SG))
+		return -EOPNOTSUPP;
+
+	return ethtool_op_set_sg(dev, data);
+}
+
+static int tun_set_tso(struct net_device *dev, u32 data)
+{
+	struct tun_struct *tun = netdev_priv(dev);
+
+	if (data && !(tun->offload & NETIF_F_TSO))
+		return -EOPNOTSUPP;
+
+	return ethtool_op_set_tso(dev, data);
+}
+
 static const struct ethtool_ops tun_ethtool_ops = {
 	.get_settings	= tun_get_settings,
 	.get_drvinfo	= tun_get_drvinfo,
@@ -1194,7 +1229,10 @@ static const struct ethtool_ops tun_ethtool_ops = {
 	.set_msglevel	= tun_set_msglevel,
 	.get_link	= tun_get_link,
 	.get_rx_csum	= tun_get_rx_csum,
-	.set_rx_csum	= tun_set_rx_csum
+	.set_rx_csum	= tun_set_rx_csum,
+	.set_tx_csum    = tun_set_tx_csum,
+	.set_sg         = tun_set_sg,
+	.set_tso        = tun_set_tso,
 };
 
 static int tun_init_net(struct net *net)
-- 
1.5.4.3
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help