Allow ethtool to change tun link settings
authorChas Williams <3chas3@gmail.com>
Sat, 2 Jun 2018 21:49:53 +0000 (17:49 -0400)
committerDavid S. Miller <davem@davemloft.net>
Mon, 4 Jun 2018 20:05:16 +0000 (16:05 -0400)
Let user space set whatever it would like to advertise for the
tun interface.  Preserve the existing defaults.

Signed-off-by: Chas Williams <3chas3@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/tun.c

index c94fffee5ea99689d8574e4e0f92a18ee85f958a..067fc9e7e3edc9d7b4603a388151915feaf6e6a4 100644 (file)
@@ -81,6 +81,9 @@
 #include <linux/uaccess.h>
 #include <linux/proc_fs.h>
 
+static void tun_default_link_ksettings(struct net_device *dev,
+                                      struct ethtool_link_ksettings *cmd);
+
 /* Uncomment to enable debugging */
 /* #define TUN_DEBUG 1 */
 
@@ -242,6 +245,7 @@ struct tun_struct {
        struct bpf_prog __rcu *xdp_prog;
        struct tun_prog __rcu *steering_prog;
        struct tun_prog __rcu *filter_prog;
+       struct ethtool_link_ksettings link_ksettings;
 };
 
 struct veth {
@@ -2295,6 +2299,7 @@ static void tun_setup(struct net_device *dev)
 
        tun->owner = INVALID_UID;
        tun->group = INVALID_GID;
+       tun_default_link_ksettings(dev, &tun->link_ksettings);
 
        dev->ethtool_ops = &tun_ethtool_ops;
        dev->needs_free_netdev = true;
@@ -3326,8 +3331,8 @@ static struct miscdevice tun_miscdev = {
 
 /* ethtool interface */
 
-static int tun_get_link_ksettings(struct net_device *dev,
-                                 struct ethtool_link_ksettings *cmd)
+static void tun_default_link_ksettings(struct net_device *dev,
+                                      struct ethtool_link_ksettings *cmd)
 {
        ethtool_link_ksettings_zero_link_mode(cmd, supported);
        ethtool_link_ksettings_zero_link_mode(cmd, advertising);
@@ -3336,6 +3341,23 @@ static int tun_get_link_ksettings(struct net_device *dev,
        cmd->base.port          = PORT_TP;
        cmd->base.phy_address   = 0;
        cmd->base.autoneg       = AUTONEG_DISABLE;
+}
+
+static int tun_get_link_ksettings(struct net_device *dev,
+                                 struct ethtool_link_ksettings *cmd)
+{
+       struct tun_struct *tun = netdev_priv(dev);
+
+       memcpy(cmd, &tun->link_ksettings, sizeof(*cmd));
+       return 0;
+}
+
+static int tun_set_link_ksettings(struct net_device *dev,
+                                 const struct ethtool_link_ksettings *cmd)
+{
+       struct tun_struct *tun = netdev_priv(dev);
+
+       memcpy(&tun->link_ksettings, cmd, sizeof(*cmd));
        return 0;
 }
 
@@ -3406,6 +3428,7 @@ static const struct ethtool_ops tun_ethtool_ops = {
        .get_coalesce   = tun_get_coalesce,
        .set_coalesce   = tun_set_coalesce,
        .get_link_ksettings = tun_get_link_ksettings,
+       .set_link_ksettings = tun_set_link_ksettings,
 };
 
 static int tun_queue_resize(struct tun_struct *tun)