]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
tun: implement carrier change
authorNicolas Dichtel <nicolas.dichtel@6wind.com>
Wed, 6 Mar 2019 18:00:18 +0000 (02:00 +0800)
committerJuerg Haefliger <juergh@canonical.com>
Fri, 8 Mar 2019 08:23:12 +0000 (09:23 +0100)
BugLink: https://bugs.launchpad.net/bugs/1806392
The userspace may need to control the carrier state.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: Didier Pallard <didier.pallard@6wind.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
(backported from commit 26d31925cd5ea4b5b168ed538b0326d63ccbb384)
Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Acked-by: Khalid Elmously <khalid.elmously@canonical.com>
Acked-by: Kleber Souza <kleber.souza@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
drivers/net/tun.c
include/uapi/linux/if_tun.h

index 4e5d038a252d3b49c8aa980446a136fd895ef110..a0c7756e304cc4ece7da07a19cd0b58c0f61af37 100644 (file)
@@ -1164,6 +1164,21 @@ static int tun_xdp(struct net_device *dev, struct netdev_bpf *xdp)
        }
 }
 
+static int tun_net_change_carrier(struct net_device *dev, bool new_carrier)
+{
+       if (new_carrier) {
+               struct tun_struct *tun = netdev_priv(dev);
+
+               if (!tun->numqueues)
+                       return -EPERM;
+
+               netif_carrier_on(dev);
+       } else {
+               netif_carrier_off(dev);
+       }
+       return 0;
+}
+
 static const struct net_device_ops tun_netdev_ops = {
        .ndo_uninit             = tun_net_uninit,
        .ndo_open               = tun_net_open,
@@ -1176,6 +1191,7 @@ static const struct net_device_ops tun_netdev_ops = {
 #endif
        .ndo_set_rx_headroom    = tun_set_headroom,
        .ndo_get_stats64        = tun_net_get_stats64,
+       .ndo_change_carrier     = tun_net_change_carrier,
 };
 
 static const struct net_device_ops tap_netdev_ops = {
@@ -1195,6 +1211,7 @@ static const struct net_device_ops tap_netdev_ops = {
        .ndo_set_rx_headroom    = tun_set_headroom,
        .ndo_get_stats64        = tun_net_get_stats64,
        .ndo_bpf                = tun_xdp,
+       .ndo_change_carrier     = tun_net_change_carrier,
 };
 
 static void tun_flow_init(struct tun_struct *tun)
@@ -2501,12 +2518,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
        struct tun_file *tfile = file->private_data;
        struct tun_struct *tun;
        void __user* argp = (void __user*)arg;
+       unsigned int ifindex, carrier;
        struct ifreq ifr;
        kuid_t owner;
        kgid_t group;
        int sndbuf;
        int vnet_hdr_sz;
-       unsigned int ifindex;
        int le;
        int ret;
 
@@ -2771,6 +2788,14 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
                ret = 0;
                break;
 
+       case TUNSETCARRIER:
+               ret = -EFAULT;
+               if (copy_from_user(&carrier, argp, sizeof(carrier)))
+                       goto unlock;
+
+               ret = tun_net_change_carrier(tun->dev, (bool)carrier);
+               break;
+
        default:
                ret = -EINVAL;
                break;
index 030d3e6d60294cf2d6ac98f1331052a5f1728001..438f87bfa504ac2ecbb4654d25387dc3d22dd9c3 100644 (file)
@@ -57,6 +57,7 @@
  */
 #define TUNSETVNETBE _IOW('T', 222, int)
 #define TUNGETVNETBE _IOR('T', 223, int)
+#define TUNSETCARRIER _IOW('T', 226, int)
 
 /* TUNSETIFF ifr flags */
 #define IFF_TUN                0x0001